rtMedia for WordPress, BuddyPress and bbPress - Version 3.8.20

Version Description

  • Fix getid3 related issue
  • Other bug fixes
Download this release

Release Info

Developer rtcamp
Plugin Icon 128x128 rtMedia for WordPress, BuddyPress and bbPress
Version 3.8.20
Comparing to
See all releases

Code changes from version 3.8.19 to 3.8.20

app/main/controllers/activity/RTMediaBuddyPressActivity.php CHANGED
@@ -330,7 +330,7 @@ class RTMediaBuddyPressActivity {
330
if( defined( $media_const ) ){
331
$media_str = constant( $media_const );
332
} else {
333
- $media_str = __( 'media', 'rtmedia' );
334
}
335
336
$action = '';
@@ -345,7 +345,7 @@ class RTMediaBuddyPressActivity {
345
&& count( array_unique( $rtmedia_media_type_array[ $activities[ $index ]->id ] ) ) == 1 ) {
346
$action = sprintf( __( '%s added %d %s', 'rtmedia' ), $user_link, $count, $media_str );
347
} else {
348
- $action = sprintf( __( '%s added %d %s', 'rtmedia' ), $user_link, $count, __( 'media', 'rtmedia' ) );
349
}
350
}
351
330
if( defined( $media_const ) ){
331
$media_str = constant( $media_const );
332
} else {
333
+ $media_str = RTMEDIA_MEDIA_SLUG;
334
}
335
336
$action = '';
345
&& count( array_unique( $rtmedia_media_type_array[ $activities[ $index ]->id ] ) ) == 1 ) {
346
$action = sprintf( __( '%s added %d %s', 'rtmedia' ), $user_link, $count, $media_str );
347
} else {
348
+ $action = sprintf( __( '%s added %d %s', 'rtmedia' ), $user_link, $count, RTMEDIA_MEDIA_SLUG );
349
}
350
}
351
app/main/controllers/upload/processors/RTMediaUploadFile.php CHANGED
@@ -43,6 +43,8 @@ class RTMediaUploadFile {
43
include_once( ABSPATH . 'wp-admin/includes/image.php' );
44
45
$upload_type = $this->fake ? 'wp_handle_sideload' : 'wp_handle_upload';
46
global $rt_set_filter_uplaod_dir;
47
if ( ! isset( $rt_set_filter_uplaod_dir ) ){
48
add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
43
include_once( ABSPATH . 'wp-admin/includes/image.php' );
44
45
$upload_type = $this->fake ? 'wp_handle_sideload' : 'wp_handle_upload';
46
+
47
+ //todo why use $rt_set_filter_uplaod_dir global variable if we can remove filter for upload_dir after upload finish
48
global $rt_set_filter_uplaod_dir;
49
if ( ! isset( $rt_set_filter_uplaod_dir ) ){
50
add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
index.php CHANGED
@@ -4,7 +4,7 @@
4
Plugin Name: rtMedia for WordPress, BuddyPress and bbPress
5
Plugin URI: http://rtcamp.com/rtmedia/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
6
Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously!
7
- Version: 3.8.19
8
Author: rtCamp
9
Text Domain: rtmedia
10
Author URI: http://rtcamp.com/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
4
Plugin Name: rtMedia for WordPress, BuddyPress and bbPress
5
Plugin URI: http://rtcamp.com/rtmedia/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
6
Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously!
7
+ Version: 3.8.20
8
Author: rtCamp
9
Text Domain: rtmedia
10
Author URI: http://rtcamp.com/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
lib/getid3/getid3.php CHANGED
@@ -77,244 +77,244 @@ if ( class_exists ( "getid3_exception" ) ) {
77
return;
78
}
79
80
81
82
- class getID3
83
- {
84
- // public: Settings
85
- public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE
86
- public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
87
-
88
- // public: Optional tag checks - disable for speed.
89
- public $option_tag_id3v1 = true; // Read and process ID3v1 tags
90
- public $option_tag_id3v2 = true; // Read and process ID3v2 tags
91
- public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags
92
- public $option_tag_apetag = true; // Read and process APE tags
93
- public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding
94
- public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
95
-
96
- // public: Optional tag/comment calucations
97
- public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc
98
-
99
- // public: Optional handling of embedded attachments (e.g. images)
100
- public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility
101
-
102
- // public: Optional calculations
103
- public $option_md5_data = false; // Get MD5 sum of data part - slow
104
- public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG
105
- public $option_sha1_data = false; // Get SHA1 sum of data part - slow
106
- public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX)
107
-
108
- // public: Read buffer size in bytes
109
- public $option_fread_buffer_size = 32768;
110
-
111
- // Public variables
112
- public $filename; // Filename of file being analysed.
113
- public $fp; // Filepointer to file being analysed.
114
- public $info; // Result array.
115
- public $tempdir = GETID3_TEMP_DIR;
116
- public $memory_limit = 0;
117
-
118
- // Protected variables
119
- protected $startup_error = '';
120
- protected $startup_warning = '';
121
-
122
- const VERSION = '1.9.10-20150914';
123
- const FREAD_BUFFER_SIZE = 32768;
124
-
125
- const ATTACHMENTS_NONE = false;
126
- const ATTACHMENTS_INLINE = true;
127
-
128
- // public: constructor
129
- public function __construct() {
130
-
131
- // Check for PHP version
132
- $required_php_version = '5.3.0';
133
- if (version_compare(PHP_VERSION, $required_php_version, '<')) {
134
- $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION;
135
- return false;
136
- }
137
-
138
- // Check memory
139
- $this->memory_limit = ini_get('memory_limit');
140
- if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
141
- // could be stored as "16M" rather than 16777216 for example
142
- $this->memory_limit = $matches[1] * 1048576;
143
- } elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
144
- // could be stored as "2G" rather than 2147483648 for example
145
- $this->memory_limit = $matches[1] * 1073741824;
146
- }
147
- if ($this->memory_limit <= 0) {
148
- // memory limits probably disabled
149
- } elseif ($this->memory_limit <= 4194304) {
150
- $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini';
151
- } elseif ($this->memory_limit <= 12582912) {
152
- $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';
153
- }
154
155
- // Check safe_mode off
156
- if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
157
- $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
158
- }
159
160
- if (intval(ini_get('mbstring.func_overload')) > 0) {
161
- $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.');
162
- }
163
164
- // Check for magic_quotes_runtime
165
- if (function_exists('get_magic_quotes_runtime')) {
166
- if (get_magic_quotes_runtime()) {
167
- return $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).');
168
}
169
- }
170
171
- // Check for magic_quotes_gpc
172
- if (function_exists('magic_quotes_gpc')) {
173
- if (get_magic_quotes_gpc()) {
174
- return $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).');
175
}
176
- }
177
178
- // Load support library
179
- if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
180
- $this->startup_error .= 'getid3.lib.php is missing or corrupt';
181
- }
182
183
- if ($this->option_max_2gb_check === null) {
184
- $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647);
185
- }
186
187
188
- // Needed for Windows only:
189
- // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
190
- // as well as other helper functions such as head, tail, md5sum, etc
191
- // This path cannot contain spaces, but the below code will attempt to get the
192
- // 8.3-equivalent path automatically
193
- // IMPORTANT: This path must include the trailing slash
194
- if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) {
195
-
196
- $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
197
-
198
- if (!is_dir($helperappsdir)) {
199
- $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist';
200
- } elseif (strpos(realpath($helperappsdir), ' ') !== false) {
201
- $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
202
- $path_so_far = array();
203
- foreach ($DirPieces as $key => $value) {
204
- if (strpos($value, ' ') !== false) {
205
- if (!empty($path_so_far)) {
206
- $commandline = 'dir /x '.escapeshellarg(implode(DIRECTORY_SEPARATOR, $path_so_far));
207
- $dir_listing = `$commandline`;
208
- $lines = explode("\n", $dir_listing);
209
- foreach ($lines as $line) {
210
- $line = trim($line);
211
- if (preg_match('#^([0-9/]{10}) +([0-9:]{4,5}( [AP]M)?) +(<DIR>|[0-9,]+) +([^ ]{0,11}) +(.+)$#', $line, $matches)) {
212
- list($dummy, $date, $time, $ampm, $filesize, $shortname, $filename) = $matches;
213
- if ((strtoupper($filesize) == '<DIR>') && (strtolower($filename) == strtolower($value))) {
214
- $value = $shortname;
215
}
216
}
217
}
218
- } else {
219
- $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.';
220
}
221
}
222
- $path_so_far[] = $value;
223
}
224
- $helperappsdir = implode(DIRECTORY_SEPARATOR, $path_so_far);
225
}
226
- define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
227
- }
228
-
229
- return true;
230
- }
231
-
232
- public function version() {
233
- return self::VERSION;
234
- }
235
-
236
- public function fread_buffer_size() {
237
- return $this->option_fread_buffer_size;
238
- }
239
240
241
- // public: setOption
242
- public function setOption($optArray) {
243
- if (!is_array($optArray) || empty($optArray)) {
244
- return false;
245
}
246
- foreach ($optArray as $opt => $val) {
247
- if (isset($this->$opt) === false) {
248
- continue;
249
- }
250
- $this->$opt = $val;
251
}
252
- return true;
253
- }
254
255
256
- public function openfile($filename, $filesize=null) {
257
- try {
258
- if (!empty($this->startup_error)) {
259
- throw new getid3_exception($this->startup_error);
260
- }
261
- if (!empty($this->startup_warning)) {
262
- $this->warning($this->startup_warning);
263
}
264
-
265
- // init result array and set parameters
266
- $this->filename = $filename;
267
- $this->info = array();
268
- $this->info['GETID3_VERSION'] = $this->version();
269
- $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
270
-
271
- // remote files not supported
272
- if (preg_match('/^(ht|f)tp:\/\//', $filename)) {
273
- throw new getid3_exception('Remote files are not supported - please copy the file locally first');
274
}
275
276
- $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
277
- $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);
278
279
- // open local file
280
- //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
281
- if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
282
- // great
283
- } else {
284
- $errormessagelist = array();
285
- if (!is_readable($filename)) {
286
- $errormessagelist[] = '!is_readable';
287
}
288
- if (!is_file($filename)) {
289
- $errormessagelist[] = '!is_file';
290
}
291
- if (!file_exists($filename)) {
292
- $errormessagelist[] = '!file_exists';
293
}
294
- if (empty($errormessagelist)) {
295
- $errormessagelist[] = 'fopen failed';
296
}
297
- throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
298
- }
299
300
- $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
301
- // set redundant parameters - might be needed in some include file
302
- // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
303
- $filename = str_replace('\\', '/', $filename);
304
- $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename)));
305
- $this->info['filename'] = getid3_lib::mb_basename($filename);
306
- $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
307
-
308
-
309
- // option_max_2gb_check
310
- if ($this->option_max_2gb_check) {
311
- // PHP (32-bit all, and 64-bit Windows) doesn't support integers larger than 2^31 (~2GB)
312
- // filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize
313
- // ftell() returns 0 if seeking to the end is beyond the range of unsigned integer
314
- $fseek = fseek($this->fp, 0, SEEK_END);
315
- if (($fseek < 0) || (($this->info['filesize'] != 0) && (ftell($this->fp) == 0)) ||
316
- ($this->info['filesize'] < 0) ||
317
- (ftell($this->fp) < 0)) {
318
$real_filesize = getid3_lib::getFileSizeSyscall($this->info['filenamepath']);
319
320
if ($real_filesize === false) {
@@ -328,377 +328,377 @@ class getID3
328
}
329
$this->info['filesize'] = $real_filesize;
330
$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.');
331
}
332
- }
333
-
334
- // set more parameters
335
- $this->info['avdataoffset'] = 0;
336
- $this->info['avdataend'] = $this->info['filesize'];
337
- $this->info['fileformat'] = ''; // filled in later
338
- $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
339
- $this->info['video']['dataformat'] = ''; // filled in later, unset if not used
340
- $this->info['tags'] = array(); // filled in later, unset if not used
341
- $this->info['error'] = array(); // filled in later, unset if not used
342
- $this->info['warning'] = array(); // filled in later, unset if not used
343
- $this->info['comments'] = array(); // filled in later, unset if not used
344
- $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
345
-
346
- return true;
347
348
- } catch (Exception $e) {
349
- $this->error($e->getMessage());
350
}
351
- return false;
352
- }
353
354
- // public: analyze file
355
- public function analyze($filename, $filesize=null, $original_filename='') {
356
- try {
357
- if (!$this->openfile($filename, $filesize)) {
358
- return $this->info;
359
- }
360
361
- // Handle tags
362
- foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
363
- $option_tag = 'option_tag_'.$tag_name;
364
- if ($this->$option_tag) {
365
- $this->include_module('tag.'.$tag_name);
366
- try {
367
- $tag_class = 'getid3_'.$tag_name;
368
- $tag = new $tag_class($this);
369
- $tag->Analyze();
370
}
371
- catch (getid3_exception $e) {
372
- throw $e;
373
}
374
}
375
- }
376
- if (isset($this->info['id3v2']['tag_offset_start'])) {
377
- $this->info['avdataoffset'] = max($this->info['avdataoffset'], $this->info['id3v2']['tag_offset_end']);
378
- }
379
- foreach (array('id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
380
- if (isset($this->info[$tag_key]['tag_offset_start'])) {
381
- $this->info['avdataend'] = min($this->info['avdataend'], $this->info[$tag_key]['tag_offset_start']);
382
}
383
- }
384
385
- // ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
386
- if (!$this->option_tag_id3v2) {
387
- fseek($this->fp, 0);
388
- $header = fread($this->fp, 10);
389
- if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
390
- $this->info['id3v2']['header'] = true;
391
- $this->info['id3v2']['majorversion'] = ord($header{3});
392
- $this->info['id3v2']['minorversion'] = ord($header{4});
393
- $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
394
}
395
- }
396
397
- // read 32 kb file data
398
- fseek($this->fp, $this->info['avdataoffset']);
399
- $formattest = fread($this->fp, 32774);
400
401
- // determine format
402
- $determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
403
404
- // unable to determine file format
405
- if (!$determined_format) {
406
- fclose($this->fp);
407
- return $this->error('unable to determine file format');
408
- }
409
410
- // check for illegal ID3 tags
411
- if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) {
412
- if ($determined_format['fail_id3'] === 'ERROR') {
413
fclose($this->fp);
414
- return $this->error('ID3 tags not allowed on this file type.');
415
- } elseif ($determined_format['fail_id3'] === 'WARNING') {
416
- $this->warning('ID3 tags not allowed on this file type.');
417
}
418
- }
419
420
- // check for illegal APE tags
421
- if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) {
422
- if ($determined_format['fail_ape'] === 'ERROR') {
423
- fclose($this->fp);
424
- return $this->error('APE tags not allowed on this file type.');
425
- } elseif ($determined_format['fail_ape'] === 'WARNING') {
426
- $this->warning('APE tags not allowed on this file type.');
427
}
428
- }
429
430
- // set mime type
431
- $this->info['mime_type'] = $determined_format['mime_type'];
432
433
- // supported format signature pattern detected, but module deleted
434
- if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) {
435
fclose($this->fp);
436
- return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
437
- }
438
439
- // module requires iconv support
440
- // Check encoding/iconv support
441
- if (!empty($determined_format['iconv_req']) && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
442
- $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. ';
443
- if (GETID3_OS_ISWINDOWS) {
444
- $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';
445
- } else {
446
- $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
447
}
448
- return $this->error($errormessage);
449
- }
450
451
- // include module
452
- include_once(GETID3_INCLUDEPATH.$determined_format['include']);
453
454
- // instantiate module class
455
- $class_name = 'getid3_'.$determined_format['module'];
456
- if (!class_exists($class_name)) {
457
- return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.');
458
- }
459
- $class = new $class_name($this);
460
- $class->Analyze();
461
- unset($class);
462
463
- // close file
464
- fclose($this->fp);
465
466
- // process all tags - copy to 'tags' and convert charsets
467
- if ($this->option_tags_process) {
468
- $this->HandleAllTags();
469
- }
470
471
- // perform more calculations
472
- if ($this->option_extra_info) {
473
- $this->ChannelsBitratePlaytimeCalculations();
474
- $this->CalculateCompressionRatioVideo();
475
- $this->CalculateCompressionRatioAudio();
476
- $this->CalculateReplayGain();
477
- $this->ProcessAudioStreams();
478
}
479
480
- // get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
481
- if ($this->option_md5_data) {
482
- // do not calc md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too
483
- if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) {
484
- $this->getHashdata('md5');
485
- }
486
- }
487
488
- // get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
489
- if ($this->option_sha1_data) {
490
- $this->getHashdata('sha1');
491
- }
492
493
- // remove undesired keys
494
$this->CleanUp();
495
-
496
- } catch (Exception $e) {
497
- $this->error('Caught exception: '.$e->getMessage());
498
}
499
500
- // return info array
501
- return $this->info;
502
- }
503
-
504
505
- // private: error handling
506
- public function error($message) {
507
- $this->CleanUp();
508
- if (!isset($this->info['error'])) {
509
- $this->info['error'] = array();
510
}
511
- $this->info['error'][] = $message;
512
- return $this->info;
513
- }
514
-
515
-
516
- // private: warning handling
517
- public function warning($message) {
518
- $this->info['warning'][] = $message;
519
- return true;
520
- }
521
522
523
- // private: CleanUp
524
- private function CleanUp() {
525
526
- // remove possible empty keys
527
- $AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate');
528
- foreach ($AVpossibleEmptyKeys as $dummy => $key) {
529
- if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) {
530
- unset($this->info['audio'][$key]);
531
}
532
- if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) {
533
- unset($this->info['video'][$key]);
534
}
535
- }
536
537
- // remove empty root keys
538
- if (!empty($this->info)) {
539
- foreach ($this->info as $key => $value) {
540
- if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !== '0')) {
541
- unset($this->info[$key]);
542
}
543
}
544
- }
545
546
- // remove meaningless entries from unknown-format files
547
- if (empty($this->info['fileformat'])) {
548
- if (isset($this->info['avdataoffset'])) {
549
- unset($this->info['avdataoffset']);
550
}
551
- if (isset($this->info['avdataend'])) {
552
- unset($this->info['avdataend']);
553
}
554
- }
555
-
556
- // remove possible duplicated identical entries
557
- if (!empty($this->info['error'])) {
558
- $this->info['error'] = array_values(array_unique($this->info['error']));
559
- }
560
- if (!empty($this->info['warning'])) {
561
- $this->info['warning'] = array_values(array_unique($this->info['warning']));
562
- }
563
564
- // remove "global variable" type keys
565
- unset($this->info['php_memory_limit']);
566
567
- return true;
568
- }
569
570
571
- // return array containing information about all supported formats
572
- public function GetFileFormatArray() {
573
- static $format_info = array();
574
- if (empty($format_info)) {
575
- $format_info = array(
576
-
577
- // Audio formats
578
-
579
- // AC-3 - audio - Dolby AC-3 / Dolby Digital
580
- 'ac3' => array(
581
- 'pattern' => '^\x0B\x77',
582
- 'group' => 'audio',
583
- 'module' => 'ac3',
584
- 'mime_type' => 'audio/ac3',
585
- ),
586
-
587
- // AAC - audio - Advanced Audio Coding (AAC) - ADIF format
588
- 'adif' => array(
589
- 'pattern' => '^ADIF',
590
- 'group' => 'audio',
591
- 'module' => 'aac',
592
- 'mime_type' => 'application/octet-stream',
593
- 'fail_ape' => 'WARNING',
594
- ),
595
-
596
- /*
597
- // AA - audio - Audible Audiobook
598
- 'aa' => array(
599
- 'pattern' => '^.{4}\x57\x90\x75\x36',
600
- 'group' => 'audio',
601
- 'module' => 'aa',
602
- 'mime_type' => 'audio/audible',
603
- ),
604
- */
605
- // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
606
- 'adts' => array(
607
- 'pattern' => '^\xFF[\xF0-\xF1\xF8-\xF9]',
608
- 'group' => 'audio',
609
- 'module' => 'aac',
610
- 'mime_type' => 'application/octet-stream',
611
- 'fail_ape' => 'WARNING',
612
- ),
613
-
614
-
615
- // AU - audio - NeXT/Sun AUdio (AU)
616
- 'au' => array(
617
- 'pattern' => '^\.snd',
618
- 'group' => 'audio',
619
- 'module' => 'au',
620
- 'mime_type' => 'audio/basic',
621
- ),
622
-
623
- // AMR - audio - Adaptive Multi Rate
624
- 'amr' => array(
625
- 'pattern' => '^\x23\x21AMR\x0A', // #!AMR[0A]
626
- 'group' => 'audio',
627
- 'module' => 'amr',
628
- 'mime_type' => 'audio/amr',
629
- ),
630
-
631
- // AVR - audio - Audio Visual Research
632
- 'avr' => array(
633
- 'pattern' => '^2BIT',
634
- 'group' => 'audio',
635
- 'module' => 'avr',
636
- 'mime_type' => 'application/octet-stream',
637
- ),
638
-
639
- // BONK - audio - Bonk v0.9+
640
- 'bonk' => array(
641
- 'pattern' => '^\x00(BONK|INFO|META| ID3)',
642
- 'group' => 'audio',
643
- 'module' => 'bonk',
644
- 'mime_type' => 'audio/xmms-bonk',
645
- ),
646
-
647
- // DSS - audio - Digital Speech Standard
648
- 'dss' => array(
649
- 'pattern' => '^[\x02-\x03]ds[s2]',
650
- 'group' => 'audio',
651
- 'module' => 'dss',
652
- 'mime_type' => 'application/octet-stream',
653
- ),
654
-
655
- // DTS - audio - Dolby Theatre System
656
- 'dts' => array(
657
- 'pattern' => '^\x7F\xFE\x80\x01',
658
- 'group' => 'audio',
659
- 'module' => 'dts',
660
- 'mime_type' => 'audio/dts',
661
- ),
662
-
663
- // FLAC - audio - Free Lossless Audio Codec
664
- 'flac' => array(
665
- 'pattern' => '^fLaC',
666
- 'group' => 'audio',
667
- 'module' => 'flac',
668
- 'mime_type' => 'audio/x-flac',
669
- ),
670
-
671
- // LA - audio - Lossless Audio (LA)
672
- 'la' => array(
673
- 'pattern' => '^LA0[2-4]',
674
- 'group' => 'audio',
675
- 'module' => 'la',
676
- 'mime_type' => 'application/octet-stream',
677
- ),
678
-
679
- // LPAC - audio - Lossless Predictive Audio Compression (LPAC)
680
- 'lpac' => array(
681
- 'pattern' => '^LPAC',
682
- 'group' => 'audio',
683
- 'module' => 'lpac',
684
- 'mime_type' => 'application/octet-stream',
685
- ),
686
-
687
- // MIDI - audio - MIDI (Musical Instrument Digital Interface)
688
- 'midi' => array(
689
- 'pattern' => '^MThd',
690
- 'group' => 'audio',
691
- 'module' => 'midi',
692
- 'mime_type' => 'audio/midi',
693
- ),
694
-
695
- // MAC - audio - Monkey's Audio Compressor
696
- 'mac' => array(
697
- 'pattern' => '^MAC ',
698
- 'group' => 'audio',
699
- 'module' => 'monkey',
700
- 'mime_type' => 'application/octet-stream',
701
- ),
702
703
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
704
// // MOD - audio - MODule (assorted sub-formats)
@@ -710,554 +710,555 @@ class getID3
710
// 'mime_type' => 'audio/mod',
711
// ),
712
713
- // MOD - audio - MODule (Impulse Tracker)
714
- 'it' => array(
715
- 'pattern' => '^IMPM',
716
- 'group' => 'audio',
717
- 'module' => 'mod',
718
- //'option' => 'it',
719
- 'mime_type' => 'audio/it',
720
- ),
721
-
722
- // MOD - audio - MODule (eXtended Module, various sub-formats)
723
- 'xm' => array(
724
- 'pattern' => '^Extended Module',
725
- 'group' => 'audio',
726
- 'module' => 'mod',
727
- //'option' => 'xm',
728
- 'mime_type' => 'audio/xm',
729
- ),
730
-
731
- // MOD - audio - MODule (ScreamTracker)
732
- 's3m' => array(
733
- 'pattern' => '^.{44}SCRM',
734
- 'group' => 'audio',
735
- 'module' => 'mod',
736
- //'option' => 's3m',
737
- 'mime_type' => 'audio/s3m',
738
- ),
739
-
740
- // MPC - audio - Musepack / MPEGplus
741
- 'mpc' => array(
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])',
743
- 'group' => 'audio',
744
- 'module' => 'mpc',
745
- 'mime_type' => 'audio/x-musepack',
746
- ),
747
-
748
- // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS)
749
- 'mp3' => array(
750
- '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]',
751
- 'group' => 'audio',
752
- 'module' => 'mp3',
753
- 'mime_type' => 'audio/mpeg',
754
- ),
755
-
756
- // OFR - audio - OptimFROG
757
- 'ofr' => array(
758
- 'pattern' => '^(\*RIFF|OFR)',
759
- 'group' => 'audio',
760
- 'module' => 'optimfrog',
761
- 'mime_type' => 'application/octet-stream',
762
- ),
763
-
764
- // RKAU - audio - RKive AUdio compressor
765
- 'rkau' => array(
766
- 'pattern' => '^RKA',
767
- 'group' => 'audio',
768
- 'module' => 'rkau',
769
- 'mime_type' => 'application/octet-stream',
770
- ),
771
-
772
- // SHN - audio - Shorten
773
- 'shn' => array(
774
- 'pattern' => '^ajkg',
775
- 'group' => 'audio',
776
- 'module' => 'shorten',
777
- 'mime_type' => 'audio/xmms-shn',
778
- 'fail_id3' => 'ERROR',
779
- 'fail_ape' => 'ERROR',
780
- ),
781
-
782
- // TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org)
783
- 'tta' => array(
784
- 'pattern' => '^TTA', // could also be '^TTA(\x01|\x02|\x03|2|1)'
785
- 'group' => 'audio',
786
- 'module' => 'tta',
787
- 'mime_type' => 'application/octet-stream',
788
- ),
789
-
790
- // VOC - audio - Creative Voice (VOC)
791
- 'voc' => array(
792
- 'pattern' => '^Creative Voice File',
793
- 'group' => 'audio',
794
- 'module' => 'voc',
795
- 'mime_type' => 'audio/voc',
796
- ),
797
-
798
- // VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF)
799
- 'vqf' => array(
800
- 'pattern' => '^TWIN',
801
- 'group' => 'audio',
802
- 'module' => 'vqf',
803
- 'mime_type' => 'application/octet-stream',
804
- ),
805
-
806
- // WV - audio - WavPack (v4.0+)
807
- 'wv' => array(
808
- 'pattern' => '^wvpk',
809
- 'group' => 'audio',
810
- 'module' => 'wavpack',
811
- 'mime_type' => 'application/octet-stream',
812
- ),
813
-
814
-
815
- // Audio-Video formats
816
-
817
- // ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
818
- 'asf' => array(
819
- 'pattern' => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
820
- 'group' => 'audio-video',
821
- 'module' => 'asf',
822
- 'mime_type' => 'video/x-ms-asf',
823
- 'iconv_req' => false,
824
- ),
825
-
826
- // BINK - audio/video - Bink / Smacker
827
- 'bink' => array(
828
- 'pattern' => '^(BIK|SMK)',
829
- 'group' => 'audio-video',
830
- 'module' => 'bink',
831
- 'mime_type' => 'application/octet-stream',
832
- ),
833
-
834
- // FLV - audio/video - FLash Video
835
- 'flv' => array(
836
- 'pattern' => '^FLV\x01',
837
- 'group' => 'audio-video',
838
- 'module' => 'flv',
839
- 'mime_type' => 'video/x-flv',
840
- ),
841
-
842
- // MKAV - audio/video - Mastroka
843
- 'matroska' => array(
844
- 'pattern' => '^\x1A\x45\xDF\xA3',
845
- 'group' => 'audio-video',
846
- 'module' => 'matroska',
847
- 'mime_type' => 'video/x-matroska', // may also be audio/x-matroska
848
- ),
849
-
850
- // MPEG - audio/video - MPEG (Moving Pictures Experts Group)
851
- 'mpeg' => array(
852
- 'pattern' => '^\x00\x00\x01(\xBA|\xB3)',
853
- 'group' => 'audio-video',
854
- 'module' => 'mpeg',
855
- 'mime_type' => 'video/mpeg',
856
- ),
857
-
858
- // NSV - audio/video - Nullsoft Streaming Video (NSV)
859
- 'nsv' => array(
860
- 'pattern' => '^NSV[sf]',
861
- 'group' => 'audio-video',
862
- 'module' => 'nsv',
863
- 'mime_type' => 'application/octet-stream',
864
- ),
865
-
866
- // Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*))
867
- 'ogg' => array(
868
- 'pattern' => '^OggS',
869
- 'group' => 'audio',
870
- 'module' => 'ogg',
871
- 'mime_type' => 'application/ogg',
872
- 'fail_id3' => 'WARNING',
873
- 'fail_ape' => 'WARNING',
874
- ),
875
-
876
- // QT - audio/video - Quicktime
877
- 'quicktime' => array(
878
- 'pattern' => '^.{4}(cmov|free|ftyp|mdat|moov|pnot|skip|wide)',
879
- 'group' => 'audio-video',
880
- 'module' => 'quicktime',
881
- 'mime_type' => 'video/quicktime',
882
- ),
883
-
884
- // RIFF - audio/video - Resource Interchange File Format (RIFF) / WAV / AVI / CD-audio / SDSS = renamed variant used by SmartSound QuickTracks (www.smartsound.com) / FORM = Audio Interchange File Format (AIFF)
885
- 'riff' => array(
886
- 'pattern' => '^(RIFF|SDSS|FORM)',
887
- 'group' => 'audio-video',
888
- 'module' => 'riff',
889
- 'mime_type' => 'audio/x-wave',
890
- 'fail_ape' => 'WARNING',
891
- ),
892
-
893
- // Real - audio/video - RealAudio, RealVideo
894
- 'real' => array(
895
- 'pattern' => '^(\\.RMF|\\.ra)',
896
- 'group' => 'audio-video',
897
- 'module' => 'real',
898
- 'mime_type' => 'audio/x-realaudio',
899
- ),
900
-
901
- // SWF - audio/video - ShockWave Flash
902
- 'swf' => array(
903
- 'pattern' => '^(F|C)WS',
904
- 'group' => 'audio-video',
905
- 'module' => 'swf',
906
- 'mime_type' => 'application/x-shockwave-flash',
907
- ),
908
-
909
- // TS - audio/video - MPEG-2 Transport Stream
910
- 'ts' => array(
911
- 'pattern' => '^(\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern
912
- 'group' => 'audio-video',
913
- 'module' => 'ts',
914
- 'mime_type' => 'video/MP2T',
915
- ),
916
-
917
-
918
- // Still-Image formats
919
-
920
- // BMP - still image - Bitmap (Windows, OS/2; uncompressed, RLE8, RLE4)
921
- 'bmp' => array(
922
- 'pattern' => '^BM',
923
- 'group' => 'graphic',
924
- 'module' => 'bmp',
925
- 'mime_type' => 'image/bmp',
926
- 'fail_id3' => 'ERROR',
927
- 'fail_ape' => 'ERROR',
928
- ),
929
-
930
- // GIF - still image - Graphics Interchange Format
931
- 'gif' => array(
932
- 'pattern' => '^GIF',
933
- 'group' => 'graphic',
934
- 'module' => 'gif',
935
- 'mime_type' => 'image/gif',
936
- 'fail_id3' => 'ERROR',
937
- 'fail_ape' => 'ERROR',
938
- ),
939
-
940
- // JPEG - still image - Joint Photographic Experts Group (JPEG)
941
- 'jpg' => array(
942
- 'pattern' => '^\xFF\xD8\xFF',
943
- 'group' => 'graphic',
944
- 'module' => 'jpg',
945
- 'mime_type' => 'image/jpeg',
946
- 'fail_id3' => 'ERROR',
947
- 'fail_ape' => 'ERROR',
948
- ),
949
-
950
- // PCD - still image - Kodak Photo CD
951
- 'pcd' => array(
952
- 'pattern' => '^.{2048}PCD_IPI\x00',
953
- 'group' => 'graphic',
954
- 'module' => 'pcd',
955
- 'mime_type' => 'image/x-photo-cd',
956
- 'fail_id3' => 'ERROR',
957
- 'fail_ape' => 'ERROR',
958
- ),
959
-
960
-
961
- // PNG - still image - Portable Network Graphics (PNG)
962
- 'png' => array(
963
- 'pattern' => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A',
964
- 'group' => 'graphic',
965
- 'module' => 'png',
966
- 'mime_type' => 'image/png',
967
- 'fail_id3' => 'ERROR',
968
- 'fail_ape' => 'ERROR',
969
- ),
970
-
971
-
972
- // SVG - still image - Scalable Vector Graphics (SVG)
973
- 'svg' => array(
974
- 'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http:\/\/www\.w3\.org\/2000\/svg")',
975
- 'group' => 'graphic',
976
- 'module' => 'svg',
977
- 'mime_type' => 'image/svg+xml',
978
- 'fail_id3' => 'ERROR',
979
- 'fail_ape' => 'ERROR',
980
- ),
981
-
982
-
983
- // TIFF - still image - Tagged Information File Format (TIFF)
984
- 'tiff' => array(
985
- 'pattern' => '^(II\x2A\x00|MM\x00\x2A)',
986
- 'group' => 'graphic',
987
- 'module' => 'tiff',
988
- 'mime_type' => 'image/tiff',
989
- 'fail_id3' => 'ERROR',
990
- 'fail_ape' => 'ERROR',
991
- ),
992
-
993
-
994
- // EFAX - still image - eFax (TIFF derivative)
995
- 'efax' => array(
996
- 'pattern' => '^\xDC\xFE',
997
- 'group' => 'graphic',
998
- 'module' => 'efax',
999
- 'mime_type' => 'image/efax',
1000
- 'fail_id3' => 'ERROR',
1001
- 'fail_ape' => 'ERROR',
1002
- ),
1003
-
1004
-
1005
- // Data formats
1006
-
1007
- // ISO - data - International Standards Organization (ISO) CD-ROM Image
1008
- 'iso' => array(
1009
- 'pattern' => '^.{32769}CD001',
1010
- 'group' => 'misc',
1011
- 'module' => 'iso',
1012
- 'mime_type' => 'application/octet-stream',
1013
- 'fail_id3' => 'ERROR',
1014
- 'fail_ape' => 'ERROR',
1015
- 'iconv_req' => false,
1016
- ),
1017
-
1018
- // RAR - data - RAR compressed data
1019
- 'rar' => array(
1020
- 'pattern' => '^Rar\!',
1021
- 'group' => 'archive',
1022
- 'module' => 'rar',
1023
- 'mime_type' => 'application/octet-stream',
1024
- 'fail_id3' => 'ERROR',
1025
- 'fail_ape' => 'ERROR',
1026
- ),
1027
-
1028
- // SZIP - audio/data - SZIP compressed data
1029
- 'szip' => array(
1030
- 'pattern' => '^SZ\x0A\x04',
1031
- 'group' => 'archive',
1032
- 'module' => 'szip',
1033
- 'mime_type' => 'application/octet-stream',
1034
- 'fail_id3' => 'ERROR',
1035
- 'fail_ape' => 'ERROR',
1036
- ),
1037
-
1038
- // TAR - data - TAR compressed data
1039
- 'tar' => array(
1040
- '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}',
1041
- 'group' => 'archive',
1042
- 'module' => 'tar',
1043
- 'mime_type' => 'application/x-tar',
1044
- 'fail_id3' => 'ERROR',
1045
- 'fail_ape' => 'ERROR',
1046
- ),
1047
-
1048
- // GZIP - data - GZIP compressed data
1049
- 'gz' => array(
1050
- 'pattern' => '^\x1F\x8B\x08',
1051
- 'group' => 'archive',
1052
- 'module' => 'gzip',
1053
- 'mime_type' => 'application/x-gzip',
1054
- 'fail_id3' => 'ERROR',
1055
- 'fail_ape' => 'ERROR',
1056
- ),
1057
-
1058
- // ZIP - data - ZIP compressed data
1059
- 'zip' => array(
1060
- 'pattern' => '^PK\x03\x04',
1061
- 'group' => 'archive',
1062
- 'module' => 'zip',
1063
- 'mime_type' => 'application/zip',
1064
- 'fail_id3' => 'ERROR',
1065
- 'fail_ape' => 'ERROR',
1066
- ),
1067
-
1068
-
1069
- // Misc other formats
1070
-
1071
- // PAR2 - data - Parity Volume Set Specification 2.0
1072
- 'par2' => array (
1073
- 'pattern' => '^PAR2\x00PKT',
1074
- 'group' => 'misc',
1075
- 'module' => 'par2',
1076
- 'mime_type' => 'application/octet-stream',
1077
- 'fail_id3' => 'ERROR',
1078
- 'fail_ape' => 'ERROR',
1079
- ),
1080
-
1081
- // PDF - data - Portable Document Format
1082
- 'pdf' => array(
1083
- 'pattern' => '^\x25PDF',
1084
- 'group' => 'misc',
1085
- 'module' => 'pdf',
1086
- 'mime_type' => 'application/pdf',
1087
- 'fail_id3' => 'ERROR',
1088
- 'fail_ape' => 'ERROR',
1089
- ),
1090
-
1091
- // MSOFFICE - data - ZIP compressed data
1092
- 'msoffice' => array(
1093
- 'pattern' => '^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
1094
- 'group' => 'misc',
1095
- 'module' => 'msoffice',
1096
- 'mime_type' => 'application/octet-stream',
1097
- 'fail_id3' => 'ERROR',
1098
- 'fail_ape' => 'ERROR',
1099
- ),
1100
-
1101
- // CUE - data - CUEsheet (index to single-file disc images)
1102
- 'cue' => array(
1103
- 'pattern' => '', // empty pattern means cannot be automatically detected, will fall through all other formats and match based on filename and very basic file contents
1104
- 'group' => 'misc',
1105
- 'module' => 'cue',
1106
- 'mime_type' => 'application/octet-stream',
1107
- ),
1108
-
1109
- );
1110
}
1111
1112
- return $format_info;
1113
- }
1114
1115
1116
1117
- public function GetFileFormat(&$filedata, $filename='') {
1118
- // this function will determine the format of a file based on usually
1119
- // the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG,
1120
- // and in the case of ISO CD image, 6 bytes offset 32kb from the start
1121
- // of the file).
1122
1123
- // Identify file format - loop through $format_info and detect with reg expr
1124
- foreach ($this->GetFileFormatArray() as $format_name => $info) {
1125
- // The /s switch on preg_match() forces preg_match() NOT to treat
1126
- // newline (0x0A) characters as special chars but do a binary match
1127
- if (!empty($info['pattern']) && preg_match('#'.$info['pattern'].'#s', $filedata)) {
1128
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
1129
return $info;
1130
}
1131
- }
1132
1133
-
1134
- if (preg_match('#\.mp[123a]$#i', $filename)) {
1135
- // Too many mp3 encoders on the market put gabage in front of mpeg files
1136
- // use assume format on these if format detection failed
1137
- $GetFileFormatArray = $this->GetFileFormatArray();
1138
- $info = $GetFileFormatArray['mp3'];
1139
- $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
1140
- return $info;
1141
- } elseif (preg_match('/\.cue#x2F;i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
1142
- // there's not really a useful consistent "magic" at the beginning of .cue files to identify them
1143
- // so until I think of something better, just go by filename if all other format checks fail
1144
- // and verify there's at least one instance of "TRACK xx AUDIO" in the file
1145
- $GetFileFormatArray = $this->GetFileFormatArray();
1146
- $info = $GetFileFormatArray['cue'];
1147
- $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
1148
- return $info;
1149
}
1150
1151
- return false;
1152
- }
1153
1154
1155
- // converts array to $encoding charset from $this->encoding
1156
- public function CharConvert(&$array, $encoding) {
1157
-
1158
- // identical encoding - end here
1159
- if ($encoding == $this->encoding) {
1160
- return;
1161
- }
1162
1163
- // loop thru array
1164
- foreach ($array as $key => $value) {
1165
1166
- // go recursive
1167
- if (is_array($value)) {
1168
- $this->CharConvert($array[$key], $encoding);
1169
- }
1170
1171
- // convert string
1172
- elseif (is_string($value)) {
1173
- $array[$key] = trim(getid3_lib::iconv_fallback($encoding, $this->encoding, $value));
1174
}
1175
}
1176
- }
1177
1178
1179
- public function HandleAllTags() {
1180
-
1181
- // key name => array (tag name, character encoding)
1182
- static $tags;
1183
- if (empty($tags)) {
1184
- $tags = array(
1185
- 'asf' => array('asf' , 'UTF-16LE'),
1186
- 'midi' => array('midi' , 'ISO-8859-1'),
1187
- 'nsv' => array('nsv' , 'ISO-8859-1'),
1188
- 'ogg' => array('vorbiscomment' , 'UTF-8'),
1189
- 'png' => array('png' , 'UTF-8'),
1190
- 'tiff' => array('tiff' , 'ISO-8859-1'),
1191
- 'quicktime' => array('quicktime' , 'UTF-8'),
1192
- 'real' => array('real' , 'ISO-8859-1'),
1193
- 'vqf' => array('vqf' , 'ISO-8859-1'),
1194
- 'zip' => array('zip' , 'ISO-8859-1'),
1195
- 'riff' => array('riff' , 'ISO-8859-1'),
1196
- 'lyrics3' => array('lyrics3' , 'ISO-8859-1'),
1197
- 'id3v1' => array('id3v1' , $this->encoding_id3v1),
1198
- 'id3v2' => array('id3v2' , 'UTF-8'), // not according to the specs (every frame can have a different encoding), but getID3() force-converts all encodings to UTF-8
1199
- 'ape' => array('ape' , 'UTF-8'),
1200
- 'cue' => array('cue' , 'ISO-8859-1'),
1201
- 'matroska' => array('matroska' , 'UTF-8'),
1202
- 'flac' => array('vorbiscomment' , 'UTF-8'),
1203
- 'divxtag' => array('divx' , 'ISO-8859-1'),
1204
- 'iptc' => array('iptc' , 'ISO-8859-1'),
1205
- );
1206
- }
1207
1208
- // loop through comments array
1209
- foreach ($tags as $comment_name => $tagname_encoding_array) {
1210
- list($tag_name, $encoding) = $tagname_encoding_array;
1211
1212
- // fill in default encoding type if not already present
1213
- if (isset($this->info[$comment_name]) && !isset($this->info[$comment_name]['encoding'])) {
1214
- $this->info[$comment_name]['encoding'] = $encoding;
1215
- }
1216
1217
- // copy comments if key name set
1218
- if (!empty($this->info[$comment_name]['comments'])) {
1219
- foreach ($this->info[$comment_name]['comments'] as $tag_key => $valuearray) {
1220
- foreach ($valuearray as $key => $value) {
1221
- if (is_string($value)) {
1222
- $value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed!
1223
- }
1224
- if ($value) {
1225
- if (!is_numeric($key)) {
1226
- $this->info['tags'][trim($tag_name)][trim($tag_key)][$key] = $value;
1227
- } else {
1228
- $this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value;
1229
}
1230
}
1231
}
1232
- if ($tag_key == 'picture') {
1233
- unset($this->info[$comment_name]['comments'][$tag_key]);
1234
- }
1235
- }
1236
1237
- if (!isset($this->info['tags'][$tag_name])) {
1238
- // comments are set but contain nothing but empty strings, so skip
1239
- continue;
1240
- }
1241
1242
- if ($this->option_tags_html) {
1243
- foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
1244
- $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $encoding);
1245
}
1246
- }
1247
1248
- // ID3v1 encoding detection hack start
1249
- // ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
1250
- // Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
1251
- if ($comment_name == 'id3v1') {
1252
- if ($encoding == 'ISO-8859-1') {
1253
- if (function_exists('iconv')) {
1254
- foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
1255
- foreach ($valuearray as $key => $value) {
1256
- if (preg_match('#^[\\x80-\\xFF]+$#', $value)) {
1257
- foreach (array('windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
1258
- if (@iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
1259
- $encoding = $id3v1_bad_encoding;
1260
- break 3;
1261
}
1262
}
1263
}
@@ -1265,570 +1266,573 @@ class getID3
1265
}
1266
}
1267
}
1268
}
1269
- // ID3v1 encoding detection hack end
1270
1271
- $this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!
1272
}
1273
1274
- }
1275
-
1276
- // pictures can take up a lot of space, and we don't need multiple copies of them
1277
- // let there be a single copy in [comments][picture], and not elsewhere
1278
- if (!empty($this->info['tags'])) {
1279
- $unset_keys = array('tags', 'tags_html');
1280
- foreach ($this->info['tags'] as $tagtype => $tagarray) {
1281
- foreach ($tagarray as $tagname => $tagdata) {
1282
- if ($tagname == 'picture') {
1283
- foreach ($tagdata as $key => $tagarray) {
1284
- $this->info['comments']['picture'][] = $tagarray;
1285
- if (isset($tagarray['data']) && isset($tagarray['image_mime'])) {
1286
- if (isset($this->info['tags'][$tagtype][$tagname][$key])) {
1287
- unset($this->info['tags'][$tagtype][$tagname][$key]);
1288
- }
1289
- if (isset($this->info['tags_html'][$tagtype][$tagname][$key])) {
1290
- unset($this->info['tags_html'][$tagtype][$tagname][$key]);
1291
}
1292
}
1293
}
1294
}
1295
- }
1296
- foreach ($unset_keys as $unset_key) {
1297
- // remove possible empty keys from (e.g. [tags][id3v2][picture])
1298
- if (empty($this->info[$unset_key][$tagtype]['picture'])) {
1299
- unset($this->info[$unset_key][$tagtype]['picture']);
1300
}
1301
- if (empty($this->info[$unset_key][$tagtype])) {
1302
- unset($this->info[$unset_key][$tagtype]);
1303
}
1304
- if (empty($this->info[$unset_key])) {
1305
- unset($this->info[$unset_key]);
1306
}
1307
- }
1308
- // remove duplicate copy of picture data from (e.g. [id3v2][comments][picture])
1309
- if (isset($this->info[$tagtype]['comments']['picture'])) {
1310
- unset($this->info[$tagtype]['comments']['picture']);
1311
- }
1312
- if (empty($this->info[$tagtype]['comments'])) {
1313
- unset($this->info[$tagtype]['comments']);
1314
- }
1315
- if (empty($this->info[$tagtype])) {
1316
- unset($this->info[$tagtype]);
1317
}
1318
}
1319
}
1320
- return true;
1321
- }
1322
1323
- public function getHashdata($algorithm) {
1324
- switch ($algorithm) {
1325
- case 'md5':
1326
- case 'sha1':
1327
- break;
1328
1329
- default:
1330
- return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()');
1331
- break;
1332
- }
1333
1334
- if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) {
1335
-
1336
- // We cannot get an identical md5_data value for Ogg files where the comments
1337
- // span more than 1 Ogg page (compared to the same audio data with smaller
1338
- // comments) using the normal getID3() method of MD5'ing the data between the
1339
- // end of the comments and the end of the file (minus any trailing tags),
1340
- // because the page sequence numbers of the pages that the audio data is on
1341
- // do not match. Under normal circumstances, where comments are smaller than
1342
- // the nominal 4-8kB page size, then this is not a problem, but if there are
1343
- // very large comments, the only way around it is to strip off the comment
1344
- // tags with vorbiscomment and MD5 that file.
1345
- // This procedure must be applied to ALL Ogg files, not just the ones with
1346
- // comments larger than 1 page, because the below method simply MD5's the
1347
- // whole file with the comments stripped, not just the portion after the
1348
- // comments block (which is the standard getID3() method.
1349
-
1350
- // The above-mentioned problem of comments spanning multiple pages and changing
1351
- // page sequence numbers likely happens for OggSpeex and OggFLAC as well, but
1352
- // currently vorbiscomment only works on OggVorbis files.
1353
1354
- if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
1355
1356
- $this->warning('Failed making system call to vorbiscomment.exe - '.$algorithm.'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)');
1357
- $this->info[$algorithm.'_data'] = false;
1358
1359
- } else {
1360
1361
- // Prevent user from aborting script
1362
- $old_abort = ignore_user_abort(true);
1363
1364
- // Create empty file
1365
- $empty = tempnam(GETID3_TEMP_DIR, 'getID3');
1366
- touch($empty);
1367
1368
- // Use vorbiscomment to make temp file without comments
1369
- $temp = tempnam(GETID3_TEMP_DIR, 'getID3');
1370
- $file = $this->info['filenamepath'];
1371
1372
- if (GETID3_OS_ISWINDOWS) {
1373
1374
- if (file_exists(GETID3_HELPERAPPSDIR.'vorbiscomment.exe')) {
1375
1376
- $commandline = '"'.GETID3_HELPERAPPSDIR.'vorbiscomment.exe" -w -c "'.$empty.'" "'.$file.'" "'.$temp.'"';
1377
$VorbisCommentError = `$commandline`;
1378
1379
} else {
1380
1381
- $VorbisCommentError = 'vorbiscomment.exe not found in '.GETID3_HELPERAPPSDIR;
1382
1383
}
1384
1385
- } else {
1386
1387
- $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1';
1388
- $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
1389
- $VorbisCommentError = `$commandline`;
1390
1391
}
1392
1393
- if (!empty($VorbisCommentError)) {
1394
1395
- $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 getID3() directory. Error returned: '.$VorbisCommentError;
1396
- $this->info[$algorithm.'_data'] = false;
1397
1398
} else {
1399
1400
- // Get hash of newly created file
1401
switch ($algorithm) {
1402
case 'md5':
1403
- $this->info[$algorithm.'_data'] = md5_file($temp);
1404
break;
1405
1406
case 'sha1':
1407
- $this->info[$algorithm.'_data'] = sha1_file($temp);
1408
break;
1409
}
1410
}
1411
1412
- // Clean up
1413
- unlink($empty);
1414
- unlink($temp);
1415
-
1416
- // Reset abort setting
1417
- ignore_user_abort($old_abort);
1418
-
1419
}
1420
1421
- } else {
1422
1423
- if (!empty($this->info['avdataoffset']) || (isset($this->info['avdataend']) && ($this->info['avdataend'] < $this->info['filesize']))) {
1424
1425
- // get hash from part of file
1426
- $this->info[$algorithm.'_data'] = getid3_lib::hash_data($this->info['filenamepath'], $this->info['avdataoffset'], $this->info['avdataend'], $algorithm);
1427
1428
- } else {
1429
1430
- // get hash from whole file
1431
- switch ($algorithm) {
1432
- case 'md5':
1433
- $this->info[$algorithm.'_data'] = md5_file($this->info['filenamepath']);
1434
- break;
1435
1436
- case 'sha1':
1437
- $this->info[$algorithm.'_data'] = sha1_file($this->info['filenamepath']);
1438
- break;
1439
}
1440
}
1441
1442
}
1443
- return true;
1444
- }
1445
1446
1447
- public function ChannelsBitratePlaytimeCalculations() {
1448
1449
- // set channelmode on audio
1450
- if (!empty($this->info['audio']['channelmode']) || !isset($this->info['audio']['channels'])) {
1451
- // ignore
1452
- } elseif ($this->info['audio']['channels'] == 1) {
1453
- $this->info['audio']['channelmode'] = 'mono';
1454
- } elseif ($this->info['audio']['channels'] == 2) {
1455
- $this->info['audio']['channelmode'] = 'stereo';
1456
- }
1457
1458
- // Calculate combined bitrate - audio + video
1459
- $CombinedBitrate = 0;
1460
- $CombinedBitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0);
1461
- $CombinedBitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0);
1462
- if (($CombinedBitrate > 0) && empty($this->info['bitrate'])) {
1463
- $this->info['bitrate'] = $CombinedBitrate;
1464
- }
1465
- //if ((isset($this->info['video']) && !isset($this->info['video']['bitrate'])) || (isset($this->info['audio']) && !isset($this->info['audio']['bitrate']))) {
1466
- // // for example, VBR MPEG video files cannot determine video bitrate:
1467
- // // should not set overall bitrate and playtime from audio bitrate only
1468
- // unset($this->info['bitrate']);
1469
- //}
1470
-
1471
- // video bitrate undetermined, but calculable
1472
- if (isset($this->info['video']['dataformat']) && $this->info['video']['dataformat'] && (!isset($this->info['video']['bitrate']) || ($this->info['video']['bitrate'] == 0))) {
1473
- // if video bitrate not set
1474
- if (isset($this->info['audio']['bitrate']) && ($this->info['audio']['bitrate'] > 0) && ($this->info['audio']['bitrate'] == $this->info['bitrate'])) {
1475
- // AND if audio bitrate is set to same as overall bitrate
1476
- if (isset($this->info['playtime_seconds']) && ($this->info['playtime_seconds'] > 0)) {
1477
- // AND if playtime is set
1478
- if (isset($this->info['avdataend']) && isset($this->info['avdataoffset'])) {
1479
- // AND if AV data offset start/end is known
1480
- // THEN we can calculate the video bitrate
1481
- $this->info['bitrate'] = round((($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']);
1482
- $this->info['video']['bitrate'] = $this->info['bitrate'] - $this->info['audio']['bitrate'];
1483
}
1484
- }
1485
}
1486
- }
1487
1488
- if ((!isset($this->info['playtime_seconds']) || ($this->info['playtime_seconds'] <= 0)) && !empty($this->info['bitrate'])) {
1489
- $this->info['playtime_seconds'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['bitrate'];
1490
}
1491
1492
- if (!isset($this->info['bitrate']) && !empty($this->info['playtime_seconds'])) {
1493
- $this->info['bitrate'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds'];
1494
- }
1495
- if (isset($this->info['bitrate']) && empty($this->info['audio']['bitrate']) && empty($this->info['video']['bitrate'])) {
1496
- if (isset($this->info['audio']['dataformat']) && empty($this->info['video']['resolution_x'])) {
1497
- // audio only
1498
- $this->info['audio']['bitrate'] = $this->info['bitrate'];
1499
- } elseif (isset($this->info['video']['resolution_x']) && empty($this->info['audio']['dataformat'])) {
1500
- // video only
1501
- $this->info['video']['bitrate'] = $this->info['bitrate'];
1502
}
1503
- }
1504
1505
- // Set playtime string
1506
- if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) {
1507
- $this->info['playtime_string'] = getid3_lib::PlaytimeString($this->info['playtime_seconds']);
1508
}
1509
- }
1510
-
1511
1512
- public function CalculateCompressionRatioVideo() {
1513
- if (empty($this->info['video'])) {
1514
- return false;
1515
- }
1516
- if (empty($this->info['video']['resolution_x']) || empty($this->info['video']['resolution_y'])) {
1517
- return false;
1518
- }
1519
- if (empty($this->info['video']['bits_per_sample'])) {
1520
- return false;
1521
- }
1522
1523
- switch ($this->info['video']['dataformat']) {
1524
- case 'bmp':
1525
- case 'gif':
1526
- case 'jpeg':
1527
- case 'jpg':
1528
- case 'png':
1529
- case 'tiff':
1530
- $FrameRate = 1;
1531
- $PlaytimeSeconds = 1;
1532
- $BitrateCompressed = $this->info['filesize'] * 8;
1533
- break;
1534
-
1535
- default:
1536
- if (!empty($this->info['video']['frame_rate'])) {
1537
- $FrameRate = $this->info['video']['frame_rate'];
1538
- } else {
1539
- return false;
1540
}
1541
- if (!empty($this->info['playtime_seconds'])) {
1542
- $PlaytimeSeconds = $this->info['playtime_seconds'];
1543
- } else {
1544
- return false;
1545
}
1546
- if (!empty($this->info['video']['bitrate'])) {
1547
- $BitrateCompressed = $this->info['video']['bitrate'];
1548
- } else {
1549
- return false;
1550
}
1551
- break;
1552
- }
1553
- $BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate;
1554
-
1555
- $this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
1556
- return true;
1557
- }
1558
-
1559
-
1560
- public function CalculateCompressionRatioAudio() {
1561
- if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) {
1562
- return false;
1563
- }
1564
- $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));
1565
1566
- if (!empty($this->info['audio']['streams'])) {
1567
- foreach ($this->info['audio']['streams'] as $streamnumber => $streamdata) {
1568
- if (!empty($streamdata['bitrate']) && !empty($streamdata['channels']) && !empty($streamdata['sample_rate'])) {
1569
- $this->info['audio']['streams'][$streamnumber]['compression_ratio'] = $streamdata['bitrate'] / ($streamdata['channels'] * $streamdata['sample_rate'] * (!empty($streamdata['bits_per_sample']) ? $streamdata['bits_per_sample'] : 16));
1570
}
1571
}
1572
}
1573
- return true;
1574
- }
1575
-
1576
-
1577
- public function CalculateReplayGain() {
1578
- if (isset($this->info['replay_gain'])) {
1579
- if (!isset($this->info['replay_gain']['reference_volume'])) {
1580
- $this->info['replay_gain']['reference_volume'] = (double) 89.0;
1581
- }
1582
- if (isset($this->info['replay_gain']['track']['adjustment'])) {
1583
- $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment'];
1584
- }
1585
- if (isset($this->info['replay_gain']['album']['adjustment'])) {
1586
- $this->info['replay_gain']['album']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['album']['adjustment'];
1587
- }
1588
-
1589
- if (isset($this->info['replay_gain']['track']['peak'])) {
1590
- $this->info['replay_gain']['track']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['track']['peak']);
1591
- }
1592
- if (isset($this->info['replay_gain']['album']['peak'])) {
1593
- $this->info['replay_gain']['album']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['album']['peak']);
1594
- }
1595
- }
1596
- return true;
1597
- }
1598
1599
- public function ProcessAudioStreams() {
1600
- if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
1601
- if (!isset($this->info['audio']['streams'])) {
1602
- foreach ($this->info['audio'] as $key => $value) {
1603
- if ($key != 'streams') {
1604
- $this->info['audio']['streams'][0][$key] = $value;
1605
}
1606
}
1607
}
1608
}
1609
- return true;
1610
- }
1611
1612
- public function getid3_tempnam() {
1613
- return tempnam($this->tempdir, 'gI3');
1614
- }
1615
1616
- public function include_module($name) {
1617
- //if (!file_exists($this->include_path.'module.'.$name.'.php')) {
1618
- if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) {
1619
- throw new getid3_exception('Required module.'.$name.'.php is missing.');
1620
}
1621
- include_once(GETID3_INCLUDEPATH.'module.'.$name.'.php');
1622
- return true;
1623
- }
1624
1625
}
1626
1627
1628
- abstract class getid3_handler {
1629
1630
- /**
1631
- * @var getID3
1632
- */
1633
- protected $getid3; // pointer
1634
1635
- protected $data_string_flag = false; // analyzing filepointer or string
1636
- protected $data_string = ''; // string to analyze
1637
- protected $data_string_position = 0; // seek position in string
1638
- protected $data_string_length = 0; // string length
1639
1640
- private $dependency_to = null;
1641
1642
1643
- public function __construct(getID3 $getid3, $call_module=null) {
1644
- $this->getid3 = $getid3;
1645
1646
- if ($call_module) {
1647
- $this->dependency_to = str_replace('getid3_', '', $call_module);
1648
}
1649
- }
1650
-
1651
1652
- // Analyze from file pointer
1653
- abstract public function Analyze();
1654
1655
1656
- // Analyze from string instead
1657
- public function AnalyzeString($string) {
1658
- // Enter string mode
1659
- $this->setStringMode($string);
1660
1661
- // Save info
1662
- $saved_avdataoffset = $this->getid3->info['avdataoffset'];
1663
- $saved_avdataend = $this->getid3->info['avdataend'];
1664
- $saved_filesize = (isset($this->getid3->info['filesize']) ? $this->getid3->info['filesize'] : null); // may be not set if called as dependency without openfile() call
1665
1666
- // Reset some info
1667
- $this->getid3->info['avdataoffset'] = 0;
1668
- $this->getid3->info['avdataend'] = $this->getid3->info['filesize'] = $this->data_string_length;
1669
1670
- // Analyze
1671
- $this->Analyze();
1672
1673
- // Restore some info
1674
- $this->getid3->info['avdataoffset'] = $saved_avdataoffset;
1675
- $this->getid3->info['avdataend'] = $saved_avdataend;
1676
- $this->getid3->info['filesize'] = $saved_filesize;
1677
1678
- // Exit string mode
1679
- $this->data_string_flag = false;
1680
- }
1681
1682
- public function setStringMode($string) {
1683
- $this->data_string_flag = true;
1684
- $this->data_string = $string;
1685
- $this->data_string_length = strlen($string);
1686
- }
1687
1688
- protected function ftell() {
1689
- if ($this->data_string_flag) {
1690
- return $this->data_string_position;
1691
}
1692
- return ftell($this->getid3->fp);
1693
- }
1694
1695
- protected function fread($bytes) {
1696
- if ($this->data_string_flag) {
1697
- $this->data_string_position += $bytes;
1698
- return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
1699
}
1700
- $pos = $this->ftell() + $bytes;
1701
- if (!getid3_lib::intValueSupported($pos)) {
1702
- throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);
1703
}
1704
- return fread($this->getid3->fp, $bytes);
1705
- }
1706
1707
- protected function fseek($bytes, $whence=SEEK_SET) {
1708
- if ($this->data_string_flag) {
1709
- switch ($whence) {
1710
- case SEEK_SET:
1711
- $this->data_string_position = $bytes;
1712
- break;
1713
1714
- case SEEK_CUR:
1715
- $this->data_string_position += $bytes;
1716
- break;
1717
1718
- case SEEK_END:
1719
- $this->data_string_position = $this->data_string_length + $bytes;
1720
- break;
1721
- }
1722
- return 0;
1723
- } else {
1724
- $pos = $bytes;
1725
- if ($whence == SEEK_CUR) {
1726
- $pos = $this->ftell() + $bytes;
1727
- } elseif ($whence == SEEK_END) {
1728
- $pos = $this->getid3->info['filesize'] + $bytes;
1729
- }
1730
- if (!getid3_lib::intValueSupported($pos)) {
1731
- throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10);
1732
}
1733
}
1734
- return fseek($this->getid3->fp, $bytes, $whence);
1735
- }
1736
1737
- protected function feof() {
1738
- if ($this->data_string_flag) {
1739
- return $this->data_string_position >= $this->data_string_length;
1740
}
1741
- return feof($this->getid3->fp);
1742
- }
1743
1744
- final protected function isDependencyFor($module) {
1745
- return $this->dependency_to == $module;
1746
- }
1747
1748
- protected function error($text) {
1749
- $this->getid3->info['error'][] = $text;
1750
1751
- return false;
1752
- }
1753
1754
- protected function warning($text) {
1755
- return $this->getid3->warning($text);
1756
- }
1757
1758
- protected function notice($text) {
1759
- // does nothing for now
1760
- }
1761
1762
- public function saveAttachment($name, $offset, $length, $image_mime=null) {
1763
- try {
1764
1765
- // do not extract at all
1766
- if ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_NONE) {
1767
1768
- $attachment = null; // do not set any
1769
1770
- // extract to return array
1771
- } elseif ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_INLINE) {
1772
1773
- $this->fseek($offset);
1774
- $attachment = $this->fread($length); // get whole data in one pass, till it is anyway stored in memory
1775
- if ($attachment === false || strlen($attachment) != $length) {
1776
- throw new Exception('failed to read attachment data');
1777
- }
1778
1779
- // assume directory path is given
1780
- } else {
1781
1782
- // set up destination path
1783
- $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
1784
- if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory
1785
- throw new Exception('supplied path ('.$dir.') does not exist, or is not writable');
1786
- }
1787
- $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : '');
1788
1789
- // create dest file
1790
- if (($fp_dest = fopen($dest, 'wb')) == false) {
1791
- throw new Exception('failed to create file '.$dest);
1792
- }
1793
1794
- // copy data
1795
- $this->fseek($offset);
1796
- $buffersize = ($this->data_string_flag ? $length : $this->getid3->fread_buffer_size());
1797
- $bytesleft = $length;
1798
- while ($bytesleft > 0) {
1799
- if (($buffer = $this->fread(min($buffersize, $bytesleft))) === false || ($byteswritten = fwrite($fp_dest, $buffer)) === false || ($byteswritten === 0)) {
1800
- throw new Exception($buffer === false ? 'not enough data to read' : 'failed to write to destination file, may be not enough disk space');
1801
}
1802
- $bytesleft -= $byteswritten;
1803
}
1804
1805
- fclose($fp_dest);
1806
- $attachment = $dest;
1807
1808
- }
1809
1810
- } catch (Exception $e) {
1811
1812
- // close and remove dest file if created
1813
- if (isset($fp_dest) && is_resource($fp_dest)) {
1814
- fclose($fp_dest);
1815
- unlink($dest);
1816
}
1817
1818
- // do not set any is case of error
1819
- $attachment = null;
1820
- $this->warning('Failed to extract attachment '.$name.': '.$e->getMessage());
1821
1822
}
1823
1824
- // seek to the end of attachment
1825
- $this->fseek($offset + $length);
1826
-
1827
- return $attachment;
1828
}
1829
-
1830
}
1831
1832
if ( ! class_exists ( "getid3_exception" ) ) {
1833
class getid3_exception extends Exception
1834
{
77
return;
78
}
79
80
+ if( ! class_exists( 'getID3' ) ){
81
82
+ class getID3
83
+ {
84
+ // public: Settings
85
+ public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE
86
+ public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
87
+
88
+ // public: Optional tag checks - disable for speed.
89
+ public $option_tag_id3v1 = true; // Read and process ID3v1 tags
90
+ public $option_tag_id3v2 = true; // Read and process ID3v2 tags
91
+ public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags
92
+ public $option_tag_apetag = true; // Read and process APE tags
93
+ public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding
94
+ public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
95
+
96
+ // public: Optional tag/comment calucations
97
+ public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc
98
+
99
+ // public: Optional handling of embedded attachments (e.g. images)
100
+ public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility
101
+
102
+ // public: Optional calculations
103
+ public $option_md5_data = false; // Get MD5 sum of data part - slow
104
+ public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG
105
+ public $option_sha1_data = false; // Get SHA1 sum of data part - slow
106
+ public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX)
107
+
108
+ // public: Read buffer size in bytes
109
+ public $option_fread_buffer_size = 32768;
110
+
111
+ // Public variables
112
+ public $filename; // Filename of file being analysed.
113
+ public $fp; // Filepointer to file being analysed.
114
+ public $info; // Result array.
115
+ public $tempdir = GETID3_TEMP_DIR;
116
+ public $memory_limit = 0;
117
+
118
+ // Protected variables
119
+ protected $startup_error = '';
120
+ protected $startup_warning = '';
121
+
122
+ const VERSION = '1.9.10-20150914';
123
+ const FREAD_BUFFER_SIZE = 32768;
124
+
125
+ const ATTACHMENTS_NONE = false;
126
+ const ATTACHMENTS_INLINE = true;
127
+
128
+ // public: constructor
129
+ public function __construct() {
130
+
131
+ // Check for PHP version
132
+ $required_php_version = '5.3.0';
133
+ if (version_compare(PHP_VERSION, $required_php_version, '<')) {
134
+ $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION;
135
+ return false;
136
+ }
137
138
+ // Check memory
139
+ $this->memory_limit = ini_get('memory_limit');
140
+ if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
141
+ // could be stored as "16M" rather than 16777216 for example
142
+ $this->memory_limit = $matches[1] * 1048576;
143
+ } elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
144
+ // could be stored as "2G" rather than 2147483648 for example
145
+ $this->memory_limit = $matches[1] * 1073741824;
146
+ }
147
+ if ($this->memory_limit <= 0) {
148
+ // memory limits probably disabled
149
+ } elseif ($this->memory_limit <= 4194304) {
150
+ $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini';
151
+ } elseif ($this->memory_limit <= 12582912) {
152
+ $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';
153
+ }
154
155
+ // Check safe_mode off
156
+ if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
157
+ $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
158
+ }
159
160
+ if (intval(ini_get('mbstring.func_overload')) > 0) {
161
+ $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.');
162
+ }
163
164
+ // Check for magic_quotes_runtime
165
+ if (function_exists('get_magic_quotes_runtime')) {
166
+ if (get_magic_quotes_runtime()) {
167
+ return $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).');
168
+ }
169
}
170
171
+ // Check for magic_quotes_gpc
172
+ if (function_exists('magic_quotes_gpc')) {
173
+ if (get_magic_quotes_gpc()) {
174
+ return $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).');
175
+ }
176
}
177
178
+ // Load support library
179
+ if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
180
+ $this->startup_error .= 'getid3.lib.php is missing or corrupt';
181
+ }
182
183
+ if ($this->option_max_2gb_check === null) {
184
+ $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647);
185
+ }
186
187
188
+ // Needed for Windows only:
189
+ // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
190
+ // as well as other helper functions such as head, tail, md5sum, etc
191
+ // This path cannot contain spaces, but the below code will attempt to get the
192
+ // 8.3-equivalent path automatically
193
+ // IMPORTANT: This path must include the trailing slash
194
+ if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) {
195
+
196
+ $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
197
+
198
+ if (!is_dir($helperappsdir)) {
199
+ $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist';
200
+ } elseif (strpos(realpath($helperappsdir), ' ') !== false) {
201
+ $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
202
+ $path_so_far = array();
203
+ foreach ($DirPieces as $key => $value) {
204
+ if (strpos($value, ' ') !== false) {
205
+ if (!empty($path_so_far)) {
206
+ $commandline = 'dir /x '.escapeshellarg(implode(DIRECTORY_SEPARATOR, $path_so_far));
207
+ $dir_listing = `$commandline`;
208
+ $lines = explode("\n", $dir_listing);
209
+ foreach ($lines as $line) {
210
+ $line = trim($line);
211
+ if (preg_match('#^([0-9/]{10}) +([0-9:]{4,5}( [AP]M)?) +(<DIR>|[0-9,]+) +([^ ]{0,11}) +(.+)$#', $line, $matches)) {
212
+ list($dummy, $date, $time, $ampm, $filesize, $shortname, $filename) = $matches;
213
+ if ((strtoupper($filesize) == '<DIR>') && (strtolower($filename) == strtolower($value))) {
214
+ $value = $shortname;
215
+ }
216
}
217
}
218
+ } else {
219
+ $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.';
220
}
221
}
222
+ $path_so_far[] = $value;
223
}
224
+ $helperappsdir = implode(DIRECTORY_SEPARATOR, $path_so_far);
225
}
226
+ define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
227
}
228
229
+ return true;
230
+ }
231
232
+ public function version() {
233
+ return self::VERSION;
234
}
235
+
236
+ public function fread_buffer_size() {
237
+ return $this->option_fread_buffer_size;
238
}
239
240
241
+ // public: setOption
242
+ public function setOption($optArray) {
243
+ if (!is_array($optArray) || empty($optArray)) {
244
+ return false;
245
}
246
+ foreach ($optArray as $opt => $val) {
247
+ if (isset($this->$opt) === false) {
248
+ continue;
249
+ }
250
+ $this->$opt = $val;
251
}
252
+ return true;
253
+ }
254
255
256
+ public function openfile($filename, $filesize=null) {
257
+ try {
258
+ if (!empty($this->startup_error)) {
259
+ throw new getid3_exception($this->startup_error);
260
}
261
+ if (!empty($this->startup_warning)) {
262
+ $this->warning($this->startup_warning);
263
}
264
+
265
+ // init result array and set parameters
266
+ $this->filename = $filename;
267
+ $this->info = array();
268
+ $this->info['GETID3_VERSION'] = $this->version();
269
+ $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
270
+
271
+ // remote files not supported
272
+ if (preg_match('/^(ht|f)tp:\/\//', $filename)) {
273
+ throw new getid3_exception('Remote files are not supported - please copy the file locally first');
274
}
275
+
276
+ $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
277
+ $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);
278
+
279
+ // open local file
280
+ //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
281
+ if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
282
+ // great
283
+ } else {
284
+ $errormessagelist = array();
285
+ if (!is_readable($filename)) {
286
+ $errormessagelist[] = '!is_readable';
287
+ }
288
+ if (!is_file($filename)) {
289
+ $errormessagelist[] = '!is_file';
290
+ }
291
+ if (!file_exists($filename)) {
292
+ $errormessagelist[] = '!file_exists';
293
+ }
294
+ if (empty($errormessagelist)) {
295
+ $errormessagelist[] = 'fopen failed';
296
+ }
297
+ throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
298
}
299
300
+ $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
301
+ // set redundant parameters - might be needed in some include file
302
+ // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
303
+ $filename = str_replace('\\', '/', $filename);
304
+ $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename)));
305
+ $this->info['filename'] = getid3_lib::mb_basename($filename);
306
+ $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
307
+
308
+
309
+ // option_max_2gb_check
310
+ if ($this->option_max_2gb_check) {
311
+ // PHP (32-bit all, and 64-bit Windows) doesn't support integers larger than 2^31 (~2GB)
312
+ // filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize
313
+ // ftell() returns 0 if seeking to the end is beyond the range of unsigned integer
314
+ $fseek = fseek($this->fp, 0, SEEK_END);
315
+ if (($fseek < 0) || (($this->info['filesize'] != 0) && (ftell($this->fp) == 0)) ||
316
+ ($this->info['filesize'] < 0) ||
317
+ (ftell($this->fp) < 0)) {
318
$real_filesize = getid3_lib::getFileSizeSyscall($this->info['filenamepath']);
319
320
if ($real_filesize === false) {
328
}
329
$this->info['filesize'] = $real_filesize;
330
$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.');
331
+ }
332
}
333
334
+ // set more parameters
335
+ $this->info['avdataoffset'] = 0;
336
+ $this->info['avdataend'] = $this->info['filesize'];
337
+ $this->info['fileformat'] = ''; // filled in later
338
+ $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
339
+ $this->info['video']['dataformat'] = ''; // filled in later, unset if not used
340
+ $this->info['tags'] = array(); // filled in later, unset if not used
341
+ $this->info['error'] = array(); // filled in later, unset if not used
342
+ $this->info['warning'] = array(); // filled in later, unset if not used
343
+ $this->info['comments'] = array(); // filled in later, unset if not used
344
+ $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
345
+
346
+ return true;
347
+
348
+ } catch (Exception $e) {
349
+ $this->error($e->getMessage());
350
+ }
351
+ return false;
352
}
353
354
+ // public: analyze file
355
+ public function analyze($filename, $filesize=null, $original_filename='') {
356
+ try {
357
+ if (!$this->openfile($filename, $filesize)) {
358
+ return $this->info;
359
+ }
360
361
+ // Handle tags
362
+ foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
363
+ $option_tag = 'option_tag_'.$tag_name;
364
+ if ($this->$option_tag) {
365
+ $this->include_module('tag.'.$tag_name);
366
+ try {
367
+ $tag_class = 'getid3_'.$tag_name;
368
+ $tag = new $tag_class($this);
369
+ $tag->Analyze();
370
+ }
371
+ catch (getid3_exception $e) {
372
+ throw $e;
373
+ }
374
}
375
+ }
376
+ if (isset($this->info['id3v2']['tag_offset_start'])) {
377
+ $this->info['avdataoffset'] = max($this->info['avdataoffset'], $this->info['id3v2']['tag_offset_end']);
378
+ }
379
+ foreach (array('id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
380
+ if (isset($this->info[$tag_key]['tag_offset_start'])) {
381
+ $this->info['avdataend'] = min($this->info['avdataend'], $this->info[$tag_key]['tag_offset_start']);
382
}
383
}
384
+
385
+ // ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
386
+ if (!$this->option_tag_id3v2) {
387
+ fseek($this->fp, 0);
388
+ $header = fread($this->fp, 10);
389
+ if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
390
+ $this->info['id3v2']['header'] = true;
391
+ $this->info['id3v2']['majorversion'] = ord($header{3});
392
+ $this->info['id3v2']['minorversion'] = ord($header{4});
393
+ $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
394
+ }
395
}
396
397
+ // read 32 kb file data
398
+ fseek($this->fp, $this->info['avdataoffset']);
399
+ $formattest = fread($this->fp, 32774);
400
+
401
+ // determine format
402
+ $determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
403
+
404
+ // unable to determine file format
405
+ if (!$determined_format) {
406
+ fclose($this->fp);
407
+ return $this->error('unable to determine file format');
408
}
409
410
+ // check for illegal ID3 tags
411
+ if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) {
412
+ if ($determined_format['fail_id3'] === 'ERROR') {
413
+ fclose($this->fp);
414
+ return $this->error('ID3 tags not allowed on this file type.');
415
+ } elseif ($determined_format['fail_id3'] === 'WARNING') {
416
+ $this->warning('ID3 tags not allowed on this file type.');
417
+ }
418
+ }
419
420
+ // check for illegal APE tags
421
+ if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) {
422
+ if ($determined_format['fail_ape'] === 'ERROR') {
423
+ fclose($this->fp);
424
+ return $this->error('APE tags not allowed on this file type.');
425
+ } elseif ($determined_format['fail_ape'] === 'WARNING') {
426
+ $this->warning('APE tags not allowed on this file type.');
427
+ }
428
+ }
429
430
+ // set mime type
431
+ $this->info['mime_type'] = $determined_format['mime_type'];
432
433
+ // supported format signature pattern detected, but module deleted
434
+ if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) {
435
fclose($this->fp);
436
+ return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
437
}
438
439
+ // module requires iconv support
440
+ // Check encoding/iconv support
441
+ if (!empty($determined_format['iconv_req']) && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
442
+ $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. ';
443
+ if (GETID3_OS_ISWINDOWS) {
444
+ $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';
445
+ } else {
446
+ $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
447
+ }
448
+ return $this->error($errormessage);
449
}
450
451
+ // include module
452
+ include_once(GETID3_INCLUDEPATH.$determined_format['include']);
453
454
+ // instantiate module class
455
+ $class_name = 'getid3_'.$determined_format['module'];
456
+ if (!class_exists($class_name)) {
457
+ return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.');
458
+ }
459
+ $class = new $class_name($this);
460
+ $class->Analyze();
461
+ unset($class);
462
+
463
+ // close file
464
fclose($this->fp);
465
466
+ // process all tags - copy to 'tags' and convert charsets
467
+ if ($this->option_tags_process) {
468
+ $this->HandleAllTags();
469
}
470
471
+ // perform more calculations
472
+ if ($this->option_extra_info) {
473
+ $this->ChannelsBitratePlaytimeCalculations();
474
+ $this->CalculateCompressionRatioVideo();
475
+ $this->CalculateCompressionRatioAudio();
476
+ $this->CalculateReplayGain();
477
+ $this->ProcessAudioStreams();
478
+ }
479
480
+ // get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
481
+ if ($this->option_md5_data) {
482
+ // do not calc md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too
483
+ if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) {
484
+ $this->getHashdata('md5');
485
+ }
486
+ }
487
488
+ // get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
489
+ if ($this->option_sha1_data) {
490
+ $this->getHashdata('sha1');
491
+ }
492
493
+ // remove undesired keys
494
+ $this->CleanUp();
495
496
+ } catch (Exception $e) {
497
+ $this->error('Caught exception: '.$e->getMessage());
498
}
499
500
+ // return info array
501
+ return $this->info;
502
+ }
503
504
505
+ // private: error handling
506
+ public function error($message) {
507
$this->CleanUp();
508
+ if (!isset($this->info['error'])) {
509
+ $this->info['error'] = array();
510
+ }
511
+ $this->info['error'][] = $message;
512
+ return $this->info;
513
}
514
515
516
+ // private: warning handling
517
+ public function warning($message) {
518
+ $this->info['warning'][] = $message;
519
+ return true;
520
}
521
522
523
+ // private: CleanUp
524
+ private function CleanUp() {
525
526
+ // remove possible empty keys
527
+ $AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate');
528
+ foreach ($AVpossibleEmptyKeys as $dummy => $key) {
529
+ if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) {
530
+ unset($this->info['audio'][$key]);
531
+ }
532
+ if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) {
533
+ unset($this->info['video'][$key]);
534
+ }
535
}
536
+
537
+ // remove empty root keys
538
+ if (!empty($this->info)) {
539
+ foreach ($this->info as $key => $value) {
540
+ if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !== '0')) {
541
+ unset($this->info[$key]);
542
+ }
543
+ }
544
}
545
546
+ // remove meaningless entries from unknown-format files
547
+ if (empty($this->info['fileformat'])) {
548
+ if (isset($this->info['avdataoffset'])) {
549
+ unset($this->info['avdataoffset']);
550
+ }
551
+ if (isset($this->info['avdataend'])) {
552
+ unset($this->info['avdataend']);
553
}
554
}
555
556
+ // remove possible duplicated identical entries
557
+ if (!empty($this->info['error'])) {
558
+ $this->info['error'] = array_values(array_unique($this->info['error']));
559
}
560
+ if (!empty($this->info['warning'])) {
561
+ $this->info['warning'] = array_values(array_unique($this->info['warning']));
562
}
563
564
+ // remove "global variable" type keys
565
+ unset($this->info['php_memory_limit']);
566
567
+ return true;
568
+ }
569
570
571
+ // return array containing information about all supported formats
572
+ public function GetFileFormatArray() {
573
+ static $format_info = array();
574
+ if (empty($format_info)) {
575
+ $format_info = array(
576
+
577
+ // Audio formats
578
+
579
+ // AC-3 - audio - Dolby AC-3 / Dolby Digital
580
+ 'ac3' => array(
581
+ 'pattern' => '^\x0B\x77',
582
+ 'group' => 'audio',
583
+ 'module' => 'ac3',
584
+ 'mime_type' => 'audio/ac3',
585
+ ),
586
+
587
+ // AAC - audio - Advanced Audio Coding (AAC) - ADIF format
588
+ 'adif' => array(
589
+ 'pattern' => '^ADIF',
590
+ 'group' => 'audio',
591
+ 'module' => 'aac',
592
+ 'mime_type' => 'application/octet-stream',
593
+ 'fail_ape' => 'WARNING',
594
+ ),
595
+
596
+ /*
597
+ // AA - audio - Audible Audiobook
598
+ 'aa' => array(
599
+ 'pattern' => '^.{4}\x57\x90\x75\x36',
600
+ 'group' => 'audio',
601
+ 'module' => 'aa',
602
+ 'mime_type' => 'audio/audible',
603
+ ),
604
+ */
605
+ // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
606
+ 'adts' => array(
607
+ 'pattern' => '^\xFF[\xF0-\xF1\xF8-\xF9]',
608
+ 'group' => 'audio',
609
+ 'module' => 'aac',
610
+ 'mime_type' => 'application/octet-stream',
611
+ 'fail_ape' => 'WARNING',
612
+ ),
613
+
614
+
615
+ // AU - audio - NeXT/Sun AUdio (AU)
616
+ 'au' => array(
617
+ 'pattern' => '^\.snd',
618
+ 'group' => 'audio',
619
+ 'module' => 'au',
620
+ 'mime_type' => 'audio/basic',
621
+ ),
622
+
623
+ // AMR - audio - Adaptive Multi Rate
624
+ 'amr' => array(
625
+ 'pattern' => '^\x23\x21AMR\x0A', // #!AMR[0A]
626
+ 'group' => 'audio',
627
+ 'module' => 'amr',
628
+ 'mime_type' => 'audio/amr',
629
+ ),
630
+
631
+ // AVR - audio - Audio Visual Research
632
+ 'avr' => array(
633
+ 'pattern' => '^2BIT',
634
+ 'group' => 'audio',
635
+ 'module' => 'avr',
636
+ 'mime_type' => 'application/octet-stream',
637
+ ),
638
+
639
+ // BONK - audio - Bonk v0.9+
640
+ 'bonk' => array(
641
+ 'pattern' => '^\x00(BONK|INFO|META| ID3)',
642
+ 'group' => 'audio',
643
+ 'module' => 'bonk',
644
+ 'mime_type' => 'audio/xmms-bonk',
645
+ ),
646
+
647
+ // DSS - audio - Digital Speech Standard
648
+ 'dss' => array(
649
+ 'pattern' => '^[\x02-\x03]ds[s2]',
650
+ 'group' => 'audio',
651
+ 'module' => 'dss',
652
+ 'mime_type' => 'application/octet-stream',
653
+ ),
654
+
655
+ // DTS - audio - Dolby Theatre System
656
+ 'dts' => array(
657
+ 'pattern' => '^\x7F\xFE\x80\x01',
658
+ 'group' => 'audio',
659
+ 'module' => 'dts',
660
+ 'mime_type' => 'audio/dts',
661
+ ),
662
+
663
+ // FLAC - audio - Free Lossless Audio Codec
664
+ 'flac' => array(
665
+ 'pattern' => '^fLaC',
666
+ 'group' => 'audio',
667
+ 'module' => 'flac',
668
+ 'mime_type' => 'audio/x-flac',
669
+ ),
670
+
671
+ // LA - audio - Lossless Audio (LA)
672
+ 'la' => array(
673
+ 'pattern' => '^LA0[2-4]',
674
+ 'group' => 'audio',
675
+ 'module' => 'la',
676
+ 'mime_type' => 'application/octet-stream',
677
+ ),
678
+
679
+ // LPAC - audio - Lossless Predictive Audio Compression (LPAC)
680
+ 'lpac' => array(
681
+ 'pattern' => '^LPAC',
682
+ 'group' => 'audio',
683
+ 'module' => 'lpac',
684
+ 'mime_type' => 'application/octet-stream',
685
+ ),
686
+
687
+ // MIDI - audio - MIDI (Musical Instrument Digital Interface)
688
+ 'midi' => array(
689
+ 'pattern' => '^MThd',
690
+ 'group' => 'audio',
691
+ 'module' => 'midi',
692
+ 'mime_type' => 'audio/midi',
693
+ ),
694
+
695
+ // MAC - audio - Monkey's Audio Compressor
696
+ 'mac' => array(
697
+ 'pattern' => '^MAC ',
698
+ 'group' => 'audio',
699
+ 'module' => 'monkey',
700
+ 'mime_type' => 'application/octet-stream',
701
+ ),
702
703
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
704
// // MOD - audio - MODule (assorted sub-formats)
710
// 'mime_type' => 'audio/mod',
711
// ),
712
713
+ // MOD - audio - MODule (Impulse Tracker)
714
+ 'it' => array(
715
+ 'pattern' => '^IMPM',
716
+ 'group' => 'audio',
717
+ 'module' => 'mod',
718
+ //'option' => 'it',
719
+ 'mime_type' => 'audio/it',
720
+ ),
721
+
722
+ // MOD - audio - MODule (eXtended Module, various sub-formats)
723
+ 'xm' => array(
724
+ 'pattern' => '^Extended Module',
725
+ 'group' => 'audio',
726
+ 'module' => 'mod',
727
+ //'option' => 'xm',
728
+ 'mime_type' => 'audio/xm',
729
+ ),
730
+
731
+ // MOD - audio - MODule (ScreamTracker)
732
+ 's3m' => array(
733
+ 'pattern' => '^.{44}SCRM',
734
+ 'group' => 'audio',
735
+ 'module' => 'mod',
736
+ //'option' => 's3m',
737
+ 'mime_type' => 'audio/s3m',
738
+ ),
739
+
740
+ // MPC - audio - Musepack / MPEGplus
741
+ 'mpc' => array(
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])',
743
+ 'group' => 'audio',
744
+ 'module' => 'mpc',
745
+ 'mime_type' => 'audio/x-musepack',
746
+ ),
747
+
748
+ // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS)
749
+ 'mp3' => array(
750
+ '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]',
751
+ 'group' => 'audio',
752
+ 'module' => 'mp3',
753
+ 'mime_type' => 'audio/mpeg',
754
+ ),
755
+
756
+ // OFR - audio - OptimFROG
757
+ 'ofr' => array(
758
+ 'pattern' => '^(\*RIFF|OFR)',
759
+ 'group' => 'audio',
760
+ 'module' => 'optimfrog',
761
+ 'mime_type' => 'application/octet-stream',
762
+ ),
763
+
764
+ // RKAU - audio - RKive AUdio compressor
765
+ 'rkau' => array(
766
+ 'pattern' => '^RKA',
767
+ 'group' => 'audio',
768
+ 'module' => 'rkau',
769
+ 'mime_type' => 'application/octet-stream',
770
+ ),
771
+
772
+ // SHN - audio - Shorten
773
+ 'shn' => array(
774
+ 'pattern' => '^ajkg',
775
+ 'group' => 'audio',
776
+ 'module' => 'shorten',
777
+ 'mime_type' => 'audio/xmms-shn',
778
+ 'fail_id3' => 'ERROR',
779
+ 'fail_ape' => 'ERROR',
780
+ ),
781
+
782
+ // TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org)
783
+ 'tta' => array(
784
+ 'pattern' => '^TTA', // could also be '^TTA(\x01|\x02|\x03|2|1)'
785
+ 'group' => 'audio',
786
+ 'module' => 'tta',
787
+ 'mime_type' => 'application/octet-stream',
788
+ ),
789
+
790
+ // VOC - audio - Creative Voice (VOC)
791
+ 'voc' => array(
792
+ 'pattern' => '^Creative Voice File',
793
+ 'group' => 'audio',
794
+ 'module' => 'voc',
795
+ 'mime_type' => 'audio/voc',
796
+ ),
797
+
798
+ // VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF)
799
+ 'vqf' => array(
800
+ 'pattern' => '^TWIN',
801
+ 'group' => 'audio',
802
+ 'module' => 'vqf',
803
+ 'mime_type' => 'application/octet-stream',
804
+ ),
805
+
806
+ // WV - audio - WavPack (v4.0+)
807
+ 'wv' => array(
808
+ 'pattern' => '^wvpk',
809
+ 'group' => 'audio',
810
+ 'module' => 'wavpack',
811
+ 'mime_type' => 'application/octet-stream',
812
+ ),
813
+
814
+
815
+ // Audio-Video formats
816
+
817
+ // ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
818
+ 'asf' => array(
819
+ 'pattern' => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
820
+ 'group' => 'audio-video',
821
+ 'module' => 'asf',
822
+ 'mime_type' => 'video/x-ms-asf',
823
+ 'iconv_req' => false,
824
+ ),
825
+
826
+ // BINK - audio/video - Bink / Smacker
827
+ 'bink' => array(
828
+ 'pattern' => '^(BIK|SMK)',
829
+ 'group' => 'audio-video',
830
+ 'module' => 'bink',
831
+ 'mime_type' => 'application/octet-stream',
832
+ ),
833
+
834
+ // FLV - audio/video - FLash Video
835
+ 'flv' => array(
836
+ 'pattern' => '^FLV\x01',
837
+ 'group' => 'audio-video',
838
+ 'module' => 'flv',
839
+ 'mime_type' => 'video/x-flv',
840
+ ),
841
+
842
+ // MKAV - audio/video - Mastroka
843
+ 'matroska' => array(
844
+ 'pattern' => '^\x1A\x45\xDF\xA3',
845
+ 'group' => 'audio-video',
846
+ 'module' => 'matroska',
847
+ 'mime_type' => 'video/x-matroska', // may also be audio/x-matroska
848
+ ),
849
+
850
+ // MPEG - audio/video - MPEG (Moving Pictures Experts Group)
851
+ 'mpeg' => array(
852
+ 'pattern' => '^\x00\x00\x01(\xBA|\xB3)',
853
+ 'group' => 'audio-video',
854
+ 'module' => 'mpeg',
855
+ 'mime_type' => 'video/mpeg',
856
+ ),
857
+
858
+ // NSV - audio/video - Nullsoft Streaming Video (NSV)
859
+ 'nsv' => array(
860
+ 'pattern' => '^NSV[sf]',
861
+ 'group' => 'audio-video',
862
+ 'module' => 'nsv',
863
+ 'mime_type' => 'application/octet-stream',
864
+ ),
865
+
866
+ // Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*))
867
+ 'ogg' => array(
868
+ 'pattern' => '^OggS',
869
+ 'group' => 'audio',
870
+ 'module' => 'ogg',
871
+ 'mime_type' => 'application/ogg',
872
+ 'fail_id3' => 'WARNING',
873
+ 'fail_ape' => 'WARNING',
874
+ ),
875
+
876
+ // QT - audio/video - Quicktime
877
+ 'quicktime' => array(
878