<!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>[41196] trunk/src/wp-includes/ID3: Media: update the `getID3` library to version `1.9.14` to avoid fatal errors in PHP7.</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 { 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/41196">41196</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/41196","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>wonderboymusic</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-07-31 19:49:31 +0000 (Mon, 31 Jul 2017)</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'>Media: update the `getID3` library to version `1.9.14` to avoid fatal errors in PHP7.

Props MyThemeShop for the initial patch.
Fixes <a href="https://core.trac.wordpress.org/ticket/41496">#41496</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="#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="#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>
</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  2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/getid3.lib.php    2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -293,6 +293,9 @@
</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">+        public static function LittleEndian2Bin($byteword) {
+               return self::BigEndian2Bin(strrev($byteword));
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><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="lines" style="display: block; padding: 0 10px; color: #888">@@ -414,7 +417,21 @@
</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">+        public static function flipped_array_merge_noclobber($array1, $array2) {
+               if (!is_array($array1) || !is_array($array2)) {
+                       return false;
+               }
+               # naturally, this only works non-recursively
+               $newarray = array_flip($array1);
+               foreach (array_flip($array2) as $key => $val) {
+                       if (!isset($newarray[$key])) {
+                               $newarray[$key] = count($newarray);
+                       }
+               }
+               return array_flip($newarray);
+       }
</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">         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">@@ -946,8 +963,20 @@
</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">+                // mb_convert_encoding() availble
+               if (function_exists('mb_convert_encoding')) {
+                       if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
+                               switch ($out_charset) {
+                                       case 'ISO-8859-1':
+                                               $converted_string = rtrim($converted_string, "\x00");
+                                               break;
+                               }
+                               return $converted_string;
+                       }
+                       return $string;
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 // iconv() availble
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (function_exists('iconv')) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         else if (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">@@ -963,7 +992,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">-                // iconv() not available
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // neither mb_convert_encoding or iconv() is available
</ins><span class="cx" style="display: block; padding: 0 10px">                 static $ConversionFunctionList = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($ConversionFunctionList)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $ConversionFunctionList['ISO-8859-1']['UTF-8']    = 'iconv_fallback_iso88591_utf8';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -985,7 +1014,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
</span><span class="cx" style="display: block; padding: 0 10px">                        return self::$ConversionFunction($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">-                throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
</del><ins style="background-color: #dfd; text-decoration:none; 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);
</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">        public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1006,38 +1035,38 @@
</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="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                switch ($charset) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         switch (strtolower($charset)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         case '1251':
</span><span class="cx" style="display: block; padding: 0 10px">                        case '1252':
</span><span class="cx" style="display: block; padding: 0 10px">                        case '866':
</span><span class="cx" style="display: block; padding: 0 10px">                        case '932':
</span><span class="cx" style="display: block; padding: 0 10px">                        case '936':
</span><span class="cx" style="display: block; padding: 0 10px">                        case '950':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'BIG5':
-                       case 'BIG5-HKSCS':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'big5':
+                       case 'big5-hkscs':
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'cp1251':
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'cp1252':
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'cp866':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'EUC-JP':
-                       case 'EUCJP':
-                       case 'GB2312':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'euc-jp':
+                       case 'eucjp':
+                       case 'gb2312':
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'ibm866':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'ISO-8859-1':
-                       case 'ISO-8859-15':
-                       case 'ISO8859-1':
-                       case 'ISO8859-15':
-                       case 'KOI8-R':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'iso-8859-1':
+                       case 'iso-8859-15':
+                       case 'iso8859-1':
+                       case 'iso8859-15':
+                       case 'koi8-r':
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'koi8-ru':
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'koi8r':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'Shift_JIS':
-                       case 'SJIS':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'shift_jis':
+                       case 'sjis':
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'win-1251':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'Windows-1251':
-                       case 'Windows-1252':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'windows-1251':
+                       case 'windows-1252':
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
</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">-                        case 'UTF-8':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'utf-8':
</ins><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><span class="cx" style="display: block; padding: 0 10px">                                        $char_ord_val = ord($string{$i});
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1065,7 +1094,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">-                        case 'UTF-16LE':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'utf-16le':
</ins><span class="cx" style="display: block; padding: 0 10px">                                 for ($i = 0; $i < strlen($string); $i += 2) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $charval = self::LittleEndian2Int(substr($string, $i, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (($charval >= 32) && ($charval <= 127)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1076,7 +1105,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">-                        case 'UTF-16BE':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'utf-16be':
</ins><span class="cx" style="display: block; padding: 0 10px">                                 for ($i = 0; $i < strlen($string); $i += 2) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $charval = self::BigEndian2Int(substr($string, $i, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (($charval >= 32) && ($charval <= 127)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1153,11 +1182,19 @@
</span><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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        if (function_exists('sys_get_temp_dir')) {
+                               $tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         // yes this is ugly, feel free to suggest a better way
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        require_once(dirname(__FILE__).'/getid3.php');
-                       $getid3_temp = new getID3();
-                       $tempdir = $getid3_temp->tempdir;
-                       unset($getid3_temp);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (include_once(dirname(__FILE__).'/getid3.php')) {
+                               if ($getid3_temp = new getID3()) {
+                                       if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
+                                               $tempdir = $getid3_temp_tempdir;
+                                       }
+                                       unset($getid3_temp, $getid3_temp_tempdir);
+                               }
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                $GetDataImageSize = false;
</span><span class="cx" style="display: block; padding: 0 10px">                if ($tempfilename = tempnam($tempdir, 'gI3')) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1165,6 +1202,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                fwrite($tmp, $imgData);
</span><span class="cx" style="display: block; padding: 0 10px">                                fclose($tmp);
</span><span class="cx" style="display: block; padding: 0 10px">                                $GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[1])) {
+                                       return false;
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $GetDataImageSize['height'] = $GetDataImageSize[0];
</span><span class="cx" style="display: block; padding: 0 10px">                                $GetDataImageSize['width']  = $GetDataImageSize[1];
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1237,10 +1277,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $value = (is_string($value) ? trim($value) : $value);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                if (!is_numeric($key)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         if (!is_int($key) && !ctype_digit($key)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         $ThisFileInfo['comments'][$tagname][$key] = $value;
</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">-                                                                        $ThisFileInfo['comments'][$tagname][]     = $value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 if (isset($ThisFileInfo['comments'][$tagname])) {
+                                                                               $ThisFileInfo['comments'][$tagname] = array($value);
+                                                                       } else {
+                                                                               $ThisFileInfo['comments'][$tagname][] = $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">@@ -1248,6 +1292,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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        // attempt to standardize spelling of returned keys
+                       $StandardizeFieldNames = array(
+                               'tracknumber' => 'track_number',
+                               'track'       => 'track_number',
+                       );
+                       foreach ($StandardizeFieldNames as $badkey => $goodkey) {
+                               if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) {
+                                       $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey];
+                                       unset($ThisFileInfo['comments'][$badkey]);
+                               }
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         // Copy to ['comments_html']
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!empty($ThisFileInfo['comments'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                foreach ($ThisFileInfo['comments'] as $field => $values) {
</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      2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/getid3.php        2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22,6 +22,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) {
</span><span class="cx" style="display: block; padding: 0 10px">        define('IMG_JPG', IMAGETYPE_JPEG);
</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 (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE
+       define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><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="lines" style="display: block; padding: 0 10px; color: #888">@@ -109,7 +112,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        protected $startup_error   = '';
</span><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.9-20141121';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const VERSION           = '1.9.14-201706111222';
</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="lines" style="display: block; padding: 0 10px; color: #888">@@ -120,19 +123,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         // could be stored as "16M" rather than 16777216 for example
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->memory_limit = $matches[1] * 1048576;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                } elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
</ins><span class="cx" style="display: block; padding: 0 10px">                         // could be stored as "2G" rather than 2147483648 for example
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->memory_limit = $matches[1] * 1073741824;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->memory_limit <= 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                        // memory limits probably disabled
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif ($this->memory_limit <= 4194304) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'."\n";
</ins><span class="cx" style="display: block; padding: 0 10px">                 } elseif ($this->memory_limit <= 12582912) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini'."\n";
</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">                // Check safe_mode off
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -140,27 +143,30 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
</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 (intval(ini_get('mbstring.func_overload')) > 0) {
-                       $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
+                       // http://php.net/manual/en/mbstring.overload.php
+                       // "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions"
+                       // getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those.
+                       $this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n";
</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">                // Check for magic_quotes_runtime
</span><span class="cx" style="display: block; padding: 0 10px">                if (function_exists('get_magic_quotes_runtime')) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (get_magic_quotes_runtime()) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return $this->startup_error('magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n";
</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="cx" style="display: block; padding: 0 10px">                // Check for magic_quotes_gpc
</span><span class="cx" style="display: block; padding: 0 10px">                if (function_exists('magic_quotes_gpc')) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (get_magic_quotes_gpc()) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return $this->startup_error('magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n";
</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="cx" style="display: block; padding: 0 10px">                // Load support library
</span><span class="cx" style="display: block; padding: 0 10px">                if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->startup_error .= 'getid3.lib.php is missing or corrupt';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->startup_error .= 'getid3.lib.php is missing or corrupt'."\n";
</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 ($this->option_max_2gb_check === null) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -179,7 +185,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!is_dir($helperappsdir)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'."\n";
</ins><span class="cx" style="display: block; padding: 0 10px">                         } elseif (strpos(realpath($helperappsdir), ' ') !== false) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
</span><span class="cx" style="display: block; padding: 0 10px">                                $path_so_far = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -199,7 +205,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">                                                } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.'."\n";
</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">                                        $path_so_far[] = $value;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -209,6 +215,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
</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">+                if (!empty($this->startup_error)) {
+                       echo $this->startup_error;
+                       throw new getid3_exception($this->startup_error);
+               }
+
</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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -236,13 +247,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">-        public function openfile($filename) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function openfile($filename, $filesize=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="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!empty($this->startup_warning)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->warning($this->startup_warning);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         foreach (explode("\n", $this->startup_warning) as $startup_warning) {
+                                       $this->warning($startup_warning);
+                               }
</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">                        // init result array and set parameters
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -252,12 +265,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // remote files not supported
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (preg_match('/^(ht|f)tp:\/\//', $filename)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (preg_match('#^(ht|f)tp://#', $filename)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 throw new getid3_exception('Remote files are not supported - please copy the file locally first');
</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('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.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><span class="cx" style="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
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -280,7 +293,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
</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->info['filesize'] = filesize($filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
</ins><span class="cx" style="display: block; padding: 0 10px">                         // set redundant parameters - might be needed in some include file
</span><span class="cx" style="display: block; padding: 0 10px">                        // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
</span><span class="cx" style="display: block; padding: 0 10px">                        $filename = str_replace('\\', '/', $filename);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -288,6 +301,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->info['filename']     = getid3_lib::mb_basename($filename);
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        // set more parameters
+                       $this->info['avdataoffset']        = 0;
+                       $this->info['avdataend']           = $this->info['filesize'];
+                       $this->info['fileformat']          = '';                // filled in later
+                       $this->info['audio']['dataformat'] = '';                // filled in later, unset if not used
+                       $this->info['video']['dataformat'] = '';                // filled in later, unset if not used
+                       $this->info['tags']                = array();           // filled in later, unset if not used
+                       $this->info['error']               = array();           // filled in later, unset if not used
+                       $this->info['warning']             = array();           // filled in later, unset if not used
+                       $this->info['comments']            = array();           // filled in later, unset if not used
+                       $this->info['encoding']            = $this->encoding;   // required by id3v2 and iso modules - can be unset at the end if desired
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // option_max_2gb_check
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($this->option_max_2gb_check) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -314,18 +338,6 @@
</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">-                        // set more parameters
-                       $this->info['avdataoffset']        = 0;
-                       $this->info['avdataend']           = $this->info['filesize'];
-                       $this->info['fileformat']          = '';                // filled in later
-                       $this->info['audio']['dataformat'] = '';                // filled in later, unset if not used
-                       $this->info['video']['dataformat'] = '';                // filled in later, unset if not used
-                       $this->info['tags']                = array();           // filled in later, unset if not used
-                       $this->info['error']               = array();           // filled in later, unset if not used
-                       $this->info['warning']             = array();           // filled in later, unset if not used
-                       $this->info['comments']            = array();           // filled in later, unset if not used
-                       $this->info['encoding']            = $this->encoding;   // required by id3v2 and iso modules - can be unset at the end if desired
-
</del><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">                } catch (Exception $e) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -335,9 +347,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">        // public: analyze file
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function analyze($filename) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function analyze($filename, $filesize=null, $original_filename='') {
</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)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (!$this->openfile($filename, $filesize)) {
</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">@@ -382,7 +394,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $formattest = fread($this->fp, 32774);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // determine format
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $determined_format = $this->GetFileFormat($formattest, $filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // unable to determine file format
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!$determined_format) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -419,14 +431,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
</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">-                        // module requires iconv support
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // module requires mb_convert_encoding/iconv support
</ins><span class="cx" style="display: block; padding: 0 10px">                         // Check encoding/iconv support
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (!empty($determined_format['iconv_req']) && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
-                               $errormessage = 'iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (!empty($determined_format['iconv_req']) && !function_exists('mb_convert_encoding') && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
+                               $errormessage = 'mb_convert_encoding() or iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if (GETID3_OS_ISWINDOWS) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $errormessage .= 'PHP does not have mb_convert_encoding() or iconv() support. Please enable php_mbstring.dll / php_iconv.dll in php.ini, and copy php_mbstring.dll / iconv.dll from c:/php/dlls to c:/windows/system32';
</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">-                                        $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $errormessage .= 'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch';
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                return $this->error($errormessage);
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -561,7 +573,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // AC-3   - audio      - Dolby AC-3 / Dolby Digital
</span><span class="cx" style="display: block; padding: 0 10px">                                'ac3'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x0B\x77',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x0B\\x77',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'ac3',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/ac3',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -579,7 +591,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /*
</span><span class="cx" style="display: block; padding: 0 10px">                                // AA   - audio       - Audible Audiobook
</span><span class="cx" style="display: block; padding: 0 10px">                                'aa'   => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^.{4}\x57\x90\x75\x36',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^.{4}\\x57\\x90\\x75\\x36',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'aa',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/audible',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -587,7 +599,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">                                // AAC  - audio       - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
</span><span class="cx" style="display: block; padding: 0 10px">                                'adts' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\xFF[\xF0-\xF1\xF8-\xF9]',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'aac',
</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">@@ -597,7 +609,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // AU   - audio       - NeXT/Sun AUdio (AU)
</span><span class="cx" style="display: block; padding: 0 10px">                                'au'   => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\.snd',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\.snd',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'au',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/basic',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -605,7 +617,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // AMR  - audio       - Adaptive Multi Rate
</span><span class="cx" style="display: block; padding: 0 10px">                                'amr'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x23\x21AMR\x0A', // #!AMR[0A]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x23\\x21AMR\\x0A', // #!AMR[0A]
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'amr',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/amr',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -621,15 +633,23 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // BONK - audio       - Bonk v0.9+
</span><span class="cx" style="display: block; padding: 0 10px">                                'bonk' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x00(BONK|INFO|META| ID3)',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x00(BONK|INFO|META| ID3)',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'bonk',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/xmms-bonk',
</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">+                                // DSF  - audio       - Direct Stream Digital (DSD) Storage Facility files (DSF) - https://en.wikipedia.org/wiki/Direct_Stream_Digital
+                               'dsf'  => array(
+                                                       'pattern'   => '^DSD ',  // including trailing space: 44 53 44 20
+                                                       'group'     => 'audio',
+                                                       'module'    => 'dsf',
+                                                       'mime_type' => 'audio/dsd',
+                                               ),
+
</ins><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-\x03]ds[s2]',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^[\\x02-\\x06]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">@@ -637,7 +657,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // DTS  - audio       - Dolby Theatre System
</span><span class="cx" style="display: block; padding: 0 10px">                                'dts'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x7F\xFE\x80\x01',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x7F\\xFE\\x80\\x01',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'dts',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/dts',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -722,7 +742,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // MPC  - audio       - Musepack / MPEGplus
</span><span class="cx" style="display: block; padding: 0 10px">                                'mpc'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^(MPCK|MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'mpc',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/x-musepack',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -730,7 +750,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // MP3  - audio       - MPEG-audio Layer 3 (very similar to AAC-ADTS)
</span><span class="cx" style="display: block; padding: 0 10px">                                'mp3'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\x0B\x10-\x1B\x20-\x2B\x30-\x3B\x40-\x4B\x50-\x5B\x60-\x6B\x70-\x7B\x80-\x8B\x90-\x9B\xA0-\xAB\xB0-\xBB\xC0-\xCB\xD0-\xDB\xE0-\xEB\xF0-\xFB]',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\x0B\\x10-\\x1B\\x20-\\x2B\\x30-\\x3B\\x40-\\x4B\\x50-\\x5B\\x60-\\x6B\\x70-\\x7B\\x80-\\x8B\\x90-\\x9B\\xA0-\\xAB\\xB0-\\xBB\\xC0-\\xCB\\xD0-\\xDB\\xE0-\\xEB\\xF0-\\xFB]',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'mp3',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/mpeg',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -738,7 +758,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // OFR  - audio       - OptimFROG
</span><span class="cx" style="display: block; padding: 0 10px">                                'ofr'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^(\*RIFF|OFR)',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^(\\*RIFF|OFR)',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'optimfrog',
</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">@@ -764,7 +784,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // TTA  - audio       - TTA Lossless Audio Compressor (http://tta.corecodec.org)
</span><span class="cx" style="display: block; padding: 0 10px">                                'tta'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^TTA',  // could also be '^TTA(\x01|\x02|\x03|2|1)'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^TTA',  // could also be '^TTA(\\x01|\\x02|\\x03|2|1)'
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'tta',
</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">@@ -799,7 +819,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // ASF  - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
</span><span class="cx" style="display: block; padding: 0 10px">                                'asf'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x30\\x26\\xB2\\x75\\x8E\\x66\\xCF\\x11\\xA6\\xD9\\x00\\xAA\\x00\\x62\\xCE\\x6C',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio-video',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'asf',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'video/x-ms-asf',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -816,7 +836,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // FLV  - audio/video - FLash Video
</span><span class="cx" style="display: block; padding: 0 10px">                                'flv' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^FLV\x01',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^FLV[\\x01]',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio-video',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'flv',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'video/x-flv',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -824,7 +844,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // MKAV - audio/video - Mastroka
</span><span class="cx" style="display: block; padding: 0 10px">                                'matroska' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x1A\x45\xDF\xA3',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x1A\\x45\\xDF\\xA3',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio-video',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'matroska',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'video/x-matroska', // may also be audio/x-matroska
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -832,7 +852,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // MPEG - audio/video - MPEG (Moving Pictures Experts Group)
</span><span class="cx" style="display: block; padding: 0 10px">                                'mpeg' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x00\x00\x01(\xBA|\xB3)',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x00\\x00\\x01[\\xB3\\xBA]',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio-video',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'mpeg',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'video/mpeg',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -869,13 +889,13 @@
</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-wave',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'mime_type' => 'audio/x-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="cx" style="display: block; padding: 0 10px">                                // Real - audio/video - RealAudio, RealVideo
</span><span class="cx" style="display: block; padding: 0 10px">                                'real' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^(\\.RMF|\\.ra)',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\.(RMF|ra)',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio-video',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'real',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'audio/x-realaudio',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -891,7 +911,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // TS - audio/video - MPEG-2 Transport Stream
</span><span class="cx" style="display: block; padding: 0 10px">                                'ts' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^(\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G".  Check for at least 10 packets matching this pattern
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^(\\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G".  Check for at least 10 packets matching this pattern
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio-video',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'ts',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'video/MP2T',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -922,7 +942,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // JPEG - still image - Joint Photographic Experts Group (JPEG)
</span><span class="cx" style="display: block; padding: 0 10px">                                'jpg'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\xFF\xD8\xFF',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\xFF\\xD8\\xFF',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'graphic',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'jpg',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'image/jpeg',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -932,7 +952,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // PCD  - still image - Kodak Photo CD
</span><span class="cx" style="display: block; padding: 0 10px">                                'pcd'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^.{2048}PCD_IPI\x00',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^.{2048}PCD_IPI\\x00',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'graphic',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'pcd',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'image/x-photo-cd',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -943,7 +963,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // PNG  - still image - Portable Network Graphics (PNG)
</span><span class="cx" style="display: block; padding: 0 10px">                                'png'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'graphic',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'png',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'image/png',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -954,7 +974,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // SVG  - still image - Scalable Vector Graphics (SVG)
</span><span class="cx" style="display: block; padding: 0 10px">                                'svg'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '(<!DOCTYPE svg PUBLIC |xmlns="http:\/\/www\.w3\.org\/2000\/svg")',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '(<!DOCTYPE svg PUBLIC |xmlns="http://www\\.w3\\.org/2000/svg")',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'graphic',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'svg',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'image/svg+xml',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -965,7 +985,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // TIFF - still image - Tagged Information File Format (TIFF)
</span><span class="cx" style="display: block; padding: 0 10px">                                'tiff' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^(II\x2A\x00|MM\x00\x2A)',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^(II\\x2A\\x00|MM\\x00\\x2A)',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'graphic',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'tiff',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'image/tiff',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -976,7 +996,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // EFAX - still image - eFax (TIFF derivative)
</span><span class="cx" style="display: block; padding: 0 10px">                                'efax'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\xDC\xFE',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\xDC\\xFE',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'graphic',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'efax',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'image/efax',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1000,7 +1020,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // RAR  - data        - RAR compressed data
</span><span class="cx" style="display: block; padding: 0 10px">                                'rar'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^Rar\!',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^Rar\\!',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'archive',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'rar',
</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">@@ -1010,7 +1030,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // SZIP - audio/data  - SZIP compressed data
</span><span class="cx" style="display: block; padding: 0 10px">                                'szip' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^SZ\x0A\x04',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^SZ\\x0A\\x04',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'archive',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'szip',
</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">@@ -1020,7 +1040,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // TAR  - data        - TAR compressed data
</span><span class="cx" style="display: block; padding: 0 10px">                                'tar'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^.{100}[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20\x00]{12}[0-9\x20\x00]{12}',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^.{100}[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20\\x00]{12}[0-9\\x20\\x00]{12}',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'archive',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'tar',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'application/x-tar',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1030,7 +1050,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // GZIP  - data        - GZIP compressed data
</span><span class="cx" style="display: block; padding: 0 10px">                                'gz'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x1F\x8B\x08',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x1F\\x8B\\x08',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'archive',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'gzip',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'application/x-gzip',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1040,7 +1060,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // ZIP  - data         - ZIP compressed data
</span><span class="cx" style="display: block; padding: 0 10px">                                'zip'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^PK\x03\x04',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^PK\\x03\\x04',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'archive',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'zip',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'application/zip',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1053,7 +1073,7 @@
</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="cx" style="display: block; padding: 0 10px">                                'par2' => array (
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^PAR2\x00PKT',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^PAR2\\x00PKT',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'misc',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'par2',
</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">@@ -1063,7 +1083,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // PDF  - data        - Portable Document Format
</span><span class="cx" style="display: block; padding: 0 10px">                                'pdf'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\x25PDF',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\x25PDF',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'misc',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'pdf',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'application/pdf',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1073,7 +1093,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // MSOFFICE  - data   - ZIP compressed data
</span><span class="cx" style="display: block; padding: 0 10px">                                'msoffice' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'misc',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'msoffice',
</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">@@ -1114,14 +1134,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">-                if (preg_match('#\.mp[123a]$#i', $filename)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (preg_match('#\\.mp[123a]$#i', $filename)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         // Too many mp3 encoders on the market put gabage in front of mpeg files
</span><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="cx" style="display: block; padding: 0 10px">                        $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
</span><span class="cx" style="display: block; padding: 0 10px">                        return $info;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                } elseif (preg_match('/\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         // there's not really a useful consistent "magic" at the beginning of .cue files to identify them
</span><span class="cx" style="display: block; padding: 0 10px">                        // so until I think of something better, just go by filename if all other format checks fail
</span><span class="cx" style="display: block; padding: 0 10px">                        // and verify there's at least one instance of "TRACK xx AUDIO" in the file
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1222,13 +1242,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        continue;
</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">+                                $this->CharConvert($this->info['tags'][$tag_name], $this->info[$comment_name]['encoding']);           // only copy gets converted!
+
</ins><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $encoding);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
</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->CharConvert($this->info['tags'][$tag_name], $encoding);           // only copy gets converted!
</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">@@ -1352,8 +1373,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!empty($VorbisCommentError)) {
</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->info['warning'][]         = 'Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError;
-                                       $this->info[$algorithm.'_data']  = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError);
+                                       $this->info[$algorithm.'_data'] = false;
</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"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1582,6 +1603,17 @@
</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">+    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><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">@@ -1661,7 +1693,23 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if (!getid3_lib::intValueSupported($pos)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 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">-                return fread($this->getid3->fp, $bytes);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               //return fread($this->getid3->fp, $bytes);
+               /*
+               * http://www.getid3.org/phpBB3/viewtopic.php?t=1930
+               * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
+               * It seems to assume that fread() would always return as many bytes as were requested.
+               * 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.
+               * The call may return only part of the requested data and a new call is needed to get more."
+               */
+               $contents = '';
+               do {
+                       $part = fread($this->getid3->fp, $bytes);
+                       $partLength  = strlen($part);
+                       $bytes      -= $partLength;
+                       $contents   .= $part;
+               } while (($bytes > 0) && ($partLength > 0));
+               return $contents;
</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">        protected function fseek($bytes, $whence=SEEK_SET) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1741,7 +1789,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // set up destination path
</span><span class="cx" style="display: block; padding: 0 10px">                                $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if (!is_dir($dir) || !getID3::is_writable($dir)) { // check supplied directory
</ins><span class="cx" style="display: block; padding: 0 10px">                                         throw new Exception('supplied path ('.$dir.') does not exist, or is not writable');
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : '');
</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      2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio-video.asf.php        2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -266,14 +266,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 16;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_asf_headerextensionobject['reserved_1_guid']     = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 //return false;
</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">                                        $thisfile_asf_headerextensionobject['reserved_2']          = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 2;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 //return false;
</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">@@ -316,7 +316,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 16;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_asf_codeclistobject['reserved_guid']             = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 //return false;
</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">@@ -349,7 +349,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = '[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-seperated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"');
</ins><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">                                                                list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -412,7 +412,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">-                                                                                $info['warning'][] = 'unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         $this->warning('unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')');
</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">@@ -458,7 +458,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 16;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_asf_scriptcommandobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 //return false;
</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">@@ -517,7 +517,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 16;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_asf_markerobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
</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">                                        $thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -525,7 +525,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 2;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_asf_markerobject['reserved_2'] != 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"');
</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">                                        $thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -576,7 +576,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_asf_bitratemutualexclusionobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 16;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or  "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or  "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 //return false;
</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">@@ -637,7 +637,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">-                                                        $info['warning'][] = 'error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or  "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or  "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         //return false;
</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">@@ -761,7 +761,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">-                                                                $info['warning'][] = 'extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 //return false;
</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">@@ -962,9 +962,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($this->GUIDname($NextObjectGUIDtext)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
</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">-                                                $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += ($NextObjectSize - 16 - 8);
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1183,7 +1183,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_asf_dataobject['reserved']           = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += 2;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 //return false;
</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">@@ -1319,9 +1319,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($this->GUIDname($NextObjectGUIDtext)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8));
</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">-                                                $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8));
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                        $this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1405,7 +1405,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">-                                                $info['warning'][] = 'Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']);
</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">@@ -1917,9 +1917,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                        $unhandled_sections++;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($this->GUIDname($thisObject['guid_text'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $this->getid3->info['warning'][] = 'unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8));
</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->getid3->info['warning'][] = 'unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8));
</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></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      2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio-video.flv.php        2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -93,7 +93,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $TypeFlags                          = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1));
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($info['flv']['header']['signature'] != self::magic) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"');
</ins><span class="cx" style="display: block; padding: 0 10px">                         unset($info['flv'], $info['fileformat']);
</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">@@ -541,7 +541,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // Long string
</span><span class="cx" style="display: block; padding: 0 10px">                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                $value = '(unknown or unsupported data type)';
</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><span class="cx" style="display: block; padding: 0 10px">                return $value;
</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 2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio-video.matroska.php   2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -234,7 +234,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                try {
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->parseEBML($info);
</span><span class="cx" style="display: block; padding: 0 10px">                } catch (Exception $e) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'EBML parser: '.$e->getMessage();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('EBML parser: '.$e->getMessage());
</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">                // calculate playtime
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -330,11 +330,13 @@
</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 'A_AC3':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                        case 'A_EAC3':
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         case 'A_DTS':
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case 'A_MPEG/L3':
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case 'A_MPEG/L2':
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case 'A_FLAC':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $module_dataformat = ($track_info['dataformat'] == 'mp2' ? 'mp3' : ($track_info['dataformat'] == 'eac3' ? 'ac3' : $track_info['dataformat']));
+                                                               getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.$module_dataformat.'.php', __FILE__, true);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -352,7 +354,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">                                                                // analyze
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $class = 'getid3_'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $class = 'getid3_'.$module_dataformat;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 $header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $getid3_audio = new $class($getid3_temp, __CLASS__);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                if ($track_info['dataformat'] == 'flac') {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -457,6 +459,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                $info['audio']['streams'][] = $track_info;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -524,6 +527,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $this->unhandledElement('header', __LINE__, $element_data);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                unset($element_data['offset'], $element_data['end']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -562,15 +566,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry);                                                                                         }
</span><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">-
-                                                                                       if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                 if (!isset($seek_entry['target_id'])) {
+                                                                                               $this->warning('seek_entry[target_id] unexpectedly not set at '.$seek_entry['offset']);
+                                                                                               break;
+                                                                                       }
+                                                                                       if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !self::$hide_clusters) { // collect clusters only if required
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                 $info['matroska']['seek'][] = $seek_entry;
</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">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('seekhead', __LINE__, $seek_entry);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -653,6 +662,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                        $this->unhandledElement('track.video', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -678,6 +688,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                        $this->unhandledElement('track.audio', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -713,6 +724,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -736,24 +748,28 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
</span><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><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="cx" style="display: block; padding: 0 10px">                                                                                                                                                                $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
</span><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><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="cx" style="display: block; padding: 0 10px">                                                                                                                                        $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
</span><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><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="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('track', __LINE__, $subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -762,6 +778,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('tracks', __LINE__, $track_entry);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -825,6 +842,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                        $info_entry[$subelement['id_name']] = $chaptertranslate_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -832,6 +850,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('info', __LINE__, $subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                $info['matroska']['info'][] = $info_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -868,6 +887,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                        $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -879,6 +899,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                        $cues_entry[] = $cuepoint_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -886,6 +907,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('cues', __LINE__, $subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                $info['matroska']['cues'] = $cues_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -927,6 +949,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                        $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $tag_entry[$sub_subelement['id_name']] = $targets_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -938,6 +961,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                        $tags_entry[] = $tag_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -945,6 +969,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('tags', __LINE__, $subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                $info['matroska']['tags'] = $tags_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -985,6 +1010,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                        $info['matroska']['attachments'][] = $attachedfile_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -992,6 +1018,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('attachments', __LINE__, $subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1051,6 +1078,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                        $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1070,6 +1098,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                        $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1077,6 +1106,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                                        $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1084,6 +1114,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                        $info['matroska']['chapters'][] = $editionentry_entry;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1091,6 +1122,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('chapters', __LINE__, $subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1119,6 +1151,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                        $cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1149,6 +1182,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
</span><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><span class="cx" style="display: block; padding: 0 10px">                                                                                        $cluster_entry[$subelement['id_name']][] = $cluster_block_group;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1160,6 +1194,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $this->unhandledElement('cluster', __LINE__, $subelement);
</span><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">                                                                        $this->current_offset = $subelement['end'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1181,12 +1216,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $this->unhandledElement('segment', __LINE__, $element_data);
</span><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><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="cx" style="display: block; padding: 0 10px">                                        $this->unhandledElement('root', __LINE__, $top_element);
</span><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><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1339,6 +1376,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                default:
</span><span class="cx" style="display: block; padding: 0 10px">                                        $this->unhandledElement('tag.simpletag', __LINE__, $element);
</span><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><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1490,6 +1528,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $CodecIDlist['A_AAC']            = 'aac';
</span><span class="cx" style="display: block; padding: 0 10px">                        $CodecIDlist['A_AAC/MPEG2/LC']   = 'aac';
</span><span class="cx" style="display: block; padding: 0 10px">                        $CodecIDlist['A_AC3']            = 'ac3';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $CodecIDlist['A_EAC3']           = 'eac3';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $CodecIDlist['A_DTS']            = 'dts';
</span><span class="cx" style="display: block; padding: 0 10px">                        $CodecIDlist['A_FLAC']           = 'flac';
</span><span class="cx" style="display: block; padding: 0 10px">                        $CodecIDlist['A_MPEG/L1']        = 'mp1';
</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        2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio-video.quicktime.php  2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -35,10 +35,10 @@
</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 = ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 2) : $this->getid3->option_fread_buffer_size * 1024); // allow [default: 32MB] if PHP configured with no memory_limit
</del><ins style="background-color: #dfd; 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]
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions';
</del><ins style="background-color: #dfd; text-decoration:none; 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');
</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">                        $this->fseek($offset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -57,7 +57,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $info['quicktime'][$atomname]['offset'] = $offset;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if (($offset + $atomsize) > $info['avdataend']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['error'][] = 'Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)');
</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">@@ -81,6 +81,81 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($info['avdataend_tmp']);
</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">+                if (!empty($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) {
+                       $durations = $this->quicktime_time_to_sample_table($info);
+                       for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) {
+                               $bookmark = array();
+                               $bookmark['title'] = $info['quicktime']['comments']['chapters'][$i];
+                               if (isset($durations[$i])) {
+                                       $bookmark['duration_sample'] = $durations[$i]['sample_duration'];
+                                       if ($i > 0) {
+                                               $bookmark['start_sample'] = $info['quicktime']['bookmarks'][($i - 1)]['start_sample'] + $info['quicktime']['bookmarks'][($i - 1)]['duration_sample'];
+                                       } else {
+                                               $bookmark['start_sample'] = 0;
+                                       }
+                                       if ($time_scale = $this->quicktime_bookmark_time_scale($info)) {
+                                               $bookmark['duration_seconds'] = $bookmark['duration_sample'] / $time_scale;
+                                               $bookmark['start_seconds']    = $bookmark['start_sample']    / $time_scale;
+                                       }
+                               }
+                               $info['quicktime']['bookmarks'][] = $bookmark;
+                       }
+               }
+
+               if (isset($info['quicktime']['temp_meta_key_names'])) {
+                       unset($info['quicktime']['temp_meta_key_names']);
+               }
+
+               if (!empty($info['quicktime']['comments']['location.ISO6709'])) {
+                       // https://en.wikipedia.org/wiki/ISO_6709
+                       foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) {
+                               $latitude  = false;
+                               $longitude = false;
+                               $altitude  = false;
+                               if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) {
+                                       @list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches;
+
+                                       if (strlen($lat_deg) == 2) {        // [+-]DD.D
+                                               $latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec);
+                                       } elseif (strlen($lat_deg) == 4) {  // [+-]DDMM.M
+                                               $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
+                                       } elseif (strlen($lat_deg) == 6) {  // [+-]DDMMSS.S
+                                               $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
+                                       }
+
+                                       if (strlen($lon_deg) == 3) {        // [+-]DDD.D
+                                               $longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec);
+                                       } elseif (strlen($lon_deg) == 5) {  // [+-]DDDMM.M
+                                               $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
+                                       } elseif (strlen($lon_deg) == 7) {  // [+-]DDDMMSS.S
+                                               $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
+                                       }
+
+                                       if (strlen($alt_deg) == 3) {        // [+-]DDD.D
+                                               $altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec);
+                                       } elseif (strlen($alt_deg) == 5) {  // [+-]DDDMM.M
+                                               $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
+                                       } elseif (strlen($alt_deg) == 7) {  // [+-]DDDMMSS.S
+                                               $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
+                                       }
+
+                                       if ($latitude !== false) {
+                                               $info['quicktime']['comments']['gps_latitude'][]  = (($lat_sign == '-') ? -1 : 1) * floatval($latitude);
+                                       }
+                                       if ($longitude !== false) {
+                                               $info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude);
+                                       }
+                                       if ($altitude !== false) {
+                                               $info['quicktime']['comments']['gps_altitude'][]  = (($alt_sign == '-') ? -1 : 1) * floatval($altitude);
+                                       }
+                               }
+                               if ($latitude === false) {
+                                       $this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug');
+                               }
+                               break;
+                       }
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -98,10 +173,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">-                if (($info['audio']['dataformat'] == 'mp4') && empty($info['video']['resolution_x'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ($info['audio']['dataformat'] == 'mp4') {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $info['fileformat'] = 'mp4';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['mime_type']  = 'audio/mp4';
-                       unset($info['video']['dataformat']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (empty($info['video']['resolution_x'])) {
+                               $info['mime_type']  = 'audio/mp4';
+                               unset($info['video']['dataformat']);
+                       } else {
+                               $info['mime_type']  = 'video/mp4';
+                       }
</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 (!$this->ReturnAtomData) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -120,6 +199,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
</ins><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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -222,81 +302,88 @@
</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><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
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'aART': // Album ARTist
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        case 'akID': // iTunes store account type
+                       case 'apID': // Purchase Account
+                       case 'atID': //
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'catg': // CaTeGory
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        case 'cmID': //
+                       case 'cnID': //
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'covr': // COVeR artwork
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'cpil': // ComPILation
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'cprt': // CoPyRighT
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'desc': // DESCription
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'disk': // DISK number
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'egid': // Episode Global ID
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        case 'geID': //
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'gnre': // GeNRE
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        case 'hdvd': // HD ViDeo
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'keyw': // KEYWord
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'ldes':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'ldes': // Long DEScription
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'pcst': // PodCaST
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'pgap': // GAPless Playback
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        case 'plID': //
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'purd': // PURchase Date
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'purl': // Podcast URL
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rati':
-                       case 'rndu':
-                       case 'rpdu':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 case 'rati': //
+                       case 'rndu': //
+                       case 'rpdu': //
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'rtng': // RaTiNG
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'stik':
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 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': //
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'tmpo': // TeMPO (BPM)
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'trkn': // TRacK Number
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        case 'tven': // tvEpisodeID
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'tves': // TV EpiSode
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'tvnn': // TV Network Name
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'tvsh': // TV SHow Name
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'tvsn': // TV SeasoN
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'akID': // iTunes store account type
-                       case 'apID':
-                       case 'atID':
-                       case 'cmID':
-                       case 'cnID':
-                       case 'geID':
-                       case 'plID':
-                       case 'sfID': // iTunes store country
-                       case "\xA9".'alb': // ALBum
-                       case "\xA9".'art': // ARTist
-                       case "\xA9".'ART':
-                       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".'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
</del><span class="cx" style="display: block; padding: 0 10px">                                 if ($atom_parent == 'udta') {
</span><span class="cx" style="display: block; padding: 0 10px">                                        // User data atom handler
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -318,7 +405,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if ($boxsmallsize <= 1) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 $atom_structure['data'] = null;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $atomoffset = strlen($atom_data);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -328,7 +415,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $atom_structure['data'] = $boxsmalldata;
</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">-                                                                        $info['warning'][] = 'Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         $atom_structure['data'] = $atom_data;
</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">@@ -340,7 +427,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $boxtype =                           substr($atom_data, $atomoffset + 4, 4);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if ($boxsize <= 1) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 $atom_structure['data'] = null;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $atomoffset = strlen($atom_data);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -361,17 +448,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                case 21: // tmpo/cpil flag
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        switch ($atomname) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                case 'cpil':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                case 'hdvd':
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                 case 'pcst':
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                case 'pgap':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // 8-bit integer (boolean)
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
</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 'tmpo':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // 16-bit integer
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
</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 'disk':
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                case 'trkn':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // binary
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        $atom_structure['data']  = empty($num) ? '' : $num;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -379,21 +470,25 @@
</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 'gnre':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // enum
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
</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 'rtng':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // 8-bit integer
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
</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 'stik':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // 8-bit integer (enum)
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
</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 'sfID':
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // 32-bit integer
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -403,7 +498,30 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        $atom_structure['data'] = substr($boxdata, 8);
</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 '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':
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                 default:
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                        // 32-bit integer
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
</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">@@ -414,9 +532,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $atom_structure['data'] = substr($boxdata, 8);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        if ($atomname == 'covr') {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                // not a foolproof check, but better than nothing
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                if (preg_match('#^\xFF\xD8\xFF#', $atom_structure['data'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                         if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure['image_mime'] = 'image/jpeg';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                } elseif (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $atom_structure['data'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                         } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         $atom_structure['image_mime'] = 'image/png';
</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="lines" style="display: block; padding: 0 10px; color: #888">@@ -428,7 +546,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">-                                                                        $info['warning'][] = 'Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         $atom_structure['data'] = $atom_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">@@ -476,7 +594,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
</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">-                                        $info['warning'][] = 'Error decompressing compressed MOV atom at offset '.$atom_structure['offset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
</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">@@ -595,7 +713,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
</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">-                                        $info['warning'][] = 'unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
</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">@@ -604,6 +722,20 @@
</span><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><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">                                 $stsdEntriesDataOffset = 8;
</span><span class="cx" style="display: block; padding: 0 10px">                                for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['sample_description_table'][$i]['size']             = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -801,7 +933,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="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']);
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($atom_structure['number_entries'] / 1048576).'MB).';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $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).');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -928,13 +1060,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['data_references'][$i]['size']                    = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $drefDataOffset += 4;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['data_references'][$i]['type']                    =               substr($atom_data, $drefDataOffset, 4);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['data_references'][$i]['type']                    =                           substr($atom_data, $drefDataOffset, 4);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $drefDataOffset += 4;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['data_references'][$i]['version']                 = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $drefDataOffset += 1;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['data_references'][$i]['flags_raw']               = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 3)); // hardcoded: 0x0000
</span><span class="cx" style="display: block; padding: 0 10px">                                        $drefDataOffset += 3;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['data_references'][$i]['data']                    =               substr($atom_data, $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">+                                 $atom_structure['data_references'][$i]['data']                    =                           substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1001,10 +1133,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['quality']               = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($atom_structure['time_scale'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Corrupt Quicktime file: mdhd.time_scale == zero');
</ins><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">-                                $info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? 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">+                         $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><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['creation_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['modify_time_unix']      = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1019,7 +1151,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'pnot': // Preview atom
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['modification_date']      = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // "standard Macintosh format"
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['version_number']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x00
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['atom_type']              =               substr($atom_data,  6, 4);        // usually: 'PICT'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $atom_structure['atom_type']              =                           substr($atom_data,  6, 4);        // usually: 'PICT'
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $atom_structure['atom_index']             = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1029,7 +1161,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'crgn': // Clipping ReGioN atom
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['region_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2)); // The Region size, Region boundary box,
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['boundary_box']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 8)); // and Clipping region data fields
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['clipping_data'] =               substr($atom_data, 10);           // constitute a QuickDraw region.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $atom_structure['clipping_data'] =                           substr($atom_data, 10);           // constitute a QuickDraw region.
</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">@@ -1115,12 +1247,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['next_track_id']      =   getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($atom_structure['time_scale'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Corrupt Quicktime file: mvhd.time_scale == zero');
</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">                                $atom_structure['creation_time_unix']        = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['modify_time_unix']          = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['quicktime']['time_scale']    = (isset($info['quicktime']['time_scale']) ? 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">+                         $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">                                 $info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['playtime_seconds']           = $atom_structure['duration'] / $atom_structure['time_scale'];
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1240,16 +1372,22 @@
</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">                                // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                while  (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         while (($mdat_offset < (strlen($atom_data) - 8))
+                                       && ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
</ins><span class="cx" style="display: block; padding: 0 10px">                                         && ($chapter_string_length < 1000)
</span><span class="cx" style="display: block; padding: 0 10px">                                        && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        && preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 && 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;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $mdat_offset += (2 + $chapter_string_length);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                @$info['quicktime']['comments']['chapters'][] = $chapter_matches[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         @$info['quicktime']['comments']['chapters'][] = $chapter_string;
+
+                                               // "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><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">                                 if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['avdataoffset'] = $atom_structure['offset'] + 8;                       // $info['quicktime'][$atomname]['offset'] + 8;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1265,7 +1403,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
</span><span class="cx" style="display: block; padding: 0 10px">                                                if (!empty($getid3_temp->info['warning'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        foreach ($getid3_temp->info['warning'] as $value) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = $value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning($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">                                                if (!empty($getid3_temp->info['mpeg'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1368,7 +1506,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
</span><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">-                                        $info['warning'][] = 'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.');
</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">@@ -1397,26 +1535,183 @@
</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 "\x00\x00\x00\x00":
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'meta': // METAdata atom
</del><span class="cx" style="display: block; padding: 0 10px">                                 // some kind of metacontainer, may contain a big data dump such as:
</span><span class="cx" style="display: block; padding: 0 10px">                                // 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
</span><span class="cx" style="display: block; padding: 0 10px">                                // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
</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['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);
</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);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 //$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
</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 'meta': // METAdata atom
+                               // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
+
+                               $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">                         case 'data': // metaDATA atom
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                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
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['language'] =                           substr($atom_data, 4 + 0, 2);
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['unknown']  = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                $atom_structure['data']     =                           substr($atom_data, 4 + 4);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++];
+
+                               if ($atom_structure['key_name'] && $atom_structure['data']) {
+                                       @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
+                               }
</ins><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 '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
+
+                                       $info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value'];
+                               }
+                               break;
+
+                       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.
+
+                               $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;
+                                                       }
+                                                       $this->fseek($gps_pointer['offset']);
+                                                       $GPS_free_data = $this->fread($gps_pointer['size']);
+
+                                                       /*
+                                                       // 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
+
+                                                       // 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
+
+                                                       //$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));
+                                                       */
+
+                                                       // $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;
+
+                                                               $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;
+
+                                                               $GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void
+
+                                                               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'  => $GPS_this_GPRMC['latitude'],
+                                                                       'longitude' => $GPS_this_GPRMC['longitude'],
+                                                                       'speed_kmh' => $GPS_this_GPRMC['speed_kmh'],
+                                                                       'heading'   => $GPS_this_GPRMC['heading'],
+                                                               );
+
+                                                       } else {
+                                                               $this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']);
+                                                       }
+                                               }
+                                               $this->fseek($previous_offset);
+
+                                       } 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;
+
+                       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;
+
</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">-                                $info['warning'][] = 'Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $atom_structure['data'] = $atom_data;
</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">@@ -1440,6 +1735,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                // Furthermore, for historical reasons the list of atoms is optionally
</span><span class="cx" style="display: block; padding: 0 10px">                                // terminated by a 32-bit integer set to 0. If you are writing a program
</span><span class="cx" style="display: block; padding: 0 10px">                                // to read user data atoms, you should allow for the terminating 0.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                if (strlen($atom_data) > 12) {
+                                       $subatomoffset += 4;
+                                       continue;
+                               }
</ins><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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1753,56 +2052,56 @@
</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="cx" style="display: block; padding: 0 10px">                        $QuicktimeIODSaudioProfileNameLookup = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                            0x00 => 'ISO Reserved (0x00)',
-                           0x01 => 'Main Audio Profile @ Level 1',
-                           0x02 => 'Main Audio Profile @ Level 2',
-                           0x03 => 'Main Audio Profile @ Level 3',
-                           0x04 => 'Main Audio Profile @ Level 4',
-                           0x05 => 'Scalable Audio Profile @ Level 1',
-                           0x06 => 'Scalable Audio Profile @ Level 2',
-                           0x07 => 'Scalable Audio Profile @ Level 3',
-                           0x08 => 'Scalable Audio Profile @ Level 4',
-                           0x09 => 'Speech Audio Profile @ Level 1',
-                           0x0A => 'Speech Audio Profile @ Level 2',
-                           0x0B => 'Synthetic Audio Profile @ Level 1',
-                           0x0C => 'Synthetic Audio Profile @ Level 2',
-                           0x0D => 'Synthetic Audio Profile @ Level 3',
-                           0x0E => 'High Quality Audio Profile @ Level 1',
-                           0x0F => 'High Quality Audio Profile @ Level 2',
-                           0x10 => 'High Quality Audio Profile @ Level 3',
-                           0x11 => 'High Quality Audio Profile @ Level 4',
-                           0x12 => 'High Quality Audio Profile @ Level 5',
-                           0x13 => 'High Quality Audio Profile @ Level 6',
-                           0x14 => 'High Quality Audio Profile @ Level 7',
-                           0x15 => 'High Quality Audio Profile @ Level 8',
-                           0x16 => 'Low Delay Audio Profile @ Level 1',
-                           0x17 => 'Low Delay Audio Profile @ Level 2',
-                           0x18 => 'Low Delay Audio Profile @ Level 3',
-                           0x19 => 'Low Delay Audio Profile @ Level 4',
-                           0x1A => 'Low Delay Audio Profile @ Level 5',
-                           0x1B => 'Low Delay Audio Profile @ Level 6',
-                           0x1C => 'Low Delay Audio Profile @ Level 7',
-                           0x1D => 'Low Delay Audio Profile @ Level 8',
-                           0x1E => 'Natural Audio Profile @ Level 1',
-                           0x1F => 'Natural Audio Profile @ Level 2',
-                           0x20 => 'Natural Audio Profile @ Level 3',
-                           0x21 => 'Natural Audio Profile @ Level 4',
-                           0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
-                           0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
-                           0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
-                           0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
-                           0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
-                           0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
-                           0x28 => 'AAC Profile @ Level 1',
-                           0x29 => 'AAC Profile @ Level 2',
-                           0x2A => 'AAC Profile @ Level 4',
-                           0x2B => 'AAC Profile @ Level 5',
-                           0x2C => 'High Efficiency AAC Profile @ Level 2',
-                           0x2D => 'High Efficiency AAC Profile @ Level 3',
-                           0x2E => 'High Efficiency AAC Profile @ Level 4',
-                           0x2F => 'High Efficiency AAC Profile @ Level 5',
-                           0xFE => 'Not part of MPEG-4 audio profiles',
-                           0xFF => 'No audio capability required',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         0x00 => 'ISO Reserved (0x00)',
+                               0x01 => 'Main Audio Profile @ Level 1',
+                               0x02 => 'Main Audio Profile @ Level 2',
+                               0x03 => 'Main Audio Profile @ Level 3',
+                               0x04 => 'Main Audio Profile @ Level 4',
+                               0x05 => 'Scalable Audio Profile @ Level 1',
+                               0x06 => 'Scalable Audio Profile @ Level 2',
+                               0x07 => 'Scalable Audio Profile @ Level 3',
+                               0x08 => 'Scalable Audio Profile @ Level 4',
+                               0x09 => 'Speech Audio Profile @ Level 1',
+                               0x0A => 'Speech Audio Profile @ Level 2',
+                               0x0B => 'Synthetic Audio Profile @ Level 1',
+                               0x0C => 'Synthetic Audio Profile @ Level 2',
+                               0x0D => 'Synthetic Audio Profile @ Level 3',
+                               0x0E => 'High Quality Audio Profile @ Level 1',
+                               0x0F => 'High Quality Audio Profile @ Level 2',
+                               0x10 => 'High Quality Audio Profile @ Level 3',
+                               0x11 => 'High Quality Audio Profile @ Level 4',
+                               0x12 => 'High Quality Audio Profile @ Level 5',
+                               0x13 => 'High Quality Audio Profile @ Level 6',
+                               0x14 => 'High Quality Audio Profile @ Level 7',
+                               0x15 => 'High Quality Audio Profile @ Level 8',
+                               0x16 => 'Low Delay Audio Profile @ Level 1',
+                               0x17 => 'Low Delay Audio Profile @ Level 2',
+                               0x18 => 'Low Delay Audio Profile @ Level 3',
+                               0x19 => 'Low Delay Audio Profile @ Level 4',
+                               0x1A => 'Low Delay Audio Profile @ Level 5',
+                               0x1B => 'Low Delay Audio Profile @ Level 6',
+                               0x1C => 'Low Delay Audio Profile @ Level 7',
+                               0x1D => 'Low Delay Audio Profile @ Level 8',
+                               0x1E => 'Natural Audio Profile @ Level 1',
+                               0x1F => 'Natural Audio Profile @ Level 2',
+                               0x20 => 'Natural Audio Profile @ Level 3',
+                               0x21 => 'Natural Audio Profile @ Level 4',
+                               0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
+                               0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
+                               0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
+                               0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
+                               0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
+                               0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
+                               0x28 => 'AAC Profile @ Level 1',
+                               0x29 => 'AAC Profile @ Level 2',
+                               0x2A => 'AAC Profile @ Level 4',
+                               0x2B => 'AAC Profile @ Level 5',
+                               0x2C => 'High Efficiency AAC Profile @ Level 2',
+                               0x2D => 'High Efficiency AAC Profile @ Level 3',
+                               0x2E => 'High Efficiency AAC Profile @ Level 4',
+                               0x2F => 'High Efficiency AAC Profile @ Level 5',
+                               0xFE => 'Not part of MPEG-4 audio profiles',
+                               0xFF => 'No audio capability 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">                return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2111,8 +2410,18 @@
</span><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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
+                       // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
+                       // http://atomicparsley.sourceforge.net/mpeg-4files.html
+                       // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
+                       $handyatomtranslatorarray["\xA9".'alb'] = 'album';               // iTunes 4.0
+                       $handyatomtranslatorarray["\xA9".'ART'] = 'artist';
+                       $handyatomtranslatorarray["\xA9".'art'] = 'artist';              // iTunes 4.0
+                       $handyatomtranslatorarray["\xA9".'aut'] = 'author';
+                       $handyatomtranslatorarray["\xA9".'cmt'] = 'comment';             // iTunes 4.0
+                       $handyatomtranslatorarray["\xA9".'com'] = 'comment';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'cpy'] = 'copyright';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray["\xA9".'day'] = 'creation_date';    // iTunes 4.0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $handyatomtranslatorarray["\xA9".'day'] = 'creation_date';       // iTunes 4.0
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'dir'] = 'director';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'ed1'] = 'edit1';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'ed2'] = 'edit2';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2123,65 +2432,61 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'ed7'] = 'edit7';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'ed8'] = 'edit8';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'ed9'] = 'edit9';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $handyatomtranslatorarray["\xA9".'enc'] = 'encoded_by';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'fmt'] = 'format';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $handyatomtranslatorarray["\xA9".'gen'] = 'genre';               // iTunes 4.0
+                       $handyatomtranslatorarray["\xA9".'grp'] = 'grouping';            // iTunes 4.2
+                       $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'inf'] = 'information';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';              // iTunes 5.0
+                       $handyatomtranslatorarray["\xA9".'mak'] = 'make';
+                       $handyatomtranslatorarray["\xA9".'mod'] = 'model';
+                       $handyatomtranslatorarray["\xA9".'nam'] = 'title';               // iTunes 4.0
+                       $handyatomtranslatorarray["\xA9".'ope'] = 'composer';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'prd'] = 'producer';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $handyatomtranslatorarray["\xA9".'PRD'] = 'product';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'prf'] = 'performers';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'req'] = 'system_requirements';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray["\xA9".'wrt'] = 'writer';
-
-                       // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
-                       $handyatomtranslatorarray["\xA9".'nam'] = 'title';           // iTunes 4.0
-                       $handyatomtranslatorarray["\xA9".'cmt'] = 'comment';         // iTunes 4.0
-                       $handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
-                       $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
-                       $handyatomtranslatorarray["\xA9".'mak'] = 'make';
-                       $handyatomtranslatorarray["\xA9".'mod'] = 'model';
-                       $handyatomtranslatorarray["\xA9".'PRD'] = 'product';
</del><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'swr'] = 'software';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray["\xA9".'aut'] = 'author';
-                       $handyatomtranslatorarray["\xA9".'ART'] = 'artist';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool';       // iTunes 4.0
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'trk'] = 'track';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray["\xA9".'alb'] = 'album';           // iTunes 4.0
-                       $handyatomtranslatorarray["\xA9".'com'] = 'comment';
-                       $handyatomtranslatorarray["\xA9".'gen'] = 'genre';           // iTunes 4.0
-                       $handyatomtranslatorarray["\xA9".'ope'] = 'composer';
</del><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'url'] = 'url';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray["\xA9".'enc'] = 'encoder';
-
-                       // http://atomicparsley.sourceforge.net/mpeg-4files.html
-                       $handyatomtranslatorarray["\xA9".'art'] = 'artist';           // iTunes 4.0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
+                       $handyatomtranslatorarray["\xA9".'wrt'] = 'composer';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray['aART'] = 'album_artist';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray['trkn'] = 'track_number';     // iTunes 4.0
-                       $handyatomtranslatorarray['disk'] = 'disc_number';      // iTunes 4.0
-                       $handyatomtranslatorarray['gnre'] = 'genre';            // iTunes 4.0
-                       $handyatomtranslatorarray["\xA9".'too'] = 'encoder';          // iTunes 4.0
-                       $handyatomtranslatorarray['tmpo'] = 'bpm';              // iTunes 4.0
-                       $handyatomtranslatorarray['cprt'] = 'copyright';        // iTunes 4.0?
-                       $handyatomtranslatorarray['cpil'] = 'compilation';      // iTunes 4.0
-                       $handyatomtranslatorarray['covr'] = 'picture';          // iTunes 4.0
-                       $handyatomtranslatorarray['rtng'] = 'rating';           // iTunes 4.0
-                       $handyatomtranslatorarray["\xA9".'grp'] = 'grouping';         // iTunes 4.2
-                       $handyatomtranslatorarray['stik'] = 'stik';             // iTunes 4.9
-                       $handyatomtranslatorarray['pcst'] = 'podcast';          // iTunes 4.9
-                       $handyatomtranslatorarray['catg'] = 'category';         // iTunes 4.9
-                       $handyatomtranslatorarray['keyw'] = 'keyword';          // iTunes 4.9
-                       $handyatomtranslatorarray['purl'] = 'podcast_url';      // iTunes 4.9
-                       $handyatomtranslatorarray['egid'] = 'episode_guid';     // iTunes 4.9
-                       $handyatomtranslatorarray['desc'] = 'description';      // iTunes 5.0
-                       $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';           // iTunes 5.0
-                       $handyatomtranslatorarray['tvnn'] = 'tv_network_name';  // iTunes 6.0
-                       $handyatomtranslatorarray['tvsh'] = 'tv_show_name';     // iTunes 6.0
-                       $handyatomtranslatorarray['tvsn'] = 'tv_season';        // iTunes 6.0
-                       $handyatomtranslatorarray['tves'] = 'tv_episode';       // iTunes 6.0
-                       $handyatomtranslatorarray['purd'] = 'purchase_date';    // iTunes 6.0.2
-                       $handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $handyatomtranslatorarray['apID'] = 'purchase_account';
+                       $handyatomtranslatorarray['catg'] = 'category';            // iTunes 4.9
+                       $handyatomtranslatorarray['covr'] = 'picture';             // iTunes 4.0
+                       $handyatomtranslatorarray['cpil'] = 'compilation';         // iTunes 4.0
+                       $handyatomtranslatorarray['cprt'] = 'copyright';           // iTunes 4.0?
+                       $handyatomtranslatorarray['desc'] = 'description';         // iTunes 5.0
+                       $handyatomtranslatorarray['disk'] = 'disc_number';         // iTunes 4.0
+                       $handyatomtranslatorarray['egid'] = 'episode_guid';        // iTunes 4.9
+                       $handyatomtranslatorarray['gnre'] = 'genre';               // iTunes 4.0
+                       $handyatomtranslatorarray['hdvd'] = 'hd_video';            // iTunes 4.0
+                       $handyatomtranslatorarray['ldes'] = 'description_long';    //
+                       $handyatomtranslatorarray['keyw'] = 'keyword';             // iTunes 4.9
+                       $handyatomtranslatorarray['pcst'] = 'podcast';             // iTunes 4.9
+                       $handyatomtranslatorarray['pgap'] = 'gapless_playback';    // iTunes 7.0
+                       $handyatomtranslatorarray['purd'] = 'purchase_date';       // iTunes 6.0.2
+                       $handyatomtranslatorarray['purl'] = 'podcast_url';         // iTunes 4.9
+                       $handyatomtranslatorarray['rtng'] = 'rating';              // iTunes 4.0
+                       $handyatomtranslatorarray['soaa'] = 'sort_album_artist';   //
+                       $handyatomtranslatorarray['soal'] = 'sort_album';          //
+                       $handyatomtranslatorarray['soar'] = 'sort_artist';         //
+                       $handyatomtranslatorarray['soco'] = 'sort_composer';       //
+                       $handyatomtranslatorarray['sonm'] = 'sort_title';          //
+                       $handyatomtranslatorarray['sosn'] = 'sort_show';           //
+                       $handyatomtranslatorarray['stik'] = 'stik';                // iTunes 4.9
+                       $handyatomtranslatorarray['tmpo'] = 'bpm';                 // iTunes 4.0
+                       $handyatomtranslatorarray['trkn'] = 'track_number';        // iTunes 4.0
+                       $handyatomtranslatorarray['tven'] = 'tv_episode_id';       //
+                       $handyatomtranslatorarray['tves'] = 'tv_episode';          // iTunes 6.0
+                       $handyatomtranslatorarray['tvnn'] = 'tv_network_name';     // iTunes 6.0
+                       $handyatomtranslatorarray['tvsh'] = 'tv_show_name';        // iTunes 6.0
+                       $handyatomtranslatorarray['tvsn'] = 'tv_season';           // iTunes 6.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">-                        // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
-
-
-
</del><span class="cx" style="display: block; padding: 0 10px">                         // boxnames:
</span><span class="cx" style="display: block; padding: 0 10px">                        /*
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray['iTunSMPB']                    = 'iTunSMPB';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2225,11 +2530,51 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $data = array('data'=>$data, 'image_mime'=>$image_mime);
</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">-                        $info['quicktime']['comments'][$comment_key][] = $data;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $gooddata = array($data);
+                       if ($comment_key == 'genre') {
+                               // some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
+                               $gooddata = explode(';', $data);
+                       }
+                       foreach ($gooddata as $data) {
+                               $info['quicktime']['comments'][$comment_key][] = $data;
+                       }
</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">+    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 '';
+                }
+
+            }
+        }
+
</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">@@ -2243,4 +2588,79 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return substr($pascalstring, 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">+
+       /*
+       // helper functions for m4b audiobook chapters
+       // code by Steffen Hartmann 2015-Nov-08
+       */
+       public function search_tag_by_key($info, $tag, $history, &$result) {
+               foreach ($info as $key => $value) {
+                       $key_history = $history.'/'.$key;
+                       if ($key === $tag) {
+                               $result[] = array($key_history, $info);
+                       } else {
+                               if (is_array($value)) {
+                                       $this->search_tag_by_key($value, $tag, $key_history, $result);
+                               }
+                       }
+               }
+       }
+
+       public function search_tag_by_pair($info, $k, $v, $history, &$result) {
+               foreach ($info as $key => $value) {
+                       $key_history = $history.'/'.$key;
+                       if (($key === $k) && ($value === $v)) {
+                               $result[] = array($key_history, $info);
+                       } else {
+                               if (is_array($value)) {
+                                       $this->search_tag_by_pair($value, $k, $v, $key_history, $result);
+                               }
+                       }
+               }
+       }
+
+       public function quicktime_time_to_sample_table($info) {
+               $res = array();
+               $this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
+               foreach ($res as $value) {
+                       $stbl_res = array();
+                       $this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
+                       if (count($stbl_res) > 0) {
+                               $stts_res = array();
+                               $this->search_tag_by_key($value[1], 'time_to_sample_table', $value[0], $stts_res);
+                               if (count($stts_res) > 0) {
+                                       return $stts_res[0][1]['time_to_sample_table'];
+                               }
+                       }
+               }
+               return array();
+       }
+
+       function quicktime_bookmark_time_scale($info) {
+               $time_scale = '';
+               $ts_prefix_len = 0;
+               $res = array();
+               $this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
+               foreach ($res as $value) {
+                       $stbl_res = array();
+                       $this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
+                       if (count($stbl_res) > 0) {
+                               $ts_res = array();
+                               $this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res);
+                               foreach ($ts_res as $value) {
+                                       $prefix = substr($value[0], 0, -12);
+                                       if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) {
+                                               $time_scale = $value[1]['time_scale'];
+                                               $ts_prefix_len = strlen($prefix);
+                                       }
+                               }
+                       }
+               }
+               return $time_scale;
+       }
+       /*
+       // END helper functions for m4b audiobook chapters
+       */
+
+
</ins><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     2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio-video.riff.php       2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -190,7 +190,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->error('Corrupt RIFF file: bitrate_audio == zero');
</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">                                        $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -199,7 +199,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'Audio codec = '.$thisfile_audio['codec'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('Audio codec = '.$thisfile_audio['codec']);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -302,10 +302,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
</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">-                                                        $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('RIFF.WAVE.BEXT.origin_time is invalid');
</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">-                                                $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('RIFF.WAVE.BEXT.origin_date is invalid');
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff['comments']['title'][]  = $thisfile_riff_WAVE_bext_0['title'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -385,10 +385,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         break;
</span><span class="cx" style="display: block; padding: 0 10px">                                                } elseif ($SNDM_thisTagSize <= 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
</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">                                                $SNDM_startoffset += $SNDM_thisTagSize;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -397,7 +397,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
</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">-                                                        $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
</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">@@ -428,13 +428,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $timestamp_sample_rate = (is_array($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) ? max($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) : $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']); // XML could possibly contain more than one TIMESTAMP_SAMPLE_RATE tag, returning as array instead of integer [why? does it make sense? perhaps doesn't matter but getID3 needs to deal with it] - see https://github.com/JamesHeinrich/getID3/issues/105
+                                                       $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds']       / 3600);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600))      / 60);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $f =       ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $thisfile_riff_WAVE['iXML'][0]['timecode_string']       = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s,       $f);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d',   $h, $m, $s, round($f));
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                        unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                unset($parsedXML);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -570,7 +572,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                // byte, in which case - skip warning
</span><span class="cx" style="display: block; padding: 0 10px">                                                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                // Short by more than one byte, throw warning
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 $info['avdataend'] = $info['filesize'];
</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">@@ -579,11 +581,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                // output file appears to be incorrectly *not* padded to nearest WORD boundary
</span><span class="cx" style="display: block; padding: 0 10px">                                                                // Output less severe warning
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 $info['avdataend'] = $info['filesize'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                // Short by more than one byte, throw warning
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 $info['avdataend'] = $info['filesize'];
</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">@@ -592,7 +594,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $info['avdataend']--;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
</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 (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -619,7 +621,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($info['avdataend'] > $info['filesize']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $info['avdataend'] = $info['filesize'];
</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">@@ -660,7 +662,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff_raw_avih['dwMicroSecPerFrame']    = $this->EitherEndian2Int(substr($avihData,  0, 4)); // frame display rate (or 0L)
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
</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">@@ -858,7 +860,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">-                                                                                        $info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                 $this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"');
</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">@@ -963,7 +965,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // structures rounded to 2-byte boundary, but dumb encoders
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // forget to pad end of file to make this actually work
</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">-                                                        $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                $info['avdataend'] = $info['filesize'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1020,7 +1022,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_audio['sample_rate']     = $thisfile_riff_audio['sample_rate'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_audio['sample_rate'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->error('Corrupted AIFF file: sample_rate == zero');
</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">                                        $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1080,7 +1082,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['avdataend']    = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($info['avdataend'] > $info['filesize']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
</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">@@ -1112,7 +1114,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">-                                                        $info['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 "'.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">@@ -1130,7 +1132,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">-                                                        $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"');
</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">@@ -1170,9 +1172,59 @@
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        case 'WEBP':
+                               // https://developers.google.com/speed/webp/docs/riff_container
+                               // https://tools.ietf.org/html/rfc6386
+                               // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
+                               $info['fileformat'] = 'webp';
+                               $info['mime_type']  = 'image/webp';
</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 (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
+                                       $old_offset = $this->ftell();
+                                       $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size
+                                       $WEBP_VP8_header = $this->fread(10);
+                                       $this->fseek($old_offset);
+                                       if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
+                                               $thisfile_riff['WEBP']['VP8 '][0]['keyframe']   = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
+                                               $thisfile_riff['WEBP']['VP8 '][0]['version']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
+                                               $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
+                                               $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >>  0;
+
+                                               $thisfile_riff['WEBP']['VP8 '][0]['scale_x']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
+                                               $thisfile_riff['WEBP']['VP8 '][0]['width']      =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
+                                               $thisfile_riff['WEBP']['VP8 '][0]['scale_y']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
+                                               $thisfile_riff['WEBP']['VP8 '][0]['height']     =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
+
+                                               $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
+                                               $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
+                                       } else {
+                                               $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
+                                       }
+
+                               }
+                               if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
+                                       $old_offset = $this->ftell();
+                                       $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size
+                                       $WEBP_VP8L_header = $this->fread(10);
+                                       $this->fseek($old_offset);
+                                       if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
+                                               $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
+                                               $thisfile_riff['WEBP']['VP8L'][0]['width']         =        bindec(substr($width_height_flags, 18, 14)) + 1;
+                                               $thisfile_riff['WEBP']['VP8L'][0]['height']        =        bindec(substr($width_height_flags,  4, 14)) + 1;
+                                               $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags,  3,  1));
+                                               $thisfile_riff['WEBP']['VP8L'][0]['version']       =        bindec(substr($width_height_flags,  0,  3));
+
+                                               $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
+                                               $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
+                                       } else {
+                                               $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
+                                       }
+
+                               }
+                               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">-                                $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 //unset($info['fileformat']);
</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">@@ -1185,7 +1237,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"');
</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">@@ -1509,7 +1561,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $info['ac3']     = $getid3_temp->info['ac3'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        if (!empty($getid3_temp->info['warning'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                foreach ($getid3_temp->info['warning'] as $key => $value) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                        $info['warning'][] = $value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 $this->warning($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">@@ -2583,4 +2635,4 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::BigEndian2Int($byteword, false, $signed);
</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">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+}
</ins></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    2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio.ac3.php      2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -20,7 +20,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">     private $AC3header = array();
</span><span class="cx" style="display: block; padding: 0 10px">     private $BSIoffset = 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">-    const syncword = "\x0B\x77";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    const syncword = 0x0B77;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><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="lines" style="display: block; padding: 0 10px; color: #888">@@ -55,182 +55,418 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // } /* end of syncinfo */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->fseek($info['avdataoffset']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->AC3header['syncinfo'] = $this->fread(5);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...?
+               $this->AC3header['syncinfo']  =     getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2));
+               $this->AC3header['bsi']       =     getid3_lib::BigEndian2Bin(substr($tempAC3header, 2));
+               $thisfile_ac3_raw_bsi['bsid'] = (getid3_lib::LittleEndian2Int(substr($tempAC3header, 5, 1)) & 0xF8) >> 3; // AC3 and E-AC3 put the "bsid" version identifier in the same place, but unfortnately the 4 bytes between the syncword and the version identifier are interpreted differently, so grab it here so the following code structure can make sense
+               unset($tempAC3header);
</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 (strpos($this->AC3header['syncinfo'], self::syncword) === 0) {
-                       $thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword;
-                       $offset = 2;
-               } else {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ($this->AC3header['syncinfo'] !== self::syncword) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         if (!$this->isDependencyFor('matroska')) {
</span><span class="cx" style="display: block; padding: 0 10px">                                unset($info['fileformat'], $info['ac3']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($this->AC3header['syncinfo'], 0, 2)).'"');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"');
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $offset = 0;
-                       $this->fseek(-2, SEEK_CUR);
</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">                $info['audio']['dataformat']   = 'ac3';
</span><span class="cx" style="display: block; padding: 0 10px">                $info['audio']['bitrate_mode'] = 'cbr';
</span><span class="cx" style="display: block; padding: 0 10px">                $info['audio']['lossless']     = 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">-                $thisfile_ac3_raw['synchinfo']['crc1']       = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], $offset, 2));
-               $ac3_synchinfo_fscod_frmsizecod              = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1));
-               $thisfile_ac3_raw['synchinfo']['fscod']      = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
-               $thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ($thisfile_ac3_raw_bsi['bsid'] <= 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">-                $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw['synchinfo']['fscod']);
-               if ($thisfile_ac3_raw['synchinfo']['fscod'] <= 3) {
-                       $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['crc1']       = getid3_lib::Bin2Dec($this->readHeaderBSI(16));
+                       $thisfile_ac3_raw_bsi['fscod']      =                     $this->readHeaderBSI(2);   // 5.4.1.3
+                       $thisfile_ac3_raw_bsi['frmsizecod'] =                     $this->readHeaderBSI(6);   // 5.4.1.4
+                       if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits)
+                               $this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly');
+                       }
</ins><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['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw['synchinfo']['frmsizecod'], $thisfile_ac3_raw['synchinfo']['fscod']);
-               $thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw['synchinfo']['frmsizecod']);
-               $info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['bsid']  = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
+                       $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
+                       $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
</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->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15));
-               $ac3_bsi_offset = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
+                               // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
+                               $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
+                               $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
+                       }
</ins><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_raw_bsi['bsid'] = $this->readHeaderBSI(5);
-               if ($thisfile_ac3_raw_bsi['bsid'] > 8) {
-                       // Decoders which can decode version 8 will thus be able to decode version numbers less than 8.
-                       // If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used.
-                       // Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8.
-                       $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8');
-                   unset($info['ac3']);
-                       return false;
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
+                               // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
+                               $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
+                               $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
+                       }
</ins><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_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
-               $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
+                               // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
+                               $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
+                               $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
+                       }
</ins><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']);
-               $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
-               foreach($ac3_coding_mode as $key => $value) {
-                       $thisfile_ac3[$key] = $value;
-               }
-               switch ($thisfile_ac3_raw_bsi['acmod']) {
-                       case 0:
-                       case 1:
-                               $info['audio']['channelmode'] = 'mono';
-                               break;
-                       case 3:
-                       case 4:
-                               $info['audio']['channelmode'] = 'stereo';
-                               break;
-                       default:
-                               $info['audio']['channelmode'] = 'surround';
-                               break;
-               }
-               $info['audio']['channels'] = $thisfile_ac3['num_channels'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(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">-                if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
-                       // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
-                       $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
-                       $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
+                       // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
+                       $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);                 // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits
</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 ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
-                       // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
-                       $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
-                       $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1);       // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit
+                       if ($thisfile_ac3_raw_bsi['flags']['compr']) {
+                               $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);                // 5.4.2.10 compr: Compression Gain Word, 8 Bits
+                               $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
+                       }
</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 ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
-                       // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
-                       $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
-                       $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1);     // 5.4.2.11 langcode: Language Code Exists, 1 Bit
+                       if ($thisfile_ac3_raw_bsi['flags']['langcod']) {
+                               $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);              // 5.4.2.12 langcod: Language Code, 8 Bits
+                       }
</ins><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_raw_bsi['lfeon'] = (bool) $this->readHeaderBSI(1);
-               $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['lfeon'];
-               if ($thisfile_ac3_raw_bsi['lfeon']) {
-                       //$info['audio']['channels']++;
-                       $info['audio']['channels'] .= '.1';
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1);  // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit
+                       if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) {
+                               $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);             // 5.4.2.14 mixlevel: Mixing Level, 5 Bits
+                               $thisfile_ac3_raw_bsi['roomtyp']  = $this->readHeaderBSI(2);             // 5.4.2.15 roomtyp: Room Type, 2 Bits
</ins><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['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
+                               $thisfile_ac3['room_type']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
+                       }
</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 indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
-               // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
-               $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
-               $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
</del><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_raw_bsi['compre_flag'] = (bool) $this->readHeaderBSI(1);
-               if ($thisfile_ac3_raw_bsi['compre_flag']) {
-                       $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
-                       $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);                // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits
+                       $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';  // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
</ins><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_raw_bsi['langcode_flag'] = (bool) $this->readHeaderBSI(1);
-               if ($thisfile_ac3_raw_bsi['langcode_flag']) {
-                       $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1);       // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit
+                       if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
+                               $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);               // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits
+                               $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
+                       }
</ins><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_raw_bsi['audprodie'] = (bool) $this->readHeaderBSI(1);
-               if ($thisfile_ac3_raw_bsi['audprodie']) {
-                       $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
-                       $thisfile_ac3_raw_bsi['roomtyp']  = $this->readHeaderBSI(2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1);    // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit
+                       if ($thisfile_ac3_raw_bsi['flags']['langcod2']) {
+                               $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);             // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits
+                       }
</ins><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['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
-                       $thisfile_ac3['room_type']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit
+                       if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) {
+                               $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);            // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits
+                               $thisfile_ac3_raw_bsi['roomtyp2']  = $this->readHeaderBSI(2);            // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits
</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 ($thisfile_ac3_raw_bsi['acmod'] == 0x00) {
-                       // If acmod is 0, then two completely independent program channels (dual mono)
-                       // are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
-                       // a number of additional items are present in BSI or audblk to fully describe Ch2.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
+                               $thisfile_ac3['room_type2']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
+                       }
</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 indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
-                       // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
-                       $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
-                       $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);         // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit
</ins><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_raw_bsi['compre_flag2'] = (bool) $this->readHeaderBSI(1);
-                       if ($thisfile_ac3_raw_bsi['compre_flag2']) {
-                               $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
-                               $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['original']  = (bool) $this->readHeaderBSI(1);         // 5.4.2.25 origbs: Original Bit Stream, 1 Bit
+
+                       $thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2);            // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits
+                       if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) {
+                               $thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14);            // 5.4.2.27 timecod1: Time code first half, 14 bits
+                               $thisfile_ac3['timecode1'] = 0;
+                               $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >>  9) * 3600;  // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0�23
+                               $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >>  3) *   60;  // The next 6 bits represent the time in minutes, with valid values of 0�59
+                               $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >>  0) *    8;  // The final 3 bits represents the time in 8 second increments, with valid values of 0�7 (representing 0, 8, 16, ... 56 seconds)
</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 ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) {
+                               $thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14);            // 5.4.2.28 timecod2: Time code second half, 14 bits
+                               $thisfile_ac3['timecode2'] = 0;
+                               $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) *   1;              // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0�7 (representing 0-7 seconds)
+                               $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >>  6) *  (1 / 30);        // The next 5 bits represents the time in frames, with valid values from 0�29 (one frame = 1/30th of a second)
+                               $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >>  0) * ((1 / 30) / 60);  // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0�63
+                       }
</ins><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_raw_bsi['langcode_flag2'] = (bool) $this->readHeaderBSI(1);
-                       if ($thisfile_ac3_raw_bsi['langcode_flag2']) {
-                               $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
+                       if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
+                               $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0�63, indicating 1�64 additional bytes, respectively.
+
+                               $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
+
+                               $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
+                               $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
</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">-                        $thisfile_ac3_raw_bsi['audprodie2'] = (bool) $this->readHeaderBSI(1);
-                       if ($thisfile_ac3_raw_bsi['audprodie2']) {
-                               $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
-                               $thisfile_ac3_raw_bsi['roomtyp2']  = $this->readHeaderBSI(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">-                                $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
-                               $thisfile_ac3['room_type2']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
+
+
+$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.');
+                       $info['audio']['dataformat'] = 'eac3';
+
+                       $thisfile_ac3_raw_bsi['strmtyp']          =        $this->readHeaderBSI(2);
+                       $thisfile_ac3_raw_bsi['substreamid']      =        $this->readHeaderBSI(3);
+                       $thisfile_ac3_raw_bsi['frmsiz']           =        $this->readHeaderBSI(11);
+                       $thisfile_ac3_raw_bsi['fscod']            =        $this->readHeaderBSI(2);
+                       if ($thisfile_ac3_raw_bsi['fscod'] == 3) {
+                               $thisfile_ac3_raw_bsi['fscod2']       =        $this->readHeaderBSI(2);
+                               $thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe
+                       } else {
+                               $thisfile_ac3_raw_bsi['numblkscod']   =        $this->readHeaderBSI(2);
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']);
+                       $thisfile_ac3_raw_bsi['acmod']            =        $this->readHeaderBSI(3);
+                       $thisfile_ac3_raw_bsi['flags']['lfeon']   = (bool) $this->readHeaderBSI(1);
+                       $thisfile_ac3_raw_bsi['bsid']             =        $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
+                       $thisfile_ac3_raw_bsi['dialnorm']         =        $this->readHeaderBSI(5);
+                       $thisfile_ac3_raw_bsi['flags']['compr']       = (bool) $this->readHeaderBSI(1);
+                       if ($thisfile_ac3_raw_bsi['flags']['compr']) {
+                               $thisfile_ac3_raw_bsi['compr']        =        $this->readHeaderBSI(8);
+                       }
+                       if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
+                               $thisfile_ac3_raw_bsi['dialnorm2']    =        $this->readHeaderBSI(5);
+                               $thisfile_ac3_raw_bsi['flags']['compr2']  = (bool) $this->readHeaderBSI(1);
+                               if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
+                                       $thisfile_ac3_raw_bsi['compr2']   =        $this->readHeaderBSI(8);
+                               }
+                       }
+                       if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream
+                               $thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1);
+                               if ($thisfile_ac3_raw_bsi['flags']['chanmap']) {
+                                       $thisfile_ac3_raw_bsi['chanmap']  =        $this->readHeaderBSI(8);
+                               }
+                       }
+                       $thisfile_ac3_raw_bsi['flags']['mixmdat']     = (bool) $this->readHeaderBSI(1);
+                       if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata
+                               if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels
+                                       $thisfile_ac3_raw_bsi['dmixmod']  =        $this->readHeaderBSI(2);
+                               }
+                               if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist
+                                       $thisfile_ac3_raw_bsi['ltrtcmixlev'] =        $this->readHeaderBSI(3);
+                                       $thisfile_ac3_raw_bsi['lorocmixlev'] =        $this->readHeaderBSI(3);
+                               }
+                               if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists
+                                       $thisfile_ac3_raw_bsi['ltrtsurmixlev'] =        $this->readHeaderBSI(3);
+                                       $thisfile_ac3_raw_bsi['lorosurmixlev'] =        $this->readHeaderBSI(3);
+                               }
+                               if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists
+                                       $thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1);
+                                       if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) {
+                                               $thisfile_ac3_raw_bsi['lfemixlevcod']  =        $this->readHeaderBSI(5);
+                                       }
+                               }
+                               if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream
+                                       $thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1);
+                                       if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) {
+                                               $thisfile_ac3_raw_bsi['pgmscl']  =        $this->readHeaderBSI(6);
+                                       }
+                                       if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
+                                               $thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1);
+                                               if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) {
+                                                       $thisfile_ac3_raw_bsi['pgmscl2']  =        $this->readHeaderBSI(6);
+                                               }
+                                       }
+                                       $thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1);
+                                       if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) {
+                                               $thisfile_ac3_raw_bsi['extpgmscl']  =        $this->readHeaderBSI(6);
+                                       }
+                                       $thisfile_ac3_raw_bsi['mixdef']  =        $this->readHeaderBSI(2);
+                                       if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2
+                                               $thisfile_ac3_raw_bsi['premixcmpsel']  = (bool) $this->readHeaderBSI(1);
+                                               $thisfile_ac3_raw_bsi['drcsrc']        = (bool) $this->readHeaderBSI(1);
+                                               $thisfile_ac3_raw_bsi['premixcmpscl']  =        $this->readHeaderBSI(3);
+                                       } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3
+                                               $thisfile_ac3_raw_bsi['mixdata']       =        $this->readHeaderBSI(12);
+                                       } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4
+                                               $mixdefbitsread = 0;
+                                               $thisfile_ac3_raw_bsi['mixdeflen']     =        $this->readHeaderBSI(5); $mixdefbitsread += 5;
+                                               $thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                               if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) {
+                                                       $thisfile_ac3_raw_bsi['premixcmpsel']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       $thisfile_ac3_raw_bsi['drcsrc']        = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       $thisfile_ac3_raw_bsi['premixcmpscl']  =        $this->readHeaderBSI(3); $mixdefbitsread += 3;
+                                                       $thisfile_ac3_raw_bsi['flags']['extpgmlscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) {
+                                                               $thisfile_ac3_raw_bsi['extpgmlscl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                       }
+                                                       $thisfile_ac3_raw_bsi['flags']['extpgmcscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) {
+                                                               $thisfile_ac3_raw_bsi['extpgmcscl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                       }
+                                                       $thisfile_ac3_raw_bsi['flags']['extpgmrscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) {
+                                                               $thisfile_ac3_raw_bsi['extpgmrscl']    =        $this->readHeaderBSI(4);
+                                                       }
+                                                       $thisfile_ac3_raw_bsi['flags']['extpgmlsscl']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) {
+                                                               $thisfile_ac3_raw_bsi['extpgmlsscl']   =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                       }
+                                                       $thisfile_ac3_raw_bsi['flags']['extpgmrsscl']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) {
+                                                               $thisfile_ac3_raw_bsi['extpgmrsscl']   =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                       }
+                                                       $thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) {
+                                                               $thisfile_ac3_raw_bsi['extpgmlfescl']  =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                       }
+                                                       $thisfile_ac3_raw_bsi['flags']['dmixscl']      = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) {
+                                                               $thisfile_ac3_raw_bsi['dmixscl']       =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                       }
+                                                       $thisfile_ac3_raw_bsi['flags']['addch']        = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['addch']) {
+                                                               $thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                               if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) {
+                                                                       $thisfile_ac3_raw_bsi['extpgmaux1scl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                               }
+                                                               $thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                               if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) {
+                                                                       $thisfile_ac3_raw_bsi['extpgmaux2scl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
+                                                               }
+                                                       }
+                                               }
+                                               $thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                               if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) {
+                                                       $thisfile_ac3_raw_bsi['spchdat']   =        $this->readHeaderBSI(5); $mixdefbitsread += 5;
+                                                       $thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                       if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) {
+                                                               $thisfile_ac3_raw_bsi['spchdat1']   =         $this->readHeaderBSI(5); $mixdefbitsread += 5;
+                                                               $thisfile_ac3_raw_bsi['spchan1att'] =         $this->readHeaderBSI(2); $mixdefbitsread += 2;
+                                                               $thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
+                                                               if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) {
+                                                                       $thisfile_ac3_raw_bsi['spchdat2']   =         $this->readHeaderBSI(5); $mixdefbitsread += 5;
+                                                                       $thisfile_ac3_raw_bsi['spchan2att'] =         $this->readHeaderBSI(3); $mixdefbitsread += 3;
+                                                               }
+                                                       }
+                                               }
+                                               $mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread;
+                                               $mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0);
+                                               $thisfile_ac3_raw_bsi['mixdata']     =        $this->readHeaderBSI($mixdata_bits);
+                                               $thisfile_ac3_raw_bsi['mixdatafill'] =        $this->readHeaderBSI($mixdata_fill);
+                                               unset($mixdefbitsread, $mixdata_bits, $mixdata_fill);
+                                       }
+                                       if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source
+                                               $thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1);
+                                               if ($thisfile_ac3_raw_bsi['flags']['paninfo']) {
+                                                       $thisfile_ac3_raw_bsi['panmean']   =        $this->readHeaderBSI(8);
+                                                       $thisfile_ac3_raw_bsi['paninfo']   =        $this->readHeaderBSI(6);
+                                               }
+                                               if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
+                                                       $thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1);
+                                                       if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) {
+                                                               $thisfile_ac3_raw_bsi['panmean2']   =        $this->readHeaderBSI(8);
+                                                               $thisfile_ac3_raw_bsi['paninfo2']   =        $this->readHeaderBSI(6);
+                                                       }
+                                               }
+                                       }
+                                       $thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1);
+                                       if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information
+                                               if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) {
+                                                       $thisfile_ac3_raw_bsi['blkmixcfginfo'][0]  =        $this->readHeaderBSI(5);
+                                               } else {
+                                                       for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) {
+                                                               $thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1);
+                                                               if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information
+                                                                       $thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk]  =        $this->readHeaderBSI(5);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       $thisfile_ac3_raw_bsi['flags']['infomdat']          = (bool) $this->readHeaderBSI(1);
+                       if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata
+                               $thisfile_ac3_raw_bsi['bsmod']                  =        $this->readHeaderBSI(3);
+                               $thisfile_ac3_raw_bsi['flags']['copyrightb']    = (bool) $this->readHeaderBSI(1);
+                               $thisfile_ac3_raw_bsi['flags']['origbs']        = (bool) $this->readHeaderBSI(1);
+                               if ($thisfile_ac3_raw_bsi['acmod'] == 2) { //  if in 2/0 mode
+                                       $thisfile_ac3_raw_bsi['dsurmod']            =        $this->readHeaderBSI(2);
+                                       $thisfile_ac3_raw_bsi['dheadphonmod']       =        $this->readHeaderBSI(2);
+                               }
+                               if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { //  if both surround channels exist
+                                       $thisfile_ac3_raw_bsi['dsurexmod']          =        $this->readHeaderBSI(2);
+                               }
+                               $thisfile_ac3_raw_bsi['flags']['audprodi']      = (bool) $this->readHeaderBSI(1);
+                               if ($thisfile_ac3_raw_bsi['flags']['audprodi']) {
+                                       $thisfile_ac3_raw_bsi['mixlevel']           =        $this->readHeaderBSI(5);
+                                       $thisfile_ac3_raw_bsi['roomtyp']            =        $this->readHeaderBSI(2);
+                                       $thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1);
+                               }
+                               if ($thisfile_ac3_raw_bsi['acmod'] == 0) { //  if 1+1 mode (dual mono, so some items need a second value)
+                                       $thisfile_ac3_raw_bsi['flags']['audprodi2']      = (bool) $this->readHeaderBSI(1);
+                                       if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) {
+                                               $thisfile_ac3_raw_bsi['mixlevel2']           =        $this->readHeaderBSI(5);
+                                               $thisfile_ac3_raw_bsi['roomtyp2']            =        $this->readHeaderBSI(2);
+                                               $thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1);
+                                       }
+                               }
+                               if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate
+                                       $thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1);
+                               }
+                       }
+                       if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { //  if both surround channels exist
+                               $thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1);
+                       }
+                       if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { //  if bit stream converted from AC-3
+                               if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe
+                                       $thisfile_ac3_raw_bsi['flags']['blkid']  = 1;
+                               } else {
+                                       $thisfile_ac3_raw_bsi['flags']['blkid']  = (bool) $this->readHeaderBSI(1);
+                               }
+                               if ($thisfile_ac3_raw_bsi['flags']['blkid']) {
+                                       $thisfile_ac3_raw_bsi['frmsizecod']  =        $this->readHeaderBSI(6);
+                               }
+                       }
+                       $thisfile_ac3_raw_bsi['flags']['addbsi']  = (bool) $this->readHeaderBSI(1);
+                       if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
+                               $thisfile_ac3_raw_bsi['addbsil']  =        $this->readHeaderBSI(6);
+                               $thisfile_ac3_raw_bsi['addbsi']   =        $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 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">-                }
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);
</del><ins style="background-color: #dfd; text-decoration:none; 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.');
+                   unset($info['ac3']);
+                       return 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">-                $thisfile_ac3_raw_bsi['original']  = (bool) $this->readHeaderBSI(1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         }
</ins><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_raw_bsi['timecode1_flag'] = (bool) $this->readHeaderBSI(1);
-               if ($thisfile_ac3_raw_bsi['timecode1_flag']) {
-                       $thisfile_ac3_raw_bsi['timecode1'] = $this->readHeaderBSI(14);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
+                       $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']);
+               } else {
+                       $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']);
</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 ($thisfile_ac3_raw_bsi['fscod'] <= 3) {
+                       $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
+               } else {
+                       $this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']);
+               }
+               if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
+                       $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
+                       $thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
+               } elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
+// 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!
+                       $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.
+// kludge-fix to make it approximately the expected value, still not "right":
+$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
+               }
+               $info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
</ins><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_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1);
-               if ($thisfile_ac3_raw_bsi['timecode2_flag']) {
-                       $thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
+               $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
+               foreach($ac3_coding_mode as $key => $value) {
+                       $thisfile_ac3[$key] = $value;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                switch ($thisfile_ac3_raw_bsi['acmod']) {
+                       case 0:
+                       case 1:
+                               $info['audio']['channelmode'] = 'mono';
+                               break;
+                       case 3:
+                       case 4:
+                               $info['audio']['channelmode'] = 'stereo';
+                               break;
+                       default:
+                               $info['audio']['channelmode'] = 'surround';
+                               break;
+               }
+               $info['audio']['channels'] = $thisfile_ac3['num_channels'];
</ins><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_raw_bsi['addbsi_flag'] = (bool) $this->readHeaderBSI(1);
-               if ($thisfile_ac3_raw_bsi['addbsi_flag']) {
-                       $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon'];
+               if ($thisfile_ac3_raw_bsi['flags']['lfeon']) {
+                       $info['audio']['channels'] .= '.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">-                        $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']);
+               $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
</ins><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_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
-                       $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
-               }
-
</del><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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -251,6 +487,16 @@
</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">+        public static function sampleRateCodeLookup2($fscod2) {
+               static $sampleRateCodeLookup2 = array(
+                       0 => 24000,
+                       1 => 22050,
+                       2 => 16000,
+                       3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
+               );
+               return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : 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">@@ -409,31 +655,32 @@
</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">        public static function frameSizeLookup($frmsizecod, $fscod) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $padding     = (bool) ($frmsizecod % 2);
-               $framesizeid =   floor($frmsizecod / 2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // LSB is whether padding is used or not
+               $padding     = (bool) ($frmsizecod & 0x01);
+               $framesizeid =        ($frmsizecod & 0x3E) >> 1;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                static $frameSizeLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($frameSizeLookup)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $frameSizeLookup = array (
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                0  => array(128, 138, 192),
-                               1  => array(40, 160, 174, 240),
-                               2  => array(48, 192, 208, 288),
-                               3  => array(56, 224, 242, 336),
-                               4  => array(64, 256, 278, 384),
-                               5  => array(80, 320, 348, 480),
-                               6  => array(96, 384, 416, 576),
-                               7  => array(112, 448, 486, 672),
-                               8  => array(128, 512, 556, 768),
-                               9  => array(160, 640, 696, 960),
-                               10 => array(192, 768, 834, 1152),
-                               11 => array(224, 896, 974, 1344),
-                               12 => array(256, 1024, 1114, 1536),
-                               13 => array(320, 1280, 1392, 1920),
-                               14 => array(384, 1536, 1670, 2304),
-                               15 => array(448, 1792, 1950, 2688),
-                               16 => array(512, 2048, 2228, 3072),
-                               17 => array(576, 2304, 2506, 3456),
-                               18 => array(640, 2560, 2786, 3840)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         0  => array( 128,  138,  192),  //  32 kbps
+                               1  => array( 160,  174,  240),  //  40 kbps
+                               2  => array( 192,  208,  288),  //  48 kbps
+                               3  => array( 224,  242,  336),  //  56 kbps
+                               4  => array( 256,  278,  384),  //  64 kbps
+                               5  => array( 320,  348,  480),  //  80 kbps
+                               6  => array( 384,  416,  576),  //  96 kbps
+                               7  => array( 448,  486,  672),  // 112 kbps
+                               8  => array( 512,  556,  768),  // 128 kbps
+                               9  => array( 640,  696,  960),  // 160 kbps
+                               10 => array( 768,  834, 1152),  // 192 kbps
+                               11 => array( 896,  974, 1344),  // 224 kbps
+                               12 => array(1024, 1114, 1536),  // 256 kbps
+                               13 => array(1280, 1392, 1920),  // 320 kbps
+                               14 => array(1536, 1670, 2304),  // 384 kbps
+                               15 => array(1792, 1950, 2688),  // 448 kbps
+                               16 => array(2048, 2228, 3072),  // 512 kbps
+                               17 => array(2304, 2506, 3456),  // 576 kbps
+                               18 => array(2560, 2786, 3840)   // 640 kbps
</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 (($fscod == 1) && $padding) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -444,19 +691,21 @@
</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">        public static function bitrateLookup($frmsizecod) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $framesizeid =   floor($frmsizecod / 2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // LSB is whether padding is used or not
+               $padding     = (bool) ($frmsizecod & 0x01);
+               $framesizeid =        ($frmsizecod & 0x3E) >> 1;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                static $bitrateLookup = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        0  => 32000,
-                       1  => 40000,
-                       2  => 48000,
-                       3  => 56000,
-                       4  => 64000,
-                       5  => 80000,
-                       6  => 96000,
-                       7  => 112000,
-                       8  => 128000,
-                       9  => 160000,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                  0 =>  32000,
+                        1 =>  40000,
+                        2 =>  48000,
+                        3 =>  56000,
+                        4 =>  64000,
+                        5 =>  80000,
+                        6 =>  96000,
+                        7 => 112000,
+                        8 => 128000,
+                        9 => 160000,
</ins><span class="cx" style="display: block; padding: 0 10px">                         10 => 192000,
</span><span class="cx" style="display: block; padding: 0 10px">                        11 => 224000,
</span><span class="cx" style="display: block; padding: 0 10px">                        12 => 256000,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -465,10 +714,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        15 => 448000,
</span><span class="cx" style="display: block; padding: 0 10px">                        16 => 512000,
</span><span class="cx" style="display: block; padding: 0 10px">                        17 => 576000,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        18 => 640000
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 18 => 640000,
</ins><span class="cx" style="display: block; padding: 0 10px">                 );
</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">+        public static function blocksPerSyncFrame($numblkscod) {
+               static $blocksPerSyncFrameLookup = array(
+                       0 => 1,
+                       1 => 2,
+                       2 => 3,
+                       3 => 6,
+               );
+               return (isset($blocksPerSyncFrameLookup[$numblkscod]) ? $blocksPerSyncFrameLookup[$numblkscod] : false);
+       }
</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></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    2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio.mp3.php      2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -34,7 +34,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['error'][] = 'Rescanning file in BruteForce mode';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Rescanning file in BruteForce mode');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $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">@@ -72,7 +72,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">-                        $info['warning'][] = $synchoffsetwarning;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning($synchoffsetwarning);
</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">@@ -134,7 +134,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">-                                        $info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"');
</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">@@ -424,7 +424,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 ($this->fseek($offset) != 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('decodeMPEGaudioHeader() failed to seek to next offset at '.$offset);
</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">                //$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -437,19 +437,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // and $cc... is the audio data
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $head4 = substr($headerstring, 0, 4);
</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">+         $head4_key = getid3_lib::PrintHexBytes($head4, true, false, false);
</ins><span class="cx" style="display: block; padding: 0 10px">                 static $MPEGaudioHeaderDecodeCache = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
-                       $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) {
+                       $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key];
</ins><span class="cx" style="display: block; padding: 0 10px">                 } else {
</span><span class="cx" style="display: block; padding: 0 10px">                        $MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray;
</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">                static $MPEGaudioHeaderValidCache = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (!isset($MPEGaudioHeaderValidCache[$head4])) { // Not in cache
-                       //$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true);  // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
-                       $MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (!isset($MPEGaudioHeaderValidCache[$head4_key])) { // Not in cache
+                       //$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true);  // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
+                       $MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
</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">                // shortcut
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -459,10 +459,10 @@
</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><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ($MPEGaudioHeaderValidCache[$head4]) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ($MPEGaudioHeaderValidCache[$head4_key]) {
</ins><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset);
</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">@@ -490,7 +490,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
</span><span class="cx" style="display: block; padding: 0 10px">                        // http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1');
</ins><span class="cx" style="display: block; padding: 0 10px">                         $thisfile_mpeg_audio['raw']['bitrate'] = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -512,7 +512,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                // these are ok
</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">-                                                $info['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->error($thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
</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">                                        break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -523,7 +523,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                // these are ok
</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">-                                                $info['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->error(intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
</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">                                        break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -545,7 +545,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (isset($thisfile_mpeg_audio['framelength'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
</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">-                                $info['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Frame at offset('.$offset.') is has an invalid frame length.');
</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">@@ -648,9 +648,20 @@
</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 (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         //if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
+                               if (!empty($thisfile_mpeg_audio['VBR_frames'])) {
+                                       $used_filesize  = 0;
+                                       if (!empty($thisfile_mpeg_audio['VBR_bytes'])) {
+                                               $used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
+                                       } elseif (!empty($info['filesize'])) {
+                                               $used_filesize  = $info['filesize'];
+                                               $used_filesize -= intval(@$info['id3v2']['headerlength']);
+                                               $used_filesize -= (isset($info['id3v1']) ? 128 : 0);
+                                               $used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
+                                               $this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes');
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_mpeg_audio['layer'] == '1') {
</span><span class="cx" style="display: block; padding: 0 10px">                                                // BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -837,7 +848,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_mpeg_audio_lame['preset_used_id']    = ($PresetSurroundBytes & 0x07FF);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_mpeg_audio_lame['preset_used']       = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
</span><span class="cx" style="display: block; padding: 0 10px">                                                if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - 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">                                                if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // this may change if 3.90.4 ever comes out
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -881,7 +892,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.');
</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">@@ -908,12 +919,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                //      $this->fseek($prenullbytefileoffset);
</span><span class="cx" style="display: block; padding: 0 10px">                                //      if ($PossibleNullByte === "\x00") {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $info['avdataend']--;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                //              $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         //              $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
</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">-                                //              $info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         //              $this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
</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">-                                        $info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
</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">@@ -931,7 +942,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
</span><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">-                                        $info['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Error calculating frame length of free-format MP3 without Xing/LAME header');
</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">@@ -948,7 +959,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['audio']['bitrate']         = $thisfile_mpeg_audio['VBR_bitrate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $info['audio']['bitrate']       = $thisfile_mpeg_audio['VBR_bitrate'];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
</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">@@ -1074,7 +1085,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $firstframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1084,7 +1095,7 @@
</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">-                        $nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($ScanAsCBR) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        // force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1098,7 +1109,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
</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">-                                        $info['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Frame at offset ('.$offset.') is has an invalid frame length.');
</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">@@ -1110,7 +1121,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">                                // next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.');
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</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">@@ -1153,10 +1164,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $framelength = $framelength2;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!$framelength) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 return false;
</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">-                                $info['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $info['audio']['codec']   = 'LAME';
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['audio']['encoder'] = 'LAME3.88';
</span><span class="cx" style="display: block; padding: 0 10px">                                $SyncPattern1 = substr($SyncPattern1, 0, 3);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1183,7 +1194,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $ActualFrameLengthValues[] = ($framelength + 1);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $nextoffset++;
</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">-                                        $info['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Did not find expected free-format sync pattern at offset '.$nextoffset);
</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">                                $nextoffset += $framelength;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1281,7 +1292,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 foreach ($Distribution as $key1 => $value1) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        foreach ($value1 as $key2 => $value2) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1308,13 +1319,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $info['mpeg']['audio']['version_distribution']   = $Distribution['version'];
</span><span class="cx" style="display: block; padding: 0 10px">                $info['mpeg']['audio']['padding_distribution']   = $Distribution['padding'];
</span><span class="cx" style="display: block; padding: 0 10px">                if (count($Distribution['version']) > 1) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Corrupt file - more than one MPEG version detected';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Corrupt file - more than one MPEG version detected');
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                if (count($Distribution['layer']) > 1) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Corrupt file - more than one MPEG layer detected';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Corrupt file - more than one MPEG layer detected');
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                if (count($Distribution['frequency']) > 1) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Corrupt file - more than one MPEG sample rate detected';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Corrupt file - more than one MPEG sample rate detected');
</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">@@ -1326,7 +1337,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $info['mpeg']['audio']['frame_count']  = array_sum($Distribution['bitrate']);
</span><span class="cx" style="display: block; padding: 0 10px">                if ($info['mpeg']['audio']['frame_count'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'no MPEG audio frames found';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('no MPEG audio frames found');
</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">                $info['mpeg']['audio']['bitrate']      = ($bittotal / $info['mpeg']['audio']['frame_count']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1361,7 +1372,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->fseek($avdataoffset);
</span><span class="cx" style="display: block; padding: 0 10px">                $sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset);
</span><span class="cx" style="display: block; padding: 0 10px">                if ($sync_seek_buffer_size <= 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Invalid $sync_seek_buffer_size at offset '.$avdataoffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Invalid $sync_seek_buffer_size at offset '.$avdataoffset);
</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">                $header = $this->fread($sync_seek_buffer_size);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1372,7 +1383,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($SynchSeekOffset > $sync_seek_buffer_size) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        // if a synch's not found within the first 128k bytes, then give up
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
</ins><span class="cx" style="display: block; padding: 0 10px">                                         if (isset($info['audio']['bitrate'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                unset($info['audio']['bitrate']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1386,7 +1397,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                } elseif (feof($this->getid3->fp)) {
</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['error'][] = 'Could not find valid MPEG audio synch before end of file';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Could not find valid MPEG audio synch before end of file');
</ins><span class="cx" style="display: block; padding: 0 10px">                                         if (isset($info['audio']['bitrate'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                unset($info['audio']['bitrate']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1401,7 +1412,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 (($SynchSeekOffset + 1) >= strlen($header)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['error'][] = 'Could not find valid MPEG synch before end of file';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Could not find valid MPEG synch before end of file');
</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">@@ -1444,9 +1455,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $info = $dummy;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $info['avdataoffset'] = $GarbageOffsetEnd;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd);
</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">-                                                                $info['warning'][] = 'using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');
</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">@@ -1539,7 +1550,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 ($pct_data_scanned > 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         foreach ($info['mpeg']['audio'] as $key1 => $value1) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                if (!preg_match('#_distribution$#i', $key1)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        continue;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1551,7 +1562,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 ($SynchErrorsFound > 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('Found '.$SynchErrorsFound.' synch errors in histogram analysis');
</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">@@ -1564,7 +1575,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 ($framecounter == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['error'][] = 'Corrupt MP3 file: framecounter == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->error('Corrupt MP3 file: framecounter == zero');
</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">                                                $info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1599,7 +1610,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if (empty($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">-                                        $info['error'][] = 'could not find valid MPEG synch before end of file';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('could not find valid MPEG synch before end of file');
</ins><span class="cx" style="display: block; padding: 0 10px">                                         if (isset($info['audio']['bitrate'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                unset($info['audio']['bitrate']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</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    2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.audio.ogg.php      2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -26,13 +26,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Warn about illegal tags - only vorbiscomments are allowed
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['id3v2'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Illegal ID3v2 tag present.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Illegal ID3v2 tag present.');
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['id3v1'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Illegal ID3v1 tag present.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Illegal ID3v1 tag present.');
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['ape'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Illegal APE tag present.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Illegal APE tag present.');
</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">@@ -44,7 +44,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->ftell() >= $this->getid3->fread_buffer_size()) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)');
</ins><span class="cx" style="display: block; padding: 0 10px">                         unset($info['fileformat']);
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($info['ogg']);
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -179,7 +179,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">-$info['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">@@ -240,7 +240,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                } elseif (substr($filedata, 1, 6) == 'theora') {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['video']['dataformat'] = 'theora1';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['error'][] = 'Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']');
</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">                                } elseif (substr($filedata, 1, 6) == 'vorbis') {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -248,7 +248,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
</span><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">-                                        $info['error'][] = 'unexpected';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('unexpected');
</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">                        //} while ($oggpageinfo['page_seqno'] == 0);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -256,12 +256,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->fseek($oggpageinfo['page_start_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">-                        $info['error'][] = 'Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
</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">                } 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">-                        $info['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 either "Speex   ", "OpusHead" or "vorbis" 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">@@ -284,7 +284,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'flac':
</span><span class="cx" style="display: block; padding: 0 10px">                                $flac = new getid3_flac($this->getid3);
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!$flac->parseMETAdata()) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['error'][] = 'Failed to parse FLAC headers';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Failed to parse FLAC headers');
</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">                                unset($flac);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -299,7 +299,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags'
</span><span class="cx" style="display: block; padding: 0 10px">                                if(substr($filedata, 0, 8)  != 'OpusTags') {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['error'][] = 'Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"');
</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">@@ -311,7 +311,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // Last Page - Number of Samples
</span><span class="cx" style="display: block; padding: 0 10px">                if (!getid3_lib::intValueSupported($info['avdataend'])) {
</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['warning'][] = 'Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)');
</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"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -323,7 +323,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['ogg']['samples']   = $info['ogg']['pageheader']['eos']['pcm_abs_position'];
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($info['ogg']['samples'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['error'][] = 'Corrupt Ogg file: eos.number of samples == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('Corrupt Ogg file: eos.number of samples == zero');
</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">                                if (!empty($info['audio']['sample_rate'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -342,7 +342,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($info['audio']['bitrate'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['error'][] = 'Corrupt Ogg file: bitrate_audio == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Corrupt Ogg file: bitrate_audio == zero');
</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">                        $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -395,7 +395,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $info['ogg']['samplerate']       = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
</span><span class="cx" style="display: block; padding: 0 10px">                $filedataoffset += 4;
</span><span class="cx" style="display: block; padding: 0 10px">                if ($info['ogg']['samplerate'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Corrupt Ogg file: sample rate == zero';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Corrupt Ogg file: sample rate == zero');
</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">                $info['audio']['sample_rate']    = $info['ogg']['samplerate'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -443,7 +443,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $filedataoffset += 1;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Unknown opus version number (only accepting 1-15)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Unknown opus version number (only accepting 1-15)');
</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">@@ -451,7 +451,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $filedataoffset += 1;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Invalid channel count in opus header (must not be zero)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Invalid channel count in opus header (must not be zero)');
</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">@@ -562,6 +562,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        default:
</span><span class="cx" style="display: block; padding: 0 10px">                                return false;
</span><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><span class="cx" style="display: block; padding: 0 10px">                $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -580,7 +581,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($i >= 10000) {
</span><span class="cx" style="display: block; padding: 0 10px">                                // https://github.com/owncloud/music/issues/212#issuecomment-43082336
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments');
</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">@@ -618,7 +619,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $commentdataoffset += 4;
</span><span class="cx" style="display: block; padding: 0 10px">                        while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments');
</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">@@ -642,12 +643,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
</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">                                $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1);
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($readlength <= 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
</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">                                $commentdata .= $this->fread($readlength);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -661,7 +662,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!$commentstring) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // no comment?
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Blank Ogg comment ['.$i.']';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Blank Ogg comment ['.$i.']');
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        } elseif (strstr($commentstring, '=')) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -711,7 +712,7 @@
</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">-                                $info['warning'][] = '[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring);
</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($ThisFileInfo_ogg_comments_raw[$i]);
</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   2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.tag.apetag.php     2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23,7 +23,7 @@
</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">                if (!getid3_lib::intValueSupported($info['filesize'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
</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">@@ -72,7 +72,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->fseek($thisfile_ape['tag_offset_end'] - $apetagheadersize);
</span><span class="cx" style="display: block; padding: 0 10px">                $APEfooterData = $this->fread(32);
</span><span class="cx" style="display: block; padding: 0 10px">                if (!($thisfile_ape['footer'] = $this->parseAPEheaderFooter($APEfooterData))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['error'][] = 'Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end']);
</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">@@ -88,7 +88,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $info['avdataend'] = $thisfile_ape['tag_offset_start'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] < $thisfile_ape['tag_offset_end'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in APEtag data';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('ID3v1 tag information ignored since it appears to be a false synch in APEtag data');
</ins><span class="cx" style="display: block; padding: 0 10px">                         unset($info['id3v1']);
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($info['warning'] as $key => $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -104,7 +104,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($thisfile_ape['header'] = $this->parseAPEheaderFooter(substr($APEtagData, 0, $apetagheadersize))) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $offset += $apetagheadersize;
</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">-                                $info['error'][] = 'Error parsing APE header at offset '.$thisfile_ape['tag_offset_start'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Error parsing APE header at offset '.$thisfile_ape['tag_offset_start']);
</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">@@ -119,7 +119,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $item_flags = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
</span><span class="cx" style="display: block; padding: 0 10px">                        $offset += 4;
</span><span class="cx" style="display: block; padding: 0 10px">                        if (strstr(substr($APEtagData, $offset), "\x00") === false) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['error'][] = 'Cannot find null-byte (0x00) seperator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Cannot find null-byte (0x00) separator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset));
</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">                        $ItemKeyLength = strpos($APEtagData, "\x00", $offset) - $offset;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -154,7 +154,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</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">@@ -163,10 +163,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
</del><ins style="background-color: #dfd; text-decoration:none; 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].'")');
</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">-                                                $info['warning'][] = 'MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</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">@@ -175,7 +175,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</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">@@ -184,10 +184,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
</del><ins style="background-color: #dfd; text-decoration:none; 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].'")');
</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">-                                                $info['warning'][] = 'MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</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">@@ -198,7 +198,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['mp3gain']['undo_wrap']  = (($mp3gain_undo_wrap == 'Y') ? true : false);
</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">-                                                $info['warning'][] = 'MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</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">@@ -208,7 +208,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);
</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">-                                                $info['warning'][] = 'MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</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">@@ -218,7 +218,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);
</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">-                                                $info['warning'][] = 'MP3gainAlbumMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('MP3gainAlbumMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</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">@@ -253,19 +253,23 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                case 'cover art (studio)':
</span><span class="cx" style="display: block; padding: 0 10px">                                        // list of possible cover arts from http://taglib-sharp.sourcearchive.com/documentation/2.0.3.0-2/Ape_2Tag_8cs-source.html
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (is_array($thisfile_ape_items_current['data'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $thisfile_ape_items_current['data'] = implode("\x00", $thisfile_ape_items_current['data']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        list($thisfile_ape_items_current['filename'], $thisfile_ape_items_current['data']) = explode("\x00", $thisfile_ape_items_current['data'], 2);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_ape_items_current['data_offset'] = $thisfile_ape_items_current['offset'] + strlen($thisfile_ape_items_current['filename']."\x00");
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_ape_items_current['data_length'] = strlen($thisfile_ape_items_current['data']);
</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_ape_items_current['image_mime'] = '';
-                                       $imageinfo = array();
-                                       $imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
-                                       $thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 do {
+                                               $thisfile_ape_items_current['image_mime'] = '';
+                                               $imageinfo = array();
+                                               $imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
+                                               if (($imagechunkcheck === false) || !isset($imagechunkcheck[2])) {
+                                                       $this->warning('APEtag "'.$item_key.'" contains invalid image data');
+                                                       break;
+                                               }
+                                               $thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[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">-                                        do {
</del><span class="cx" style="display: block; padding: 0 10px">                                                 if ($this->inline_attachments === false) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // skip entirely
</span><span class="cx" style="display: block; padding: 0 10px">                                                        unset($thisfile_ape_items_current['data']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -276,15 +280,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                } elseif (is_int($this->inline_attachments)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if ($this->inline_attachments < $thisfile_ape_items_current['data_length']) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                // too big, skip
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' is too large to process inline ('.number_format($thisfile_ape_items_current['data_length']).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('attachment at '.$thisfile_ape_items_current['offset'].' is too large to process inline ('.number_format($thisfile_ape_items_current['data_length']).' bytes)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 unset($thisfile_ape_items_current['data']);
</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">                                                } elseif (is_string($this->inline_attachments)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $this->inline_attachments = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->inline_attachments), DIRECTORY_SEPARATOR);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        if (!is_dir($this->inline_attachments) || !is_writable($this->inline_attachments)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 if (!is_dir($this->inline_attachments) || !getID3::is_writable($this->inline_attachments)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 // cannot write, skip
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 unset($thisfile_ape_items_current['data']);
</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">@@ -292,10 +296,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                // if we get this far, must be OK
</span><span class="cx" style="display: block; padding: 0 10px">                                                if (is_string($this->inline_attachments)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $destination_filename = $this->inline_attachments.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$thisfile_ape_items_current['data_offset'];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        if (!file_exists($destination_filename) || is_writable($destination_filename)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 file_put_contents($destination_filename, $thisfile_ape_items_current['data']);
</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">-                                                                $info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $thisfile_ape_items_current['data_filename'] = $destination_filename;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        unset($thisfile_ape_items_current['data']);
</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    2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.tag.id3v1.php      2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22,7 +22,7 @@
</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">                if (!getid3_lib::intValueSupported($info['filesize'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
</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">@@ -60,6 +60,26 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($ParsedID3v1 as $key => $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $ParsedID3v1['comments'][$key][0] = $value;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        // ID3v1 encoding detection hack START
+                       // ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
+                       // Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
+                       $ID3v1encoding = 'ISO-8859-1';
+                       foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
+                               foreach ($valuearray as $key => $value) {
+                                       if (preg_match('#^[\\x00-\\x40\\xA8\\B8\\x80-\\xFF]+$#', $value)) {
+                                               foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
+                                                       if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
+                                                               $ID3v1encoding = $id3v1_bad_encoding;
+                                                               break 3;
+                                                       } elseif (function_exists('iconv') && @iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
+                                                               $ID3v1encoding = $id3v1_bad_encoding;
+                                                               break 3;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       // ID3v1 encoding detection hack END
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces
</span><span class="cx" style="display: block; padding: 0 10px">                        $GoodFormatID3v1tag = $this->GenerateID3v1Tag(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -73,13 +93,14 @@
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Some ID3v1 fields do not use NULL characters for padding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Some ID3v1 fields do not use NULL characters for padding');
</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">                        $ParsedID3v1['tag_offset_end']   = $info['filesize'];
</span><span class="cx" style="display: block; padding: 0 10px">                        $ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $info['id3v1'] = $ParsedID3v1;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $info['id3v1']['encoding'] = $ID3v1encoding;
</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 (substr($preid3v1, 0, 3) == 'TAG') {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -95,7 +116,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                // a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                // APE and Lyrics3 footers not found - assume double ID3v1
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Duplicate ID3v1 tag detected - this has been known to happen with iTunes';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Duplicate ID3v1 tag detected - this has been known to happen with iTunes');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $info['avdataend'] -= 128;
</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="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    2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.tag.id3v2.php      2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -71,7 +71,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($id3v2_majorversion > 4) { // this script probably won't correctly parse ID3v2.5.x and above (if it ever exists)
</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['error'][] = 'this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$id3v2_majorversion.'.'.$thisfile_id3v2['minorversion'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$id3v2_majorversion.'.'.$thisfile_id3v2['minorversion']);
</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">@@ -241,7 +241,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 ($thisfile_id3v2['exthead']['length'] != $extended_header_offset) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'ID3v2.4 extended header length mismatch (expecting '.intval($thisfile_id3v2['exthead']['length']).', found '.intval($extended_header_offset).')';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('ID3v2.4 extended header length mismatch (expecting '.intval($thisfile_id3v2['exthead']['length']).', found '.intval($extended_header_offset).')');
</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">@@ -260,7 +260,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($framedata{$i} != "\x00") {
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)';
</del><ins style="background-color: #dfd; text-decoration:none; 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)');
</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">@@ -300,7 +300,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                } elseif (($frame_name == "\x00".'MP3') || ($frame_name == "\x00\x00".'MP') || ($frame_name == ' MP3') || ($frame_name == 'MP3e')) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // MP3ext known broken frames - "ok" for the purposes of this test
</span><span class="cx" style="display: block; padding: 0 10px">                                                } elseif (($id3v2_majorversion == 4) && ($this->IsValidID3v2FrameName(substr($framedata, getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0), 4), 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of (Helium2; iTunes) are known culprits of this. Tag has been parsed as ID3v2.3';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of (Helium2; iTunes) are known culprits of this. Tag has been parsed as ID3v2.3');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $id3v2_majorversion = 3;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -322,16 +322,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($framedata{$i} != "\x00") {
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)';
</del><ins style="background-color: #dfd; text-decoration:none; 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)');
</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="cx" style="display: block; padding: 0 10px">                                        break; // skip rest of ID3v2 header
</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 ($frame_name == 'COM ') {
-                                       $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably others too)]';
-                                       $frame_name = 'COMM';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ($iTunesBrokenFrameNameFixed = self::ID3v22iTunesBrokenFrameName($frame_name)) {
+                                       $this->warning('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by iTunes (versions "X v2.0.3", "v3.0.1", "v7.0.0.70" are known-guilty, probably others too)]. Translated frame name from "'.str_replace("\x00", ' ', $frame_name).'" to "'.$iTunesBrokenFrameNameFixed.'" for parsing.');
+                                       $frame_name = $iTunesBrokenFrameNameFixed;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                if (($frame_size <= strlen($framedata)) && ($this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion))) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -355,28 +355,28 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // next frame is valid, just skip the current frame
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $framedata = substr($framedata, $frame_size);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'Next ID3v2 frame is valid, skipping current frame.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('Next ID3v2 frame is valid, skipping current frame.');
</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"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // next frame is invalid too, abort processing
</span><span class="cx" style="display: block; padding: 0 10px">                                                        //unset($framedata);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $framedata = null;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['error'][] = 'Next ID3v2 frame is also invalid, aborting processing.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->error('Next ID3v2 frame is also invalid, aborting processing.');
</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="cx" style="display: block; padding: 0 10px">                                        } elseif ($frame_size == strlen($framedata)) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                // this is the last frame, just skip
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'This was the last ID3v2 frame.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('This was the last ID3v2 frame.');
</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"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                // next frame is invalid too, abort processing
</span><span class="cx" style="display: block; padding: 0 10px">                                                //unset($framedata);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $framedata = null;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'Invalid ID3v2 frame size, aborting.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('Invalid ID3v2 frame size, aborting.');
</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 (!$this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -389,21 +389,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case "\x00".'MP':
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case ' MP':
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case 'MP3':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by "MP3ext (www.mutschler.de/mp3ext/)"]';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by "MP3ext (www.mutschler.de/mp3ext/)"]');
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))).';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $this->warning('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))).');
</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="cx" style="display: block; padding: 0 10px">                                        } elseif (!isset($framedata) || ($frame_size > strlen($framedata))) {
</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['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: $frame_size ('.$frame_size.') > strlen($framedata) ('.(isset($framedata) ? strlen($framedata) : 'null').')).';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->error('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: $frame_size ('.$frame_size.') > strlen($framedata) ('.(isset($framedata) ? strlen($framedata) : 'null').')).');
</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"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag).';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->error('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag).');
</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">@@ -442,10 +442,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                } // end footer
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($thisfile_id3v2['comments']['genre'])) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $genres = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                         foreach ($thisfile_id3v2['comments']['genre'] as $key => $value) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                unset($thisfile_id3v2['comments']['genre'][$key]);
-                               $thisfile_id3v2['comments'] = getid3_lib::array_merge_noclobber($thisfile_id3v2['comments'], array('genre'=>$this->ParseID3v2GenreString($value)));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         foreach ($this->ParseID3v2GenreString($value) as $genre) {
+                                       $genres[] = $genre;
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $thisfile_id3v2['comments']['genre'] = array_unique($genres);
+                       unset($key, $value, $genres, $genre);
</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 (isset($thisfile_id3v2['comments']['track'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -500,9 +504,28 @@
</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="cx" style="display: block; padding: 0 10px">                // ID3v2.4.x: '21' $00 'Eurodisco' $00
</span><span class="cx" style="display: block; padding: 0 10px">                $clean_genres = array();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               // hack-fixes for some badly-written ID3v2.3 taggers, while trying not to break correctly-written tags
+               if (($this->getid3->info['id3v2']['majorversion'] == 3) && !preg_match('#[\x00]#', $genrestring)) {
+                       // note: MusicBrainz Picard incorrectly stores plaintext genres separated by "/" when writing in ID3v2.3 mode, hack-fix here:
+                       // replace / with NULL, then replace back the two ID3v1 genres that legitimately have "/" as part of the single genre name
+                       if (preg_match('#/#', $genrestring)) {
+                               $genrestring = str_replace('/', "\x00", $genrestring);
+                               $genrestring = str_replace('Pop'."\x00".'Funk', 'Pop/Funk', $genrestring);
+                               $genrestring = str_replace('Rock'."\x00".'Rock', 'Folk/Rock', $genrestring);
+                       }
+
+                       // some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
+                       if (preg_match('#;#', $genrestring)) {
+                               $genrestring = str_replace(';', "\x00", $genrestring);
+                       }
+               }
+
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 if (strpos($genrestring, "\x00") === false) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $genrestring = preg_replace('#\(([0-9]{1,3})\)#', '$1'."\x00", $genrestring);
</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 class="cx" style="display: block; padding: 0 10px">                 $genre_elements = explode("\x00", $genrestring);
</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="lines" style="display: block; padding: 0 10px; color: #888">@@ -571,14 +594,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($parsedFrame['flags']['compression']) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $parsedFrame['decompressed_size'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 4));
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!function_exists('gzuncompress')) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame['frame_name'].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame['frame_name'].'"');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($decompresseddata = @gzuncompress(substr($parsedFrame['data'], 4))) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        //if ($decompresseddata = @gzuncompress($parsedFrame['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $parsedFrame['data'] = $decompresseddata;
</span><span class="cx" style="display: block; padding: 0 10px">                                                unset($decompresseddata);
</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">-                                                $info['warning'][] = 'gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame['frame_name'].'"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame['frame_name'].'"');
</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">@@ -586,7 +609,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if (!empty($parsedFrame['flags']['DataLengthIndicator'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($parsedFrame['data_length_indicator'] != strlen($parsedFrame['data'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'ID3v2 frame "'.$parsedFrame['frame_name'].'" should be '.$parsedFrame['data_length_indicator'].' bytes long according to DataLengthIndicator, but found '.strlen($parsedFrame['data']).' bytes of data';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('ID3v2 frame "'.$parsedFrame['frame_name'].'" should be '.$parsedFrame['data_length_indicator'].' bytes long according to DataLengthIndicator, but found '.strlen($parsedFrame['data']).' bytes of data');
</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">@@ -601,7 +624,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                default:
</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">-                        $info['warning'][] = $warning;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning($warning);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'UFID')) || // 4.1   UFID Unique file identifier
</span><span class="cx" style="display: block; padding: 0 10px">                        (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'UFI'))) {  // 4.1   UFI  Unique file identifier
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -627,7 +650,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_textencoding_terminator = "\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'], $frame_textencoding_terminator, $frame_offset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -635,7 +658,8 @@
</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><span class="cx" style="display: block; padding: 0 10px">                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 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
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_description = '';
</span><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="lines" style="display: block; padding: 0 10px; color: #888">@@ -664,7 +688,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</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">                        $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -720,7 +744,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_textencoding_terminator = "\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'], $frame_textencoding_terminator, $frame_offset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -728,8 +752,8 @@
</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><span class="cx" style="display: block; padding: 0 10px">                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-                       if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 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
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_description = '';
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -783,7 +807,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</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($parsedFrame['encodingid']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -961,7 +985,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_textencoding_terminator = "\x00";
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -971,7 +995,8 @@
</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><span class="cx" style="display: block; padding: 0 10px">                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 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
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_description = '';
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -979,7 +1004,6 @@
</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']         = $parsedFrame['data'];
</del><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><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['description']  = $frame_description;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1009,7 +1033,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_textencoding_terminator = "\x00";
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1061,7 +1085,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if (strlen($parsedFrame['data']) < 5) {
</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['warning'][] = 'Invalid data (too short) for "'.$parsedFrame['frame_name'].'" frame at offset '.$parsedFrame['dataoffset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid data (too short) for "'.$parsedFrame['frame_name'].'" frame at offset '.$parsedFrame['dataoffset']);
</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"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1069,7 +1093,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                                if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $frame_textencoding_terminator = "\x00";
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1079,7 +1103,8 @@
</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><span class="cx" style="display: block; padding: 0 10px">                                $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         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
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $frame_description = '';
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1132,7 +1157,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_offset += 2;
</span><span class="cx" style="display: block; padding: 0 10px">                                $parsedFrame[$RVA2channelcounter]['bitspeakvolume'] = ord(substr($frame_remainingdata, $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                                if (($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] < 1) || ($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] > 4)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'ID3v2::RVA2 frame['.$RVA2channelcounter.'] contains invalid '.$parsedFrame[$RVA2channelcounter]['bitspeakvolume'].'-byte bits-representing-peak value';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('ID3v2::RVA2 frame['.$RVA2channelcounter.'] contains invalid '.$parsedFrame[$RVA2channelcounter]['bitspeakvolume'].'-byte bits-representing-peak value');
</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">                                $frame_bytespeakvolume = ceil($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] / 8);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1341,7 +1366,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_textencoding_terminator = "\x00";
</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">@@ -1376,14 +1401,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_picturetype = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($frame_offset >= $parsedFrame['datalength']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'data portion of APIC frame is missing at offset '.($parsedFrame['dataoffset'] + 8 + $frame_offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('data portion of APIC frame is missing at offset '.($parsedFrame['dataoffset'] + 8 + $frame_offset));
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
</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><span class="cx" style="display: block; padding: 0 10px">                                $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         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
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $frame_description = '';
</span><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="lines" style="display: block; padding: 0 10px; color: #888">@@ -1402,15 +1428,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                $parsedFrame['image_mime'] = '';
</span><span class="cx" style="display: block; padding: 0 10px">                                $imageinfo = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo);
-                               if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
-                                       $parsedFrame['image_mime']       = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
-                                       if ($imagechunkcheck[0]) {
-                                               $parsedFrame['image_width']  = $imagechunkcheck[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
+                                       if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
+                                               $parsedFrame['image_mime']       = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
+                                               if ($imagechunkcheck[0]) {
+                                                       $parsedFrame['image_width']  = $imagechunkcheck[0];
+                                               }
+                                               if ($imagechunkcheck[1]) {
+                                                       $parsedFrame['image_height'] = $imagechunkcheck[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">-                                        if ($imagechunkcheck[1]) {
-                                               $parsedFrame['image_height'] = $imagechunkcheck[1];
-                                       }
</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">                                do {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1425,16 +1452,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        } elseif (is_int($this->getid3->option_save_attachments)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($this->getid3->option_save_attachments < $parsedFrame['data_length']) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // too big, skip
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'attachment at '.$frame_offset.' is too large to process inline ('.number_format($parsedFrame['data_length']).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('attachment at '.$frame_offset.' is too large to process inline ('.number_format($parsedFrame['data_length']).' bytes)');
</ins><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><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">                                        } elseif (is_string($this->getid3->option_save_attachments)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                if (!is_dir($dir) || !is_writable($dir)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         if (!is_dir($dir) || !getID3::is_writable($dir)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         // cannot write, skip
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)');
</ins><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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1442,10 +1469,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        // if we get this far, must be OK
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (is_string($this->getid3->option_save_attachments)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $destination_filename = $dir.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$frame_offset;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                if (!file_exists($destination_filename) || is_writable($destination_filename)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         file_put_contents($destination_filename, $parsedFrame['data']);
</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">-                                                        $info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                $parsedFrame['data_filename'] = $destination_filename;
</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">@@ -1482,7 +1509,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_textencoding_terminator = "\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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1507,7 +1534,8 @@
</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><span class="cx" style="display: block; padding: 0 10px">                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 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
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_description = '';
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1589,7 +1617,8 @@
</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="cx" style="display: block; padding: 0 10px">                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 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
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_description = '';
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = $frame_terminatorpos + strlen("\x00");
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1614,7 +1643,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><span class="cx" style="display: block; padding: 0 10px">                        if (ord($frame_ownerid) === 0) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $frame_ownerid == '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $frame_ownerid = '';
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</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">                        $parsedFrame['ownerid'] = $frame_ownerid;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1683,7 +1712,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset += 3;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1710,7 +1739,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</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">@@ -1724,7 +1753,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['pricepaid']['value']      = substr($frame_pricepaid, 3);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['purchasedate'] = substr($parsedFrame['data'], $frame_offset, 8);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (!$this->IsValidDateStampString($parsedFrame['purchasedate'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ($this->IsValidDateStampString($parsedFrame['purchasedate'])) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $parsedFrame['purchasedateunix'] = mktime (0, 0, 0, substr($parsedFrame['purchasedate'], 4, 2), substr($parsedFrame['purchasedate'], 6, 2), substr($parsedFrame['purchasedate'], 0, 4));
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset += 8;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1751,7 +1780,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_textencoding_terminator = "\x00";
</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">@@ -1789,7 +1818,8 @@
</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><span class="cx" style="display: block; padding: 0 10px">                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (ord($frame_description) === 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 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
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_description = '';
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2006,7 +2036,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $frame_offset += 2;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'CHAP subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('CHAP subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)');
</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">                                        $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2043,7 +2073,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                $parsedFrame['subframes'][] = $subframe;
</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">-                                                $info['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">+                                         $this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
</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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2103,7 +2133,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $frame_offset += 2;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $info['warning'][] = 'CTOS subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('CTOS subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)');
</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">                                        $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2140,7 +2170,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                $parsedFrame['subframes'][] = $subframe;
</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">-                                                $info['warning'][] = 'ID3v2.CTOC subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('ID3v2.CTOC subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
</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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3623,5 +3653,89 @@
</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">+        public static function ID3v22iTunesBrokenFrameName($frame_name) {
+               // iTunes (multiple versions) has been known to write ID3v2.3 style frames
+               // but use ID3v2.2 frame names, right-padded using either [space] or [null]
+               // to make them fit in the 4-byte frame name space of the ID3v2.3 frame.
+               // This function will detect and translate the corrupt frame name into ID3v2.3 standard.
+               static $ID3v22_iTunes_BrokenFrames = array(
+                       'BUF' => 'RBUF', // Recommended buffer size
+                       'CNT' => 'PCNT', // Play counter
+                       'COM' => 'COMM', // Comments
+                       'CRA' => 'AENC', // Audio encryption
+                       'EQU' => 'EQUA', // Equalisation
+                       'ETC' => 'ETCO', // Event timing codes
+                       'GEO' => 'GEOB', // General encapsulated object
+                       'IPL' => 'IPLS', // Involved people list
+                       'LNK' => 'LINK', // Linked information
+                       'MCI' => 'MCDI', // Music CD identifier
+                       'MLL' => 'MLLT', // MPEG location lookup table
+                       'PIC' => 'APIC', // Attached picture
+                       'POP' => 'POPM', // Popularimeter
+                       'REV' => 'RVRB', // Reverb
+                       'RVA' => 'RVAD', // Relative volume adjustment
+                       'SLT' => 'SYLT', // Synchronised lyric/text
+                       'STC' => 'SYTC', // Synchronised tempo codes
+                       'TAL' => 'TALB', // Album/Movie/Show title
+                       'TBP' => 'TBPM', // BPM (beats per minute)
+                       'TCM' => 'TCOM', // Composer
+                       'TCO' => 'TCON', // Content type
+                       'TCP' => 'TCMP', // Part of a compilation
+                       'TCR' => 'TCOP', // Copyright message
+                       'TDA' => 'TDAT', // Date
+                       'TDY' => 'TDLY', // Playlist delay
+                       'TEN' => 'TENC', // Encoded by
+                       'TFT' => 'TFLT', // File type
+                       'TIM' => 'TIME', // Time
+                       'TKE' => 'TKEY', // Initial key
+                       'TLA' => 'TLAN', // Language(s)
+                       'TLE' => 'TLEN', // Length
+                       'TMT' => 'TMED', // Media type
+                       'TOA' => 'TOPE', // Original artist(s)/performer(s)
+                       'TOF' => 'TOFN', // Original filename
+                       'TOL' => 'TOLY', // Original lyricist(s)/text writer(s)
+                       'TOR' => 'TORY', // Original release year
+                       'TOT' => 'TOAL', // Original album/movie/show title
+                       'TP1' => 'TPE1', // Lead performer(s)/Soloist(s)
+                       'TP2' => 'TPE2', // Band/orchestra/accompaniment
+                       'TP3' => 'TPE3', // Conductor/performer refinement
+                       'TP4' => 'TPE4', // Interpreted, remixed, or otherwise modified by
+                       'TPA' => 'TPOS', // Part of a set
+                       'TPB' => 'TPUB', // Publisher
+                       'TRC' => 'TSRC', // ISRC (international standard recording code)
+                       'TRD' => 'TRDA', // Recording dates
+                       'TRK' => 'TRCK', // Track number/Position in set
+                       'TS2' => 'TSO2', // Album-Artist sort order
+                       'TSA' => 'TSOA', // Album sort order
+                       'TSC' => 'TSOC', // Composer sort order
+                       'TSI' => 'TSIZ', // Size
+                       'TSP' => 'TSOP', // Performer sort order
+                       'TSS' => 'TSSE', // Software/Hardware and settings used for encoding
+                       'TST' => 'TSOT', // Title sort order
+                       'TT1' => 'TIT1', // Content group description
+                       'TT2' => 'TIT2', // Title/songname/content description
+                       'TT3' => 'TIT3', // Subtitle/Description refinement
+                       'TXT' => 'TEXT', // Lyricist/Text writer
+                       'TXX' => 'TXXX', // User defined text information frame
+                       'TYE' => 'TYER', // Year
+                       'UFI' => 'UFID', // Unique file identifier
+                       'ULT' => 'USLT', // Unsynchronised lyric/text transcription
+                       'WAF' => 'WOAF', // Official audio file webpage
+                       'WAR' => 'WOAR', // Official artist/performer webpage
+                       'WAS' => 'WOAS', // Official audio source webpage
+                       'WCM' => 'WCOM', // Commercial information
+                       'WCP' => 'WCOP', // Copyright/Legal information
+                       'WPB' => 'WPUB', // Publishers official webpage
+                       'WXX' => 'WXXX', // User defined URL link frame
+               );
+               if (strlen($frame_name) == 4) {
+                       if ((substr($frame_name, 3, 1) == ' ') || (substr($frame_name, 3, 1) == "\x00")) {
+                               if (isset($ID3v22_iTunes_BrokenFrames[substr($frame_name, 0, 3)])) {
+                                       return $ID3v22_iTunes_BrokenFrames[substr($frame_name, 0, 3)];
+                               }
+                       }
+               }
+               return 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">-
</del></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  2017-07-30 15:45:50 UTC (rev 41195)
+++ trunk/src/wp-includes/ID3/module.tag.lyrics3.php    2017-07-31 19:49:31 UTC (rev 41196)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24,7 +24,7 @@
</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="cx" style="display: block; padding: 0 10px">                if (!getid3_lib::intValueSupported($info['filesize'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
</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">@@ -80,7 +80,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $lyrics3offset  = $info['ape']['tag_offset_start'] - $lyrics3size;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['avdataend'] = $lyrics3offset;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $lyrics3version = 1;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability');
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                } elseif ($lyrics3end == 'LYRICS200') {
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Lyrics3v2, APE, maybe ID3v1
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -88,7 +88,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $lyrics3size    = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
</span><span class="cx" style="display: block; padding: 0 10px">                                        $lyrics3offset  = $info['ape']['tag_offset_start'] - $lyrics3size;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $lyrics3version = 2;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability');
</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">@@ -117,7 +117,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        unset($getid3_temp, $getid3_apetag);
</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">-                                        $info['warning'][] = 'Lyrics3 and APE tags appear to have become entangled (most likely due to updating the APE tags with a non-Lyrics3-aware tagger)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->warning('Lyrics3 and APE tags appear to have become entangled (most likely due to updating the APE tags with a non-Lyrics3-aware tagger)');
</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">@@ -132,7 +132,7 @@
</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">                if (!getid3_lib::intValueSupported($endoffset)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
</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">@@ -150,7 +150,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($rawdata, 0, 11) != 'LYRICSBEGIN') {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (strpos($rawdata, 'LYRICSBEGIN') !== 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">-                                $info['warning'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $info['avdataend'] = $endoffset + strpos($rawdata, 'LYRICSBEGIN');
</span><span class="cx" style="display: block; padding: 0 10px">                                $rawdata = substr($rawdata, strpos($rawdata, 'LYRICSBEGIN'));
</span><span class="cx" style="display: block; padding: 0 10px">                                $length = strlen($rawdata);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -159,7 +159,7 @@
</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">-                                $info['error'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead');
</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">@@ -173,7 +173,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $ParsedLyrics3['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $this->Lyrics3LyricsTimestampParse($ParsedLyrics3);
</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">-                                        $info['error'][] = '"LYRICSEND" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('"LYRICSEND" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead');
</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">                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -221,20 +221,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $this->Lyrics3LyricsTimestampParse($ParsedLyrics3);
</span><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">-                                        $info['error'][] = '"LYRICS200" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->error('"LYRICS200" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead');
</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">                                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">-                                $info['error'][] = 'Cannot process Lyrics3 version '.$version.' (only v1 and v2)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->error('Cannot process Lyrics3 version '.$version.' (only v1 and v2)');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 return false;
</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><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] <= $ParsedLyrics3['tag_offset_end'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data');
</ins><span class="cx" style="display: block; padding: 0 10px">                         unset($info['id3v1']);
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($info['warning'] as $key => $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
</span></span></pre>
</div>
</div>

</body>
</html>