X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/?a=blobdiff_plain;f=www%2Fplugins-dist%2Fmedias%2Flib%2Fgetid3%2Fgetid3.php;fp=www%2Fplugins-dist%2Fmedias%2Flib%2Fgetid3%2Fgetid3.php;h=90d7c9c2a7a036ed636147364d8f9d8e892c6e12;hb=77a53a65e59f60f4d49b41f1b82d72830ba68987;hp=37bf94437ffc365b3bd3cb05df2a52426f04e213;hpb=9a3d4353e89ac94da6b21cff26e28fa704369cb2;p=lhc%2Fweb%2Fwww.git diff --git a/www/plugins-dist/medias/lib/getid3/getid3.php b/www/plugins-dist/medias/lib/getid3/getid3.php index 37bf9443..90d7c9c2 100644 --- a/www/plugins-dist/medias/lib/getid3/getid3.php +++ b/www/plugins-dist/medias/lib/getid3/getid3.php @@ -1,10 +1,10 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // // // // Please see readme.txt for more information // // /// @@ -26,6 +26,14 @@ if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUB define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8)); } +/* +https://www.getid3.org/phpBB3/viewtopic.php?t=2114 +If you are running into a the problem where filenames with special characters are being handled +incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed, +and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line: +*/ +//setlocale(LC_CTYPE, 'en_US.UTF-8'); + // 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))) { @@ -74,66 +82,196 @@ unset($open_basedir, $temp_dir); class getID3 { - // public: Settings - public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE - public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' - - // public: Optional tag checks - disable for speed. - public $option_tag_id3v1 = true; // Read and process ID3v1 tags - public $option_tag_id3v2 = true; // Read and process ID3v2 tags - public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags - public $option_tag_apetag = true; // Read and process APE tags - public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding - public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities - - // public: Optional tag/comment calucations - public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc - - // public: Optional handling of embedded attachments (e.g. images) - public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility - - // public: Optional calculations - public $option_md5_data = false; // Get MD5 sum of data part - slow - public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG - public $option_sha1_data = false; // Get SHA1 sum of data part - slow - public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX) - - // public: Read buffer size in bytes + /* + * Settings + */ + + /** + * CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE + * + * @var string + */ + public $encoding = 'UTF-8'; + + /** + * Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' + * + * @var string + */ + public $encoding_id3v1 = 'ISO-8859-1'; + + /* + * Optional tag checks - disable for speed. + */ + + /** + * Read and process ID3v1 tags + * + * @var bool + */ + public $option_tag_id3v1 = true; + + /** + * Read and process ID3v2 tags + * + * @var bool + */ + public $option_tag_id3v2 = true; + + /** + * Read and process Lyrics3 tags + * + * @var bool + */ + public $option_tag_lyrics3 = true; + + /** + * Read and process APE tags + * + * @var bool + */ + public $option_tag_apetag = true; + + /** + * Copy tags to root key 'tags' and encode to $this->encoding + * + * @var bool + */ + public $option_tags_process = true; + + /** + * Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities + * + * @var bool + */ + public $option_tags_html = true; + + /* + * Optional tag/comment calculations + */ + + /** + * Calculate additional info such as bitrate, channelmode etc + * + * @var bool + */ + public $option_extra_info = true; + + /* + * Optional handling of embedded attachments (e.g. images) + */ + + /** + * Defaults to true (ATTACHMENTS_INLINE) for backward compatibility + * + * @var bool|string + */ + public $option_save_attachments = true; + + /* + * Optional calculations + */ + + /** + * Get MD5 sum of data part - slow + * + * @var bool + */ + public $option_md5_data = false; + + /** + * Use MD5 of source file if availble - only FLAC and OptimFROG + * + * @var bool + */ + public $option_md5_data_source = false; + + /** + * Get SHA1 sum of data part - slow + * + * @var bool + */ + public $option_sha1_data = false; + + /** + * Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on + * PHP_INT_MAX) + * + * @var bool|null + */ + public $option_max_2gb_check; + + /** + * Read buffer size in bytes + * + * @var int + */ public $option_fread_buffer_size = 32768; // Public variables - public $filename; // Filename of file being analysed. - public $fp; // Filepointer to file being analysed. - public $info; // Result array. + + /** + * Filename of file being analysed. + * + * @var string + */ + public $filename; + + /** + * Filepointer to file being analysed. + * + * @var resource + */ + public $fp; + + /** + * Result array. + * + * @var array + */ + public $info; + + /** + * @var string + */ public $tempdir = GETID3_TEMP_DIR; + + /** + * @var int + */ public $memory_limit = 0; - // Protected variables + /** + * @var string + */ protected $startup_error = ''; + + /** + * @var string + */ protected $startup_warning = ''; - const VERSION = '1.9.14-201703261440'; + const VERSION = '1.9.16-201810171314'; const FREAD_BUFFER_SIZE = 32768; const ATTACHMENTS_NONE = false; const ATTACHMENTS_INLINE = true; - // public: constructor public function __construct() { // Check for PHP version $required_php_version = '5.3.0'; if (version_compare(PHP_VERSION, $required_php_version, '<')) { $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION."\n"; - return false; + return; } // 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; } @@ -226,20 +364,27 @@ class getID3 echo $this->startup_error; throw new getid3_exception($this->startup_error); } - - return true; } + /** + * @return string + */ public function version() { return self::VERSION; } + /** + * @return int + */ public function fread_buffer_size() { return $this->option_fread_buffer_size; } - - // public: setOption + /** + * @param array $optArray + * + * @return bool + */ public function setOption($optArray) { if (!is_array($optArray) || empty($optArray)) { return false; @@ -253,7 +398,14 @@ class getID3 return true; } - + /** + * @param string $filename + * @param int $filesize + * + * @return bool + * + * @throws getid3_exception + */ public function openfile($filename, $filesize=null) { try { if (!empty($this->startup_error)) { @@ -277,10 +429,10 @@ class getID3 } $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); - $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename); + //$filename = preg_replace('#(?fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 + //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see https://www.getid3.org/phpBB3/viewtopic.php?t=1720 if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // great } else { @@ -338,10 +490,10 @@ class getID3 } elseif (getid3_lib::intValueSupported($real_filesize)) { unset($this->info['filesize']); fclose($this->fp); - throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize, 3).'GB, please report to info@getid3.org'); + throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB, please report to info@getid3.org'); } $this->info['filesize'] = $real_filesize; - $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.'); + $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB) and is not properly supported by PHP.'); } } @@ -353,7 +505,15 @@ class getID3 return false; } - // public: analyze file + /** + * analyze file + * + * @param string $filename + * @param int $filesize + * @param string $original_filename + * + * @return array + */ public function analyze($filename, $filesize=null, $original_filename='') { try { if (!$this->openfile($filename, $filesize)) { @@ -504,7 +664,13 @@ class getID3 } - // private: error handling + /** + * Error handling. + * + * @param string $message + * + * @return array + */ public function error($message) { $this->CleanUp(); if (!isset($this->info['error'])) { @@ -515,14 +681,22 @@ class getID3 } - // private: warning handling + /** + * Warning handling. + * + * @param string $message + * + * @return bool + */ public function warning($message) { $this->info['warning'][] = $message; return true; } - // private: CleanUp + /** + * @return bool + */ private function CleanUp() { // remove possible empty keys @@ -569,8 +743,11 @@ class getID3 return true; } - - // return array containing information about all supported formats + /** + * Return array containing information about all supported formats. + * + * @return array + */ public function GetFileFormatArray() { static $format_info = array(); if (empty($format_info)) { @@ -591,7 +768,7 @@ class getID3 'pattern' => '^ADIF', 'group' => 'audio', 'module' => 'aac', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/aac', 'fail_ape' => 'WARNING', ), @@ -609,7 +786,7 @@ class getID3 'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]', 'group' => 'audio', 'module' => 'aac', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/aac', 'fail_ape' => 'WARNING', ), @@ -675,7 +852,7 @@ class getID3 'pattern' => '^fLaC', 'group' => 'audio', 'module' => 'flac', - 'mime_type' => 'audio/x-flac', + 'mime_type' => 'audio/flac', ), // LA - audio - Lossless Audio (LA) @@ -707,7 +884,7 @@ class getID3 '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 @@ -896,7 +1073,7 @@ class getID3 'pattern' => '^(RIFF|SDSS|FORM)', 'group' => 'audio-video', 'module' => 'riff', - 'mime_type' => 'audio/x-wav', + 'mime_type' => 'audio/wav', 'fail_ape' => 'WARNING', ), @@ -1060,7 +1237,7 @@ class getID3 'pattern' => '^\\x1F\\x8B\\x08', 'group' => 'archive', 'module' => 'gzip', - 'mime_type' => 'application/x-gzip', + 'mime_type' => 'application/gzip', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', ), @@ -1122,8 +1299,12 @@ class getID3 return $format_info; } - - + /** + * @param string $filedata + * @param string $filename + * + * @return mixed|false + */ public function GetFileFormat(&$filedata, $filename='') { // this function will determine the format of a file based on usually // the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG, @@ -1161,8 +1342,12 @@ class getID3 return false; } - - // converts array to $encoding charset from $this->encoding + /** + * Converts array to $encoding charset from $this->encoding. + * + * @param array $array + * @param string $encoding + */ public function CharConvert(&$array, $encoding) { // identical encoding - end here @@ -1185,7 +1370,9 @@ class getID3 } } - + /** + * @return bool + */ public function HandleAllTags() { // key name => array (tag name, character encoding) @@ -1308,6 +1495,11 @@ class getID3 return true; } + /** + * @param string $algorithm + * + * @return array|bool + */ public function getHashdata($algorithm) { switch ($algorithm) { case 'md5': @@ -1372,7 +1564,6 @@ class getID3 } else { - $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1'; $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1'; $VorbisCommentError = `$commandline`; @@ -1431,7 +1622,6 @@ class getID3 return true; } - public function ChannelsBitratePlaytimeCalculations() { // set channelmode on audio @@ -1496,7 +1686,9 @@ class getID3 } } - + /** + * @return bool + */ public function CalculateCompressionRatioVideo() { if (empty($this->info['video'])) { return false; @@ -1544,7 +1736,9 @@ class getID3 return true; } - + /** + * @return bool + */ public function CalculateCompressionRatioAudio() { if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) { return false; @@ -1561,11 +1755,13 @@ class getID3 return true; } - + /** + * @return bool + */ public function CalculateReplayGain() { if (isset($this->info['replay_gain'])) { if (!isset($this->info['replay_gain']['reference_volume'])) { - $this->info['replay_gain']['reference_volume'] = (double) 89.0; + $this->info['replay_gain']['reference_volume'] = 89.0; } if (isset($this->info['replay_gain']['track']['adjustment'])) { $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment']; @@ -1584,6 +1780,9 @@ class getID3 return true; } + /** + * @return bool + */ public function ProcessAudioStreams() { if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) { if (!isset($this->info['audio']['streams'])) { @@ -1597,10 +1796,20 @@ class getID3 return true; } + /** + * @return string|bool + */ public function getid3_tempnam() { return tempnam($this->tempdir, 'gI3'); } + /** + * @param string $name + * + * @return bool + * + * @throws getid3_exception + */ public function include_module($name) { //if (!file_exists($this->include_path.'module.'.$name.'.php')) { if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) { @@ -1610,24 +1819,72 @@ class getID3 return true; } + /** + * @param string $filename + * + * @return bool + */ + public static function is_writable ($filename) { + $ret = is_writable($filename); + + if (!$ret) { + $perms = fileperms($filename); + $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002); + } + + return $ret; + } + } -abstract class getid3_handler { +abstract class getid3_handler +{ /** * @var getID3 */ protected $getid3; // pointer - protected $data_string_flag = false; // analyzing filepointer or string - protected $data_string = ''; // string to analyze - protected $data_string_position = 0; // seek position in string - protected $data_string_length = 0; // string length + /** + * Analyzing filepointer or string. + * + * @var bool + */ + protected $data_string_flag = false; - private $dependency_to = null; + /** + * String to analyze. + * + * @var string + */ + protected $data_string = ''; + /** + * Seek position in string. + * + * @var int + */ + protected $data_string_position = 0; + /** + * String length. + * + * @var int + */ + protected $data_string_length = 0; + + /** + * @var string + */ + private $dependency_to; + + /** + * getid3_handler constructor. + * + * @param getID3 $getid3 + * @param string $call_module + */ public function __construct(getID3 $getid3, $call_module=null) { $this->getid3 = $getid3; @@ -1636,12 +1893,18 @@ abstract class getid3_handler { } } - - // Analyze from file pointer + /** + * Analyze from file pointer. + * + * @return bool + */ abstract public function Analyze(); - - // Analyze from string instead + /** + * Analyze from string instead. + * + * @param string $string + */ public function AnalyzeString($string) { // Enter string mode $this->setStringMode($string); @@ -1667,12 +1930,18 @@ abstract class getid3_handler { $this->data_string_flag = false; } + /** + * @param string $string + */ public function setStringMode($string) { $this->data_string_flag = true; $this->data_string = $string; $this->data_string_length = strlen($string); } + /** + * @return int|bool + */ protected function ftell() { if ($this->data_string_flag) { return $this->data_string_position; @@ -1680,6 +1949,13 @@ abstract class getid3_handler { return ftell($this->getid3->fp); } + /** + * @param int $bytes + * + * @return string|false + * + * @throws getid3_exception + */ protected function fread($bytes) { if ($this->data_string_flag) { $this->data_string_position += $bytes; @@ -1692,7 +1968,7 @@ abstract class getid3_handler { //return fread($this->getid3->fp, $bytes); /* - * http://www.getid3.org/phpBB3/viewtopic.php?t=1930 + * https://www.getid3.org/phpBB3/viewtopic.php?t=1930 * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread(). * It seems to assume that fread() would always return as many bytes as were requested. * However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes. @@ -1700,6 +1976,9 @@ abstract class getid3_handler { */ $contents = ''; do { + if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) { + throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') that is more than available PHP memory ('.$this->getid3->memory_limit.')', 10); + } $part = fread($this->getid3->fp, $bytes); $partLength = strlen($part); $bytes -= $partLength; @@ -1708,6 +1987,14 @@ abstract class getid3_handler { return $contents; } + /** + * @param int $bytes + * @param int $whence + * + * @return int + * + * @throws getid3_exception + */ protected function fseek($bytes, $whence=SEEK_SET) { if ($this->data_string_flag) { switch ($whence) { @@ -1738,6 +2025,9 @@ abstract class getid3_handler { return fseek($this->getid3->fp, $bytes, $whence); } + /** + * @return bool + */ protected function feof() { if ($this->data_string_flag) { return $this->data_string_position >= $this->data_string_length; @@ -1745,24 +2035,53 @@ abstract class getid3_handler { return feof($this->getid3->fp); } + /** + * @param string $module + * + * @return bool + */ final protected function isDependencyFor($module) { return $this->dependency_to == $module; } + /** + * @param string $text + * + * @return bool + */ protected function error($text) { $this->getid3->info['error'][] = $text; return false; } + /** + * @param string $text + * + * @return bool + */ protected function warning($text) { return $this->getid3->warning($text); } + /** + * @param string $text + */ protected function notice($text) { // does nothing for now } + /** + * @param string $name + * @param int $offset + * @param int $length + * @param string $image_mime + * + * @return string|null + * + * @throws Exception + * @throws getid3_exception + */ public function saveAttachment($name, $offset, $length, $image_mime=null) { try { @@ -1785,7 +2104,7 @@ abstract class getid3_handler { // 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) : ''); @@ -1816,6 +2135,9 @@ abstract class getid3_handler { // close and remove dest file if created if (isset($fp_dest) && is_resource($fp_dest)) { fclose($fp_dest); + } + + if (isset($dest) && file_exists($dest)) { unlink($dest); }