wp/wp-includes/ID3/getid3.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     1 <?php
     1 <?php
     2 /////////////////////////////////////////////////////////////////
     2 /////////////////////////////////////////////////////////////////
     3 /// getID3() by James Heinrich <info@getid3.org>               //
     3 /// getID3() by James Heinrich <info@getid3.org>               //
     4 //  available at http://getid3.sourceforge.net                 //
     4 //  available at http://getid3.sourceforge.net                 //
     5 //            or http://www.getid3.org                         //
     5 //            or http://www.getid3.org                         //
       
     6 //          also https://github.com/JamesHeinrich/getID3       //
     6 /////////////////////////////////////////////////////////////////
     7 /////////////////////////////////////////////////////////////////
     7 //                                                             //
     8 //                                                             //
     8 // Please see readme.txt for more information                  //
     9 // Please see readme.txt for more information                  //
     9 //                                                            ///
    10 //                                                            ///
    10 /////////////////////////////////////////////////////////////////
    11 /////////////////////////////////////////////////////////////////
    15 }
    16 }
    16 // Get base path of getID3() - ONCE
    17 // Get base path of getID3() - ONCE
    17 if (!defined('GETID3_INCLUDEPATH')) {
    18 if (!defined('GETID3_INCLUDEPATH')) {
    18 	define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
    19 	define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
    19 }
    20 }
       
    21 // Workaround Bug #39923 (https://bugs.php.net/bug.php?id=39923)
       
    22 if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) {
       
    23 	define('IMG_JPG', IMAGETYPE_JPEG);
       
    24 }
    20 
    25 
    21 // attempt to define temp dir as something flexible but reliable
    26 // attempt to define temp dir as something flexible but reliable
    22 $temp_dir = ini_get('upload_tmp_dir');
    27 $temp_dir = ini_get('upload_tmp_dir');
    23 if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) {
    28 if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) {
    24 	$temp_dir = '';
    29 	$temp_dir = '';
    25 }
    30 }
    26 if (!$temp_dir && function_exists('sys_get_temp_dir')) {
    31 if (!$temp_dir) {
    27 	// PHP v5.2.1+
       
    28 	// sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts
    32 	// sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts
    29 	$temp_dir = sys_get_temp_dir();
    33 	$temp_dir = sys_get_temp_dir();
    30 }
    34 }
    31 $temp_dir = realpath($temp_dir);
    35 $temp_dir = @realpath($temp_dir); // see https://github.com/JamesHeinrich/getID3/pull/10
    32 $open_basedir = ini_get('open_basedir');
    36 $open_basedir = ini_get('open_basedir');
    33 if ($open_basedir) {
    37 if ($open_basedir) {
    34 	// e.g. "/var/www/vhosts/getid3.org/httpdocs/:/tmp/"
    38 	// e.g. "/var/www/vhosts/getid3.org/httpdocs/:/tmp/"
    35 	$temp_dir     = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $temp_dir);
    39 	$temp_dir     = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $temp_dir);
    36 	$open_basedir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $open_basedir);
    40 	$open_basedir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $open_basedir);
    55 }
    59 }
    56 if (!$temp_dir) {
    60 if (!$temp_dir) {
    57 	$temp_dir = '*'; // invalid directory name should force tempnam() to use system default temp dir
    61 	$temp_dir = '*'; // invalid directory name should force tempnam() to use system default temp dir
    58 }
    62 }
    59 // $temp_dir = '/something/else/';  // feel free to override temp dir here if it works better for your system
    63 // $temp_dir = '/something/else/';  // feel free to override temp dir here if it works better for your system
    60 define('GETID3_TEMP_DIR', $temp_dir);
    64 if (!defined('GETID3_TEMP_DIR')) {
       
    65 	define('GETID3_TEMP_DIR', $temp_dir);
       
    66 }
    61 unset($open_basedir, $temp_dir);
    67 unset($open_basedir, $temp_dir);
    62 
    68 
    63 // End: Defines
    69 // End: Defines
    64 
    70 
    65 
    71 
    95 	// Public variables
   101 	// Public variables
    96 	public $filename;                         // Filename of file being analysed.
   102 	public $filename;                         // Filename of file being analysed.
    97 	public $fp;                               // Filepointer to file being analysed.
   103 	public $fp;                               // Filepointer to file being analysed.
    98 	public $info;                             // Result array.
   104 	public $info;                             // Result array.
    99 	public $tempdir = GETID3_TEMP_DIR;
   105 	public $tempdir = GETID3_TEMP_DIR;
       
   106 	public $memory_limit = 0;
   100 
   107 
   101 	// Protected variables
   108 	// Protected variables
   102 	protected $startup_error   = '';
   109 	protected $startup_error   = '';
   103 	protected $startup_warning = '';
   110 	protected $startup_warning = '';
   104 	protected $memory_limit    = 0;
   111 
   105 
   112 	const VERSION           = '1.9.8-20140511';
   106 	const VERSION           = '1.9.7-20130705';
       
   107 	const FREAD_BUFFER_SIZE = 32768;
   113 	const FREAD_BUFFER_SIZE = 32768;
   108 
   114 
   109 	const ATTACHMENTS_NONE   = false;
   115 	const ATTACHMENTS_NONE   = false;
   110 	const ATTACHMENTS_INLINE = true;
   116 	const ATTACHMENTS_INLINE = true;
   111 
   117 
   112 	// public: constructor
   118 	// public: constructor
   113 	public function __construct() {
   119 	public function __construct() {
   114 
       
   115 		// Check for PHP version
       
   116 		$required_php_version = '5.0.5';
       
   117 		if (version_compare(PHP_VERSION, $required_php_version, '<')) {
       
   118 			$this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION;
       
   119 			return false;
       
   120 		}
       
   121 
   120 
   122 		// Check memory
   121 		// Check memory
   123 		$this->memory_limit = ini_get('memory_limit');
   122 		$this->memory_limit = ini_get('memory_limit');
   124 		if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
   123 		if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
   125 			// could be stored as "16M" rather than 16777216 for example
   124 			// could be stored as "16M" rather than 16777216 for example
   259 
   258 
   260 			$filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
   259 			$filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
   261 			$filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);
   260 			$filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);
   262 
   261 
   263 			// open local file
   262 			// open local file
   264 			if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
   263 			//if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
       
   264 			if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
   265 				// great
   265 				// great
   266 			} else {
   266 			} else {
   267 				throw new getid3_exception('Could not open "'.$filename.'" (does not exist, or is not a file)');
   267 				$errormessagelist = array();
       
   268 				if (!is_readable($filename)) {
       
   269 					$errormessagelist[] = '!is_readable';
       
   270 				}
       
   271 				if (!is_file($filename)) {
       
   272 					$errormessagelist[] = '!is_file';
       
   273 				}
       
   274 				if (!file_exists($filename)) {
       
   275 					$errormessagelist[] = '!file_exists';
       
   276 				}
       
   277 				if (empty($errormessagelist)) {
       
   278 					$errormessagelist[] = 'fopen failed';
       
   279 				}
       
   280 				throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
   268 			}
   281 			}
   269 
   282 
   270 			$this->info['filesize'] = filesize($filename);
   283 			$this->info['filesize'] = filesize($filename);
   271 			// set redundant parameters - might be needed in some include file
   284 			// set redundant parameters - might be needed in some include file
   272 			$this->info['filename']     = basename($filename);
   285 			// filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
       
   286 			$filename = str_replace('\\', '/', $filename);
   273 			$this->info['filepath']     = str_replace('\\', '/', realpath(dirname($filename)));
   287 			$this->info['filepath']     = str_replace('\\', '/', realpath(dirname($filename)));
       
   288 			$this->info['filename']     = getid3_lib::mb_basename($filename);
   274 			$this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
   289 			$this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
   275 
   290 
   276 
   291 
   277 			// option_max_2gb_check
   292 			// option_max_2gb_check
   278 			if ($this->option_max_2gb_check) {
   293 			if ($this->option_max_2gb_check) {
   350 				}
   365 				}
   351 			}
   366 			}
   352 
   367 
   353 			// ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
   368 			// ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
   354 			if (!$this->option_tag_id3v2) {
   369 			if (!$this->option_tag_id3v2) {
   355 				fseek($this->fp, 0, SEEK_SET);
   370 				fseek($this->fp, 0);
   356 				$header = fread($this->fp, 10);
   371 				$header = fread($this->fp, 10);
   357 				if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
   372 				if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
   358 					$this->info['id3v2']['header']        = true;
   373 					$this->info['id3v2']['header']        = true;
   359 					$this->info['id3v2']['majorversion']  = ord($header{3});
   374 					$this->info['id3v2']['majorversion']  = ord($header{3});
   360 					$this->info['id3v2']['minorversion']  = ord($header{4});
   375 					$this->info['id3v2']['minorversion']  = ord($header{4});
   361 					$this->info['avdataoffset']          += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
   376 					$this->info['avdataoffset']          += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
   362 				}
   377 				}
   363 			}
   378 			}
   364 
   379 
   365 			// read 32 kb file data
   380 			// read 32 kb file data
   366 			fseek($this->fp, $this->info['avdataoffset'], SEEK_SET);
   381 			fseek($this->fp, $this->info['avdataoffset']);
   367 			$formattest = fread($this->fp, 32774);
   382 			$formattest = fread($this->fp, 32774);
   368 
   383 
   369 			// determine format
   384 			// determine format
   370 			$determined_format = $this->GetFileFormat($formattest, $filename);
   385 			$determined_format = $this->GetFileFormat($formattest, $filename);
   371 
   386 
   584 				'au'   => array(
   599 				'au'   => array(
   585 							'pattern'   => '^\.snd',
   600 							'pattern'   => '^\.snd',
   586 							'group'     => 'audio',
   601 							'group'     => 'audio',
   587 							'module'    => 'au',
   602 							'module'    => 'au',
   588 							'mime_type' => 'audio/basic',
   603 							'mime_type' => 'audio/basic',
       
   604 						),
       
   605 
       
   606 				// AMR  - audio       - Adaptive Multi Rate
       
   607 				'amr'  => array(
       
   608 							'pattern'   => '^\x23\x21AMR\x0A', // #!AMR[0A]
       
   609 							'group'     => 'audio',
       
   610 							'module'    => 'amr',
       
   611 							'mime_type' => 'audio/amr',
   589 						),
   612 						),
   590 
   613 
   591 				// AVR  - audio       - Audio Visual Research
   614 				// AVR  - audio       - Audio Visual Research
   592 				'avr'  => array(
   615 				'avr'  => array(
   593 							'pattern'   => '^2BIT',
   616 							'pattern'   => '^2BIT',
  1159 				'ape'       => array('ape'           , 'UTF-8'),
  1182 				'ape'       => array('ape'           , 'UTF-8'),
  1160 				'cue'       => array('cue'           , 'ISO-8859-1'),
  1183 				'cue'       => array('cue'           , 'ISO-8859-1'),
  1161 				'matroska'  => array('matroska'      , 'UTF-8'),
  1184 				'matroska'  => array('matroska'      , 'UTF-8'),
  1162 				'flac'      => array('vorbiscomment' , 'UTF-8'),
  1185 				'flac'      => array('vorbiscomment' , 'UTF-8'),
  1163 				'divxtag'   => array('divx'          , 'ISO-8859-1'),
  1186 				'divxtag'   => array('divx'          , 'ISO-8859-1'),
       
  1187 				'iptc'      => array('iptc'          , 'ISO-8859-1'),
  1164 			);
  1188 			);
  1165 		}
  1189 		}
  1166 
  1190 
  1167 		// loop through comments array
  1191 		// loop through comments array
  1168 		foreach ($tags as $comment_name => $tagname_encoding_array) {
  1192 		foreach ($tags as $comment_name => $tagname_encoding_array) {
  1179 					foreach ($valuearray as $key => $value) {
  1203 					foreach ($valuearray as $key => $value) {
  1180 						if (is_string($value)) {
  1204 						if (is_string($value)) {
  1181 							$value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed!
  1205 							$value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed!
  1182 						}
  1206 						}
  1183 						if ($value) {
  1207 						if ($value) {
  1184 							$this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value;
  1208 							if (!is_numeric($key)) {
       
  1209 								$this->info['tags'][trim($tag_name)][trim($tag_key)][$key] = $value;
       
  1210 							} else {
       
  1211 								$this->info['tags'][trim($tag_name)][trim($tag_key)][]     = $value;
       
  1212 							}
  1185 						}
  1213 						}
  1186 					}
  1214 					}
  1187 					if ($tag_key == 'picture') {
  1215 					if ($tag_key == 'picture') {
  1188 						unset($this->info[$comment_name]['comments'][$tag_key]);
  1216 						unset($this->info[$comment_name]['comments'][$tag_key]);
  1189 					}
  1217 					}
  1194 					continue;
  1222 					continue;
  1195 				}
  1223 				}
  1196 
  1224 
  1197 				if ($this->option_tags_html) {
  1225 				if ($this->option_tags_html) {
  1198 					foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
  1226 					foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
  1199 						foreach ($valuearray as $key => $value) {
  1227 						$this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $encoding);
  1200 							if (is_string($value)) {
       
  1201 								//$this->info['tags_html'][$tag_name][$tag_key][$key] = getid3_lib::MultiByteCharString2HTML($value, $encoding);
       
  1202 								$this->info['tags_html'][$tag_name][$tag_key][$key] = str_replace('&#0;', '', trim(getid3_lib::MultiByteCharString2HTML($value, $encoding)));
       
  1203 							} else {
       
  1204 								$this->info['tags_html'][$tag_name][$tag_key][$key] = $value;
       
  1205 							}
       
  1206 						}
       
  1207 					}
  1228 					}
  1208 				}
  1229 				}
  1209 
  1230 
  1210 				$this->CharConvert($this->info['tags'][$tag_name], $encoding);           // only copy gets converted!
  1231 				$this->CharConvert($this->info['tags'][$tag_name], $encoding);           // only copy gets converted!
  1211 			}
  1232 			}
  1257 			}
  1278 			}
  1258 		}
  1279 		}
  1259 		return true;
  1280 		return true;
  1260 	}
  1281 	}
  1261 
  1282 
  1262 
       
  1263 	public function getHashdata($algorithm) {
  1283 	public function getHashdata($algorithm) {
  1264 		switch ($algorithm) {
  1284 		switch ($algorithm) {
  1265 			case 'md5':
  1285 			case 'md5':
  1266 			case 'sha1':
  1286 			case 'sha1':
  1267 				break;
  1287 				break;
  1563 	}
  1583 	}
  1564 
  1584 
  1565 }
  1585 }
  1566 
  1586 
  1567 
  1587 
  1568 abstract class getid3_handler
  1588 abstract class getid3_handler {
  1569 {
  1589 
       
  1590 	/**
       
  1591 	* @var getID3
       
  1592 	*/
  1570 	protected $getid3;                       // pointer
  1593 	protected $getid3;                       // pointer
  1571 
  1594 
  1572 	protected $data_string_flag     = false; // analyzing filepointer or string
  1595 	protected $data_string_flag     = false; // analyzing filepointer or string
  1573 	protected $data_string          = '';    // string to analyze
  1596 	protected $data_string          = '';    // string to analyze
  1574 	protected $data_string_position = 0;     // seek position in string
  1597 	protected $data_string_position = 0;     // seek position in string
  1591 
  1614 
  1592 
  1615 
  1593 	// Analyze from string instead
  1616 	// Analyze from string instead
  1594 	public function AnalyzeString($string) {
  1617 	public function AnalyzeString($string) {
  1595 		// Enter string mode
  1618 		// Enter string mode
  1596 	    $this->setStringMode($string);
  1619 		$this->setStringMode($string);
  1597 
  1620 
  1598 		// Save info
  1621 		// Save info
  1599 		$saved_avdataoffset = $this->getid3->info['avdataoffset'];
  1622 		$saved_avdataoffset = $this->getid3->info['avdataoffset'];
  1600 		$saved_avdataend    = $this->getid3->info['avdataend'];
  1623 		$saved_avdataend    = $this->getid3->info['avdataend'];
  1601 		$saved_filesize     = (isset($this->getid3->info['filesize']) ? $this->getid3->info['filesize'] : null); // may be not set if called as dependency without openfile() call
  1624 		$saved_filesize     = (isset($this->getid3->info['filesize']) ? $this->getid3->info['filesize'] : null); // may be not set if called as dependency without openfile() call
  1632 	protected function fread($bytes) {
  1655 	protected function fread($bytes) {
  1633 		if ($this->data_string_flag) {
  1656 		if ($this->data_string_flag) {
  1634 			$this->data_string_position += $bytes;
  1657 			$this->data_string_position += $bytes;
  1635 			return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
  1658 			return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
  1636 		}
  1659 		}
  1637 	    $pos = $this->ftell() + $bytes;
  1660 		$pos = $this->ftell() + $bytes;
  1638 	    if (!getid3_lib::intValueSupported($pos)) {
  1661 		if (!getid3_lib::intValueSupported($pos)) {
  1639 			throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);
  1662 			throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);
  1640 	    }
  1663 		}
  1641 		return fread($this->getid3->fp, $bytes);
  1664 		return fread($this->getid3->fp, $bytes);
  1642 	}
  1665 	}
  1643 
  1666 
  1644 	protected function fseek($bytes, $whence=SEEK_SET) {
  1667 	protected function fseek($bytes, $whence=SEEK_SET) {
  1645 		if ($this->data_string_flag) {
  1668 		if ($this->data_string_flag) {
  1655 				case SEEK_END:
  1678 				case SEEK_END:
  1656 					$this->data_string_position = $this->data_string_length + $bytes;
  1679 					$this->data_string_position = $this->data_string_length + $bytes;
  1657 					break;
  1680 					break;
  1658 			}
  1681 			}
  1659 			return 0;
  1682 			return 0;
  1660 	    } else {
  1683 		} else {
  1661 	    	$pos = $bytes;
  1684 			$pos = $bytes;
  1662 	    	if ($whence == SEEK_CUR) {
  1685 			if ($whence == SEEK_CUR) {
  1663 				$pos = $this->ftell() + $bytes;
  1686 				$pos = $this->ftell() + $bytes;
  1664 	    	} elseif ($whence == SEEK_END) {
  1687 			} elseif ($whence == SEEK_END) {
  1665 				$pos = $this->info['filesize'] + $bytes;
  1688 				$pos = $this->getid3->info['filesize'] + $bytes;
  1666 	    	}
  1689 			}
  1667 	    	if (!getid3_lib::intValueSupported($pos)) {
  1690 			if (!getid3_lib::intValueSupported($pos)) {
  1668 				throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10);
  1691 				throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10);
  1669 			}
  1692 			}
  1670 		}
  1693 		}
  1671 		return fseek($this->getid3->fp, $bytes, $whence);
  1694 		return fseek($this->getid3->fp, $bytes, $whence);
  1672 	}
  1695 	}
  1680 
  1703 
  1681 	final protected function isDependencyFor($module) {
  1704 	final protected function isDependencyFor($module) {
  1682 		return $this->dependency_to == $module;
  1705 		return $this->dependency_to == $module;
  1683 	}
  1706 	}
  1684 
  1707 
  1685 	protected function error($text)
  1708 	protected function error($text) {
  1686 	{
       
  1687 		$this->getid3->info['error'][] = $text;
  1709 		$this->getid3->info['error'][] = $text;
  1688 
  1710 
  1689 		return false;
  1711 		return false;
  1690 	}
  1712 	}
  1691 
  1713 
  1692 	protected function warning($text)
  1714 	protected function warning($text) {
  1693 	{
       
  1694 		return $this->getid3->warning($text);
  1715 		return $this->getid3->warning($text);
  1695 	}
  1716 	}
  1696 
  1717 
  1697 	protected function notice($text)
  1718 	protected function notice($text) {
  1698 	{
       
  1699 		// does nothing for now
  1719 		// does nothing for now
  1700 	}
  1720 	}
  1701 
  1721 
  1702 	public function saveAttachment($name, $offset, $length, $image_mime=null) {
  1722 	public function saveAttachment($name, $offset, $length, $image_mime=null) {
  1703 		try {
  1723 		try {