Browse Source

- Mise à jour de la lib getid3 en 1.9.20, nous étions en 1.9.18

- Le changelog est dispo ici: https://github.com/JamesHeinrich/getID3/blob/master/changelog.txt

- Fixe une partie des tickets #4413 et #4414
pull/7/head
Franck 9 months ago
committed by Gitea
parent
commit
5bdb2f9e60
  1. 11
      lib/getid3/extension.cache.dbm.php
  2. 11
      lib/getid3/extension.cache.mysql.php
  3. 15
      lib/getid3/extension.cache.mysqli.php
  4. 18
      lib/getid3/extension.cache.sqlite3.php
  5. 102
      lib/getid3/getid3.lib.php
  6. 169
      lib/getid3/getid3.php
  7. 3
      lib/getid3/module.archive.gzip.php
  8. 92
      lib/getid3/module.archive.hpk.php
  9. 3
      lib/getid3/module.archive.rar.php
  10. 3
      lib/getid3/module.archive.szip.php
  11. 3
      lib/getid3/module.archive.tar.php
  12. 3
      lib/getid3/module.archive.xz.php
  13. 23
      lib/getid3/module.archive.zip.php
  14. 7
      lib/getid3/module.audio-video.asf.php
  15. 9
      lib/getid3/module.audio-video.bink.php
  16. 5
      lib/getid3/module.audio-video.flv.php
  17. 80
      lib/getid3/module.audio-video.ivf.php
  18. 39
      lib/getid3/module.audio-video.matroska.php
  19. 7
      lib/getid3/module.audio-video.mpeg.php
  20. 4
      lib/getid3/module.audio-video.nsv.php
  21. 310
      lib/getid3/module.audio-video.quicktime.php
  22. 6
      lib/getid3/module.audio-video.real.php
  23. 5
      lib/getid3/module.audio-video.riff.php
  24. 4
      lib/getid3/module.audio-video.swf.php
  25. 3
      lib/getid3/module.audio-video.ts.php
  26. 37
      lib/getid3/module.audio-video.wtv.php
  27. 3
      lib/getid3/module.audio.aa.php
  28. 3
      lib/getid3/module.audio.aac.php
  29. 5
      lib/getid3/module.audio.ac3.php
  30. 3
      lib/getid3/module.audio.amr.php
  31. 3
      lib/getid3/module.audio.au.php
  32. 3
      lib/getid3/module.audio.avr.php
  33. 5
      lib/getid3/module.audio.bonk.php
  34. 310
      lib/getid3/module.audio.dsdiff.php
  35. 3
      lib/getid3/module.audio.dsf.php
  36. 7
      lib/getid3/module.audio.dss.php
  37. 15
      lib/getid3/module.audio.dts.php
  38. 4
      lib/getid3/module.audio.flac.php
  39. 4
      lib/getid3/module.audio.la.php
  40. 5
      lib/getid3/module.audio.lpac.php
  41. 4
      lib/getid3/module.audio.midi.php
  42. 3
      lib/getid3/module.audio.mod.php
  43. 3
      lib/getid3/module.audio.monkey.php
  44. 28
      lib/getid3/module.audio.mp3.php
  45. 5
      lib/getid3/module.audio.mpc.php
  46. 4
      lib/getid3/module.audio.ogg.php
  47. 7
      lib/getid3/module.audio.optimfrog.php
  48. 3
      lib/getid3/module.audio.rkau.php
  49. 7
      lib/getid3/module.audio.shorten.php
  50. 214
      lib/getid3/module.audio.tak.php
  51. 4
      lib/getid3/module.audio.tta.php
  52. 3
      lib/getid3/module.audio.voc.php
  53. 3
      lib/getid3/module.audio.vqf.php
  54. 9
      lib/getid3/module.audio.wavpack.php
  55. 3
      lib/getid3/module.graphic.bmp.php
  56. 5
      lib/getid3/module.graphic.efax.php
  57. 5
      lib/getid3/module.graphic.gif.php
  58. 4
      lib/getid3/module.graphic.jpg.php
  59. 6
      lib/getid3/module.graphic.pcd.php
  60. 8
      lib/getid3/module.graphic.png.php
  61. 3
      lib/getid3/module.graphic.svg.php
  62. 4
      lib/getid3/module.graphic.tiff.php
  63. 5
      lib/getid3/module.misc.cue.php
  64. 3
      lib/getid3/module.misc.exe.php
  65. 3
      lib/getid3/module.misc.iso.php
  66. 3
      lib/getid3/module.misc.msoffice.php
  67. 3
      lib/getid3/module.misc.par2.php
  68. 118
      lib/getid3/module.misc.pdf.php
  69. 4
      lib/getid3/module.tag.apetag.php
  70. 37
      lib/getid3/module.tag.id3v1.php
  71. 20
      lib/getid3/module.tag.id3v2.php
  72. 9
      lib/getid3/module.tag.lyrics3.php
  73. 12
      lib/getid3/module.tag.xmp.php
  74. 4
      lib/getid3/write.apetag.php
  75. 3
      lib/getid3/write.id3v1.php
  76. 30
      lib/getid3/write.id3v2.php
  77. 15
      lib/getid3/write.php
  78. 2
      paquet.xml

11
lib/getid3/extension.cache.dbm.php

@ -215,13 +215,14 @@ class getID3_cached_dbm extends getID3
/**
* clear cache
*
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param resource $fp
*
* @return mixed
*/
public function analyze($filename, $filesize=null, $original_filename='') {
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
if (file_exists($filename)) {
@ -238,7 +239,7 @@ class getID3_cached_dbm extends getID3
}
// Miss
$result = parent::analyze($filename);
$result = parent::analyze($filename, $filesize, $original_filename, $fp);
// Save result
if (isset($key) && file_exists($filename)) {

11
lib/getid3/extension.cache.mysql.php

@ -159,13 +159,14 @@ class getID3_cached_mysql extends getID3
/**
* analyze file
*
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param resource $fp
*
* @return mixed
*/
public function analyze($filename, $filesize=null, $original_filename='') {
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
$filetime = 0;
if (file_exists($filename)) {
@ -189,7 +190,7 @@ class getID3_cached_mysql extends getID3
}
// Miss
$analysis = parent::analyze($filename, $filesize, $original_filename);
$analysis = parent::analyze($filename, $filesize, $original_filename, $fp);
// Save result
if (file_exists($filename)) {

15
lib/getid3/extension.cache.mysqli.php

@ -114,8 +114,8 @@ class getID3_cached_mysqli extends getID3
// Connect to database
$this->mysqli = new mysqli($host, $username, $password);
if (!$this->mysqli) {
throw new Exception('mysqli_connect() failed - check permissions and spelling.');
if ($this->mysqli->connect_error) {
throw new Exception('Connect Error (' . $this->mysqli->connect_errno . ') ' . $this->mysqli->connect_error);
}
// Select database
@ -192,13 +192,14 @@ class getID3_cached_mysqli extends getID3
/**
* analyze file
*
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param resource $fp
*
* @return mixed
*/
public function analyze($filename, $filesize=null, $original_filename='') {
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
$filetime = 0;
if (file_exists($filename)) {
@ -220,7 +221,7 @@ class getID3_cached_mysqli extends getID3
}
// Miss
$analysis = parent::analyze($filename, $filesize, $original_filename);
$analysis = parent::analyze($filename, $filesize, $original_filename, $fp);
// Save result
if (file_exists($filename)) {

18
lib/getid3/extension.cache.sqlite3.php

@ -172,13 +172,14 @@ class getID3_cached_sqlite3 extends getID3
/**
* analyze file and cache them, if cached pull from the db
*
* @param string $filename
* @param integer $filesize
* @param string $original_filename
* @param string $filename
* @param integer $filesize
* @param string $original_filename
* @param resource $fp
*
* @return mixed|false
*/
public function analyze($filename, $filesize=null, $original_filename='') {
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
if (!file_exists($filename)) {
return false;
}
@ -201,7 +202,7 @@ class getID3_cached_sqlite3 extends getID3
return unserialize(base64_decode($result));
}
// if it hasn't been analyzed before, then do it now
$analysis = parent::analyze($filename, $filesize, $original_filename);
$analysis = parent::analyze($filename, $filesize, $original_filename, $fp);
// Save result
$sql = $this->getQuery('cache_file');
$stmt = $db->prepare($sql);
@ -262,25 +263,18 @@ class getID3_cached_sqlite3 extends getID3
switch ($name) {
case 'version_check':
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
break;
case 'delete_cache':
return "DELETE FROM $this->table";
break;
case 'set_version':
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
break;
case 'get_id3_data':
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
break;
case 'cache_file':
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
break;
case 'make_table':
return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
break;
case 'get_cached_dir':
return "SELECT val FROM $this->table WHERE dirname = :dirname";
break;
default:
return null;
}

102
lib/getid3/getid3.lib.php

@ -15,10 +15,10 @@
class getid3_lib
{
/**
* @param string $string
* @param bool $hex
* @param bool $spaces
* @param string $htmlencoding
* @param string $string
* @param bool $hex
* @param bool $spaces
* @param string|bool $htmlencoding
*
* @return string
*/
@ -216,7 +216,6 @@ class getid3_lib
default:
return false;
break;
}
if ($floatvalue >= 0) {
$signbit = '0';
@ -284,11 +283,9 @@ class getid3_lib
$floatvalue *= -1;
}
return $floatvalue;
break;
default:
return false;
break;
}
$exponentstring = substr($bitword, 1, $exponentbits);
$fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
@ -500,8 +497,8 @@ class getid3_lib
}
/**
* @param array $array1
* @param array $array2
* @param mixed $array1
* @param mixed $array2
*
* @return array|false
*/
@ -523,8 +520,8 @@ class getid3_lib
}
/**
* @param array $array1
* @param array $array2
* @param mixed $array1
* @param mixed $array2
*
* @return array|false
*/
@ -544,8 +541,8 @@ class getid3_lib
}
/**
* @param array $array1
* @param array $array2
* @param mixed $array1
* @param mixed $array2
*
* @return array|false|null
*/
@ -684,10 +681,10 @@ class getid3_lib
*/
public static function array_max($arraydata, $returnkey=false) {
$maxvalue = false;
$maxkey = false;
$maxkey = false;
foreach ($arraydata as $key => $value) {
if (!is_array($value)) {
if ($value > $maxvalue) {
if (($maxvalue === false) || ($value > $maxvalue)) {
$maxvalue = $value;
$maxkey = $key;
}
@ -704,10 +701,10 @@ class getid3_lib
*/
public static function array_min($arraydata, $returnkey=false) {
$minvalue = false;
$minkey = false;
$minkey = false;
foreach ($arraydata as $key => $value) {
if (!is_array($value)) {
if ($value > $minvalue) {
if (($minvalue === false) || ($value < $minvalue)) {
$minvalue = $value;
$minkey = $key;
}
@ -735,9 +732,9 @@ class getid3_lib
}
/**
* @param SimpleXMLElement|array $XMLobject
* @param SimpleXMLElement|array|mixed $XMLobject
*
* @return array
* @return mixed
*/
public static function SimpleXMLelement2array($XMLobject) {
if (!is_object($XMLobject) && !is_array($XMLobject)) {
@ -1479,6 +1476,15 @@ class getid3_lib
* @return array|false
*/
public static function GetDataImageSize($imgData, &$imageinfo=array()) {
if (PHP_VERSION_ID >= 50400) {
$GetDataImageSize = @getimagesizefromstring($imgData, $imageinfo);
if ($GetDataImageSize === false || !isset($GetDataImageSize[0], $GetDataImageSize[1])) {
return false;
}
$GetDataImageSize['height'] = $GetDataImageSize[0];
$GetDataImageSize['width'] = $GetDataImageSize[1];
return $GetDataImageSize;
}
static $tempdir = '';
if (empty($tempdir)) {
if (function_exists('sys_get_temp_dir')) {
@ -1487,12 +1493,11 @@ class getid3_lib
// yes this is ugly, feel free to suggest a better way
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);
$getid3_temp = new getID3();
if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
$tempdir = $getid3_temp_tempdir;
}
unset($getid3_temp, $getid3_temp_tempdir);
}
}
$GetDataImageSize = false;
@ -1524,13 +1529,20 @@ class getid3_lib
/**
* @param array $ThisFileInfo
* @param bool $option_tags_html default true (just as in the main getID3 class)
*
* @return bool
*/
public static function CopyTagsToComments(&$ThisFileInfo) {
public static function CopyTagsToComments(&$ThisFileInfo, $option_tags_html=true) {
// Copy all entries from ['tags'] into common ['comments']
if (!empty($ThisFileInfo['tags'])) {
if (isset($ThisFileInfo['tags']['id3v1'])) {
// bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings
$ID3v1 = $ThisFileInfo['tags']['id3v1'];
unset($ThisFileInfo['tags']['id3v1']);
$ThisFileInfo['tags']['id3v1'] = $ID3v1;
unset($ID3v1);
}
foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
foreach ($tagarray as $tagname => $tagdata) {
foreach ($tagdata as $key => $value) {
@ -1549,6 +1561,13 @@ class getid3_lib
break 2;
}
}
if (function_exists('mb_convert_encoding')) {
if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) {
// value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1.
// As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character
break 2;
}
}
} elseif (!is_array($value)) {
@ -1557,7 +1576,6 @@ class getid3_lib
$oldvaluelength = strlen(trim($existingvalue));
if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
$ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
//break 2;
break;
}
}
@ -1568,7 +1586,7 @@ class getid3_lib
if (!is_int($key) && !ctype_digit($key)) {
$ThisFileInfo['comments'][$tagname][$key] = $value;
} else {
if (isset($ThisFileInfo['comments'][$tagname])) {
if (!isset($ThisFileInfo['comments'][$tagname])) {
$ThisFileInfo['comments'][$tagname] = array($value);
} else {
$ThisFileInfo['comments'][$tagname][] = $value;
@ -1592,19 +1610,21 @@ class getid3_lib
}
}
// Copy to ['comments_html']
if (!empty($ThisFileInfo['comments'])) {
foreach ($ThisFileInfo['comments'] as $field => $values) {
if ($field == 'picture') {
// pictures can take up a lot of space, and we don't need multiple copies of them
// let there be a single copy in [comments][picture], and not elsewhere
continue;
}
foreach ($values as $index => $value) {
if (is_array($value)) {
$ThisFileInfo['comments_html'][$field][$index] = $value;
} else {
$ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
if ($option_tags_html) {
// Copy ['comments'] to ['comments_html']
if (!empty($ThisFileInfo['comments'])) {
foreach ($ThisFileInfo['comments'] as $field => $values) {
if ($field == 'picture') {
// pictures can take up a lot of space, and we don't need multiple copies of them
// let there be a single copy in [comments][picture], and not elsewhere
continue;
}
foreach ($values as $index => $value) {
if (is_array($value)) {
$ThisFileInfo['comments_html'][$field][$index] = $value;
} else {
$ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
}
}
}
}

169
lib/getid3/getid3.php

@ -99,6 +99,13 @@ class getID3
*/
public $encoding_id3v1 = 'ISO-8859-1';
/**
* ID3v1 should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'Windows-1251' or 'KOI8-R'. If true attempt to detect these encodings, but may return incorrect values for some tags actually in ISO-8859-1 encoding
*
* @var bool
*/
public $encoding_id3v1_autodetect = false;
/*
* Optional tag checks - disable for speed.
*/
@ -250,7 +257,7 @@ class getID3
*/
protected $startup_warning = '';
const VERSION = '1.9.18-201907240906';
const VERSION = '1.9.20-202006061653';
const FREAD_BUFFER_SIZE = 32768;
const ATTACHMENTS_NONE = false;
@ -266,14 +273,16 @@ class getID3
}
// Check memory
$this->memory_limit = ini_get('memory_limit');
if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
$memoryLimit = ini_get('memory_limit');
if (preg_match('#([0-9]+) ?M#i', $memoryLimit, $matches)) {
// could be stored as "16M" rather than 16777216 for example
$this->memory_limit = $matches[1] * 1048576;
} elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
$memoryLimit = $matches[1] * 1048576;
} elseif (preg_match('#([0-9]+) ?G#i', $memoryLimit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
// could be stored as "2G" rather than 2147483648 for example
$this->memory_limit = $matches[1] * 1073741824;
$memoryLimit = $matches[1] * 1073741824;
}
$this->memory_limit = $memoryLimit;
if ($this->memory_limit <= 0) {
// memory limits probably disabled
} elseif ($this->memory_limit <= 4194304) {
@ -287,24 +296,26 @@ class getID3
$this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
}
if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
if (($mbstring_func_overload = (int) 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";
}
// Check for magic_quotes_runtime
if (function_exists('get_magic_quotes_runtime')) {
if (get_magic_quotes_runtime()) {
$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";
// check for magic quotes in PHP < 7.4.0 (when these functions became deprecated)
if (version_compare(PHP_VERSION, '7.4.0', '<')) {
// Check for magic_quotes_runtime
if (function_exists('get_magic_quotes_runtime')) {
if (get_magic_quotes_runtime()) {
$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";
}
}
}
// Check for magic_quotes_gpc
if (function_exists('magic_quotes_gpc')) {
if (get_magic_quotes_gpc()) {
$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";
// Check for magic_quotes_gpc
if (function_exists('get_magic_quotes_gpc')) {
if (get_magic_quotes_gpc()) {
$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";
}
}
}
@ -398,8 +409,9 @@ class getID3
}
/**
* @param string $filename
* @param int $filesize
* @param string $filename
* @param int $filesize
* @param resource $fp
*
* @return bool
*
@ -509,9 +521,10 @@ class getID3
/**
* analyze file
*
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param string $filename
* @param int $filesize
* @param string $original_filename
* @param resource $fp
*
* @return array
*/
@ -840,6 +853,14 @@ class getID3
'mime_type' => 'application/octet-stream',
),
// DSDIFF - audio - Direct Stream Digital Interchange File Format
'dsdiff' => array(
'pattern' => '^FRM8',
'group' => 'audio',
'module' => 'dsdiff',
'mime_type' => 'audio/dsd',
),
// DTS - audio - Dolby Theatre System
'dts' => array(
'pattern' => '^\\x7F\\xFE\\x80\\x01',
@ -967,6 +988,14 @@ class getID3
'fail_ape' => 'ERROR',
),
// TAK - audio - Tom's lossless Audio Kompressor
'tak' => array(
'pattern' => '^tBaK',
'group' => 'audio',
'module' => 'tak',
'mime_type' => 'application/octet-stream',
),
// TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org)
'tta' => array(
'pattern' => '^TTA', // could also be '^TTA(\\x01|\\x02|\\x03|2|1)'
@ -1027,6 +1056,14 @@ class getID3
'mime_type' => 'video/x-flv',
),
// IVF - audio/video - IVF
'ivf' => array(
'pattern' => '^DKIF',
'group' => 'audio-video',
'module' => 'ivf',
'mime_type' => 'video/x-ivf',
),
// MKAV - audio/video - Mastroka
'matroska' => array(
'pattern' => '^\\x1A\\x45\\xDF\\xA3',
@ -1102,6 +1139,14 @@ class getID3
'mime_type' => 'video/MP2T',
),
// WTV - audio/video - Windows Recorded TV Show
'wtv' => array(
'pattern' => '^\\xB7\\xD8\\x00\\x20\\x37\\x49\\xDA\\x11\\xA6\\x4E\\x00\\x07\\xE9\\x5E\\xAD\\x8D',
'group' => 'audio-video',
'module' => 'wtv',
'mime_type' => 'video/x-ms-wtv',
),
// Still-Image formats
@ -1203,12 +1248,22 @@ class getID3
'iconv_req' => false,
),
// HPK - data - HPK compressed data
'hpk' => array(
'pattern' => '^BPUL',
'group' => 'archive',
'module' => 'hpk',
'mime_type' => 'application/octet-stream',
'fail_id3' => 'ERROR',
'fail_ape' => 'ERROR',
),
// RAR - data - RAR compressed data
'rar' => array(
'pattern' => '^Rar\\!',
'group' => 'archive',
'module' => 'rar',
'mime_type' => 'application/octet-stream',
'mime_type' => 'application/vnd.rar',
'fail_id3' => 'ERROR',
'fail_ape' => 'ERROR',
),
@ -1410,6 +1465,7 @@ class getID3
'flac' => array('vorbiscomment' , 'UTF-8'),
'divxtag' => array('divx' , 'ISO-8859-1'),
'iptc' => array('iptc' , 'ISO-8859-1'),
'dsdiff' => array('dsdiff' , 'ISO-8859-1'),
);
}
@ -1511,6 +1567,17 @@ class getID3
return true;
}
/**
* Calls getid3_lib::CopyTagsToComments() but passes in the option_tags_html setting from this instance of getID3
*
* @param array $ThisFileInfo
*
* @return bool
*/
public function CopyTagsToComments(&$ThisFileInfo) {
return getid3_lib::CopyTagsToComments($ThisFileInfo, $this->option_tags_html);
}
/**
* @param string $algorithm
*
@ -1524,7 +1591,6 @@ class getID3
default:
return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()');
break;
}
if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) {
@ -2040,6 +2106,61 @@ abstract class getid3_handler
return fseek($this->getid3->fp, $bytes, $whence);
}
/**
* @return string|false
*
* @throws getid3_exception
*/
protected function fgets() {
// must be able to handle CR/LF/CRLF but not read more than one lineend
$buffer = ''; // final string we will return
$prevchar = ''; // save previously-read character for end-of-line checking
if ($this->data_string_flag) {
while (true) {
$thischar = substr($this->data_string, $this->data_string_position++, 1);
if (($prevchar == "\r") && ($thischar != "\n")) {
// read one byte too many, back up
$this->data_string_position--;
break;
}
$buffer .= $thischar;
if ($thischar == "\n") {
break;
}
if ($this->data_string_position >= $this->data_string_length) {
// EOF
break;
}
$prevchar = $thischar;
}
} else {
// Ideally we would just use PHP's fgets() function, however...
// it does not behave consistently with regards to mixed line endings, may be system-dependent
// and breaks entirely when given a file with mixed \r vs \n vs \r\n line endings (e.g. some PDFs)
//return fgets($this->getid3->fp);
while (true) {
$thischar = fgetc($this->getid3->fp);
if (($prevchar == "\r") && ($thischar != "\n")) {
// read one byte too many, back up
fseek($this->getid3->fp, -1, SEEK_CUR);
break;
}
$buffer .= $thischar;
if ($thischar == "\n") {
break;
}
if (feof($this->getid3->fp)) {
break;
}
$prevchar = $thischar;
}
}
return $buffer;
}
/**
* @return bool
*/

3
lib/getid3/module.archive.gzip.php

@ -19,6 +19,9 @@
// //
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_gzip extends getid3_handler
{

92
lib/getid3/module.archive.hpk.php

@ -0,0 +1,92 @@
<?php
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
// available at https://github.com/JamesHeinrich/getID3 //
// or https://www.getid3.org //
// or http://getid3.sourceforge.net //
// see readme.txt for more details //
/////////////////////////////////////////////////////////////////
// //
// module.archive.hpk.php //
// module for analyzing HPK files //
// dependencies: NONE //
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_hpk extends getid3_handler
{
/**
* @return bool
*/
public function Analyze() {
$info = &$this->getid3->info;
$info['fileformat'] = 'hpk';
$this->fseek($info['avdataoffset']);
$HPKheader = $this->fread(36);
if (substr($HPKheader, 0, 4) == 'BPUL') {
$info['hpk']['header']['signature'] = substr($HPKheader, 0, 4);
$info['hpk']['header']['data_offset'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 4, 4));
$info['hpk']['header']['fragments_per_file'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 8, 4));
//$info['hpk']['header']['unknown1'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 12, 4));
$info['hpk']['header']['fragments_residual_offset'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 16, 4));
$info['hpk']['header']['fragments_residual_count'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 20, 4));
//$info['hpk']['header']['unknown2'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 24, 4));
$info['hpk']['header']['fragmented_filesystem_offset'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 28, 4));
$info['hpk']['header']['fragmented_filesystem_length'] = getid3_lib::LittleEndian2Int(substr($HPKheader, 32, 4));
$info['hpk']['header']['filesystem_entries'] = $info['hpk']['header']['fragmented_filesystem_length'] / ($info['hpk']['header']['fragments_per_file'] * 8);
$this->fseek($info['hpk']['header']['fragmented_filesystem_offset']);
for ($i = 0; $i < $info['hpk']['header']['filesystem_entries']; $i++) {
$offset = getid3_lib::LittleEndian2Int($this->fread(4));
$length = getid3_lib::LittleEndian2Int($this->fread(4));
$info['hpk']['filesystem'][$i] = array('offset' => $offset, 'length' => $length);
}
$this->error('HPK parsing incomplete (and mostly broken) in this version of getID3() ['.$this->getid3->version().']');
/*
$filename = '';
$dirs = array();
foreach ($info['hpk']['filesystem'] as $key => $filesystemdata) {
$this->fseek($filesystemdata['offset']);
$first4 = $this->fread(4);
if (($first4 == 'LZ4 ') || ($first4 == 'ZLIB')) {
// actual data, ignore
$info['hpk']['toc'][$key] = array(
'filename' => ltrim(implode('/', $dirs).'/'.$filename, '/'),
'offset' => $filesystemdata['offset'],
'length' => $filesystemdata['length'],
);
$filename = '';
$dirs = array();
} else {
$fragment_index = getid3_lib::LittleEndian2Int($first4);
$fragment_type = getid3_lib::LittleEndian2Int($this->fread(4)); // file = 0, directory = 1
$name_length = getid3_lib::LittleEndian2Int($this->fread(2));
if ($fragment_type == 1) {
$dirs[] = $this->fread($name_length);
} else {
$filename = $this->fread($name_length);
}
}
}
*/
} else {
$this->error('Expecting "BPUL" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($HPKheader, 0, 4)).'"');
return false;
}
return true;
}
}

3
lib/getid3/module.archive.rar.php

@ -14,6 +14,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_rar extends getid3_handler
{

3
lib/getid3/module.archive.szip.php

@ -14,6 +14,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_szip extends getid3_handler
{

3
lib/getid3/module.archive.tar.php

@ -19,6 +19,9 @@
// //
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_tar extends getid3_handler
{

3
lib/getid3/module.archive.xz.php

@ -14,6 +14,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_xz extends getid3_handler
{

23
lib/getid3/module.archive.zip.php

@ -14,6 +14,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_zip extends getid3_handler
{
@ -92,6 +95,26 @@ class getid3_zip extends getid3_handler
}
}
// check for EPUB files
if (!empty($info['zip']['entries'][0]['filename']) &&
($info['zip']['entries'][0]['filename'] == 'mimetype') &&
($info['zip']['entries'][0]['compression_method'] == 'store') &&
($info['zip']['entries'][0]['uncompressed_size'] == 20) &&
isset($info['zip']['entries'][0]['data_offset'])) {
// http://idpf.org/epub/30/spec/epub30-ocf.html
// "3.3 OCF ZIP Container Media Type Identification
// OCF ZIP Containers must include a mimetype file as the first file in the Container, and the contents of this file must be the MIME type string application/epub+zip.
// The contents of the mimetype file must not contain any leading padding or whitespace, must not begin with the Unicode signature (or Byte Order Mark),
// and the case of the MIME type string must be exactly as presented above. The mimetype file additionally must be neither compressed nor encrypted,
// and there must not be an extra field in its ZIP header."
$this->fseek($info['zip']['entries'][0]['data_offset']);
if ($this->fread(20) == 'application/epub+zip') {
$info['fileformat'] = 'zip.epub';
$info['mime_type'] = 'application/epub+zip';
}
}
// check for Office Open XML files (e.g. .docx, .xlsx)
if (!empty($info['zip']['files']['[Content_Types].xml']) &&
!empty($info['zip']['files']['_rels']['.rels']) &&
!empty($info['zip']['files']['docProps']['app.xml']) &&

7
lib/getid3/module.audio-video.asf.php

@ -13,6 +13,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
class getid3_asf extends getid3_handler
@ -363,7 +366,7 @@ class getid3_asf extends getid3_handler
$thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']);
if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) {
$thisfile_audio['bitrate'] = (int) (trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000);
$thisfile_audio['bitrate'] = (int) trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000;
}
//if (!isset($thisfile_video['bitrate']) && isset($thisfile_audio['bitrate']) && isset($thisfile_asf['file_properties_object']['max_bitrate']) && ($thisfile_asf_codeclistobject['codec_entries_count'] > 1)) {
if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) {
@ -807,7 +810,7 @@ class getid3_asf extends getid3_handler
case 'wm/track':
if (empty($thisfile_asf_comments['track_number'])) {
$thisfile_asf_comments['track_number'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
$thisfile_asf_comments['track_number'] = array(1 + (int) $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
}
break;

9
lib/getid3/module.audio-video.bink.php

@ -13,6 +13,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_bink extends getid3_handler
{
@ -29,20 +32,14 @@ class getid3_bink extends getid3_handler
switch ($fileTypeID) {
case 'BIK':
return $this->ParseBink();
break;
case 'SMK':
return $this->ParseSmacker();
break;
default:
$this->error('Expecting "BIK" or "SMK" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($fileTypeID).'"');
return false;
break;
}
return true;
}
/**

5
lib/getid3/module.audio-video.flv.php

@ -53,6 +53,10 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
define('GETID3_FLV_TAG_AUDIO', 8);
define('GETID3_FLV_TAG_VIDEO', 9);
define('GETID3_FLV_TAG_META', 18);
@ -597,7 +601,6 @@ class AMFReader
// null
case 6:
return null;
break;
// Mixed array
case 8:

80
lib/getid3/module.audio-video.ivf.php

@ -0,0 +1,80 @@
<?php
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
// available at https://github.com/JamesHeinrich/getID3 //
// or https://www.getid3.org //
// or http://getid3.sourceforge.net //
// see readme.txt for more details //
/////////////////////////////////////////////////////////////////
// //
// module.audio.ivf.php //
// module for analyzing IVF audio-video files //
// dependencies: NONE //
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_ivf extends getid3_handler
{
/**
* @return bool
*/
public function Analyze() {
$info = &$this->getid3->info;
$info['fileformat'] = 'ivf';
$info['video']['dataformat'] = 'ivf';
$this->fseek($info['avdataoffset']);
$IVFheader = $this->fread(32);
if (substr($IVFheader, 0, 4) == 'DKIF') {
// https://wiki.multimedia.cx/index.php/IVF
$info['ivf']['header']['signature'] = substr($IVFheader, 0, 4);
$info['ivf']['header']['version'] = getid3_lib::LittleEndian2Int(substr($IVFheader, 4, 2)); // should be 0
$info['ivf']['header']['headersize'] = getid3_lib::LittleEndian2Int(substr($IVFheader, 6, 2));
$info['ivf']['header']['fourcc'] = substr($IVFheader, 8, 4);
$info['ivf']['header']['resolution_x'] = getid3_lib::LittleEndian2Int(substr($IVFheader, 12, 2));
$info['ivf']['header']['resolution_y'] = getid3_lib::LittleEndian2Int(substr($IVFheader, 14, 2));
$info['ivf']['header']['timebase_numerator'] = getid3_lib::LittleEndian2Int(substr($IVFheader, 16, 4));
$info['ivf']['header']['timebase_denominator'] = getid3_lib::LittleEndian2Int(substr($IVFheader, 20, 4));
$info['ivf']['header']['frame_count'] = getid3_lib::LittleEndian2Int(substr($IVFheader, 24, 4));
//$info['ivf']['header']['reserved'] = substr($IVFheader, 28, 4);
$info['ivf']['header']['frame_rate'] = (float) $info['ivf']['header']['timebase_numerator'] / $info['ivf']['header']['timebase_denominator'];
if ($info['ivf']['header']['version'] > 0) {
$this->warning('Expecting IVF header version 0, found version '.$info['ivf']['header']['version'].', results may not be accurate');
}
$info['video']['resolution_x'] = $info['ivf']['header']['resolution_x'];
$info['video']['resolution_y'] = $info['ivf']['header']['resolution_y'];
$info['video']['codec'] = $info['ivf']['header']['fourcc'];
$info['ivf']['frame_count'] = 0;
while (!$this->feof()) {
if ($frameheader = $this->fread(12)) {
$framesize = getid3_lib::LittleEndian2Int(substr($frameheader, 0, 4)); // size of frame in bytes (not including the 12-byte header)
$timestamp = getid3_lib::LittleEndian2Int(substr($frameheader, 4, 8)); // 64-bit presentation timestamp
$this->fseek($framesize, SEEK_CUR);
$info['ivf']['frame_count']++;
}
}
if ($info['ivf']['frame_count']) {
$info['playtime_seconds'] = $timestamp / 100000;
$info['video']['frame_rate'] = (float) $info['ivf']['frame_count'] / $info['playtime_seconds'];
}
} else {
$this->error('Expecting "DKIF" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($IVFheader, 0, 4)).'"');
return false;
}
return true;
}
}

39
lib/getid3/module.audio-video.matroska.php

@ -14,6 +14,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
define('EBML_ID_CHAPTERS', 0x0043A770); // [10][43][A7][70] -- A system to define basic menus and partition data. For more detailed information, look at the Chapters Explanation.
define('EBML_ID_SEEKHEAD', 0x014D9B74); // [11][4D][9B][74] -- Contains the position of other level 1 elements.
@ -329,7 +332,7 @@ class getid3_matroska extends getid3_handler
break;*/
}
$info['video']['streams'][] = $track_info;
$info['video']['streams'][$trackarray['TrackUID']] = $track_info;
break;
case 2: // Audio
@ -362,7 +365,7 @@ class getid3_matroska extends getid3_handler
// create temp instance
$getid3_temp = new getID3();
if ($track_info['dataformat'] != 'flac') {
$getid3_temp->openfile($this->getid3->filename);
$getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
}
$getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
if ($track_info['dataformat'][0] == 'm' || $track_info['dataformat'] == 'flac') {
@ -478,7 +481,7 @@ class getid3_matroska extends getid3_handler
break;
}
$info['audio']['streams'][] = $track_info;
$info['audio']['streams'][$trackarray['TrackUID']] = $track_info;
break;
}
}
@ -509,6 +512,30 @@ class getid3_matroska extends getid3_handler
unset($info['mime_type']);
}
// use _STATISTICS_TAGS if available to set audio/video bitrates
if (!empty($info['matroska']['tags'])) {
$_STATISTICS_byTrackUID = array();
foreach ($info['matroska']['tags'] as $key1 => $value1) {
if (!empty($value1['Targets']['TagTrackUID'][0]) && !empty($value1['SimpleTag'])) {
foreach ($value1['SimpleTag'] as $key2 => $value2) {
if (!empty($value2['TagName']) && isset($value2['TagString'])) {
$_STATISTICS_byTrackUID[$value1['Targets']['TagTrackUID'][0]][$value2['TagName']] = $value2['TagString'];
}
}
}
}
foreach (array('audio','video') as $avtype) {
if (!empty($info[$avtype]['streams'])) {
foreach ($info[$avtype]['streams'] as $trackUID => $trackdata) {
if (!isset($trackdata['bitrate']) && !empty($_STATISTICS_byTrackUID[$trackUID]['BPS'])) {
$info[$avtype]['streams'][$trackUID]['bitrate'] = (int) $_STATISTICS_byTrackUID[$trackUID]['BPS'];
@$info[$avtype]['bitrate'] += $info[$avtype]['streams'][$trackUID]['bitrate'];
}
}
}
}
}
return true;
}
@ -614,8 +641,10 @@ class getid3_matroska extends getid3_handler
while ($this->getEBMLelement($subelement, $track_entry['end'], array(EBML_ID_VIDEO, EBML_ID_AUDIO, EBML_ID_CONTENTENCODINGS, EBML_ID_CODECPRIVATE))) {
switch ($subelement['id']) {
case EBML_ID_TRACKNUMBER:
case EBML_ID_TRACKUID:
$track_entry[$subelement['id_name']] = getid3_lib::PrintHexBytes($subelement['data'], true, false);
break;
case EBML_ID_TRACKNUMBER:
case EBML_ID_TRACKTYPE:
case EBML_ID_MINCACHE:
case EBML_ID_MAXCACHE:
@ -963,7 +992,7 @@ class getid3_matroska extends getid3_handler
case EBML_ID_TAGEDITIONUID:
case EBML_ID_TAGCHAPTERUID:
case EBML_ID_TAGATTACHMENTUID:
$targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
$targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::PrintHexBytes($sub_sub_subelement['data'], true, false);
break;
default:

7
lib/getid3/module.audio-video.mpeg.php

@ -14,6 +14,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
class getid3_mpeg extends getid3_handler
@ -391,7 +394,7 @@ $PackedElementaryStream['additional_header_bytes'] = $additional_header_bytes;
$info['mpeg']['packed_elementary_streams'][$PackedElementaryStream['stream_type']][$PackedElementaryStream['stream_id']][] = $PackedElementaryStream;
*/
$getid3_temp = new getID3();
$getid3_temp->openfile($this->getid3->filename);
$getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_temp->info = $info;
$getid3_mp3 = new getid3_mp3($getid3_temp);
for ($i = 0; $i <= 7; $i++) {
@ -519,7 +522,7 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v
* @param int $bits_to_read
* @param bool $return_singlebit_as_boolean
*
* @return bool|float|int
* @return bool|int
*/
private function readBitsFromStream(&$bitstream, &$bitstreamoffset, $bits_to_read, $return_singlebit_as_boolean=true) {
$return = bindec(substr($bitstream, $bitstreamoffset, $bits_to_read));

4
lib/getid3/module.audio-video.nsv.php

@ -14,6 +14,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
class getid3_nsv extends getid3_handler
{
@ -51,7 +54,6 @@ class getid3_nsv extends getid3_handler
default:
$this->error('Expecting "NSVs" or "NSVf" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($NSVheader).'"');
return false;
break;
}
if (!isset($info['nsv']['NSVf'])) {

310
lib/getid3/module.audio-video.quicktime.php

@ -15,6 +15,9 @@
// ///
/////////////////////////////////////////////////////////////////
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
exit;
}
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); // needed for ISO 639-2 language code lookup
@ -55,23 +58,33 @@ class getid3_quicktime extends getid3_handler
$atomsize = getid3_lib::BigEndian2Int($this->fread(8));
}
$info['quicktime'][$atomname]['name'] = $atomname;
$info['quicktime'][$atomname]['size'] = $atomsize;
$info['quicktime'][$atomname]['offset'] = $offset;
if (($offset + $atomsize) > $info['avdataend']) {
$info['quicktime'][$atomname]['name'] = $atomname;
$info['quicktime'][$atomname]['size'] = $atomsize;
$info['quicktime'][$atomname]['offset'] = $offset;
$this->error('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)');
return false;
}
if ($atomsize == 0) {
// Furthermore, for historical reasons the list of atoms is optionally
// terminated by a 32-bit integer set to 0. If you are writing a program
// to read user data atoms, you should allow for the terminating 0.
$info['quicktime'][$atomname]['name'] = $atomname;
$info['quicktime'][$atomname]['size'] = $atomsize;
$info['quicktime'][$atomname]['offset'] = $offset;
break;
}
$atomHierarchy = array();
$info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
$parsedAtomData = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
$parsedAtomData['name'] = $atomname;
$parsedAtomData['size'] = $atomsize;
$parsedAtomData['offset'] = $offset;
if (in_array($atomname, array('uuid'))) {
@$info['quicktime'][$atomname][] = $parsedAtomData;
} else {
$info['quicktime'][$atomname] = $parsedAtomData;
}
$offset += $atomsize;
$atomcounter++;
@ -112,47 +125,44 @@ class getid3_quicktime extends getid3_handler
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;
$ISO6709parsed = array('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);
$ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * 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);
$ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * 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);
foreach (array('latitude', 'longitude', 'altitude') as $key) {
if ($ISO6709parsed[$key] !== false) {