14 if (!
defined(
'GETID3_OS_ISWINDOWS')) {
15 define(
'GETID3_OS_ISWINDOWS', (stripos(PHP_OS,
'WIN') === 0));
18 if (!
defined(
'GETID3_INCLUDEPATH')) {
19 define(
'GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
23 define(
'IMG_JPG', IMAGETYPE_JPEG);
25 if (!
defined(
'ENT_SUBSTITUTE')) {
26 define(
'ENT_SUBSTITUTE', (
defined(
'ENT_IGNORE') ? ENT_IGNORE : 8));
34 if (!
$temp_dir && function_exists(
'sys_get_temp_dir')) {
44 if (substr(
$temp_dir, -1, 1) != DIRECTORY_SEPARATOR) {
47 $found_valid_tempdir =
false;
49 foreach ($open_basedirs as $basedir) {
50 if (substr($basedir, -1, 1) != DIRECTORY_SEPARATOR) {
51 $basedir .= DIRECTORY_SEPARATOR;
53 if (preg_match(
'#^'.preg_quote($basedir).
'#',
$temp_dir)) {
54 $found_valid_tempdir =
true;
58 if (!$found_valid_tempdir) {
61 unset($open_basedirs, $found_valid_tempdir, $basedir);
67 if (!
defined(
'GETID3_TEMP_DIR')) {
125 $required_php_version =
'5.3.0';
126 if (version_compare(PHP_VERSION, $required_php_version,
'<')) {
127 $this->startup_error .=
'getID3() requires PHP v'.$required_php_version.
' or higher - you are running v'.PHP_VERSION.
"\n";
132 $this->memory_limit = ini_get(
'memory_limit');
133 if (preg_match(
'#([0-9]+)M#i', $this->memory_limit, $matches)) {
135 $this->memory_limit = $matches[1] * 1048576;
136 } elseif (preg_match(
'#([0-9]+)G#i', $this->memory_limit, $matches)) {
138 $this->memory_limit = $matches[1] * 1073741824;
140 if ($this->memory_limit <= 0) {
142 } elseif ($this->memory_limit <= 4194304) {
143 $this->startup_error .=
'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'.
"\n";
144 } elseif ($this->memory_limit <= 12582912) {
145 $this->startup_warning .=
'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini'.
"\n";
149 if (preg_match(
'#(1|ON)#i', ini_get(
'safe_mode'))) {
150 $this->
warning(
'WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
153 if (($mbstring_func_overload = ini_get(
'mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
157 $this->startup_error .=
'WARNING: php.ini contains "mbstring.func_overload = '.ini_get(
'mbstring.func_overload').
'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'.
"\n";
161 if (function_exists(
'get_magic_quotes_runtime')) {
162 if (get_magic_quotes_runtime()) {
163 $this->startup_error .=
'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'.
"\n";
168 if (function_exists(
'magic_quotes_gpc')) {
169 if (get_magic_quotes_gpc()) {
170 $this->startup_error .=
'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'.
"\n";
175 if (!include_once(GETID3_INCLUDEPATH.
'getid3.lib.php')) {
176 $this->startup_error .=
'getid3.lib.php is missing or corrupt'.
"\n";
179 if ($this->option_max_2gb_check === null) {
180 $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647);
190 if (GETID3_OS_ISWINDOWS && !
defined(
'GETID3_HELPERAPPSDIR')) {
192 $helperappsdir = GETID3_INCLUDEPATH.
'..'.DIRECTORY_SEPARATOR.
'helperapps';
194 if (!is_dir($helperappsdir)) {
195 $this->startup_warning .=
'"'.$helperappsdir.
'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'.
"\n";
196 } elseif (strpos(realpath($helperappsdir),
' ') !==
false) {
197 $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
198 $path_so_far =
array();
199 foreach ($DirPieces as
$key => $value) {
200 if (strpos($value,
' ') !==
false) {
201 if (!empty($path_so_far)) {
202 $commandline =
'dir /x '.escapeshellarg(implode(DIRECTORY_SEPARATOR, $path_so_far));
203 $dir_listing = `$commandline`;
204 $lines = explode(
"\n", $dir_listing);
205 foreach ($lines as $line) {
207 if (preg_match(
'#^([0-9/]{10}) +([0-9:]{4,5}( [AP]M)?) +(<DIR>|[0-9,]+) +([^ ]{0,11}) +(.+)$#', $line, $matches)) {
208 list($dummy, $date,
$time, $ampm, $filesize, $shortname,
$filename) = $matches;
209 if ((strtoupper($filesize) ==
'<DIR>') && (strtolower(
$filename) == strtolower($value))) {
215 $this->startup_warning .=
'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.'.
"\n";
218 $path_so_far[] = $value;
220 $helperappsdir = implode(DIRECTORY_SEPARATOR, $path_so_far);
222 define(
'GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
225 if (!empty($this->startup_error)) {
234 return self::VERSION;
244 if (!is_array($optArray) || empty($optArray)) {
247 foreach ($optArray as $opt => $val) {
248 if (isset($this->$opt) ===
false) {
259 if (!empty($this->startup_error)) {
262 if (!empty($this->startup_warning)) {
264 $this->
warning($startup_warning);
270 $this->info =
array();
271 $this->info[
'GETID3_VERSION'] = $this->
version();
272 $this->info[
'php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit :
false);
275 if (preg_match(
'#^(ht|f)tp://#',
$filename)) {
276 throw new getid3_exception(
'Remote files are not supported - please copy the file locally first');
280 $filename = preg_replace(
'#(.+)'.preg_quote(DIRECTORY_SEPARATOR).
'{2,}#U',
'\1'.DIRECTORY_SEPARATOR,
$filename);
287 $errormessagelist =
array();
289 $errormessagelist[] =
'!is_readable';
292 $errormessagelist[] =
'!is_file';
295 $errormessagelist[] =
'!file_exists';
297 if (empty($errormessagelist)) {
298 $errormessagelist[] =
'fopen failed';
303 $this->info[
'filesize'] = (!is_null($filesize) ? $filesize : filesize(
$filename));
307 $this->info[
'filepath'] = str_replace(
'\\',
'/', realpath(dirname(
$filename)));
309 $this->info[
'filenamepath'] = $this->info[
'filepath'].
'/'.$this->info[
'filename'];
312 $this->info[
'avdataoffset'] = 0;
313 $this->info[
'avdataend'] = $this->info[
'filesize'];
314 $this->info[
'fileformat'] =
'';
315 $this->info[
'audio'][
'dataformat'] =
'';
316 $this->info[
'video'][
'dataformat'] =
'';
317 $this->info[
'tags'] =
array();
318 $this->info[
'error'] =
array();
319 $this->info[
'warning'] =
array();
320 $this->info[
'comments'] =
array();
324 if ($this->option_max_2gb_check) {
328 $fseek = fseek($this->fp, 0, SEEK_END);
329 if (($fseek < 0) || (($this->info[
'filesize'] != 0) && (ftell($this->fp) == 0)) ||
330 ($this->info[
'filesize'] < 0) ||
331 (ftell($this->fp) < 0)) {
334 if ($real_filesize ===
false) {
335 unset($this->info[
'filesize']);
337 throw new getid3_exception(
'Unable to determine actual filesize. File is most likely larger than '.round(PHP_INT_MAX / 1073741824).
'GB and is not supported by PHP.');
339 unset($this->info[
'filesize']);
341 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');
343 $this->info[
'filesize'] = $real_filesize;
344 $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.');
351 $this->
error($e->getMessage());
364 foreach (
array(
'id3v2'=>
'id3v2',
'id3v1'=>
'id3v1',
'apetag'=>
'ape',
'lyrics3'=>
'lyrics3') as $tag_name => $tag_key) {
365 $option_tag =
'option_tag_'.$tag_name;
366 if ($this->$option_tag) {
369 $tag_class =
'getid3_'.$tag_name;
370 $tag =
new $tag_class($this);
378 if (isset($this->info[
'id3v2'][
'tag_offset_start'])) {
379 $this->info[
'avdataoffset'] = max($this->info[
'avdataoffset'], $this->info[
'id3v2'][
'tag_offset_end']);
381 foreach (
array(
'id3v1'=>
'id3v1',
'apetag'=>
'ape',
'lyrics3'=>
'lyrics3') as $tag_name => $tag_key) {
382 if (isset($this->info[$tag_key][
'tag_offset_start'])) {
383 $this->info[
'avdataend'] = min($this->info[
'avdataend'], $this->info[$tag_key][
'tag_offset_start']);
388 if (!$this->option_tag_id3v2) {
390 $header = fread($this->fp, 10);
391 if ((substr(
$header, 0, 3) ==
'ID3') && (strlen(
$header) == 10)) {
392 $this->info[
'id3v2'][
'header'] =
true;
393 $this->info[
'id3v2'][
'majorversion'] = ord(
$header{3});
394 $this->info[
'id3v2'][
'minorversion'] = ord(
$header{4});
400 fseek($this->fp, $this->info[
'avdataoffset']);
401 $formattest = fread($this->fp, 32774);
404 $determined_format = $this->
GetFileFormat($formattest, ($original_filename ? $original_filename :
$filename));
407 if (!$determined_format) {
409 return $this->
error(
'unable to determine file format');
413 if (isset($determined_format[
'fail_id3']) && (in_array(
'id3v1', $this->info[
'tags']) || in_array(
'id3v2', $this->info[
'tags']))) {
414 if ($determined_format[
'fail_id3'] ===
'ERROR') {
416 return $this->
error(
'ID3 tags not allowed on this file type.');
417 } elseif ($determined_format[
'fail_id3'] ===
'WARNING') {
418 $this->
warning(
'ID3 tags not allowed on this file type.');
423 if (isset($determined_format[
'fail_ape']) && in_array(
'ape', $this->info[
'tags'])) {
424 if ($determined_format[
'fail_ape'] ===
'ERROR') {
426 return $this->
error(
'APE tags not allowed on this file type.');
427 } elseif ($determined_format[
'fail_ape'] ===
'WARNING') {
428 $this->
warning(
'APE tags not allowed on this file type.');
433 $this->info[
'mime_type'] = $determined_format[
'mime_type'];
436 if (!file_exists(GETID3_INCLUDEPATH.$determined_format[
'include'])) {
438 return $this->
error(
'Format not supported, module "'.$determined_format[
'include'].
'" was removed.');
443 if (!empty($determined_format[
'iconv_req']) && !function_exists(
'mb_convert_encoding') && !function_exists(
'iconv') && !in_array($this->encoding,
array(
'ISO-8859-1',
'UTF-8',
'UTF-16LE',
'UTF-16BE',
'UTF-16'))) {
444 $errormessage =
'mb_convert_encoding() or iconv() support is required for this module ('.$determined_format[
'include'].
') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
445 if (GETID3_OS_ISWINDOWS) {
446 $errormessage .=
'PHP does not have mb_convert_encoding() or iconv() support. Please enable php_mbstring.dll / php_iconv.dll in php.ini, and copy php_mbstring.dll / iconv.dll from c:/php/dlls to c:/windows/system32';
448 $errormessage .=
'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch';
450 return $this->
error($errormessage);
454 include_once(GETID3_INCLUDEPATH.$determined_format[
'include']);
457 $class_name =
'getid3_'.$determined_format[
'module'];
458 if (!class_exists($class_name)) {
459 return $this->
error(
'Format not supported, module "'.$determined_format[
'include'].
'" is corrupt.');
461 $class =
new $class_name($this);
469 if ($this->option_tags_process) {
474 if ($this->option_extra_info) {
483 if ($this->option_md5_data) {
485 if (!$this->option_md5_data_source || empty($this->info[
'md5_data_source'])) {
491 if ($this->option_sha1_data) {
499 $this->
error(
'Caught exception: '.$e->getMessage());
510 if (!isset($this->info[
'error'])) {
511 $this->info[
'error'] =
array();
520 $this->info[
'warning'][] =
$message;
529 $AVpossibleEmptyKeys =
array(
'dataformat',
'bits_per_sample',
'encoder_options',
'streams',
'bitrate');
530 foreach ($AVpossibleEmptyKeys as $dummy =>
$key) {
531 if (empty($this->info[
'audio'][
$key]) && isset($this->info[
'audio'][$key])) {
532 unset($this->info[
'audio'][$key]);
534 if (empty($this->info[
'video'][$key]) && isset($this->info[
'video'][$key])) {
535 unset($this->info[
'video'][$key]);
540 if (!empty($this->info)) {
541 foreach ($this->info as
$key => $value) {
542 if (empty($this->info[
$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !==
'0')) {
543 unset($this->info[$key]);
549 if (empty($this->info[
'fileformat'])) {
550 if (isset($this->info[
'avdataoffset'])) {
551 unset($this->info[
'avdataoffset']);
553 if (isset($this->info[
'avdataend'])) {
554 unset($this->info[
'avdataend']);
559 if (!empty($this->info[
'error'])) {
560 $this->info[
'error'] = array_values(array_unique($this->info[
'error']));
562 if (!empty($this->info[
'warning'])) {
563 $this->info[
'warning'] = array_values(array_unique($this->info[
'warning']));
567 unset($this->info[
'php_memory_limit']);
575 static $format_info =
array();
576 if (empty($format_info)) {
577 $format_info =
array(
583 'pattern' =>
'^\\x0B\\x77',
586 'mime_type' =>
'audio/ac3',
591 'pattern' =>
'^ADIF',
594 'mime_type' =>
'application/octet-stream',
595 'fail_ape' =>
'WARNING',
609 'pattern' =>
'^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
612 'mime_type' =>
'application/octet-stream',
613 'fail_ape' =>
'WARNING',
619 'pattern' =>
'^\\.snd',
622 'mime_type' =>
'audio/basic',
627 'pattern' =>
'^\\x23\\x21AMR\\x0A',
630 'mime_type' =>
'audio/amr',
635 'pattern' =>
'^2BIT',
638 'mime_type' =>
'application/octet-stream',
643 'pattern' =>
'^\\x00(BONK|INFO|META| ID3)',
646 'mime_type' =>
'audio/xmms-bonk',
651 'pattern' =>
'^DSD ',
654 'mime_type' =>
'audio/dsd',
659 'pattern' =>
'^[\\x02-\\x06]ds[s2]',
662 'mime_type' =>
'application/octet-stream',
667 'pattern' =>
'^\\x7F\\xFE\\x80\\x01',
670 'mime_type' =>
'audio/dts',
675 'pattern' =>
'^fLaC',
678 'mime_type' =>
'audio/x-flac',
683 'pattern' =>
'^LA0[2-4]',
686 'mime_type' =>
'application/octet-stream',
691 'pattern' =>
'^LPAC',
694 'mime_type' =>
'application/octet-stream',
699 'pattern' =>
'^MThd',
702 'mime_type' =>
'audio/midi',
707 'pattern' =>
'^MAC ',
709 'module' =>
'monkey',
710 'mime_type' =>
'application/octet-stream',
725 'pattern' =>
'^IMPM',
729 'mime_type' =>
'audio/it',
734 'pattern' =>
'^Extended Module',
738 'mime_type' =>
'audio/xm',
743 'pattern' =>
'^.{44}SCRM',
747 'mime_type' =>
'audio/s3m',
752 'pattern' =>
'^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])',
755 'mime_type' =>
'audio/x-musepack',
760 'pattern' =>
'^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\x0B\\x10-\\x1B\\x20-\\x2B\\x30-\\x3B\\x40-\\x4B\\x50-\\x5B\\x60-\\x6B\\x70-\\x7B\\x80-\\x8B\\x90-\\x9B\\xA0-\\xAB\\xB0-\\xBB\\xC0-\\xCB\\xD0-\\xDB\\xE0-\\xEB\\xF0-\\xFB]',
763 'mime_type' =>
'audio/mpeg',
768 'pattern' =>
'^(\\*RIFF|OFR)',
770 'module' =>
'optimfrog',
771 'mime_type' =>
'application/octet-stream',
779 'mime_type' =>
'application/octet-stream',
784 'pattern' =>
'^ajkg',
786 'module' =>
'shorten',
787 'mime_type' =>
'audio/xmms-shn',
788 'fail_id3' =>
'ERROR',
789 'fail_ape' =>
'ERROR',
797 'mime_type' =>
'application/octet-stream',
802 'pattern' =>
'^Creative Voice File',
805 'mime_type' =>
'audio/voc',
810 'pattern' =>
'^TWIN',
813 'mime_type' =>
'application/octet-stream',
818 'pattern' =>
'^wvpk',
820 'module' =>
'wavpack',
821 'mime_type' =>
'application/octet-stream',
829 'pattern' =>
'^\\x30\\x26\\xB2\\x75\\x8E\\x66\\xCF\\x11\\xA6\\xD9\\x00\\xAA\\x00\\x62\\xCE\\x6C',
830 'group' =>
'audio-video',
832 'mime_type' =>
'video/x-ms-asf',
833 'iconv_req' =>
false,
838 'pattern' =>
'^(BIK|SMK)',
839 'group' =>
'audio-video',
841 'mime_type' =>
'application/octet-stream',
846 'pattern' =>
'^FLV[\\x01]',
847 'group' =>
'audio-video',
849 'mime_type' =>
'video/x-flv',
854 'pattern' =>
'^\\x1A\\x45\\xDF\\xA3',
855 'group' =>
'audio-video',
856 'module' =>
'matroska',
857 'mime_type' =>
'video/x-matroska',
862 'pattern' =>
'^\\x00\\x00\\x01[\\xB3\\xBA]',
863 'group' =>
'audio-video',
865 'mime_type' =>
'video/mpeg',
870 'pattern' =>
'^NSV[sf]',
871 'group' =>
'audio-video',
873 'mime_type' =>
'application/octet-stream',
878 'pattern' =>
'^OggS',
881 'mime_type' =>
'application/ogg',
882 'fail_id3' =>
'WARNING',
883 'fail_ape' =>
'WARNING',
887 'quicktime' =>
array(
888 'pattern' =>
'^.{4}(cmov|free|ftyp|mdat|moov|pnot|skip|wide)',
889 'group' =>
'audio-video',
890 'module' =>
'quicktime',
891 'mime_type' =>
'video/quicktime',
896 'pattern' =>
'^(RIFF|SDSS|FORM)',
897 'group' =>
'audio-video',
899 'mime_type' =>
'audio/x-wav',
900 'fail_ape' =>
'WARNING',
905 'pattern' =>
'^\\.(RMF|ra)',
906 'group' =>
'audio-video',
908 'mime_type' =>
'audio/x-realaudio',
913 'pattern' =>
'^(F|C)WS',
914 'group' =>
'audio-video',
916 'mime_type' =>
'application/x-shockwave-flash',
921 'pattern' =>
'^(\\x47.{187}){10,}',
922 'group' =>
'audio-video',
924 'mime_type' =>
'video/MP2T',
933 'group' =>
'graphic',
935 'mime_type' =>
'image/bmp',
936 'fail_id3' =>
'ERROR',
937 'fail_ape' =>
'ERROR',
943 'group' =>
'graphic',
945 'mime_type' =>
'image/gif',
946 'fail_id3' =>
'ERROR',
947 'fail_ape' =>
'ERROR',
952 'pattern' =>
'^\\xFF\\xD8\\xFF',
953 'group' =>
'graphic',
955 'mime_type' =>
'image/jpeg',
956 'fail_id3' =>
'ERROR',
957 'fail_ape' =>
'ERROR',
962 'pattern' =>
'^.{2048}PCD_IPI\\x00',
963 'group' =>
'graphic',
965 'mime_type' =>
'image/x-photo-cd',
966 'fail_id3' =>
'ERROR',
967 'fail_ape' =>
'ERROR',
973 'pattern' =>
'^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A',
974 'group' =>
'graphic',
976 'mime_type' =>
'image/png',
977 'fail_id3' =>
'ERROR',
978 'fail_ape' =>
'ERROR',
984 'pattern' =>
'(<!DOCTYPE svg PUBLIC |xmlns="http://www\\.w3\\.org/2000/svg")',
985 'group' =>
'graphic',
987 'mime_type' =>
'image/svg+xml',
988 'fail_id3' =>
'ERROR',
989 'fail_ape' =>
'ERROR',
995 'pattern' =>
'^(II\\x2A\\x00|MM\\x00\\x2A)',
996 'group' =>
'graphic',
998 'mime_type' =>
'image/tiff',
999 'fail_id3' =>
'ERROR',
1000 'fail_ape' =>
'ERROR',
1006 'pattern' =>
'^\\xDC\\xFE',
1007 'group' =>
'graphic',
1009 'mime_type' =>
'image/efax',
1010 'fail_id3' =>
'ERROR',
1011 'fail_ape' =>
'ERROR',
1019 'pattern' =>
'^.{32769}CD001',
1022 'mime_type' =>
'application/octet-stream',
1023 'fail_id3' =>
'ERROR',
1024 'fail_ape' =>
'ERROR',
1025 'iconv_req' =>
false,
1030 'pattern' =>
'^Rar\\!',
1031 'group' =>
'archive',
1033 'mime_type' =>
'application/octet-stream',
1034 'fail_id3' =>
'ERROR',
1035 'fail_ape' =>
'ERROR',
1040 'pattern' =>
'^SZ\\x0A\\x04',
1041 'group' =>
'archive',
1043 'mime_type' =>
'application/octet-stream',
1044 'fail_id3' =>
'ERROR',
1045 'fail_ape' =>
'ERROR',
1050 'pattern' =>
'^.{100}[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20\\x00]{12}[0-9\\x20\\x00]{12}',
1051 'group' =>
'archive',
1053 'mime_type' =>
'application/x-tar',
1054 'fail_id3' =>
'ERROR',
1055 'fail_ape' =>
'ERROR',
1060 'pattern' =>
'^\\x1F\\x8B\\x08',
1061 'group' =>
'archive',
1063 'mime_type' =>
'application/x-gzip',
1064 'fail_id3' =>
'ERROR',
1065 'fail_ape' =>
'ERROR',
1070 'pattern' =>
'^PK\\x03\\x04',
1071 'group' =>
'archive',
1073 'mime_type' =>
'application/zip',
1074 'fail_id3' =>
'ERROR',
1075 'fail_ape' =>
'ERROR',
1083 'pattern' =>
'^PAR2\\x00PKT',
1086 'mime_type' =>
'application/octet-stream',
1087 'fail_id3' =>
'ERROR',
1088 'fail_ape' =>
'ERROR',
1093 'pattern' =>
'^\\x25PDF',
1096 'mime_type' =>
'application/pdf',
1097 'fail_id3' =>
'ERROR',
1098 'fail_ape' =>
'ERROR',
1102 'msoffice' =>
array(
1103 'pattern' =>
'^\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1',
1105 'module' =>
'msoffice',
1106 'mime_type' =>
'application/octet-stream',
1107 'fail_id3' =>
'ERROR',
1108 'fail_ape' =>
'ERROR',
1116 'mime_type' =>
'application/octet-stream',
1122 return $format_info;
1137 if (!empty(
$info[
'pattern']) && preg_match(
'#'.
$info[
'pattern'].
'#s', $filedata)) {
1138 $info[
'include'] =
'module.'.$info[
'group'].
'.'.
$info[
'module'].
'.php';
1144 if (preg_match(
'#\\.mp[123a]$#i',
$filename)) {
1148 $info = $GetFileFormatArray[
'mp3'];
1149 $info[
'include'] =
'module.'.$info[
'group'].
'.'.
$info[
'module'].
'.php';
1151 } elseif (preg_match(
'#\\.cue$#i',
$filename) && preg_match(
'#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
1156 $info = $GetFileFormatArray[
'cue'];
1157 $info[
'include'] =
'module.'.$info[
'group'].
'.'.
$info[
'module'].
'.php';
1174 foreach ($array as
$key => $value) {
1177 if (is_array($value)) {
1182 elseif (is_string($value)) {
1195 'asf' =>
array(
'asf' ,
'UTF-16LE'),
1196 'midi' =>
array(
'midi' ,
'ISO-8859-1'),
1197 'nsv' =>
array(
'nsv' ,
'ISO-8859-1'),
1198 'ogg' =>
array(
'vorbiscomment' ,
'UTF-8'),
1199 'png' =>
array(
'png' ,
'UTF-8'),
1200 'tiff' =>
array(
'tiff' ,
'ISO-8859-1'),
1201 'quicktime' =>
array(
'quicktime' ,
'UTF-8'),
1202 'real' =>
array(
'real' ,
'ISO-8859-1'),
1203 'vqf' =>
array(
'vqf' ,
'ISO-8859-1'),
1204 'zip' =>
array(
'zip' ,
'ISO-8859-1'),
1205 'riff' =>
array(
'riff' ,
'ISO-8859-1'),
1206 'lyrics3' =>
array(
'lyrics3' ,
'ISO-8859-1'),
1207 'id3v1' =>
array(
'id3v1' , $this->encoding_id3v1),
1208 'id3v2' =>
array(
'id3v2' ,
'UTF-8'),
1209 'ape' =>
array(
'ape' ,
'UTF-8'),
1210 'cue' =>
array(
'cue' ,
'ISO-8859-1'),
1211 'matroska' =>
array(
'matroska' ,
'UTF-8'),
1212 'flac' =>
array(
'vorbiscomment' ,
'UTF-8'),
1213 'divxtag' =>
array(
'divx' ,
'ISO-8859-1'),
1214 'iptc' =>
array(
'iptc' ,
'ISO-8859-1'),
1219 foreach (
$tags as $comment_name => $tagname_encoding_array) {
1220 list($tag_name,
$encoding) = $tagname_encoding_array;
1223 if (isset($this->info[$comment_name]) && !isset($this->info[$comment_name][
'encoding'])) {
1224 $this->info[$comment_name][
'encoding'] =
$encoding;
1228 if (!empty($this->info[$comment_name][
'comments'])) {
1229 foreach ($this->info[$comment_name][
'comments'] as $tag_key => $valuearray) {
1230 foreach ($valuearray as
$key => $value) {
1231 if (is_string($value)) {
1232 $value = trim($value,
" \r\n\t");
1235 if (!is_numeric(
$key)) {
1236 $this->info[
'tags'][trim($tag_name)][trim($tag_key)][
$key] = $value;
1238 $this->info[
'tags'][trim($tag_name)][trim($tag_key)][] = $value;
1242 if ($tag_key ==
'picture') {
1243 unset($this->info[$comment_name][
'comments'][$tag_key]);
1247 if (!isset($this->info[
'tags'][$tag_name])) {
1252 $this->
CharConvert($this->info[
'tags'][$tag_name], $this->info[$comment_name][
'encoding']);
1254 if ($this->option_tags_html) {
1255 foreach ($this->info[
'tags'][$tag_name] as $tag_key => $valuearray) {
1266 if (!empty($this->info[
'tags'])) {
1267 $unset_keys =
array(
'tags',
'tags_html');
1268 foreach ($this->info[
'tags'] as $tagtype => $tagarray) {
1269 foreach ($tagarray as $tagname => $tagdata) {
1270 if ($tagname ==
'picture') {
1271 foreach ($tagdata as
$key => $tagarray) {
1272 $this->info[
'comments'][
'picture'][] = $tagarray;
1273 if (isset($tagarray[
'data']) && isset($tagarray[
'image_mime'])) {
1274 if (isset($this->info[
'tags'][$tagtype][$tagname][
$key])) {
1275 unset($this->info[
'tags'][$tagtype][$tagname][$key]);
1277 if (isset($this->info[
'tags_html'][$tagtype][$tagname][$key])) {
1278 unset($this->info[
'tags_html'][$tagtype][$tagname][$key]);
1284 foreach ($unset_keys as $unset_key) {
1286 if (empty($this->info[$unset_key][$tagtype][
'picture'])) {
1287 unset($this->info[$unset_key][$tagtype][
'picture']);
1289 if (empty($this->info[$unset_key][$tagtype])) {
1290 unset($this->info[$unset_key][$tagtype]);
1292 if (empty($this->info[$unset_key])) {
1293 unset($this->info[$unset_key]);
1297 if (isset($this->info[$tagtype][
'comments'][
'picture'])) {
1298 unset($this->info[$tagtype][
'comments'][
'picture']);
1300 if (empty($this->info[$tagtype][
'comments'])) {
1301 unset($this->info[$tagtype][
'comments']);
1303 if (empty($this->info[$tagtype])) {
1304 unset($this->info[$tagtype]);
1312 switch ($algorithm) {
1318 return $this->
error(
'bad algorithm "'.$algorithm.
'" in getHashdata()');
1322 if (!empty($this->info[
'fileformat']) && !empty($this->info[
'dataformat']) && ($this->info[
'fileformat'] ==
'ogg') && ($this->info[
'audio'][
'dataformat'] ==
'vorbis')) {
1342 if (preg_match(
'#(1|ON)#i', ini_get(
'safe_mode'))) {
1344 $this->
warning(
'Failed making system call to vorbiscomment.exe - '.$algorithm.
'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)');
1345 $this->info[$algorithm.
'_data'] =
false;
1350 $old_abort = ignore_user_abort(
true);
1353 $empty = tempnam(GETID3_TEMP_DIR,
'getID3');
1357 $temp = tempnam(GETID3_TEMP_DIR,
'getID3');
1358 $file = $this->info[
'filenamepath'];
1360 if (GETID3_OS_ISWINDOWS) {
1362 if (file_exists(GETID3_HELPERAPPSDIR.
'vorbiscomment.exe')) {
1364 $commandline =
'"'.GETID3_HELPERAPPSDIR.
'vorbiscomment.exe" -w -c "'.$empty.
'" "'.
$file.
'" "'.$temp.
'"';
1365 $VorbisCommentError = `$commandline`;
1369 $VorbisCommentError =
'vorbiscomment.exe not found in '.GETID3_HELPERAPPSDIR;
1375 $commandline =
'vorbiscomment -w -c "'.$empty.
'" "'.
$file.
'" "'.$temp.
'" 2>&1';
1376 $commandline =
'vorbiscomment -w -c '.escapeshellarg($empty).
' '.escapeshellarg(
$file).
' '.escapeshellarg($temp).
' 2>&1';
1377 $VorbisCommentError = `$commandline`;
1381 if (!empty($VorbisCommentError)) {
1383 $this->
warning(
'Failed making system call to vorbiscomment(.exe) - '.$algorithm.
'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError);
1384 $this->info[$algorithm.
'_data'] =
false;
1389 switch ($algorithm) {
1391 $this->info[$algorithm.
'_data'] = md5_file($temp);
1395 $this->info[$algorithm.
'_data'] = sha1_file($temp);
1405 ignore_user_abort($old_abort);
1411 if (!empty($this->info[
'avdataoffset']) || (isset($this->info[
'avdataend']) && ($this->info[
'avdataend'] < $this->info[
'filesize']))) {
1414 $this->info[$algorithm.
'_data'] =
getid3_lib::hash_data($this->info[
'filenamepath'], $this->info[
'avdataoffset'], $this->info[
'avdataend'], $algorithm);
1419 switch ($algorithm) {
1421 $this->info[$algorithm.
'_data'] = md5_file($this->info[
'filenamepath']);
1425 $this->info[$algorithm.
'_data'] = sha1_file($this->info[
'filenamepath']);
1438 if (!empty($this->info[
'audio'][
'channelmode']) || !isset($this->info[
'audio'][
'channels'])) {
1440 } elseif ($this->info[
'audio'][
'channels'] == 1) {
1441 $this->info[
'audio'][
'channelmode'] =
'mono';
1442 } elseif ($this->info[
'audio'][
'channels'] == 2) {
1443 $this->info[
'audio'][
'channelmode'] =
'stereo';
1447 $CombinedBitrate = 0;
1448 $CombinedBitrate += (isset($this->info[
'audio'][
'bitrate']) ? $this->info[
'audio'][
'bitrate'] : 0);
1449 $CombinedBitrate += (isset($this->info[
'video'][
'bitrate']) ? $this->info[
'video'][
'bitrate'] : 0);
1450 if (($CombinedBitrate > 0) && empty($this->info[
'bitrate'])) {
1451 $this->info[
'bitrate'] = $CombinedBitrate;
1460 if (isset($this->info[
'video'][
'dataformat']) && $this->info[
'video'][
'dataformat'] && (!isset($this->info[
'video'][
'bitrate']) || ($this->info[
'video'][
'bitrate'] == 0))) {
1462 if (isset($this->info[
'audio'][
'bitrate']) && ($this->info[
'audio'][
'bitrate'] > 0) && ($this->info[
'audio'][
'bitrate'] == $this->info[
'bitrate'])) {
1464 if (isset($this->info[
'playtime_seconds']) && ($this->info[
'playtime_seconds'] > 0)) {
1466 if (isset($this->info[
'avdataend']) && isset($this->info[
'avdataoffset'])) {
1469 $this->info[
'bitrate'] = round((($this->info[
'avdataend'] - $this->info[
'avdataoffset']) * 8) / $this->info[
'playtime_seconds']);
1470 $this->info[
'video'][
'bitrate'] = $this->info[
'bitrate'] - $this->info[
'audio'][
'bitrate'];
1476 if ((!isset($this->info[
'playtime_seconds']) || ($this->info[
'playtime_seconds'] <= 0)) && !empty($this->info[
'bitrate'])) {
1477 $this->info[
'playtime_seconds'] = (($this->info[
'avdataend'] - $this->info[
'avdataoffset']) * 8) / $this->info[
'bitrate'];
1480 if (!isset($this->info[
'bitrate']) && !empty($this->info[
'playtime_seconds'])) {
1481 $this->info[
'bitrate'] = (($this->info[
'avdataend'] - $this->info[
'avdataoffset']) * 8) / $this->info[
'playtime_seconds'];
1483 if (isset($this->info[
'bitrate']) && empty($this->info[
'audio'][
'bitrate']) && empty($this->info[
'video'][
'bitrate'])) {
1484 if (isset($this->info[
'audio'][
'dataformat']) && empty($this->info[
'video'][
'resolution_x'])) {
1486 $this->info[
'audio'][
'bitrate'] = $this->info[
'bitrate'];
1487 } elseif (isset($this->info[
'video'][
'resolution_x']) && empty($this->info[
'audio'][
'dataformat'])) {
1489 $this->info[
'video'][
'bitrate'] = $this->info[
'bitrate'];
1494 if (!empty($this->info[
'playtime_seconds']) && empty($this->info[
'playtime_string'])) {
1501 if (empty($this->info[
'video'])) {
1504 if (empty($this->info[
'video'][
'resolution_x']) || empty($this->info[
'video'][
'resolution_y'])) {
1507 if (empty($this->info[
'video'][
'bits_per_sample'])) {
1511 switch ($this->info[
'video'][
'dataformat']) {
1519 $PlaytimeSeconds = 1;
1520 $BitrateCompressed = $this->info[
'filesize'] * 8;
1524 if (!empty($this->info[
'video'][
'frame_rate'])) {
1525 $FrameRate = $this->info[
'video'][
'frame_rate'];
1529 if (!empty($this->info[
'playtime_seconds'])) {
1530 $PlaytimeSeconds = $this->info[
'playtime_seconds'];
1534 if (!empty($this->info[
'video'][
'bitrate'])) {
1535 $BitrateCompressed = $this->info[
'video'][
'bitrate'];
1541 $BitrateUncompressed = $this->info[
'video'][
'resolution_x'] * $this->info[
'video'][
'resolution_y'] * $this->info[
'video'][
'bits_per_sample'] * $FrameRate;
1543 $this->info[
'video'][
'compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
1549 if (empty($this->info[
'audio'][
'bitrate']) || empty($this->info[
'audio'][
'channels']) || empty($this->info[
'audio'][
'sample_rate']) || !is_numeric($this->info[
'audio'][
'sample_rate'])) {
1552 $this->info[
'audio'][
'compression_ratio'] = $this->info[
'audio'][
'bitrate'] / ($this->info[
'audio'][
'channels'] * $this->info[
'audio'][
'sample_rate'] * (!empty($this->info[
'audio'][
'bits_per_sample']) ? $this->info[
'audio'][
'bits_per_sample'] : 16));
1554 if (!empty($this->info[
'audio'][
'streams'])) {
1555 foreach ($this->info[
'audio'][
'streams'] as $streamnumber => $streamdata) {
1556 if (!empty($streamdata[
'bitrate']) && !empty($streamdata[
'channels']) && !empty($streamdata[
'sample_rate'])) {
1557 $this->info[
'audio'][
'streams'][$streamnumber][
'compression_ratio'] = $streamdata[
'bitrate'] / ($streamdata[
'channels'] * $streamdata[
'sample_rate'] * (!empty($streamdata[
'bits_per_sample']) ? $streamdata[
'bits_per_sample'] : 16));
1566 if (isset($this->info[
'replay_gain'])) {
1567 if (!isset($this->info[
'replay_gain'][
'reference_volume'])) {
1568 $this->info[
'replay_gain'][
'reference_volume'] = (double) 89.0;
1570 if (isset($this->info[
'replay_gain'][
'track'][
'adjustment'])) {
1571 $this->info[
'replay_gain'][
'track'][
'volume'] = $this->info[
'replay_gain'][
'reference_volume'] - $this->info[
'replay_gain'][
'track'][
'adjustment'];
1573 if (isset($this->info[
'replay_gain'][
'album'][
'adjustment'])) {
1574 $this->info[
'replay_gain'][
'album'][
'volume'] = $this->info[
'replay_gain'][
'reference_volume'] - $this->info[
'replay_gain'][
'album'][
'adjustment'];
1577 if (isset($this->info[
'replay_gain'][
'track'][
'peak'])) {
1578 $this->info[
'replay_gain'][
'track'][
'max_noclip_gain'] = 0 -
getid3_lib::RGADamplitude2dB($this->info[
'replay_gain'][
'track'][
'peak']);
1580 if (isset($this->info[
'replay_gain'][
'album'][
'peak'])) {
1581 $this->info[
'replay_gain'][
'album'][
'max_noclip_gain'] = 0 -
getid3_lib::RGADamplitude2dB($this->info[
'replay_gain'][
'album'][
'peak']);
1588 if (!empty($this->info[
'audio'][
'bitrate']) || !empty($this->info[
'audio'][
'channels']) || !empty($this->info[
'audio'][
'sample_rate'])) {
1589 if (!isset($this->info[
'audio'][
'streams'])) {
1590 foreach ($this->info[
'audio'] as
$key => $value) {
1591 if (
$key !=
'streams') {
1592 $this->info[
'audio'][
'streams'][0][
$key] = $value;
1601 return tempnam($this->tempdir,
'gI3');
1606 if (!file_exists(GETID3_INCLUDEPATH.
'module.'.
$name.
'.php')) {
1609 include_once(GETID3_INCLUDEPATH.
'module.'.
$name.
'.php');
1623 protected $data_string_flag =
false;
1624 protected $data_string =
'';
1625 protected $data_string_position = 0;
1626 protected $data_string_length = 0;
1628 private $dependency_to = null;
1632 $this->getid3 = $getid3;
1635 $this->dependency_to = str_replace(
'getid3_',
'', $call_module);
1641 abstract public function Analyze();
1647 $this->setStringMode($string);
1650 $saved_avdataoffset = $this->getid3->info[
'avdataoffset'];
1651 $saved_avdataend = $this->getid3->info[
'avdataend'];
1652 $saved_filesize = (isset($this->getid3->info[
'filesize']) ? $this->getid3->info[
'filesize'] : null);
1655 $this->getid3->info[
'avdataoffset'] = 0;
1656 $this->getid3->info[
'avdataend'] = $this->getid3->info[
'filesize'] = $this->data_string_length;
1662 $this->getid3->info[
'avdataoffset'] = $saved_avdataoffset;
1663 $this->getid3->info[
'avdataend'] = $saved_avdataend;
1664 $this->getid3->info[
'filesize'] = $saved_filesize;
1667 $this->data_string_flag =
false;
1671 $this->data_string_flag =
true;
1672 $this->data_string = $string;
1673 $this->data_string_length = strlen($string);
1677 if ($this->data_string_flag) {
1678 return $this->data_string_position;
1680 return ftell($this->getid3->fp);
1684 if ($this->data_string_flag) {
1685 $this->data_string_position += $bytes;
1686 return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
1688 $pos = $this->ftell() + $bytes;
1690 throw new getid3_exception(
'cannot fread('.$bytes.
' from '.$this->ftell().
') because beyond PHP filesystem limit', 10);
1703 $part = fread($this->getid3->fp, $bytes);
1704 $partLength = strlen($part);
1705 $bytes -= $partLength;
1707 }
while (($bytes > 0) && ($partLength > 0));
1711 protected function fseek($bytes, $whence=SEEK_SET) {
1712 if ($this->data_string_flag) {
1715 $this->data_string_position = $bytes;
1719 $this->data_string_position += $bytes;
1723 $this->data_string_position = $this->data_string_length + $bytes;
1729 if ($whence == SEEK_CUR) {
1730 $pos = $this->ftell() + $bytes;
1731 } elseif ($whence == SEEK_END) {
1732 $pos = $this->getid3->info[
'filesize'] + $bytes;
1735 throw new getid3_exception(
'cannot fseek('.$pos.
') because beyond PHP filesystem limit', 10);
1738 return fseek($this->getid3->fp, $bytes, $whence);
1742 if ($this->data_string_flag) {
1743 return $this->data_string_position >= $this->data_string_length;
1745 return feof($this->getid3->fp);
1749 return $this->dependency_to ==
$module;
1753 $this->getid3->info[
'error'][] =
$text;
1759 return $this->getid3->warning(
$text);
1777 $this->fseek($offset);
1778 $attachment = $this->fread($length);
1779 if ($attachment ===
false || strlen($attachment) != $length) {
1780 throw new Exception(
'failed to read attachment data');
1787 $dir = rtrim(str_replace(
array(
'/',
'\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
1788 if (!is_dir($dir) || !is_writable($dir)) {
1789 throw new Exception(
'supplied path ('.$dir.
') does not exist, or is not writable');
1791 $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ?
'.'.getid3_lib::ImageExtFromMime($image_mime) :
'');
1794 if (($fp_dest = fopen($dest,
'wb')) ==
false) {
1795 throw new Exception(
'failed to create file '.$dest);
1799 $this->fseek($offset);
1800 $buffersize = ($this->data_string_flag ? $length : $this->getid3->fread_buffer_size());
1801 $bytesleft = $length;
1802 while ($bytesleft > 0) {
1803 if (($buffer = $this->fread(min($buffersize, $bytesleft))) ===
false || ($byteswritten = fwrite($fp_dest, $buffer)) ===
false || ($byteswritten === 0)) {
1804 throw new Exception($buffer ===
false ?
'not enough data to read' :
'failed to write to destination file, may be not enough disk space');
1806 $bytesleft -= $byteswritten;
1810 $attachment = $dest;
1817 if (isset($fp_dest) && is_resource($fp_dest)) {
1824 $this->
warning(
'Failed to extract attachment '.
$name.
': '.$e->getMessage());
1829 $this->fseek($offset + $length);
analyze($filename, $filesize=null, $original_filename='')
$option_fread_buffer_size
GetFileFormat(&$filedata, $filename='')
static intValueSupported($num)
saveAttachment($name, $offset, $length, $image_mime=null)
static iconv_fallback($in_charset, $out_charset, $string)
CalculateCompressionRatioAudio()
static RGADamplitude2dB($amplitude)
CharConvert(&$array, $encoding)
if($modEnd===false) $module
static getFileSizeSyscall($path)
catch(Exception $e) $message
static PlaytimeString($seconds)
__construct(getID3 $getid3, $call_module=null)
Create styles array
The data for the language used.
if(!defined('GETID3_OS_ISWINDOWS')) if(!defined('GETID3_INCLUDEPATH')) if(!defined('IMG_JPG') &&defined('IMAGETYPE_JPEG')) if(!defined('ENT_SUBSTITUTE')) $temp_dir
getID3() by James Heinrich info@getid3.org //
static hash_data($file, $offset, $end, $algorithm)
CalculateCompressionRatioVideo()
static recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1')
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
fseek($bytes, $whence=SEEK_SET)
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
openfile($filename, $filesize=null)
static mb_basename($path, $suffix=null)
Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
ChannelsBitratePlaytimeCalculations()
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag