Reedy has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/392196 )
Change subject: Update james-heinrich/getid3 from v1.9.14 to v1.9.15 ...................................................................... Update james-heinrich/getid3 from v1.9.14 to v1.9.15 https://github.com/JamesHeinrich/getID3/releases/tag/v1.9.15 https://github.com/JamesHeinrich/getID3/compare/v1.9.14...v1.9.15 Change-Id: Ibb06bf575292e8babaf571a357b404741c39595c --- M composer.json M composer.lock M composer/installed.json M james-heinrich/getid3/changelog.txt M james-heinrich/getid3/demos/demo.audioinfo.class.php R james-heinrich/getid3/demos/demo.dirscan.php M james-heinrich/getid3/demos/demo.write.php M james-heinrich/getid3/getid3/extension.cache.mysql.php M james-heinrich/getid3/getid3/extension.cache.mysqli.php M james-heinrich/getid3/getid3/extension.cache.sqlite3.php M james-heinrich/getid3/getid3/getid3.lib.php M james-heinrich/getid3/getid3/getid3.php M james-heinrich/getid3/getid3/module.audio-video.matroska.php M james-heinrich/getid3/getid3/module.audio-video.quicktime.php M james-heinrich/getid3/getid3/module.audio-video.riff.php M james-heinrich/getid3/getid3/module.audio.ac3.php M james-heinrich/getid3/getid3/module.audio.mp3.php M james-heinrich/getid3/getid3/module.graphic.gif.php M james-heinrich/getid3/getid3/module.graphic.png.php M james-heinrich/getid3/getid3/module.tag.apetag.php M james-heinrich/getid3/getid3/module.tag.id3v2.php M james-heinrich/getid3/getid3/write.apetag.php M james-heinrich/getid3/getid3/write.id3v1.php M james-heinrich/getid3/getid3/write.id3v2.php M james-heinrich/getid3/getid3/write.lyrics3.php M james-heinrich/getid3/getid3/write.metaflac.php M james-heinrich/getid3/getid3/write.php M james-heinrich/getid3/getid3/write.real.php M james-heinrich/getid3/getid3/write.vorbiscomment.php R james-heinrich/getid3/licenses/license.gpl-10.txt R james-heinrich/getid3/licenses/license.gpl-20.txt R james-heinrich/getid3/licenses/license.gpl-30.txt R james-heinrich/getid3/licenses/license.lgpl-30.txt R james-heinrich/getid3/licenses/license.mpl-20.txt 34 files changed, 527 insertions(+), 203 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/vendor refs/changes/96/392196/1 diff --git a/composer.json b/composer.json index 1bca234..6e1db15 100644 --- a/composer.json +++ b/composer.json @@ -75,7 +75,7 @@ "firebase/php-jwt": "4.0.0", "jakub-onderka/php-console-color": "0.1", "jakub-onderka/php-console-highlighter": "0.3.2", - "james-heinrich/getid3": "1.9.14", + "james-heinrich/getid3": "1.9.15", "justinrainbow/json-schema": "5.2.6", "liuggio/statsd-php-client": "1.0.18", "mediawiki/at-ease": "1.1.0", diff --git a/composer.lock b/composer.lock index 8e4f42b..a49d0ba 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "95b93c0b05044e2fa80616204cfa4f1a", + "content-hash": "d08dfab3a3b9756fafddd3c479ae0df1", "packages": [ { "name": "composer/semver", @@ -827,16 +827,16 @@ }, { "name": "james-heinrich/getid3", - "version": "v1.9.14", + "version": "v1.9.15", "source": { "type": "git", "url": "https://github.com/JamesHeinrich/getID3.git", - "reference": "30bd11473b0eef6f1b47866ef7ab0a557917fc21" + "reference": "df9b441e547da1018b1be0e239bee095c9962c96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/30bd11473b0eef6f1b47866ef7ab0a557917fc21", - "reference": "30bd11473b0eef6f1b47866ef7ab0a557917fc21", + "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/df9b441e547da1018b1be0e239bee095c9962c96", + "reference": "df9b441e547da1018b1be0e239bee095c9962c96", "shasum": "" }, "require": { @@ -859,7 +859,7 @@ "php", "tags" ], - "time": "2017-03-27T21:12:55+00:00" + "time": "2017-10-26T18:34:37+00:00" }, { "name": "justinrainbow/json-schema", diff --git a/composer/installed.json b/composer/installed.json index a07a7e1..f171bed 100644 --- a/composer/installed.json +++ b/composer/installed.json @@ -1635,44 +1635,6 @@ ] }, { - "name": "james-heinrich/getid3", - "version": "v1.9.14", - "version_normalized": "1.9.14.0", - "source": { - "type": "git", - "url": "https://github.com/JamesHeinrich/getID3.git", - "reference": "30bd11473b0eef6f1b47866ef7ab0a557917fc21" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/30bd11473b0eef6f1b47866ef7ab0a557917fc21", - "reference": "30bd11473b0eef6f1b47866ef7ab0a557917fc21", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2017-03-27T21:12:55+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "getid3/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL" - ], - "description": "PHP script that extracts useful information from popular multimedia file formats", - "homepage": "http://www.getid3.org/", - "keywords": [ - "codecs", - "php", - "tags" - ] - }, - { "name": "symfony/process", "version": "v3.2.6", "version_normalized": "3.2.6.0", @@ -3835,5 +3797,43 @@ "json", "schema" ] + }, + { + "name": "james-heinrich/getid3", + "version": "v1.9.15", + "version_normalized": "1.9.15.0", + "source": { + "type": "git", + "url": "https://github.com/JamesHeinrich/getID3.git", + "reference": "df9b441e547da1018b1be0e239bee095c9962c96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/df9b441e547da1018b1be0e239bee095c9962c96", + "reference": "df9b441e547da1018b1be0e239bee095c9962c96", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2017-10-26T18:34:37+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "getid3/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL" + ], + "description": "PHP script that extracts useful information from popular multimedia file formats", + "homepage": "http://www.getid3.org/", + "keywords": [ + "codecs", + "php", + "tags" + ] } ] diff --git a/james-heinrich/getid3/changelog.txt b/james-heinrich/getid3/changelog.txt index d8c50fc..5ab9d50 100644 --- a/james-heinrich/getid3/changelog.txt +++ b/james-heinrich/getid3/changelog.txt @@ -18,6 +18,21 @@ Version History =============== +1.9.15: [2017-10-26] James Heinrich :: 1.9.15-201709291043 + » (G:108) add basic APNG support + » (G:107) add basic WebP support + * return RIFF.WAV.CART comments in merged comments section + * add support for QuickTime 'loci' chunk + * bugfix: (#2124) support for Quicktime/MP4 "chpl" (CHaPter List) atom + * bugfix: (G:128) undefinied bsmod in module.ac3 + * bugfix: (#2114) possible issue with UTF8 filenames and metaflac + * bugfix: (G:123) remove MySQL engine and collation from create table + * bugfix: (#2066) fix AAC MIME type, remove video key for audio-only files + * bugfix: (G:111) QuickTime stsd number_entries deadlock + * bugfix: (G:110) PHP memory limit with space + * bugfix: (G:109) improved animated GIF support + * bugfix: (#1966) GPS track in QuickTime + 1.9.14: [2017-03-27] James Heinrich » Add experimental support for E-AC3 * bugfix (G:105): RIFF.WAVE.iXML multiple TIMESTAMP_SAMPLE_RATE diff --git a/james-heinrich/getid3/demos/demo.audioinfo.class.php b/james-heinrich/getid3/demos/demo.audioinfo.class.php index dc12a1e..96852a5 100644 --- a/james-heinrich/getid3/demos/demo.audioinfo.class.php +++ b/james-heinrich/getid3/demos/demo.audioinfo.class.php @@ -58,7 +58,7 @@ * Constructor */ - function AudioInfo() { + function __construct() { // Initialize getID3 engine $this->getID3 = new getID3; diff --git a/james-heinrich/getid3/demos/getid3.demo.dirscan.php b/james-heinrich/getid3/demos/demo.dirscan.php similarity index 97% rename from james-heinrich/getid3/demos/getid3.demo.dirscan.php rename to james-heinrich/getid3/demos/demo.dirscan.php index bfb7c9d..c041a6d 100644 --- a/james-heinrich/getid3/demos/getid3.demo.dirscan.php +++ b/james-heinrich/getid3/demos/demo.dirscan.php @@ -6,7 +6,7 @@ // also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////////////////////// /// // -// getid3.dirscan.php - tool for batch media file processing with getID3() // +// demo.dirscan.php - tool for batch media file processing with getID3() // // /// ///////////////////////////////////////////////////////////////////////////////// /// // @@ -19,11 +19,11 @@ * use like so for the default sqlite3 database, which is hidden: * * cd <path you want to start scanning from> -* php <path to getid3 files>/getid3.dirscan.php +* php <path to getid3 files>/demo.dirscan.php * * or * -* php <path to getid3 files>/getid3.dirscan.php <dir to scan> <file ext in csv list> +* php <path to getid3 files>/demo.dirscan.php <dir to scan> <file ext in csv list> * * Supported Cache Types (this extension) * diff --git a/james-heinrich/getid3/demos/demo.write.php b/james-heinrich/getid3/demos/demo.write.php index c15394b..2703b75 100644 --- a/james-heinrich/getid3/demos/demo.write.php +++ b/james-heinrich/getid3/demos/demo.write.php @@ -69,31 +69,23 @@ if (!empty($_FILES['userfile']['tmp_name'])) { if (in_array('id3v2.4', $tagwriter->tagformats) || in_array('id3v2.3', $tagwriter->tagformats) || in_array('id3v2.2', $tagwriter->tagformats)) { if (is_uploaded_file($_FILES['userfile']['tmp_name'])) { - ob_start(); - if ($fd = fopen($_FILES['userfile']['tmp_name'], 'rb')) { - ob_end_clean(); - $APICdata = fread($fd, filesize($_FILES['userfile']['tmp_name'])); - fclose ($fd); + if ($APICdata = file_get_contents($_FILES['userfile']['tmp_name'])) { - list($APIC_width, $APIC_height, $APIC_imageTypeID) = GetImageSize($_FILES['userfile']['tmp_name']); - $imagetypes = array(1=>'gif', 2=>'jpeg', 3=>'png'); - if (isset($imagetypes[$APIC_imageTypeID])) { + if ($exif_imagetype = exif_imagetype($_FILES['userfile']['tmp_name'])) { $TagData['attached_picture'][0]['data'] = $APICdata; $TagData['attached_picture'][0]['picturetypeid'] = $_POST['APICpictureType']; $TagData['attached_picture'][0]['description'] = $_FILES['userfile']['name']; - $TagData['attached_picture'][0]['mime'] = 'image/'.$imagetypes[$APIC_imageTypeID]; + $TagData['attached_picture'][0]['mime'] = image_type_to_mime_type($exif_imagetype), } else { echo '<b>invalid image format (only GIF, JPEG, PNG)</b><br>'; } } else { - $errormessage = ob_get_contents(); - ob_end_clean(); - echo '<b>cannot open '.$_FILES['userfile']['tmp_name'].'</b><br>'; + echo '<b>cannot open '.htmlentities($_FILES['userfile']['tmp_name']).'</b><br>'; } } else { - echo '<b>!is_uploaded_file('.$_FILES['userfile']['tmp_name'].')</b><br>'; + echo '<b>!is_uploaded_file('.htmlentities($_FILES['userfile']['tmp_name']).')</b><br>'; } } else { echo '<b>WARNING:</b> Can only embed images for ID3v2<br>'; @@ -104,10 +96,10 @@ if ($tagwriter->WriteTags()) { echo 'Successfully wrote tags<BR>'; if (!empty($tagwriter->warnings)) { - echo 'There were some warnings:<BLOCKQUOTE STYLE="background-color:#FFCC33; padding: 10px;">'.implode('<br><br>', $tagwriter->warnings).'</BLOCKQUOTE>'; + echo 'There were some warnings:<blockquote style="background-color: #FFCC33; padding: 10px;">'.implode('<br><br>', $tagwriter->warnings).'</div>'; } } else { - echo 'Failed to write tags!<BLOCKQUOTE STYLE="background-color:#FF9999; padding: 10px;">'.implode('<br><br>', $tagwriter->errors).'</BLOCKQUOTE>'; + echo 'Failed to write tags!<div style="background-color: #FF9999; padding: 10px;">'.implode('<br><br>', $tagwriter->errors).'</div>'; } } else { diff --git a/james-heinrich/getid3/getid3/extension.cache.mysql.php b/james-heinrich/getid3/getid3/extension.cache.mysql.php index b572676..305064d 100644 --- a/james-heinrich/getid3/getid3/extension.cache.mysql.php +++ b/james-heinrich/getid3/getid3/extension.cache.mysql.php @@ -183,7 +183,7 @@ $SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\''; $SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\''; $SQLquery .= ', `value` LONGTEXT NOT NULL'; - $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`)) ENGINE=MyISAM CHARACTER SET=latin1 COLLATE=latin1_general_ci'; + $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))'; $this->cursor = mysql_query($SQLquery, $this->connection); echo mysql_error($this->connection); } diff --git a/james-heinrich/getid3/getid3/extension.cache.mysqli.php b/james-heinrich/getid3/getid3/extension.cache.mysqli.php index 3299caa..185e831 100644 --- a/james-heinrich/getid3/getid3/extension.cache.mysqli.php +++ b/james-heinrich/getid3/getid3/extension.cache.mysqli.php @@ -176,7 +176,7 @@ $SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\''; $SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\''; $SQLquery .= ', `value` LONGTEXT NOT NULL'; - $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`)) ENGINE=MyISAM CHARACTER SET=latin1 COLLATE=latin1_general_ci'; + $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))'; $this->cursor = $this->mysqli->query($SQLquery); echo $this->mysqli->error; } diff --git a/james-heinrich/getid3/getid3/extension.cache.sqlite3.php b/james-heinrich/getid3/getid3/extension.cache.sqlite3.php index 58d4dc8..dccd78d 100644 --- a/james-heinrich/getid3/getid3/extension.cache.sqlite3.php +++ b/james-heinrich/getid3/getid3/extension.cache.sqlite3.php @@ -253,7 +253,6 @@ 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) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))"; 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': diff --git a/james-heinrich/getid3/getid3/getid3.lib.php b/james-heinrich/getid3/getid3/getid3.lib.php index 808f592..1931bb3 100644 --- a/james-heinrich/getid3/getid3/getid3.lib.php +++ b/james-heinrich/getid3/getid3/getid3.lib.php @@ -293,6 +293,9 @@ return self::BigEndian2Int(strrev($byteword), false, $signed); } + public static function LittleEndian2Bin($byteword) { + return self::BigEndian2Bin(strrev($byteword)); + } public static function BigEndian2Bin($byteword) { $binvalue = ''; diff --git a/james-heinrich/getid3/getid3/getid3.php b/james-heinrich/getid3/getid3/getid3.php index 37bf944..5b6e953 100644 --- a/james-heinrich/getid3/getid3/getid3.php +++ b/james-heinrich/getid3/getid3/getid3.php @@ -26,6 +26,14 @@ define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8)); } +/* +http://www.getid3.org/phpBB3/viewtopic.php?t=2114 +If you are running into a the problem where filenames with special characters are being handled +incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed, +and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line: +*/ +//setlocale(LC_CTYPE, 'en_US.UTF-8'); + // attempt to define temp dir as something flexible but reliable $temp_dir = ini_get('upload_tmp_dir'); if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) { @@ -112,7 +120,7 @@ protected $startup_error = ''; protected $startup_warning = ''; - const VERSION = '1.9.14-201703261440'; + const VERSION = '1.9.15-201709291043'; const FREAD_BUFFER_SIZE = 32768; const ATTACHMENTS_NONE = false; @@ -130,10 +138,10 @@ // Check memory $this->memory_limit = ini_get('memory_limit'); - if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) { + if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $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 + } elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $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; } @@ -277,7 +285,7 @@ } $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); - $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename); + $filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename); // open local file //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 @@ -591,7 +599,7 @@ 'pattern' => '^ADIF', 'group' => 'audio', 'module' => 'aac', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/aac', 'fail_ape' => 'WARNING', ), @@ -609,7 +617,7 @@ 'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]', 'group' => 'audio', 'module' => 'aac', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/aac', 'fail_ape' => 'WARNING', ), @@ -707,7 +715,7 @@ 'pattern' => '^MAC ', 'group' => 'audio', 'module' => 'monkey', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/x-monkeys-audio', ), // has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available @@ -1372,7 +1380,6 @@ } else { - $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1'; $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1'; $VorbisCommentError = `$commandline`; @@ -1610,6 +1617,17 @@ return true; } + public static function is_writable ($filename) { + $ret = is_writable($filename); + + if (!$ret) { + $perms = fileperms($filename); + $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002); + } + + return $ret; + } + } @@ -1785,7 +1803,7 @@ // set up destination path $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR); - if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory + if (!is_dir($dir) || !getID3::is_writable($dir)) { // check supplied directory throw new Exception('supplied path ('.$dir.') does not exist, or is not writable'); } $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : ''); diff --git a/james-heinrich/getid3/getid3/module.audio-video.matroska.php b/james-heinrich/getid3/getid3/module.audio-video.matroska.php index 825a22e..0852969 100644 --- a/james-heinrich/getid3/getid3/module.audio-video.matroska.php +++ b/james-heinrich/getid3/getid3/module.audio-video.matroska.php @@ -72,7 +72,7 @@ define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file. define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible. define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values: -define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the the data was encrypted with. +define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with. define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents. define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with. define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values: diff --git a/james-heinrich/getid3/getid3/module.audio-video.quicktime.php b/james-heinrich/getid3/getid3/module.audio-video.quicktime.php index 2ae7c74..3651c4f 100644 --- a/james-heinrich/getid3/getid3/module.audio-video.quicktime.php +++ b/james-heinrich/getid3/getid3/module.audio-video.quicktime.php @@ -193,6 +193,9 @@ if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) { $info['video']['dataformat'] = 'quicktime'; } + if (isset($info['video']) && ($info['mime_type'] == 'audio/mp4') && empty($info['video']['resolution_x']) && empty($info['video']['resolution_y'])) { + unset($info['video']); + } return true; } @@ -722,6 +725,20 @@ $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + + // 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 [email protected] referencing bug report #111'); + } + } + $stsdEntriesDataOffset = 8; for ($i = 0; $i < $atom_structure['number_entries']; $i++) { $atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4)); @@ -1570,6 +1587,152 @@ } 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) + $loffset = 0; + $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)); + $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; + + case 'chpl': // CHaPter List + // https://www.adobe.com/content/dam/Adobe/en/devnet/flv/pdfs/video_file_format_spec_v10.pdf + $chpl_version = getid3_lib::BigEndian2Int(substr($atom_data, 4, 1)); // Expected to be 0 + $chpl_flags = getid3_lib::BigEndian2Int(substr($atom_data, 5, 3)); // Reserved, set to 0 + $chpl_count = getid3_lib::BigEndian2Int(substr($atom_data, 8, 1)); + $chpl_offset = 9; + for ($i = 0; $i < $chpl_count; $i++) { + if (($chpl_offset + 9) >= strlen($atom_data)) { + $this->warning('QuickTime chapter '.$i.' extends beyond end of "chpl" atom'); + break; + } + $info['quicktime']['chapters'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 8)) / 10000000; // timestamps are stored as 100-nanosecond units + $chpl_offset += 8; + $chpl_title_size = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 1)); + $chpl_offset += 1; + $info['quicktime']['chapters'][$i]['title'] = substr($atom_data, $chpl_offset, $chpl_title_size); + $chpl_offset += $chpl_title_size; + } + break; + default: $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset); $atom_structure['data'] = $atom_data; @@ -2402,6 +2565,39 @@ return true; } + 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 ''; + } + + } + } + public function NoNullString($nullterminatedstring) { // remove the single null terminator on null terminated strings if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") { diff --git a/james-heinrich/getid3/getid3/module.audio-video.riff.php b/james-heinrich/getid3/getid3/module.audio-video.riff.php index f61f28a..fcf965c 100644 --- a/james-heinrich/getid3/getid3/module.audio-video.riff.php +++ b/james-heinrich/getid3/getid3/module.audio-video.riff.php @@ -357,6 +357,7 @@ } $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024)); $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772))); + $thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772); $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist']; $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title']; @@ -1174,10 +1175,53 @@ 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'; -$this->error('WebP image parsing not supported in this version of getID3()'); + 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; default: diff --git a/james-heinrich/getid3/getid3/module.audio.ac3.php b/james-heinrich/getid3/getid3/module.audio.ac3.php index c370c7f..6834d92 100644 --- a/james-heinrich/getid3/getid3/module.audio.ac3.php +++ b/james-heinrich/getid3/getid3/module.audio.ac3.php @@ -439,7 +439,9 @@ } $info['audio']['bitrate'] = $thisfile_ac3['bitrate']; - $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']); + if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) { + $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']); + } $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']); foreach($ac3_coding_mode as $key => $value) { $thisfile_ac3[$key] = $value; diff --git a/james-heinrich/getid3/getid3/module.audio.mp3.php b/james-heinrich/getid3/getid3/module.audio.mp3.php index ca3ec54..ed2d844 100644 --- a/james-heinrich/getid3/getid3/module.audio.mp3.php +++ b/james-heinrich/getid3/getid3/module.audio.mp3.php @@ -437,18 +437,19 @@ // and $cc... is the audio data $head4 = substr($headerstring, 0, 4); + $head4_key = getid3_lib::PrintHexBytes($head4, true, false, false); static $MPEGaudioHeaderDecodeCache = array(); - if (isset($MPEGaudioHeaderDecodeCache[$head4])) { - $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4]; + if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) { + $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key]; } else { $MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4); - $MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray; + $MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray; } static $MPEGaudioHeaderValidCache = array(); - 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); + 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); } // shortcut @@ -458,7 +459,7 @@ $thisfile_mpeg_audio = &$info['mpeg']['audio']; - if ($MPEGaudioHeaderValidCache[$head4]) { + if ($MPEGaudioHeaderValidCache[$head4_key]) { $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray; } else { $this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset); diff --git a/james-heinrich/getid3/getid3/module.graphic.gif.php b/james-heinrich/getid3/getid3/module.graphic.gif.php index ab7d62a..c73c0ff 100644 --- a/james-heinrich/getid3/getid3/module.graphic.gif.php +++ b/james-heinrich/getid3/getid3/module.graphic.gif.php @@ -14,6 +14,8 @@ // /// ///////////////////////////////////////////////////////////////// +// https://www.w3.org/Graphics/GIF/spec-gif89a.txt +// http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp class getid3_gif extends getid3_handler { @@ -78,91 +80,102 @@ $info['gif']['header']['aspect_ratio'] = ($info['gif']['header']['raw']['aspect_ratio'] + 15) / 64; } -// if ($info['gif']['header']['flags']['global_color_table']) { -// $GIFcolorTable = $this->fread(3 * $info['gif']['header']['global_color_size']); -// $offset = 0; -// for ($i = 0; $i < $info['gif']['header']['global_color_size']; $i++) { -// $red = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1)); -// $green = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1)); -// $blue = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1)); -// $info['gif']['global_color_table'][$i] = (($red << 16) | ($green << 8) | ($blue)); -// } -// } -// -// // Image Descriptor -// while (!feof($this->getid3->fp)) { -// $NextBlockTest = $this->fread(1); -// switch ($NextBlockTest) { -// -// case ',': // ',' - Image separator character -// -// $ImageDescriptorData = $NextBlockTest.$this->fread(9); -// $ImageDescriptor = array(); -// $ImageDescriptor['image_left'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 1, 2)); -// $ImageDescriptor['image_top'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 3, 2)); -// $ImageDescriptor['image_width'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 5, 2)); -// $ImageDescriptor['image_height'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 7, 2)); -// $ImageDescriptor['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 9, 1)); -// $ImageDescriptor['flags']['use_local_color_map'] = (bool) ($ImageDescriptor['flags_raw'] & 0x80); -// $ImageDescriptor['flags']['image_interlaced'] = (bool) ($ImageDescriptor['flags_raw'] & 0x40); -// $info['gif']['image_descriptor'][] = $ImageDescriptor; -// -// if ($ImageDescriptor['flags']['use_local_color_map']) { -// -// $this->warning('This version of getID3() cannot parse local color maps for GIFs'); -// return true; -// -// } -//echo 'Start of raster data: '.$this->ftell().'<BR>'; -// $RasterData = array(); -// $RasterData['code_size'] = getid3_lib::LittleEndian2Int($this->fread(1)); -// $RasterData['block_byte_count'] = getid3_lib::LittleEndian2Int($this->fread(1)); -// $info['gif']['raster_data'][count($info['gif']['image_descriptor']) - 1] = $RasterData; -// -// $CurrentCodeSize = $RasterData['code_size'] + 1; -// for ($i = 0; $i < pow(2, $RasterData['code_size']); $i++) { -// $DefaultDataLookupTable[$i] = chr($i); -// } -// $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 0] = ''; // Clear Code -// $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 1] = ''; // End Of Image Code -// -// -// $NextValue = $this->GetLSBits($CurrentCodeSize); -// echo 'Clear Code: '.$NextValue.'<BR>'; -// -// $NextValue = $this->GetLSBits($CurrentCodeSize); -// echo 'First Color: '.$NextValue.'<BR>'; -// -// $Prefix = $NextValue; -//$i = 0; -// while ($i++ < 20) { -// $NextValue = $this->GetLSBits($CurrentCodeSize); -// echo $NextValue.'<BR>'; -// } -//return true; -// break; -// -// case '!': -// // GIF Extension Block -// $ExtensionBlockData = $NextBlockTest.$this->fread(2); -// $ExtensionBlock = array(); -// $ExtensionBlock['function_code'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 1, 1)); -// $ExtensionBlock['byte_length'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 2, 1)); -// $ExtensionBlock['data'] = $this->fread($ExtensionBlock['byte_length']); -// $info['gif']['extension_blocks'][] = $ExtensionBlock; -// break; -// -// case ';': -// $info['gif']['terminator_offset'] = $this->ftell() - 1; -// // GIF Terminator -// break; -// -// default: -// break; -// -// -// } -// } + if ($info['gif']['header']['flags']['global_color_table']) { + $GIFcolorTable = $this->fread(3 * $info['gif']['header']['global_color_size']); + $offset = 0; + for ($i = 0; $i < $info['gif']['header']['global_color_size']; $i++) { + $red = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1)); + $green = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1)); + $blue = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1)); + $info['gif']['global_color_table'][$i] = (($red << 16) | ($green << 8) | ($blue)); + } + } + + // Image Descriptor + while (!feof($this->getid3->fp)) { + $NextBlockTest = $this->fread(1); + switch ($NextBlockTest) { + +/* + case ',': // ',' - Image separator character + $ImageDescriptorData = $NextBlockTest.$this->fread(9); + $ImageDescriptor = array(); + $ImageDescriptor['image_left'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 1, 2)); + $ImageDescriptor['image_top'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 3, 2)); + $ImageDescriptor['image_width'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 5, 2)); + $ImageDescriptor['image_height'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 7, 2)); + $ImageDescriptor['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 9, 1)); + $ImageDescriptor['flags']['use_local_color_map'] = (bool) ($ImageDescriptor['flags_raw'] & 0x80); + $ImageDescriptor['flags']['image_interlaced'] = (bool) ($ImageDescriptor['flags_raw'] & 0x40); + $info['gif']['image_descriptor'][] = $ImageDescriptor; + + if ($ImageDescriptor['flags']['use_local_color_map']) { + + $this->warning('This version of getID3() cannot parse local color maps for GIFs'); + return true; + + } + $RasterData = array(); + $RasterData['code_size'] = getid3_lib::LittleEndian2Int($this->fread(1)); + $RasterData['block_byte_count'] = getid3_lib::LittleEndian2Int($this->fread(1)); + $info['gif']['raster_data'][count($info['gif']['image_descriptor']) - 1] = $RasterData; + + $CurrentCodeSize = $RasterData['code_size'] + 1; + for ($i = 0; $i < pow(2, $RasterData['code_size']); $i++) { + $DefaultDataLookupTable[$i] = chr($i); + } + $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 0] = ''; // Clear Code + $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 1] = ''; // End Of Image Code + + $NextValue = $this->GetLSBits($CurrentCodeSize); + echo 'Clear Code: '.$NextValue.'<BR>'; + + $NextValue = $this->GetLSBits($CurrentCodeSize); + echo 'First Color: '.$NextValue.'<BR>'; + + $Prefix = $NextValue; + $i = 0; + while ($i++ < 20) { + $NextValue = $this->GetLSBits($CurrentCodeSize); + echo $NextValue.'<br>'; + } + echo 'escaping<br>'; + return true; + break; +*/ + + case '!': + // GIF Extension Block + $ExtensionBlockData = $NextBlockTest.$this->fread(2); + $ExtensionBlock = array(); + $ExtensionBlock['function_code'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 1, 1)); + $ExtensionBlock['byte_length'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 2, 1)); + $ExtensionBlock['data'] = (($ExtensionBlock['byte_length'] > 0) ? $this->fread($ExtensionBlock['byte_length']) : null); + + if (substr($ExtensionBlock['data'], 0, 11) == 'NETSCAPE2.0') { // Netscape Application Block (NAB) + $ExtensionBlock['data'] .= $this->fread(4); + if (substr($ExtensionBlock['data'], 11, 2) == "\x03\x01") { + $info['gif']['animation']['animated'] = true; + $info['gif']['animation']['loop_count'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlock['data'], 13, 2)); + } else { + $this->warning('Expecting 03 01 at offset '.($this->ftell() - 4).', found "'.getid3_lib::PrintHexBytes(substr($ExtensionBlock['data'], 11, 2)).'"'); + } + } + + $info['gif']['extension_blocks'][] = $ExtensionBlock; + break; + + case ';': + $info['gif']['terminator_offset'] = $this->ftell() - 1; + // GIF Terminator + break; + + default: + break; + + + } + } return true; } diff --git a/james-heinrich/getid3/getid3/module.graphic.png.php b/james-heinrich/getid3/getid3/module.graphic.png.php index c30caa4..365d0d4 100644 --- a/james-heinrich/getid3/getid3/module.graphic.png.php +++ b/james-heinrich/getid3/getid3/module.graphic.png.php @@ -434,11 +434,46 @@ $thisfile_png_chunk_type_text[$idatinformationfieldindex]['header'] = $chunk; break; - case 'IEND': // Image Trailer $thisfile_png_chunk_type_text['header'] = $chunk; break; + case 'acTL': // Animation Control chunk + // https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk + $thisfile_png['animation']['num_frames'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); // Number of frames + $thisfile_png['animation']['num_plays'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); // Number of times to loop this APNG. 0 indicates infinite looping. + + unset($chunk['data']); + $thisfile_png_chunk_type_text['header'] = $chunk; + break; + + case 'fcTL': // Frame Control chunk + // https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk + $fcTL = array(); + $fcTL['sequence_number'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); // Sequence number of the animation chunk, starting from 0 + $fcTL['width'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); // Width of the following frame + $fcTL['height'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 4)); // Height of the following frame + $fcTL['x_offset'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 4)); // X position at which to render the following frame + $fcTL['y_offset'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 16, 4)); // Y position at which to render the following frame + $fcTL['delay_num'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 20, 2)); // Frame delay fraction numerator + $fcTL['delay_den'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 22, 2)); // Frame delay fraction numerator + $fcTL['dispose_op'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 23, 1)); // Type of frame area disposal to be done after rendering this frame + $fcTL['blend_op'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 23, 1)); // Type of frame area rendering for this frame + if ($fcTL['delay_den']) { + $fcTL['delay'] = $fcTL['delay_num'] / $fcTL['delay_den']; + } + $thisfile_png['animation']['fcTL'][$fcTL['sequence_number']] = $fcTL; + + unset($chunk['data']); + $thisfile_png_chunk_type_text['header'] = $chunk; + break; + + case 'fdAT': // Frame Data chunk + // https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk + // "The `fdAT` chunk has the same purpose as an `IDAT` chunk. It has the same structure as an `IDAT` chunk, except preceded by a sequence number." + unset($chunk['data']); + $thisfile_png_chunk_type_text['header'] = $chunk; + break; default: //unset($chunk['data']); @@ -447,7 +482,13 @@ break; } } - + if (!empty($thisfile_png['animation']['num_frames']) && !empty($thisfile_png['animation']['fcTL'])) { + $info['video']['dataformat'] = 'apng'; + $info['playtime_seconds'] = 0; + foreach ($thisfile_png['animation']['fcTL'] as $seqno => $fcTL) { + $info['playtime_seconds'] += $fcTL['delay']; + } + } return true; } diff --git a/james-heinrich/getid3/getid3/module.tag.apetag.php b/james-heinrich/getid3/getid3/module.tag.apetag.php index 938625a..eb081b4 100644 --- a/james-heinrich/getid3/getid3/module.tag.apetag.php +++ b/james-heinrich/getid3/getid3/module.tag.apetag.php @@ -286,7 +286,7 @@ } } elseif (is_string($this->inline_attachments)) { $this->inline_attachments = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->inline_attachments), DIRECTORY_SEPARATOR); - if (!is_dir($this->inline_attachments) || !is_writable($this->inline_attachments)) { + if (!is_dir($this->inline_attachments) || !getID3::is_writable($this->inline_attachments)) { // cannot write, skip $this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)'); unset($thisfile_ape_items_current['data']); @@ -296,7 +296,7 @@ // if we get this far, must be OK if (is_string($this->inline_attachments)) { $destination_filename = $this->inline_attachments.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$thisfile_ape_items_current['data_offset']; - if (!file_exists($destination_filename) || is_writable($destination_filename)) { + if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) { file_put_contents($destination_filename, $thisfile_ape_items_current['data']); } else { $this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)'); diff --git a/james-heinrich/getid3/getid3/module.tag.id3v2.php b/james-heinrich/getid3/getid3/module.tag.id3v2.php index 829f5ee..139238a 100644 --- a/james-heinrich/getid3/getid3/module.tag.id3v2.php +++ b/james-heinrich/getid3/getid3/module.tag.id3v2.php @@ -774,10 +774,10 @@ $parsedFrame['encodingid'] = $frame_textencoding; $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); - $parsedFrame['url'] = $frame_urldata; - $parsedFrame['description'] = $frame_description; + $parsedFrame['url'] = $frame_urldata; // always ISO-8859-1 + $parsedFrame['description'] = $frame_description; // according to the frame text encoding if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) { - $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']); + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']); } unset($parsedFrame['data']); @@ -789,9 +789,9 @@ // described in 4.3.2.> // URL <text string> - $parsedFrame['url'] = trim($parsedFrame['data']); + $parsedFrame['url'] = trim($parsedFrame['data']); // always ISO-8859-1 if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) { - $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url']; + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']); } unset($parsedFrame['data']); @@ -1459,7 +1459,7 @@ */ } elseif (is_string($this->getid3->option_save_attachments)) { $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR); - if (!is_dir($dir) || !is_writable($dir)) { + if (!is_dir($dir) || !getID3::is_writable($dir)) { // cannot write, skip $this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)'); unset($parsedFrame['data']); @@ -1469,7 +1469,7 @@ // if we get this far, must be OK if (is_string($this->getid3->option_save_attachments)) { $destination_filename = $dir.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$frame_offset; - if (!file_exists($destination_filename) || is_writable($destination_filename)) { + if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) { file_put_contents($destination_filename, $parsedFrame['data']); } else { $this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)'); diff --git a/james-heinrich/getid3/getid3/write.apetag.php b/james-heinrich/getid3/getid3/write.apetag.php index d6044b2..6daaf3a 100644 --- a/james-heinrich/getid3/getid3/write.apetag.php +++ b/james-heinrich/getid3/getid3/write.apetag.php @@ -57,7 +57,7 @@ } if ($APEtag = $this->GenerateAPEtag()) { - if (is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { $oldignoreuserabort = ignore_user_abort(true); flock($fp, LOCK_EX); @@ -96,7 +96,7 @@ $getID3 = new getID3; $ThisFileInfo = $getID3->analyze($this->filename); if (isset($ThisFileInfo['ape']['tag_offset_start']) && isset($ThisFileInfo['ape']['tag_offset_end'])) { - if (is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { flock($fp, LOCK_EX); $oldignoreuserabort = ignore_user_abort(true); diff --git a/james-heinrich/getid3/getid3/write.id3v1.php b/james-heinrich/getid3/getid3/write.id3v1.php index 4fa6a6c..387abe7 100644 --- a/james-heinrich/getid3/getid3/write.id3v1.php +++ b/james-heinrich/getid3/getid3/write.id3v1.php @@ -30,7 +30,7 @@ public function WriteID3v1() { // File MUST be writeable - CHMOD(646) at least - if (!empty($this->filename) && is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename)) { + if (!empty($this->filename) && is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename)) { $this->setRealFileSize(); if (($this->filesize <= 0) || !getid3_lib::intValueSupported($this->filesize)) { $this->errors[] = 'Unable to WriteID3v1('.$this->filename.') because filesize ('.$this->filesize.') is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; @@ -90,7 +90,7 @@ public function RemoveID3v1() { // File MUST be writeable - CHMOD(646) at least - if (!empty($this->filename) && is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename)) { + if (!empty($this->filename) && is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename)) { $this->setRealFileSize(); if (($this->filesize <= 0) || !getid3_lib::intValueSupported($this->filesize)) { $this->errors[] = 'Unable to RemoveID3v1('.$this->filename.') because filesize ('.$this->filesize.') is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; diff --git a/james-heinrich/getid3/getid3/write.id3v2.php b/james-heinrich/getid3/getid3/write.id3v2.php index 17138db..cc5c8a1 100644 --- a/james-heinrich/getid3/getid3/write.id3v2.php +++ b/james-heinrich/getid3/getid3/write.id3v2.php @@ -38,7 +38,7 @@ // File MUST be writeable - CHMOD(646) at least. It's best if the // directory is also writeable, because that method is both faster and less susceptible to errors. - if (!empty($this->filename) && (is_writeable($this->filename) || (!file_exists($this->filename) && is_writeable(dirname($this->filename))))) { + if (!empty($this->filename) && (getID3::is_writable($this->filename) || (!file_exists($this->filename) && getID3::is_writable(dirname($this->filename))))) { // Initialize getID3 engine $getID3 = new getID3; $OldThisFileInfo = $getID3->analyze($this->filename); @@ -57,12 +57,12 @@ if ($NewID3v2Tag = $this->GenerateID3v2Tag()) { - if (file_exists($this->filename) && is_writeable($this->filename) && isset($OldThisFileInfo['id3v2']['headerlength']) && ($OldThisFileInfo['id3v2']['headerlength'] == strlen($NewID3v2Tag))) { + if (file_exists($this->filename) && getID3::is_writable($this->filename) && isset($OldThisFileInfo['id3v2']['headerlength']) && ($OldThisFileInfo['id3v2']['headerlength'] == strlen($NewID3v2Tag))) { // best and fastest method - insert-overwrite existing tag (padded to length of old tag if neccesary) if (file_exists($this->filename)) { - if (is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'r+b'))) { + if (is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'r+b'))) { rewind($fp); fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag)); fclose($fp); @@ -72,7 +72,7 @@ } else { - if (is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'wb'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'wb'))) { rewind($fp); fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag)); fclose($fp); @@ -86,7 +86,7 @@ if ($tempfilename = tempnam(GETID3_TEMP_DIR, 'getID3')) { if (is_readable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'rb'))) { - if (is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { + if (getID3::is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { fwrite($fp_temp, $NewID3v2Tag, strlen($NewID3v2Tag)); @@ -137,7 +137,7 @@ public function RemoveID3v2() { // File MUST be writeable - CHMOD(646) at least. It's best if the // directory is also writeable, because that method is both faster and less susceptible to errors. - if (is_writeable(dirname($this->filename))) { + if (getID3::is_writable(dirname($this->filename))) { // preferred method - only one copying operation, minimal chance of corrupting // original file if script is interrupted, but required directory to be writeable @@ -155,7 +155,7 @@ if ($OldThisFileInfo['avdataoffset'] !== false) { fseek($fp_source, $OldThisFileInfo['avdataoffset']); } - if (is_writable($this->filename) && is_file($this->filename) && ($fp_temp = fopen($this->filename.'getid3tmp', 'w+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_temp = fopen($this->filename.'getid3tmp', 'w+b'))) { while ($buffer = fread($fp_source, $this->fread_buffer_size)) { fwrite($fp_temp, $buffer, strlen($buffer)); } @@ -172,7 +172,7 @@ } rename($this->filename.'getid3tmp', $this->filename); - } elseif (is_writable($this->filename)) { + } elseif (getID3::is_writable($this->filename)) { // less desirable alternate method - double-copies the file, overwrites original file // and could corrupt source file if the script is interrupted or an error occurs. @@ -195,7 +195,7 @@ fwrite($fp_temp, $buffer, strlen($buffer)); } fclose($fp_source); - if (is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'wb'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'wb'))) { rewind($fp_temp); while ($buffer = fread($fp_temp, $this->fread_buffer_size)) { fwrite($fp_source, $buffer, strlen($buffer)); diff --git a/james-heinrich/getid3/getid3/write.lyrics3.php b/james-heinrich/getid3/getid3/write.lyrics3.php index 12275f4..06fc943 100644 --- a/james-heinrich/getid3/getid3/write.lyrics3.php +++ b/james-heinrich/getid3/getid3/write.lyrics3.php @@ -36,7 +36,7 @@ $getID3 = new getID3; $ThisFileInfo = $getID3->analyze($this->filename); if (isset($ThisFileInfo['lyrics3']['tag_offset_start']) && isset($ThisFileInfo['lyrics3']['tag_offset_end'])) { - if (is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { + if (is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { flock($fp, LOCK_EX); $oldignoreuserabort = ignore_user_abort(true); diff --git a/james-heinrich/getid3/getid3/write.metaflac.php b/james-heinrich/getid3/getid3/write.metaflac.php index 186e2c1..8c2b75d 100644 --- a/james-heinrich/getid3/getid3/write.metaflac.php +++ b/james-heinrich/getid3/getid3/write.metaflac.php @@ -36,7 +36,7 @@ // Create file with new comments $tempcommentsfilename = tempnam(GETID3_TEMP_DIR, 'getID3'); - if (is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { + if (getID3::is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { foreach ($this->tag_data as $key => $value) { foreach ($value as $commentdata) { fwrite($fpcomments, $this->CleanmetaflacName($key).'='.$commentdata."\n"); diff --git a/james-heinrich/getid3/getid3/write.php b/james-heinrich/getid3/getid3/write.php index d441654..4f2d851 100644 --- a/james-heinrich/getid3/getid3/write.php +++ b/james-heinrich/getid3/getid3/write.php @@ -414,7 +414,7 @@ if ($this->overwrite_tags) { // do nothing - ignore previous data } else { -throw new Exception('$this->overwrite_tags=false is known to be buggy in this version of getID3. Will be fixed in the near future, check www.getid3.org for a newer version.'); +throw new Exception('$this->overwrite_tags=false is known to be buggy in this version of getID3. Check http://github.com/JamesHeinrich/getID3 for a newer version.'); if (!isset($this->ThisFileInfo['tags'][$TagFormat])) { return false; } diff --git a/james-heinrich/getid3/getid3/write.real.php b/james-heinrich/getid3/getid3/write.real.php index fd67c85..7f91165 100644 --- a/james-heinrich/getid3/getid3/write.real.php +++ b/james-heinrich/getid3/getid3/write.real.php @@ -29,7 +29,7 @@ public function WriteReal() { // File MUST be writeable - CHMOD(646) at least - if (is_writeable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { // Initialize getID3 engine $getID3 = new getID3; @@ -94,7 +94,7 @@ $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; } if ($tempfilename = tempnam(GETID3_TEMP_DIR, 'getID3')) { - if (is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { + if (getID3::is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { rewind($fp_source); fwrite($fp_temp, fread($fp_source, $BeforeOffset)); @@ -213,7 +213,7 @@ public function RemoveReal() { // File MUST be writeable - CHMOD(646) at least - if (is_writeable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { // Initialize getID3 engine $getID3 = new getID3; @@ -242,7 +242,7 @@ $BeforeOffset = $oldChunkInfo['CONT']['offset']; $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; if ($tempfilename = tempnam(GETID3_TEMP_DIR, 'getID3')) { - if (is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { + if (getID3::is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { rewind($fp_source); fwrite($fp_temp, fread($fp_source, $BeforeOffset)); diff --git a/james-heinrich/getid3/getid3/write.vorbiscomment.php b/james-heinrich/getid3/getid3/write.vorbiscomment.php index 971f91f..3f427ef 100644 --- a/james-heinrich/getid3/getid3/write.vorbiscomment.php +++ b/james-heinrich/getid3/getid3/write.vorbiscomment.php @@ -36,7 +36,7 @@ // Create file with new comments $tempcommentsfilename = tempnam(GETID3_TEMP_DIR, 'getID3'); - if (is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { + if (getID3::is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { foreach ($this->tag_data as $key => $value) { foreach ($value as $commentdata) { diff --git a/james-heinrich/getid3/licenses/licence.gpl-10.txt b/james-heinrich/getid3/licenses/license.gpl-10.txt similarity index 100% rename from james-heinrich/getid3/licenses/licence.gpl-10.txt rename to james-heinrich/getid3/licenses/license.gpl-10.txt diff --git a/james-heinrich/getid3/licenses/licence.gpl-20.txt b/james-heinrich/getid3/licenses/license.gpl-20.txt similarity index 100% rename from james-heinrich/getid3/licenses/licence.gpl-20.txt rename to james-heinrich/getid3/licenses/license.gpl-20.txt diff --git a/james-heinrich/getid3/licenses/licence.gpl-30.txt b/james-heinrich/getid3/licenses/license.gpl-30.txt similarity index 100% rename from james-heinrich/getid3/licenses/licence.gpl-30.txt rename to james-heinrich/getid3/licenses/license.gpl-30.txt diff --git a/james-heinrich/getid3/licenses/licence.lgpl-30.txt b/james-heinrich/getid3/licenses/license.lgpl-30.txt similarity index 100% rename from james-heinrich/getid3/licenses/licence.lgpl-30.txt rename to james-heinrich/getid3/licenses/license.lgpl-30.txt diff --git a/james-heinrich/getid3/licenses/licence.mpl-20.txt b/james-heinrich/getid3/licenses/license.mpl-20.txt similarity index 100% rename from james-heinrich/getid3/licenses/licence.mpl-20.txt rename to james-heinrich/getid3/licenses/license.mpl-20.txt -- To view, visit https://gerrit.wikimedia.org/r/392196 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ibb06bf575292e8babaf571a357b404741c39595c Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/vendor Gerrit-Branch: master Gerrit-Owner: Reedy <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
