28 public $encoding =
'UTF-8';
29 public $encoding_id3v1 =
'ISO-8859-1';
31 public $option_tag_id3v1 =
true;
32 public $option_tag_id3v2 =
true;
33 public $option_tag_lyrics3 =
true;
34 public $option_tag_apetag =
true;
35 public $option_tags_process =
true;
36 public $option_tags_html =
true;
38 public $option_extra_info =
true;
40 public $option_save_attachments =
true;
42 public $option_md5_data =
false;
43 public $option_md5_data_source =
false;
44 public $option_sha1_data =
false;
45 public $option_max_2gb_check = null;
47 public $option_fread_buffer_size = 32768;
53 protected $startup_error =
'';
54 protected $startup_warning =
'';
55 protected $memory_limit = 0;
62 const VERSION =
'1.9.4-20120530';
63 const FREAD_BUFFER_SIZE = 32768;
64 const ATTACHMENTS_NONE =
false;
65 const ATTACHMENTS_INLINE =
true;
73 $this->tempdir = self::getTempDir();
75 $required_php_version =
'5.0.5';
76 if (version_compare(PHP_VERSION, $required_php_version,
'<')) {
77 $this->startup_error .=
'getID3() requires PHP v' . $required_php_version .
' or higher - you are running v' . PHP_VERSION;
83 $this->memory_limit = ini_get(
'memory_limit');
84 if (preg_match(
'#([0-9]+)M#i', $this->memory_limit, $matches)) {
86 $this->memory_limit = $matches[1] * 1048576;
87 } elseif (preg_match(
'#([0-9]+)G#i', $this->memory_limit, $matches)) {
89 $this->memory_limit = $matches[1] * 1073741824;
91 if ($this->memory_limit <= 0) {
93 } elseif ($this->memory_limit <= 4194304) {
94 $this->startup_error .=
'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini';
95 } elseif ($this->memory_limit <= 12582912) {
96 $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';
100 if (preg_match(
'#(1|ON)#i', ini_get(
'safe_mode'))) {
101 $this->warning(
'WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
104 if (intval(ini_get(
'mbstring.func_overload')) > 0) {
105 $this->warning(
'WARNING: php.ini contains "mbstring.func_overload = ' . ini_get(
'mbstring.func_overload') .
'", this may break things.');
109 if (function_exists(
'get_magic_quotes_runtime')) {
110 if (get_magic_quotes_runtime()) {
111 return $this->startup_error(
'magic_quotes_runtime must be disabled before running GetId3Core(). Surround GetId3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).');
116 if (function_exists(
'magic_quotes_gpc')) {
117 if (get_magic_quotes_gpc()) {
118 return $this->startup_error(
'magic_quotes_gpc must be disabled before running GetId3Core(). Surround GetId3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).');
123 if (!class_exists(
'GetId3\\Lib\\Helper')) {
124 $this->startup_error .= str_replace(
'\\', DIRECTORY_SEPARATOR,
'GetId3\\Lib\\Helper') .
'.php is missing or corrupt';
127 if ($this->option_max_2gb_check === null) {
128 $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647);
131 $this->setHelperAppsDir();
147 if (self::$EnvironmentIsWindows && null === self::$HelperAppsDir) {
149 $helperappsdir = self::$IncludePath .
'Resources' . DIRECTORY_SEPARATOR .
'helperapps';
151 if (!is_dir($helperappsdir)) {
152 $this->startup_warning .=
'"' . $helperappsdir .
'" cannot be defined as self::getHelperAppsDir() because it does not exist';
153 } elseif (strpos(realpath($helperappsdir),
' ') !==
false) {
154 $DirPieces = explode(DIRECTORY_SEPARATOR,
155 realpath($helperappsdir));
156 $path_so_far =
array();
157 foreach ($DirPieces as $key => $value) {
158 if (strpos($value,
' ') !==
false) {
159 if (!empty($path_so_far)) {
160 $commandline =
'dir /x ' . escapeshellarg(implode(DIRECTORY_SEPARATOR,
162 $dir_listing = `$commandline`;
163 $lines = explode(
"\n", $dir_listing);
164 foreach ($lines as $line) {
166 if (preg_match(
'#^([0-9/]{10}) +([0-9:]{4,5}( [AP]M)?) +(<DIR>|[0-9,]+) +([^ ]{0,11}) +(.+)$#',
168 list($dummy, $date, $time, $ampm, $filesize, $shortname,
$filename) = $matches;
169 if ((strtoupper($filesize) ==
'<DIR>') && (strtolower(
$filename) == strtolower($value))) {
175 $this->startup_warning .=
'self::getHelperAppsDir() 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.';
178 $path_so_far[] = $value;
180 $helperappsdir = implode(DIRECTORY_SEPARATOR, $path_so_far);
182 self::$HelperAppsDir = $helperappsdir . DIRECTORY_SEPARATOR;
188 return self::$HelperAppsDir;
197 return self::VERSION;
206 return $this->option_fread_buffer_size;
216 if (!is_array($optArray) || empty($optArray)) {
219 foreach ($optArray as $opt => $val) {
220 if (isset($this->$opt) ===
false) {
238 if (!empty($this->startup_error)) {
239 throw new DefaultException($this->startup_error);
241 if (!empty($this->startup_warning)) {
242 $this->warning($this->startup_warning);
247 $this->info =
array();
248 $this->info[
'GETID3_VERSION'] = $this->version();
249 $this->info[
'php_memory_limit'] = $this->memory_limit;
252 if (preg_match(
'/^(ht|f)tp:\/\//',
$filename)) {
253 throw new DefaultException(
'Remote files are not supported - please copy the file locally first');
257 $filename = preg_replace(
'#(.+)' . preg_quote(DIRECTORY_SEPARATOR) .
'{2,}#U',
258 '\1' . DIRECTORY_SEPARATOR,
266 throw new DefaultException(
'Could not open "' .
$filename .
'" (does not exist, or is not a file)');
269 $this->info[
'filesize'] = filesize(
$filename);
271 $this->info[
'filename'] = basename(
$filename);
272 $this->info[
'filepath'] = str_replace(
'\\',
'/',
274 $this->info[
'filenamepath'] = $this->info[
'filepath'] .
'/' . $this->info[
'filename'];
277 if ($this->option_max_2gb_check) {
281 $fseek = fseek($this->fp, 0, SEEK_END);
282 if (($fseek < 0) || (($this->info[
'filesize'] != 0) && (ftell($this->fp) == 0)) ||
283 ($this->info[
'filesize'] < 0) ||
284 (ftell($this->fp) < 0)) {
285 $real_filesize =
false;
286 if (self::$EnvironmentIsWindows) {
287 $commandline =
'dir /-C "' . str_replace(
'/',
290 $dir_output = `$commandline`;
291 if (preg_match(
'#1 File\(s\)[ ]+([0-9]+) bytes#i',
292 $dir_output, $matches)) {
293 $real_filesize = (float) $matches[1];
296 $commandline =
'ls -o -g -G --time-style=long-iso ' . escapeshellarg(
$filename);
297 $dir_output = `$commandline`;
298 if (preg_match(
'#([0-9]+) ([0-9]{4}-[0-9]{2}\-[0-9]{2} [0-9]{2}:[0-9]{2}) ' . str_replace(
'#',
303 $real_filesize = (float) $matches[1];
306 if ($real_filesize ===
false) {
307 unset($this->info[
'filesize']);
309 throw new DefaultException(
'Unable to determine actual filesize. File is most likely larger than ' . round(PHP_INT_MAX / 1073741824) .
'GB and is not supported by PHP.');
310 } elseif (Helper::intValueSupported($real_filesize)) {
311 unset($this->info[
'filesize']);
313 throw new DefaultException(
'PHP seems to think the file is larger than ' . round(PHP_INT_MAX / 1073741824) .
'GB, but filesystem reports it as ' . number_format($real_filesize,
314 3) .
'GB, please report to info@getid3.org');
316 $this->info[
'filesize'] = $real_filesize;
317 $this->error(
'File is larger than ' . round(PHP_INT_MAX / 1073741824) .
'GB (filesystem reports it as ' . number_format($real_filesize,
318 3) .
'GB) and is not properly supported by PHP.');
323 $this->info[
'avdataoffset'] = 0;
324 $this->info[
'avdataend'] = $this->info[
'filesize'];
325 $this->info[
'fileformat'] =
'';
326 $this->info[
'audio'][
'dataformat'] =
'';
327 $this->info[
'video'][
'dataformat'] =
'';
328 $this->info[
'tags'] =
array();
329 $this->info[
'error'] =
array();
330 $this->info[
'warning'] =
array();
331 $this->info[
'comments'] =
array();
332 $this->info[
'encoding'] = $this->encoding;
335 }
catch (DefaultException $e) {
336 $this->error($e->getMessage());
356 foreach (
array(
'id3v2' =>
'id3v2',
'id3v1' =>
'id3v1',
'apetag' =>
'ape',
'lyrics3' =>
'lyrics3') as $tag_name => $tag_key) {
357 $option_tag =
'option_tag_' . $tag_name;
358 if ($this->$option_tag) {
360 $tag_class =
'GetId3\\Module\\Tag\\' . ucfirst($tag_name);
361 $tag =
new $tag_class($this);
363 }
catch (DefaultException $e) {
368 if (isset($this->info[
'id3v2'][
'tag_offset_start'])) {
369 $this->info[
'avdataoffset'] = max($this->info[
'avdataoffset'],
370 $this->info[
'id3v2'][
'tag_offset_end']);
372 foreach (
array(
'id3v1' =>
'id3v1',
'apetag' =>
'ape',
'lyrics3' =>
'lyrics3') as $tag_name => $tag_key) {
373 if (isset($this->info[$tag_key][
'tag_offset_start'])) {
374 $this->info[
'avdataend'] = min($this->info[
'avdataend'],
375 $this->info[$tag_key][
'tag_offset_start']);
380 if (!$this->option_tag_id3v2) {
381 fseek($this->fp, 0, SEEK_SET);
382 $header = fread($this->fp, 10);
383 if ((substr(
$header, 0, 3) ==
'ID3') && (strlen(
$header) == 10)) {
384 $this->info[
'id3v2'][
'header'] =
true;
385 $this->info[
'id3v2'][
'majorversion'] = ord(
$header{3});
386 $this->info[
'id3v2'][
'minorversion'] = ord(
$header{4});
387 $this->info[
'avdataoffset'] += Helper::BigEndian2Int(substr(
$header,
395 fseek($this->fp, $this->info[
'avdataoffset'], SEEK_SET);
396 $formattest = fread($this->fp, 32774);
399 $determined_format = $this->GetFileFormat($formattest,
$filename);
402 if (!$determined_format) {
405 return $this->error(
'unable to determine file format');
409 if (isset($determined_format[
'fail_id3']) && (in_array(
'id3v1',
410 $this->info[
'tags']) || in_array(
'id3v2',
411 $this->info[
'tags']))) {
412 if ($determined_format[
'fail_id3'] ===
'ERROR') {
415 return $this->error(
'ID3 tags not allowed on this file type.');
416 } elseif ($determined_format[
'fail_id3'] ===
'WARNING') {
417 $this->warning(
'ID3 tags not allowed on this file type.');
422 if (isset($determined_format[
'fail_ape']) && in_array(
'ape',
423 $this->info[
'tags'])) {
424 if ($determined_format[
'fail_ape'] ===
'ERROR') {
427 return $this->error(
'APE tags not allowed on this file type.');
428 } elseif ($determined_format[
'fail_ape'] ===
'WARNING') {
429 $this->warning(
'APE tags not allowed on this file type.');
434 $this->info[
'mime_type'] = $determined_format[
'mime_type'];
437 if (!class_exists($determined_format[
'class'])) {
440 return $this->error(
'Format not supported, module "' . $determined_format[
'include'] .
'" was removed.');
445 if (!empty($determined_format[
'iconv_req']) && !function_exists(
'iconv') && !in_array($this->encoding,
446 array(
'ISO-8859-1',
'UTF-8',
'UTF-16LE',
'UTF-16BE',
'UTF-16'))) {
447 $errormessage =
'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. ';
448 if (self::$EnvironmentIsWindows) {
449 $errormessage .=
'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32';
451 $errormessage .=
'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
454 return $this->error($errormessage);
458 $class_name =
'GetId3\\Module\\' . Helper::toCamelCase($determined_format[
'group'],
'-',
true) .
'\\' . ucfirst($determined_format[
'module']);
459 if (!class_exists($class_name)) {
460 return $this->error(
'Format not supported, module "' . $determined_format[
'include'] .
'" is corrupt.');
466 $class =
new $class_name($this);
469 if (!empty($determined_format[
'set_inline_attachments'])) {
470 $class->inline_attachments = $this->option_save_attachments;
480 if ($this->option_tags_process) {
481 $this->HandleAllTags();
485 if ($this->option_extra_info) {
486 $this->ChannelsBitratePlaytimeCalculations();
487 $this->CalculateCompressionRatioVideo();
488 $this->CalculateCompressionRatioAudio();
489 $this->CalculateReplayGain();
490 $this->ProcessAudioStreams();
494 if ($this->option_md5_data) {
496 if (!$this->option_md5_data_source || empty($this->info[
'md5_data_source'])) {
497 $this->getHashdata(
'md5');
502 if ($this->option_sha1_data) {
503 $this->getHashdata(
'sha1');
509 $this->error(
'Caught exception: ' . $e->getMessage());
524 if (!isset($this->info[
'error'])) {
525 $this->info[
'error'] =
array();
527 $this->info[
'error'][] = $message;
539 $this->info[
'warning'][] = $message;
552 $AVpossibleEmptyKeys =
array(
'dataformat',
'bits_per_sample',
'encoder_options',
'streams',
'bitrate');
553 foreach ($AVpossibleEmptyKeys as $dummy => $key) {
554 if (empty($this->info[
'audio'][$key]) && isset($this->info[
'audio'][$key])) {
555 unset($this->info[
'audio'][$key]);
557 if (empty($this->info[
'video'][$key]) && isset($this->info[
'video'][$key])) {
558 unset($this->info[
'video'][$key]);
563 if (!empty($this->info)) {
564 foreach ($this->info as $key => $value) {
565 if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !==
'0')) {
566 unset($this->info[$key]);
572 if (empty($this->info[
'fileformat'])) {
573 if (isset($this->info[
'avdataoffset'])) {
574 unset($this->info[
'avdataoffset']);
576 if (isset($this->info[
'avdataend'])) {
577 unset($this->info[
'avdataend']);
582 if (!empty($this->info[
'error'])) {
583 $this->info[
'error'] = array_values(array_unique($this->info[
'error']));
585 if (!empty($this->info[
'warning'])) {
586 $this->info[
'warning'] = array_values(array_unique($this->info[
'warning']));
590 unset($this->info[
'php_memory_limit']);
602 static $format_info =
array();
603 if (empty($format_info)) {
604 $format_info =
array(
608 'pattern' =>
'^\x0B\x77',
611 'mime_type' =>
'audio/ac3',
615 'pattern' =>
'^ADIF',
618 'mime_type' =>
'application/octet-stream',
619 'fail_ape' =>
'WARNING',
623 'pattern' =>
'^.{4}\x57\x90\x75\x36',
626 'mime_type' =>
'audio/audible',
630 'pattern' =>
'^\xFF[\xF0-\xF1\xF8-\xF9]',
633 'mime_type' =>
'application/octet-stream',
634 'fail_ape' =>
'WARNING',
638 'pattern' =>
'^\.snd',
641 'mime_type' =>
'audio/basic',
645 'pattern' =>
'^2BIT',
648 'mime_type' =>
'application/octet-stream',
652 'pattern' =>
'^\x00(BONK|INFO|META| ID3)',
655 'mime_type' =>
'audio/xmms-bonk',
659 'pattern' =>
'^[\x02-\x03]dss',
662 'mime_type' =>
'application/octet-stream',
666 'pattern' =>
'^\x7F\xFE\x80\x01',
669 'mime_type' =>
'audio/dts',
673 'pattern' =>
'^fLaC',
676 'mime_type' =>
'audio/x-flac',
677 'set_inline_attachments' =>
true,
681 'pattern' =>
'^LA0[2-4]',
684 'mime_type' =>
'application/octet-stream',
688 'pattern' =>
'^LPAC',
691 'mime_type' =>
'application/octet-stream',
695 'pattern' =>
'^MThd',
698 'mime_type' =>
'audio/midi',
702 'pattern' =>
'^MAC ',
704 'module' =>
'monkey',
705 'mime_type' =>
'application/octet-stream',
718 'pattern' =>
'^IMPM',
722 'mime_type' =>
'audio/it',
726 'pattern' =>
'^Extended Module',
730 'mime_type' =>
'audio/xm',
734 'pattern' =>
'^.{44}SCRM',
738 'mime_type' =>
'audio/s3m',
742 'pattern' =>
'^(MPCK|MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])',
745 'mime_type' =>
'audio/x-musepack',
749 '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]',
752 'mime_type' =>
'audio/mpeg',
756 'pattern' =>
'^(\*RIFF|OFR)',
758 'module' =>
'optimfrog',
759 'mime_type' =>
'application/octet-stream',
766 'mime_type' =>
'application/octet-stream',
770 'pattern' =>
'^ajkg',
772 'module' =>
'shorten',
773 'mime_type' =>
'audio/xmms-shn',
774 'fail_id3' =>
'ERROR',
775 'fail_ape' =>
'ERROR',
782 'mime_type' =>
'application/octet-stream',
786 'pattern' =>
'^Creative Voice File',
789 'mime_type' =>
'audio/voc',
793 'pattern' =>
'^TWIN',
796 'mime_type' =>
'application/octet-stream',
800 'pattern' =>
'^wvpk',
802 'module' =>
'wavpack',
803 'mime_type' =>
'application/octet-stream',
808 'pattern' =>
'^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
809 'group' =>
'audio-video',
811 'mime_type' =>
'video/x-ms-asf',
812 'iconv_req' =>
false,
816 'pattern' =>
'^(BIK|SMK)',
817 'group' =>
'audio-video',
819 'mime_type' =>
'application/octet-stream',
823 'pattern' =>
'^FLV\x01',
824 'group' =>
'audio-video',
826 'mime_type' =>
'video/x-flv',
830 'pattern' =>
'^\x1A\x45\xDF\xA3',
831 'group' =>
'audio-video',
832 'module' =>
'matroska',
833 'mime_type' =>
'video/x-matroska',
834 'set_inline_attachments' =>
true,
838 'pattern' =>
'^\x00\x00\x01(\xBA|\xB3)',
839 'group' =>
'audio-video',
841 'mime_type' =>
'video/mpeg',
845 'pattern' =>
'^NSV[sf]',
846 'group' =>
'audio-video',
848 'mime_type' =>
'application/octet-stream',
852 'pattern' =>
'^OggS',
855 'mime_type' =>
'application/ogg',
856 'fail_id3' =>
'WARNING',
857 'fail_ape' =>
'WARNING',
858 'set_inline_attachments' =>
true,
861 'quicktime' =>
array(
862 'pattern' =>
'^.{4}(cmov|free|ftyp|mdat|moov|pnot|skip|wide)',
863 'group' =>
'audio-video',
864 'module' =>
'quicktime',
865 'mime_type' =>
'video/quicktime',
869 'pattern' =>
'^(RIFF|SDSS|FORM)',
870 'group' =>
'audio-video',
872 'mime_type' =>
'audio/x-wave',
873 'fail_ape' =>
'WARNING',
877 'pattern' =>
'^(\\.RMF|\\.ra)',
878 'group' =>
'audio-video',
880 'mime_type' =>
'audio/x-realaudio',
884 'pattern' =>
'^(F|C)WS',
885 'group' =>
'audio-video',
887 'mime_type' =>
'application/x-shockwave-flash',
891 'pattern' =>
'^\x47',
892 'group' =>
'audio-video',
894 'mime_type' =>
'video/MP2T',
900 'group' =>
'graphic',
902 'mime_type' =>
'image/bmp',
903 'fail_id3' =>
'ERROR',
904 'fail_ape' =>
'ERROR',
909 'group' =>
'graphic',
911 'mime_type' =>
'image/gif',
912 'fail_id3' =>
'ERROR',
913 'fail_ape' =>
'ERROR',
917 'pattern' =>
'^\xFF\xD8\xFF',
918 'group' =>
'graphic',
920 'mime_type' =>
'image/jpeg',
921 'fail_id3' =>
'ERROR',
922 'fail_ape' =>
'ERROR',
926 'pattern' =>
'^.{2048}PCD_IPI\x00',
927 'group' =>
'graphic',
929 'mime_type' =>
'image/x-photo-cd',
930 'fail_id3' =>
'ERROR',
931 'fail_ape' =>
'ERROR',
935 'pattern' =>
'^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A',
936 'group' =>
'graphic',
938 'mime_type' =>
'image/png',
939 'fail_id3' =>
'ERROR',
940 'fail_ape' =>
'ERROR',
944 'pattern' =>
'(<!DOCTYPE svg PUBLIC |xmlns="http:\/\/www\.w3\.org\/2000\/svg")',
945 'group' =>
'graphic',
947 'mime_type' =>
'image/svg+xml',
948 'fail_id3' =>
'ERROR',
949 'fail_ape' =>
'ERROR',
953 'pattern' =>
'^(II\x2A\x00|MM\x00\x2A)',
954 'group' =>
'graphic',
956 'mime_type' =>
'image/tiff',
957 'fail_id3' =>
'ERROR',
958 'fail_ape' =>
'ERROR',
962 'pattern' =>
'^\xDC\xFE',
963 'group' =>
'graphic',
965 'mime_type' =>
'image/efax',
966 'fail_id3' =>
'ERROR',
967 'fail_ape' =>
'ERROR',
972 'pattern' =>
'^.{32769}CD001',
975 'mime_type' =>
'application/octet-stream',
976 'fail_id3' =>
'ERROR',
977 'fail_ape' =>
'ERROR',
978 'iconv_req' =>
false,
982 'pattern' =>
'^Rar\!',
983 'group' =>
'archive',
985 'mime_type' =>
'application/octet-stream',
986 'fail_id3' =>
'ERROR',
987 'fail_ape' =>
'ERROR',
991 'pattern' =>
'^SZ\x0A\x04',
992 'group' =>
'archive',
994 'mime_type' =>
'application/octet-stream',
995 'fail_id3' =>
'ERROR',
996 'fail_ape' =>
'ERROR',
1000 '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}',
1001 'group' =>
'archive',
1003 'mime_type' =>
'application/x-tar',
1004 'fail_id3' =>
'ERROR',
1005 'fail_ape' =>
'ERROR',
1009 'pattern' =>
'^\x1F\x8B\x08',
1010 'group' =>
'archive',
1012 'mime_type' =>
'application/x-gzip',
1013 'fail_id3' =>
'ERROR',
1014 'fail_ape' =>
'ERROR',
1018 'pattern' =>
'^PK\x03\x04',
1019 'group' =>
'archive',
1021 'mime_type' =>
'application/zip',
1022 'fail_id3' =>
'ERROR',
1023 'fail_ape' =>
'ERROR',
1028 'pattern' =>
'^PAR2\x00PKT',
1031 'mime_type' =>
'application/octet-stream',
1032 'fail_id3' =>
'ERROR',
1033 'fail_ape' =>
'ERROR',
1037 'pattern' =>
'^\x25PDF',
1040 'mime_type' =>
'application/pdf',
1041 'fail_id3' =>
'ERROR',
1042 'fail_ape' =>
'ERROR',
1045 'msoffice' =>
array(
1046 'pattern' =>
'^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1',
1048 'module' =>
'msoffice',
1049 'mime_type' =>
'application/octet-stream',
1050 'fail_id3' =>
'ERROR',
1051 'fail_ape' =>
'ERROR',
1058 'mime_type' =>
'application/octet-stream',
1063 return $format_info;
1079 $GetFileFormatArray = $this->GetFileFormatArray();
1080 foreach ($GetFileFormatArray as $format_name =>
$info) {
1083 if (!empty(
$info[
'pattern'])
1084 && preg_match(
'#' .
$info[
'pattern'] .
'#s', $filedata)
1086 $info[
'class'] =
'GetId3\\Module\\' . Helper::toCamelCase(
$info[
'group'],
'-',
true) .
'\\' . ucfirst(
$info[
'module']);
1087 $info[
'include'] = str_replace(
'\\', DIRECTORY_SEPARATOR,
$info[
'class']) .
'.php';
1093 if (preg_match(
'#\.mp[123a]$#i',
$filename)) {
1096 $info = $GetFileFormatArray[
'mp3'];
1097 $info[
'class'] =
'GetId3\\Module\\' . Helper::toCamelCase(
$info[
'group'],
'-',
true) .
'\\' . ucfirst(
$info[
'module']);
1098 $info[
'include'] = str_replace(
'\\', DIRECTORY_SEPARATOR,
$info[
'class']) .
'.php';
1101 } elseif (preg_match(
'/\.cue$/i',
$filename) && preg_match(
'#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#',
1106 $info = $GetFileFormatArray[
'cue'];
1107 $info[
'class'] =
'GetId3\\Module\\' . Helper::toCamelCase(
$info[
'group'],
'-',
true) .
'\\' . ucfirst(
$info[
'module']);
1108 $info[
'include'] = str_replace(
'\\', DIRECTORY_SEPARATOR,
$info[
'class']) .
'.php';
1126 if ($encoding == $this->encoding) {
1131 foreach ($array as $key => $value) {
1134 if (is_array($value)) {
1135 $this->CharConvert($array[$key], $encoding);
1139 elseif (is_string($value)) {
1140 $array[$key] = trim(Helper::iconv_fallback($encoding,
1159 'asf' =>
array(
'asf',
'UTF-16LE'),
1160 'midi' =>
array(
'midi',
'ISO-8859-1'),
1161 'nsv' =>
array(
'nsv',
'ISO-8859-1'),
1162 'ogg' =>
array(
'vorbiscomment',
'UTF-8'),
1163 'png' =>
array(
'png',
'UTF-8'),
1164 'tiff' =>
array(
'tiff',
'ISO-8859-1'),
1165 'quicktime' =>
array(
'quicktime',
'UTF-8'),
1166 'real' =>
array(
'real',
'ISO-8859-1'),
1167 'vqf' =>
array(
'vqf',
'ISO-8859-1'),
1168 'zip' =>
array(
'zip',
'ISO-8859-1'),
1169 'riff' =>
array(
'riff',
'ISO-8859-1'),
1170 'lyrics3' =>
array(
'lyrics3',
'ISO-8859-1'),
1171 'id3v1' =>
array(
'id3v1', $this->encoding_id3v1),
1172 'id3v2' =>
array(
'id3v2',
'UTF-8'),
1173 'ape' =>
array(
'ape',
'UTF-8'),
1174 'cue' =>
array(
'cue',
'ISO-8859-1'),
1175 'matroska' =>
array(
'matroska',
'UTF-8'),
1176 'flac' =>
array(
'vorbiscomment',
'UTF-8'),
1181 foreach ($tags as $comment_name => $tagname_encoding_array) {
1182 list($tag_name, $encoding) = $tagname_encoding_array;
1185 if (isset($this->info[$comment_name]) && !isset($this->info[$comment_name][
'encoding'])) {
1186 $this->info[$comment_name][
'encoding'] = $encoding;
1190 if (!empty($this->info[$comment_name][
'comments'])) {
1191 foreach ($this->info[$comment_name][
'comments'] as $tag_key => $valuearray) {
1192 foreach ($valuearray as $key => $value) {
1193 if (is_string($value)) {
1194 $value = trim($value,
" \r\n\t");
1197 $this->info[
'tags'][trim($tag_name)][trim($tag_key)][] = $value;
1200 if ($tag_key ==
'picture') {
1201 unset($this->info[$comment_name][
'comments'][$tag_key]);
1205 if (!isset($this->info[
'tags'][$tag_name])) {
1210 if ($this->option_tags_html) {
1211 foreach ($this->info[
'tags'][$tag_name] as $tag_key => $valuearray) {
1212 foreach ($valuearray as $key => $value) {
1213 if (is_string($value)) {
1215 $this->info[
'tags_html'][$tag_name][$tag_key][$key] = str_replace(
'�',
1217 trim(Helper::MultiByteCharString2HTML($value,
1220 $this->info[
'tags_html'][$tag_name][$tag_key][$key] = $value;
1226 $this->CharConvert($this->info[
'tags'][$tag_name], $encoding);
1232 if (!empty($this->info[
'tags'])) {
1233 $unset_keys =
array(
'tags',
'tags_html');
1234 foreach ($this->info[
'tags'] as $tagtype => $tagarray) {
1235 foreach ($tagarray as $tagname => $tagdata) {
1236 if ($tagname ==
'picture') {
1237 foreach ($tagdata as $key => $tagarray) {
1238 $this->info[
'comments'][
'picture'][] = $tagarray;
1239 if (isset($tagarray[
'data']) && isset($tagarray[
'image_mime'])) {
1240 if (isset($this->info[
'tags'][$tagtype][$tagname][$key])) {
1241 unset($this->info[
'tags'][$tagtype][$tagname][$key]);
1243 if (isset($this->info[
'tags_html'][$tagtype][$tagname][$key])) {
1244 unset($this->info[
'tags_html'][$tagtype][$tagname][$key]);
1250 foreach ($unset_keys as $unset_key) {
1252 if (empty($this->info[$unset_key][$tagtype][
'picture'])) {
1253 unset($this->info[$unset_key][$tagtype][
'picture']);
1255 if (empty($this->info[$unset_key][$tagtype])) {
1256 unset($this->info[$unset_key][$tagtype]);
1258 if (empty($this->info[$unset_key])) {
1259 unset($this->info[$unset_key]);
1263 if (isset($this->info[$tagtype][
'comments'][
'picture'])) {
1264 unset($this->info[$tagtype][
'comments'][
'picture']);
1266 if (empty($this->info[$tagtype][
'comments'])) {
1267 unset($this->info[$tagtype][
'comments']);
1269 if (empty($this->info[$tagtype])) {
1270 unset($this->info[$tagtype]);
1285 switch ($algorithm) {
1291 return $this->error(
'bad algorithm "' . $algorithm .
'" in getHashdata()');
1295 if (!empty($this->info[
'fileformat']) && !empty($this->info[
'dataformat']) && ($this->info[
'fileformat'] ==
'ogg') && ($this->info[
'audio'][
'dataformat'] ==
'vorbis')) {
1314 if (preg_match(
'#(1|ON)#i', ini_get(
'safe_mode'))) {
1316 $this->warning(
'Failed making system call to vorbiscomment.exe - ' . $algorithm .
'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)');
1317 $this->info[$algorithm .
'_data'] =
false;
1321 $old_abort = ignore_user_abort(
true);
1324 $empty = tempnam(self::getTempDir(),
'getID3');
1328 $temp = tempnam(self::getTempDir(),
'getID3');
1329 $file = $this->info[
'filenamepath'];
1331 if (self::$EnvironmentIsWindows) {
1333 if (file_exists(self::getHelperAppsDir() .
'vorbiscomment.exe')) {
1335 $commandline =
'"' . self::getHelperAppsDir() .
'vorbiscomment.exe" -w -c "' . $empty .
'" "' .
$file .
'" "' . $temp .
'"';
1336 $VorbisCommentError = `$commandline`;
1339 $VorbisCommentError =
'vorbiscomment.exe not found in ' . self::getHelperAppsDir();
1343 $commandline =
'vorbiscomment -w -c "' . $empty .
'" "' .
$file .
'" "' . $temp .
'" 2>&1';
1344 $commandline =
'vorbiscomment -w -c ' . escapeshellarg($empty) .
' ' . escapeshellarg(
$file) .
' ' . escapeshellarg($temp) .
' 2>&1';
1345 $VorbisCommentError = `$commandline`;
1348 if (!empty($VorbisCommentError)) {
1350 $this->info[
'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 GetId3Core() directory. Error returned: ' . $VorbisCommentError;
1351 $this->info[$algorithm .
'_data'] =
false;
1355 switch ($algorithm) {
1357 $this->info[$algorithm .
'_data'] = md5_file($temp);
1361 $this->info[$algorithm .
'_data'] = sha1_file($temp);
1371 ignore_user_abort($old_abort);
1375 if (!empty($this->info[
'avdataoffset']) || (isset($this->info[
'avdataend']) && ($this->info[
'avdataend'] < $this->info[
'filesize']))) {
1378 $this->info[$algorithm .
'_data'] = Helper::hash_data($this->info[
'filenamepath'],
1379 $this->info[
'avdataoffset'],
1380 $this->info[
'avdataend'],
1385 switch ($algorithm) {
1387 $this->info[$algorithm .
'_data'] = md5_file($this->info[
'filenamepath']);
1391 $this->info[$algorithm .
'_data'] = sha1_file($this->info[
'filenamepath']);
1407 if (!empty($this->info[
'audio'][
'channelmode']) || !isset($this->info[
'audio'][
'channels'])) {
1409 } elseif ($this->info[
'audio'][
'channels'] == 1) {
1410 $this->info[
'audio'][
'channelmode'] =
'mono';
1411 } elseif ($this->info[
'audio'][
'channels'] == 2) {
1412 $this->info[
'audio'][
'channelmode'] =
'stereo';
1416 $CombinedBitrate = 0;
1417 $CombinedBitrate += (isset($this->info[
'audio'][
'bitrate']) ? $this->info[
'audio'][
'bitrate'] : 0);
1418 $CombinedBitrate += (isset($this->info[
'video'][
'bitrate']) ? $this->info[
'video'][
'bitrate'] : 0);
1419 if (($CombinedBitrate > 0) && empty($this->info[
'bitrate'])) {
1420 $this->info[
'bitrate'] = $CombinedBitrate;
1428 if (isset($this->info[
'video'][
'dataformat']) && $this->info[
'video'][
'dataformat'] && (!isset($this->info[
'video'][
'bitrate']) || ($this->info[
'video'][
'bitrate'] == 0))) {
1430 if (isset($this->info[
'audio'][
'bitrate']) && ($this->info[
'audio'][
'bitrate'] > 0) && ($this->info[
'audio'][
'bitrate'] == $this->info[
'bitrate'])) {
1432 if (isset($this->info[
'playtime_seconds']) && ($this->info[
'playtime_seconds'] > 0)) {
1434 if (isset($this->info[
'avdataend']) && isset($this->info[
'avdataoffset'])) {
1437 $this->info[
'bitrate'] = round((($this->info[
'avdataend'] - $this->info[
'avdataoffset']) * 8) / $this->info[
'playtime_seconds']);
1438 $this->info[
'video'][
'bitrate'] = $this->info[
'bitrate'] - $this->info[
'audio'][
'bitrate'];
1444 if ((!isset($this->info[
'playtime_seconds']) || ($this->info[
'playtime_seconds'] <= 0)) && !empty($this->info[
'bitrate'])) {
1445 $this->info[
'playtime_seconds'] = (($this->info[
'avdataend'] - $this->info[
'avdataoffset']) * 8) / $this->info[
'bitrate'];
1448 if (!isset($this->info[
'bitrate']) && !empty($this->info[
'playtime_seconds'])) {
1449 $this->info[
'bitrate'] = (($this->info[
'avdataend'] - $this->info[
'avdataoffset']) * 8) / $this->info[
'playtime_seconds'];
1451 if (isset($this->info[
'bitrate']) && empty($this->info[
'audio'][
'bitrate']) && empty($this->info[
'video'][
'bitrate'])) {
1452 if (isset($this->info[
'audio'][
'dataformat']) && empty($this->info[
'video'][
'resolution_x'])) {
1454 $this->info[
'audio'][
'bitrate'] = $this->info[
'bitrate'];
1455 } elseif (isset($this->info[
'video'][
'resolution_x']) && empty($this->info[
'audio'][
'dataformat'])) {
1457 $this->info[
'video'][
'bitrate'] = $this->info[
'bitrate'];
1462 if (!empty($this->info[
'playtime_seconds']) && empty($this->info[
'playtime_string'])) {
1463 $this->info[
'playtime_string'] = Helper::PlaytimeString($this->info[
'playtime_seconds']);
1473 if (empty($this->info[
'video'])) {
1476 if (empty($this->info[
'video'][
'resolution_x']) || empty($this->info[
'video'][
'resolution_y'])) {
1479 if (empty($this->info[
'video'][
'bits_per_sample'])) {
1483 switch ($this->info[
'video'][
'dataformat']) {
1491 $PlaytimeSeconds = 1;
1492 $BitrateCompressed = $this->info[
'filesize'] * 8;
1496 if (!empty($this->info[
'video'][
'frame_rate'])) {
1497 $FrameRate = $this->info[
'video'][
'frame_rate'];
1501 if (!empty($this->info[
'playtime_seconds'])) {
1502 $PlaytimeSeconds = $this->info[
'playtime_seconds'];
1506 if (!empty($this->info[
'video'][
'bitrate'])) {
1507 $BitrateCompressed = $this->info[
'video'][
'bitrate'];
1513 $BitrateUncompressed = $this->info[
'video'][
'resolution_x'] * $this->info[
'video'][
'resolution_y'] * $this->info[
'video'][
'bits_per_sample'] * $FrameRate;
1515 $this->info[
'video'][
'compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
1526 if (empty($this->info[
'audio'][
'bitrate']) || empty($this->info[
'audio'][
'channels']) || empty($this->info[
'audio'][
'sample_rate'])) {
1529 $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));
1531 if (!empty($this->info[
'audio'][
'streams'])) {
1532 foreach ($this->info[
'audio'][
'streams'] as $streamnumber => $streamdata) {
1533 if (!empty($streamdata[
'bitrate']) && !empty($streamdata[
'channels']) && !empty($streamdata[
'sample_rate'])) {
1534 $this->info[
'audio'][
'streams'][$streamnumber][
'compression_ratio'] = $streamdata[
'bitrate'] / ($streamdata[
'channels'] * $streamdata[
'sample_rate'] * (!empty($streamdata[
'bits_per_sample']) ? $streamdata[
'bits_per_sample'] : 16));
1548 if (isset($this->info[
'replay_gain'])) {
1549 if (!isset($this->info[
'replay_gain'][
'reference_volume'])) {
1550 $this->info[
'replay_gain'][
'reference_volume'] = (double) 89.0;
1552 if (isset($this->info[
'replay_gain'][
'track'][
'adjustment'])) {
1553 $this->info[
'replay_gain'][
'track'][
'volume'] = $this->info[
'replay_gain'][
'reference_volume'] - $this->info[
'replay_gain'][
'track'][
'adjustment'];
1555 if (isset($this->info[
'replay_gain'][
'album'][
'adjustment'])) {
1556 $this->info[
'replay_gain'][
'album'][
'volume'] = $this->info[
'replay_gain'][
'reference_volume'] - $this->info[
'replay_gain'][
'album'][
'adjustment'];
1559 if (isset($this->info[
'replay_gain'][
'track'][
'peak'])) {
1560 $this->info[
'replay_gain'][
'track'][
'max_noclip_gain'] = 0 - Helper::RGADamplitude2dB($this->info[
'replay_gain'][
'track'][
'peak']);
1562 if (isset($this->info[
'replay_gain'][
'album'][
'peak'])) {
1563 $this->info[
'replay_gain'][
'album'][
'max_noclip_gain'] = 0 - Helper::RGADamplitude2dB($this->info[
'replay_gain'][
'album'][
'peak']);
1576 if (!empty($this->info[
'audio'][
'bitrate']) || !empty($this->info[
'audio'][
'channels']) || !empty($this->info[
'audio'][
'sample_rate'])) {
1577 if (!isset($this->info[
'audio'][
'streams'])) {
1578 foreach ($this->info[
'audio'] as $key => $value) {
1579 if ($key !=
'streams') {
1580 $this->info[
'audio'][
'streams'][0][$key] = $value;
1595 return tempnam($this->tempdir,
'gI3');
1603 if (null === self::$TempDir) {
1604 $temp_dir = ini_get(
'upload_tmp_dir');
1605 if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) {
1608 if (!$temp_dir && function_exists(
'sys_get_temp_dir')) {
1611 $temp_dir = sys_get_temp_dir();
1613 $temp_dir = realpath($temp_dir);
1614 $open_basedir = ini_get(
'open_basedir');
1616 if ($open_basedir) {
1618 $temp_dir = str_replace(
array(
'/',
'\\'), DIRECTORY_SEPARATOR,
1620 $open_basedir = str_replace(
array(
'/',
'\\'),
1621 DIRECTORY_SEPARATOR, $open_basedir);
1622 if (substr($temp_dir, -1, 1) != DIRECTORY_SEPARATOR) {
1623 $temp_dir .= DIRECTORY_SEPARATOR;
1625 $found_valid_tempdir =
false;
1626 $open_basedirs = explode(
':', $open_basedir);
1627 foreach ($open_basedirs as $basedir) {
1628 if (substr($basedir, -1, 1) != DIRECTORY_SEPARATOR) {
1629 $basedir .= DIRECTORY_SEPARATOR;
1631 if (preg_match(
'#^' . preg_quote($basedir) .
'#', $temp_dir)) {
1632 $found_valid_tempdir =
true;
1636 if (!$found_valid_tempdir) {
1639 unset($open_basedirs, $found_valid_tempdir, $basedir);
1644 self::$TempDir = $temp_dir;
1645 unset($open_basedir, $temp_dir);
1648 return self::$TempDir;
1658 if (null === self::$EnvironmentIsWindows) {
1659 self::$EnvironmentIsWindows = strtolower(substr(PHP_OS, 0, 3)) ==
'win';
1662 return self::$EnvironmentIsWindows;
1671 if (null === self::$IncludePath) {
1672 foreach (get_included_files() as $val) {
1673 if (basename($val) ==
'getid3.php') {
1674 self::$IncludePath = dirname($val) . DIRECTORY_SEPARATOR;
1680 return self::$IncludePath;
CleanUp()
private: CleanUp
CalculateCompressionRatioVideo()
GetFileFormat(&$filedata, $filename='')
warning($message)
private: warning handling
__construct()
public: constructor
error($message)
private: error handling
CharConvert(&$array, $encoding)
ChannelsBitratePlaytimeCalculations()
static $EnvironmentIsWindows
GetFileFormatArray()
array $format_info
static environmentIsWindows()
GetId3() by James Heinrich info@getid3.org //.
Create styles array
The data for the language used.
setOption($optArray)
public: setOption
HandleAllTags()
array $tags
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
CalculateCompressionRatioAudio()
static getHelperAppsDir()
analyze($filename)
public: analyze file