20 } |
20 } |
21 // Workaround Bug #39923 (https://bugs.php.net/bug.php?id=39923) |
21 // Workaround Bug #39923 (https://bugs.php.net/bug.php?id=39923) |
22 if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) { |
22 if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) { |
23 define('IMG_JPG', IMAGETYPE_JPEG); |
23 define('IMG_JPG', IMAGETYPE_JPEG); |
24 } |
24 } |
|
25 if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE |
|
26 define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8)); |
|
27 } |
25 |
28 |
26 // attempt to define temp dir as something flexible but reliable |
29 // attempt to define temp dir as something flexible but reliable |
27 $temp_dir = ini_get('upload_tmp_dir'); |
30 $temp_dir = ini_get('upload_tmp_dir'); |
28 if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) { |
31 if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) { |
29 $temp_dir = ''; |
32 $temp_dir = ''; |
30 } |
33 } |
31 if (!$temp_dir) { |
34 if (!$temp_dir && function_exists('sys_get_temp_dir')) { // sys_get_temp_dir added in PHP v5.2.1 |
32 // sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts |
35 // sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts |
33 $temp_dir = sys_get_temp_dir(); |
36 $temp_dir = sys_get_temp_dir(); |
34 } |
37 } |
35 $temp_dir = @realpath($temp_dir); // see https://github.com/JamesHeinrich/getID3/pull/10 |
38 $temp_dir = @realpath($temp_dir); // see https://github.com/JamesHeinrich/getID3/pull/10 |
36 $open_basedir = ini_get('open_basedir'); |
39 $open_basedir = ini_get('open_basedir'); |
107 |
110 |
108 // Protected variables |
111 // Protected variables |
109 protected $startup_error = ''; |
112 protected $startup_error = ''; |
110 protected $startup_warning = ''; |
113 protected $startup_warning = ''; |
111 |
114 |
112 const VERSION = '1.9.8-20140511'; |
115 const VERSION = '1.9.14-201706111222'; |
113 const FREAD_BUFFER_SIZE = 32768; |
116 const FREAD_BUFFER_SIZE = 32768; |
114 |
117 |
115 const ATTACHMENTS_NONE = false; |
118 const ATTACHMENTS_NONE = false; |
116 const ATTACHMENTS_INLINE = true; |
119 const ATTACHMENTS_INLINE = true; |
117 |
120 |
118 // public: constructor |
121 // public: constructor |
119 public function __construct() { |
122 public function __construct() { |
120 |
123 |
121 // Check memory |
124 // Check memory |
122 $this->memory_limit = ini_get('memory_limit'); |
125 $this->memory_limit = ini_get('memory_limit'); |
123 if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) { |
126 if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) { |
124 // could be stored as "16M" rather than 16777216 for example |
127 // could be stored as "16M" rather than 16777216 for example |
125 $this->memory_limit = $matches[1] * 1048576; |
128 $this->memory_limit = $matches[1] * 1048576; |
126 } elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0 |
129 } elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0 |
127 // could be stored as "2G" rather than 2147483648 for example |
130 // could be stored as "2G" rather than 2147483648 for example |
128 $this->memory_limit = $matches[1] * 1073741824; |
131 $this->memory_limit = $matches[1] * 1073741824; |
129 } |
132 } |
130 if ($this->memory_limit <= 0) { |
133 if ($this->memory_limit <= 0) { |
131 // memory limits probably disabled |
134 // memory limits probably disabled |
132 } elseif ($this->memory_limit <= 4194304) { |
135 } elseif ($this->memory_limit <= 4194304) { |
133 $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'; |
136 $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'."\n"; |
134 } elseif ($this->memory_limit <= 12582912) { |
137 } elseif ($this->memory_limit <= 12582912) { |
135 $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'; |
138 $this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini'."\n"; |
136 } |
139 } |
137 |
140 |
138 // Check safe_mode off |
141 // Check safe_mode off |
139 if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { |
142 if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { |
140 $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.'); |
143 $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.'); |
141 } |
144 } |
142 |
145 |
143 if (intval(ini_get('mbstring.func_overload')) > 0) { |
146 if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) { |
144 $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.'); |
147 // http://php.net/manual/en/mbstring.overload.php |
|
148 // "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions" |
|
149 // getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those. |
|
150 $this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n"; |
145 } |
151 } |
146 |
152 |
147 // Check for magic_quotes_runtime |
153 // Check for magic_quotes_runtime |
148 if (function_exists('get_magic_quotes_runtime')) { |
154 if (function_exists('get_magic_quotes_runtime')) { |
149 if (get_magic_quotes_runtime()) { |
155 if (get_magic_quotes_runtime()) { |
150 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).'); |
156 $this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n"; |
151 } |
157 } |
152 } |
158 } |
153 |
159 |
154 // Check for magic_quotes_gpc |
160 // Check for magic_quotes_gpc |
155 if (function_exists('magic_quotes_gpc')) { |
161 if (function_exists('magic_quotes_gpc')) { |
156 if (get_magic_quotes_gpc()) { |
162 if (get_magic_quotes_gpc()) { |
157 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).'); |
163 $this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n"; |
158 } |
164 } |
159 } |
165 } |
160 |
166 |
161 // Load support library |
167 // Load support library |
162 if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) { |
168 if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) { |
163 $this->startup_error .= 'getid3.lib.php is missing or corrupt'; |
169 $this->startup_error .= 'getid3.lib.php is missing or corrupt'."\n"; |
164 } |
170 } |
165 |
171 |
166 if ($this->option_max_2gb_check === null) { |
172 if ($this->option_max_2gb_check === null) { |
167 $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647); |
173 $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647); |
168 } |
174 } |
177 if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) { |
183 if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) { |
178 |
184 |
179 $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path |
185 $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path |
180 |
186 |
181 if (!is_dir($helperappsdir)) { |
187 if (!is_dir($helperappsdir)) { |
182 $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'; |
188 $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'."\n"; |
183 } elseif (strpos(realpath($helperappsdir), ' ') !== false) { |
189 } elseif (strpos(realpath($helperappsdir), ' ') !== false) { |
184 $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir)); |
190 $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir)); |
185 $path_so_far = array(); |
191 $path_so_far = array(); |
186 foreach ($DirPieces as $key => $value) { |
192 foreach ($DirPieces as $key => $value) { |
187 if (strpos($value, ' ') !== false) { |
193 if (strpos($value, ' ') !== false) { |
234 } |
245 } |
235 return true; |
246 return true; |
236 } |
247 } |
237 |
248 |
238 |
249 |
239 public function openfile($filename) { |
250 public function openfile($filename, $filesize=null) { |
240 try { |
251 try { |
241 if (!empty($this->startup_error)) { |
252 if (!empty($this->startup_error)) { |
242 throw new getid3_exception($this->startup_error); |
253 throw new getid3_exception($this->startup_error); |
243 } |
254 } |
244 if (!empty($this->startup_warning)) { |
255 if (!empty($this->startup_warning)) { |
245 $this->warning($this->startup_warning); |
256 foreach (explode("\n", $this->startup_warning) as $startup_warning) { |
|
257 $this->warning($startup_warning); |
|
258 } |
246 } |
259 } |
247 |
260 |
248 // init result array and set parameters |
261 // init result array and set parameters |
249 $this->filename = $filename; |
262 $this->filename = $filename; |
250 $this->info = array(); |
263 $this->info = array(); |
251 $this->info['GETID3_VERSION'] = $this->version(); |
264 $this->info['GETID3_VERSION'] = $this->version(); |
252 $this->info['php_memory_limit'] = $this->memory_limit; |
265 $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false); |
253 |
266 |
254 // remote files not supported |
267 // remote files not supported |
255 if (preg_match('/^(ht|f)tp:\/\//', $filename)) { |
268 if (preg_match('#^(ht|f)tp://#', $filename)) { |
256 throw new getid3_exception('Remote files are not supported - please copy the file locally first'); |
269 throw new getid3_exception('Remote files are not supported - please copy the file locally first'); |
257 } |
270 } |
258 |
271 |
259 $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); |
272 $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); |
260 $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename); |
273 $filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename); |
261 |
274 |
262 // open local file |
275 // open local file |
263 //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 |
276 //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 |
264 if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { |
277 if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { |
265 // great |
278 // great |
278 $errormessagelist[] = 'fopen failed'; |
291 $errormessagelist[] = 'fopen failed'; |
279 } |
292 } |
280 throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')'); |
293 throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')'); |
281 } |
294 } |
282 |
295 |
283 $this->info['filesize'] = filesize($filename); |
296 $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename)); |
284 // set redundant parameters - might be needed in some include file |
297 // set redundant parameters - might be needed in some include file |
285 // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion |
298 // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion |
286 $filename = str_replace('\\', '/', $filename); |
299 $filename = str_replace('\\', '/', $filename); |
287 $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename))); |
300 $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename))); |
288 $this->info['filename'] = getid3_lib::mb_basename($filename); |
301 $this->info['filename'] = getid3_lib::mb_basename($filename); |
289 $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename']; |
302 $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename']; |
290 |
303 |
|
304 // set more parameters |
|
305 $this->info['avdataoffset'] = 0; |
|
306 $this->info['avdataend'] = $this->info['filesize']; |
|
307 $this->info['fileformat'] = ''; // filled in later |
|
308 $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used |
|
309 $this->info['video']['dataformat'] = ''; // filled in later, unset if not used |
|
310 $this->info['tags'] = array(); // filled in later, unset if not used |
|
311 $this->info['error'] = array(); // filled in later, unset if not used |
|
312 $this->info['warning'] = array(); // filled in later, unset if not used |
|
313 $this->info['comments'] = array(); // filled in later, unset if not used |
|
314 $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired |
291 |
315 |
292 // option_max_2gb_check |
316 // option_max_2gb_check |
293 if ($this->option_max_2gb_check) { |
317 if ($this->option_max_2gb_check) { |
294 // PHP (32-bit all, and 64-bit Windows) doesn't support integers larger than 2^31 (~2GB) |
318 // PHP (32-bit all, and 64-bit Windows) doesn't support integers larger than 2^31 (~2GB) |
295 // filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize |
319 // filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize |
312 $this->info['filesize'] = $real_filesize; |
336 $this->info['filesize'] = $real_filesize; |
313 $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.'); |
337 $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.'); |
314 } |
338 } |
315 } |
339 } |
316 |
340 |
317 // set more parameters |
|
318 $this->info['avdataoffset'] = 0; |
|
319 $this->info['avdataend'] = $this->info['filesize']; |
|
320 $this->info['fileformat'] = ''; // filled in later |
|
321 $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used |
|
322 $this->info['video']['dataformat'] = ''; // filled in later, unset if not used |
|
323 $this->info['tags'] = array(); // filled in later, unset if not used |
|
324 $this->info['error'] = array(); // filled in later, unset if not used |
|
325 $this->info['warning'] = array(); // filled in later, unset if not used |
|
326 $this->info['comments'] = array(); // filled in later, unset if not used |
|
327 $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired |
|
328 |
|
329 return true; |
341 return true; |
330 |
342 |
331 } catch (Exception $e) { |
343 } catch (Exception $e) { |
332 $this->error($e->getMessage()); |
344 $this->error($e->getMessage()); |
333 } |
345 } |
334 return false; |
346 return false; |
335 } |
347 } |
336 |
348 |
337 // public: analyze file |
349 // public: analyze file |
338 public function analyze($filename) { |
350 public function analyze($filename, $filesize=null, $original_filename='') { |
339 try { |
351 try { |
340 if (!$this->openfile($filename)) { |
352 if (!$this->openfile($filename, $filesize)) { |
341 return $this->info; |
353 return $this->info; |
342 } |
354 } |
343 |
355 |
344 // Handle tags |
356 // Handle tags |
345 foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) { |
357 foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) { |
417 if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) { |
429 if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) { |
418 fclose($this->fp); |
430 fclose($this->fp); |
419 return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.'); |
431 return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.'); |
420 } |
432 } |
421 |
433 |
422 // module requires iconv support |
434 // module requires mb_convert_encoding/iconv support |
423 // Check encoding/iconv support |
435 // Check encoding/iconv support |
424 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'))) { |
436 if (!empty($determined_format['iconv_req']) && !function_exists('mb_convert_encoding') && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) { |
425 $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. '; |
437 $errormessage = 'mb_convert_encoding() or iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. '; |
426 if (GETID3_OS_ISWINDOWS) { |
438 if (GETID3_OS_ISWINDOWS) { |
427 $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'; |
439 $errormessage .= 'PHP does not have mb_convert_encoding() or iconv() support. Please enable php_mbstring.dll / php_iconv.dll in php.ini, and copy php_mbstring.dll / iconv.dll from c:/php/dlls to c:/windows/system32'; |
428 } else { |
440 } else { |
429 $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch'; |
441 $errormessage .= 'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch'; |
430 } |
442 } |
431 return $this->error($errormessage); |
443 return $this->error($errormessage); |
432 } |
444 } |
433 |
445 |
434 // include module |
446 // include module |
577 ), |
589 ), |
578 |
590 |
579 /* |
591 /* |
580 // AA - audio - Audible Audiobook |
592 // AA - audio - Audible Audiobook |
581 'aa' => array( |
593 'aa' => array( |
582 'pattern' => '^.{4}\x57\x90\x75\x36', |
594 'pattern' => '^.{4}\\x57\\x90\\x75\\x36', |
583 'group' => 'audio', |
595 'group' => 'audio', |
584 'module' => 'aa', |
596 'module' => 'aa', |
585 'mime_type' => 'audio/audible', |
597 'mime_type' => 'audio/audible', |
586 ), |
598 ), |
587 */ |
599 */ |
588 // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3) |
600 // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3) |
589 'adts' => array( |
601 'adts' => array( |
590 'pattern' => '^\xFF[\xF0-\xF1\xF8-\xF9]', |
602 'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]', |
591 'group' => 'audio', |
603 'group' => 'audio', |
592 'module' => 'aac', |
604 'module' => 'aac', |
593 'mime_type' => 'application/octet-stream', |
605 'mime_type' => 'application/octet-stream', |
594 'fail_ape' => 'WARNING', |
606 'fail_ape' => 'WARNING', |
595 ), |
607 ), |
596 |
608 |
597 |
609 |
598 // AU - audio - NeXT/Sun AUdio (AU) |
610 // AU - audio - NeXT/Sun AUdio (AU) |
599 'au' => array( |
611 'au' => array( |
600 'pattern' => '^\.snd', |
612 'pattern' => '^\\.snd', |
601 'group' => 'audio', |
613 'group' => 'audio', |
602 'module' => 'au', |
614 'module' => 'au', |
603 'mime_type' => 'audio/basic', |
615 'mime_type' => 'audio/basic', |
604 ), |
616 ), |
605 |
617 |
606 // AMR - audio - Adaptive Multi Rate |
618 // AMR - audio - Adaptive Multi Rate |
607 'amr' => array( |
619 'amr' => array( |
608 'pattern' => '^\x23\x21AMR\x0A', // #!AMR[0A] |
620 'pattern' => '^\\x23\\x21AMR\\x0A', // #!AMR[0A] |
609 'group' => 'audio', |
621 'group' => 'audio', |
610 'module' => 'amr', |
622 'module' => 'amr', |
611 'mime_type' => 'audio/amr', |
623 'mime_type' => 'audio/amr', |
612 ), |
624 ), |
613 |
625 |
619 'mime_type' => 'application/octet-stream', |
631 'mime_type' => 'application/octet-stream', |
620 ), |
632 ), |
621 |
633 |
622 // BONK - audio - Bonk v0.9+ |
634 // BONK - audio - Bonk v0.9+ |
623 'bonk' => array( |
635 'bonk' => array( |
624 'pattern' => '^\x00(BONK|INFO|META| ID3)', |
636 'pattern' => '^\\x00(BONK|INFO|META| ID3)', |
625 'group' => 'audio', |
637 'group' => 'audio', |
626 'module' => 'bonk', |
638 'module' => 'bonk', |
627 'mime_type' => 'audio/xmms-bonk', |
639 'mime_type' => 'audio/xmms-bonk', |
628 ), |
640 ), |
629 |
641 |
|
642 // DSF - audio - Direct Stream Digital (DSD) Storage Facility files (DSF) - https://en.wikipedia.org/wiki/Direct_Stream_Digital |
|
643 'dsf' => array( |
|
644 'pattern' => '^DSD ', // including trailing space: 44 53 44 20 |
|
645 'group' => 'audio', |
|
646 'module' => 'dsf', |
|
647 'mime_type' => 'audio/dsd', |
|
648 ), |
|
649 |
630 // DSS - audio - Digital Speech Standard |
650 // DSS - audio - Digital Speech Standard |
631 'dss' => array( |
651 'dss' => array( |
632 'pattern' => '^[\x02-\x03]ds[s2]', |
652 'pattern' => '^[\\x02-\\x06]ds[s2]', |
633 'group' => 'audio', |
653 'group' => 'audio', |
634 'module' => 'dss', |
654 'module' => 'dss', |
635 'mime_type' => 'application/octet-stream', |
655 'mime_type' => 'application/octet-stream', |
636 ), |
656 ), |
637 |
657 |
638 // DTS - audio - Dolby Theatre System |
658 // DTS - audio - Dolby Theatre System |
639 'dts' => array( |
659 'dts' => array( |
640 'pattern' => '^\x7F\xFE\x80\x01', |
660 'pattern' => '^\\x7F\\xFE\\x80\\x01', |
641 'group' => 'audio', |
661 'group' => 'audio', |
642 'module' => 'dts', |
662 'module' => 'dts', |
643 'mime_type' => 'audio/dts', |
663 'mime_type' => 'audio/dts', |
644 ), |
664 ), |
645 |
665 |
720 'mime_type' => 'audio/s3m', |
740 'mime_type' => 'audio/s3m', |
721 ), |
741 ), |
722 |
742 |
723 // MPC - audio - Musepack / MPEGplus |
743 // MPC - audio - Musepack / MPEGplus |
724 'mpc' => array( |
744 'mpc' => array( |
725 'pattern' => '^(MPCK|MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])', |
745 'pattern' => '^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])', |
726 'group' => 'audio', |
746 'group' => 'audio', |
727 'module' => 'mpc', |
747 'module' => 'mpc', |
728 'mime_type' => 'audio/x-musepack', |
748 'mime_type' => 'audio/x-musepack', |
729 ), |
749 ), |
730 |
750 |
731 // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS) |
751 // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS) |
732 'mp3' => array( |
752 'mp3' => array( |
733 '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]', |
753 '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]', |
734 'group' => 'audio', |
754 'group' => 'audio', |
735 'module' => 'mp3', |
755 'module' => 'mp3', |
736 'mime_type' => 'audio/mpeg', |
756 'mime_type' => 'audio/mpeg', |
737 ), |
757 ), |
738 |
758 |
739 // OFR - audio - OptimFROG |
759 // OFR - audio - OptimFROG |
740 'ofr' => array( |
760 'ofr' => array( |
741 'pattern' => '^(\*RIFF|OFR)', |
761 'pattern' => '^(\\*RIFF|OFR)', |
742 'group' => 'audio', |
762 'group' => 'audio', |
743 'module' => 'optimfrog', |
763 'module' => 'optimfrog', |
744 'mime_type' => 'application/octet-stream', |
764 'mime_type' => 'application/octet-stream', |
745 ), |
765 ), |
746 |
766 |
814 'mime_type' => 'application/octet-stream', |
834 'mime_type' => 'application/octet-stream', |
815 ), |
835 ), |
816 |
836 |
817 // FLV - audio/video - FLash Video |
837 // FLV - audio/video - FLash Video |
818 'flv' => array( |
838 'flv' => array( |
819 'pattern' => '^FLV\x01', |
839 'pattern' => '^FLV[\\x01]', |
820 'group' => 'audio-video', |
840 'group' => 'audio-video', |
821 'module' => 'flv', |
841 'module' => 'flv', |
822 'mime_type' => 'video/x-flv', |
842 'mime_type' => 'video/x-flv', |
823 ), |
843 ), |
824 |
844 |
825 // MKAV - audio/video - Mastroka |
845 // MKAV - audio/video - Mastroka |
826 'matroska' => array( |
846 'matroska' => array( |
827 'pattern' => '^\x1A\x45\xDF\xA3', |
847 'pattern' => '^\\x1A\\x45\\xDF\\xA3', |
828 'group' => 'audio-video', |
848 'group' => 'audio-video', |
829 'module' => 'matroska', |
849 'module' => 'matroska', |
830 'mime_type' => 'video/x-matroska', // may also be audio/x-matroska |
850 'mime_type' => 'video/x-matroska', // may also be audio/x-matroska |
831 ), |
851 ), |
832 |
852 |
833 // MPEG - audio/video - MPEG (Moving Pictures Experts Group) |
853 // MPEG - audio/video - MPEG (Moving Pictures Experts Group) |
834 'mpeg' => array( |
854 'mpeg' => array( |
835 'pattern' => '^\x00\x00\x01(\xBA|\xB3)', |
855 'pattern' => '^\\x00\\x00\\x01[\\xB3\\xBA]', |
836 'group' => 'audio-video', |
856 'group' => 'audio-video', |
837 'module' => 'mpeg', |
857 'module' => 'mpeg', |
838 'mime_type' => 'video/mpeg', |
858 'mime_type' => 'video/mpeg', |
839 ), |
859 ), |
840 |
860 |
867 // 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) |
887 // 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) |
868 'riff' => array( |
888 'riff' => array( |
869 'pattern' => '^(RIFF|SDSS|FORM)', |
889 'pattern' => '^(RIFF|SDSS|FORM)', |
870 'group' => 'audio-video', |
890 'group' => 'audio-video', |
871 'module' => 'riff', |
891 'module' => 'riff', |
872 'mime_type' => 'audio/x-wave', |
892 'mime_type' => 'audio/x-wav', |
873 'fail_ape' => 'WARNING', |
893 'fail_ape' => 'WARNING', |
874 ), |
894 ), |
875 |
895 |
876 // Real - audio/video - RealAudio, RealVideo |
896 // Real - audio/video - RealAudio, RealVideo |
877 'real' => array( |
897 'real' => array( |
878 'pattern' => '^(\\.RMF|\\.ra)', |
898 'pattern' => '^\\.(RMF|ra)', |
879 'group' => 'audio-video', |
899 'group' => 'audio-video', |
880 'module' => 'real', |
900 'module' => 'real', |
881 'mime_type' => 'audio/x-realaudio', |
901 'mime_type' => 'audio/x-realaudio', |
882 ), |
902 ), |
883 |
903 |
920 'fail_ape' => 'ERROR', |
940 'fail_ape' => 'ERROR', |
921 ), |
941 ), |
922 |
942 |
923 // JPEG - still image - Joint Photographic Experts Group (JPEG) |
943 // JPEG - still image - Joint Photographic Experts Group (JPEG) |
924 'jpg' => array( |
944 'jpg' => array( |
925 'pattern' => '^\xFF\xD8\xFF', |
945 'pattern' => '^\\xFF\\xD8\\xFF', |
926 'group' => 'graphic', |
946 'group' => 'graphic', |
927 'module' => 'jpg', |
947 'module' => 'jpg', |
928 'mime_type' => 'image/jpeg', |
948 'mime_type' => 'image/jpeg', |
929 'fail_id3' => 'ERROR', |
949 'fail_id3' => 'ERROR', |
930 'fail_ape' => 'ERROR', |
950 'fail_ape' => 'ERROR', |
931 ), |
951 ), |
932 |
952 |
933 // PCD - still image - Kodak Photo CD |
953 // PCD - still image - Kodak Photo CD |
934 'pcd' => array( |
954 'pcd' => array( |
935 'pattern' => '^.{2048}PCD_IPI\x00', |
955 'pattern' => '^.{2048}PCD_IPI\\x00', |
936 'group' => 'graphic', |
956 'group' => 'graphic', |
937 'module' => 'pcd', |
957 'module' => 'pcd', |
938 'mime_type' => 'image/x-photo-cd', |
958 'mime_type' => 'image/x-photo-cd', |
939 'fail_id3' => 'ERROR', |
959 'fail_id3' => 'ERROR', |
940 'fail_ape' => 'ERROR', |
960 'fail_ape' => 'ERROR', |
941 ), |
961 ), |
942 |
962 |
943 |
963 |
944 // PNG - still image - Portable Network Graphics (PNG) |
964 // PNG - still image - Portable Network Graphics (PNG) |
945 'png' => array( |
965 'png' => array( |
946 'pattern' => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A', |
966 'pattern' => '^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A', |
947 'group' => 'graphic', |
967 'group' => 'graphic', |
948 'module' => 'png', |
968 'module' => 'png', |
949 'mime_type' => 'image/png', |
969 'mime_type' => 'image/png', |
950 'fail_id3' => 'ERROR', |
970 'fail_id3' => 'ERROR', |
951 'fail_ape' => 'ERROR', |
971 'fail_ape' => 'ERROR', |
952 ), |
972 ), |
953 |
973 |
954 |
974 |
955 // SVG - still image - Scalable Vector Graphics (SVG) |
975 // SVG - still image - Scalable Vector Graphics (SVG) |
956 'svg' => array( |
976 'svg' => array( |
957 'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http:\/\/www\.w3\.org\/2000\/svg")', |
977 'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http://www\\.w3\\.org/2000/svg")', |
958 'group' => 'graphic', |
978 'group' => 'graphic', |
959 'module' => 'svg', |
979 'module' => 'svg', |
960 'mime_type' => 'image/svg+xml', |
980 'mime_type' => 'image/svg+xml', |
961 'fail_id3' => 'ERROR', |
981 'fail_id3' => 'ERROR', |
962 'fail_ape' => 'ERROR', |
982 'fail_ape' => 'ERROR', |
963 ), |
983 ), |
964 |
984 |
965 |
985 |
966 // TIFF - still image - Tagged Information File Format (TIFF) |
986 // TIFF - still image - Tagged Information File Format (TIFF) |
967 'tiff' => array( |
987 'tiff' => array( |
968 'pattern' => '^(II\x2A\x00|MM\x00\x2A)', |
988 'pattern' => '^(II\\x2A\\x00|MM\\x00\\x2A)', |
969 'group' => 'graphic', |
989 'group' => 'graphic', |
970 'module' => 'tiff', |
990 'module' => 'tiff', |
971 'mime_type' => 'image/tiff', |
991 'mime_type' => 'image/tiff', |
972 'fail_id3' => 'ERROR', |
992 'fail_id3' => 'ERROR', |
973 'fail_ape' => 'ERROR', |
993 'fail_ape' => 'ERROR', |
974 ), |
994 ), |
975 |
995 |
976 |
996 |
977 // EFAX - still image - eFax (TIFF derivative) |
997 // EFAX - still image - eFax (TIFF derivative) |
978 'efax' => array( |
998 'efax' => array( |
979 'pattern' => '^\xDC\xFE', |
999 'pattern' => '^\\xDC\\xFE', |
980 'group' => 'graphic', |
1000 'group' => 'graphic', |
981 'module' => 'efax', |
1001 'module' => 'efax', |
982 'mime_type' => 'image/efax', |
1002 'mime_type' => 'image/efax', |
983 'fail_id3' => 'ERROR', |
1003 'fail_id3' => 'ERROR', |
984 'fail_ape' => 'ERROR', |
1004 'fail_ape' => 'ERROR', |
998 'iconv_req' => false, |
1018 'iconv_req' => false, |
999 ), |
1019 ), |
1000 |
1020 |
1001 // RAR - data - RAR compressed data |
1021 // RAR - data - RAR compressed data |
1002 'rar' => array( |
1022 'rar' => array( |
1003 'pattern' => '^Rar\!', |
1023 'pattern' => '^Rar\\!', |
1004 'group' => 'archive', |
1024 'group' => 'archive', |
1005 'module' => 'rar', |
1025 'module' => 'rar', |
1006 'mime_type' => 'application/octet-stream', |
1026 'mime_type' => 'application/octet-stream', |
1007 'fail_id3' => 'ERROR', |
1027 'fail_id3' => 'ERROR', |
1008 'fail_ape' => 'ERROR', |
1028 'fail_ape' => 'ERROR', |
1009 ), |
1029 ), |
1010 |
1030 |
1011 // SZIP - audio/data - SZIP compressed data |
1031 // SZIP - audio/data - SZIP compressed data |
1012 'szip' => array( |
1032 'szip' => array( |
1013 'pattern' => '^SZ\x0A\x04', |
1033 'pattern' => '^SZ\\x0A\\x04', |
1014 'group' => 'archive', |
1034 'group' => 'archive', |
1015 'module' => 'szip', |
1035 'module' => 'szip', |
1016 'mime_type' => 'application/octet-stream', |
1036 'mime_type' => 'application/octet-stream', |
1017 'fail_id3' => 'ERROR', |
1037 'fail_id3' => 'ERROR', |
1018 'fail_ape' => 'ERROR', |
1038 'fail_ape' => 'ERROR', |
1019 ), |
1039 ), |
1020 |
1040 |
1021 // TAR - data - TAR compressed data |
1041 // TAR - data - TAR compressed data |
1022 'tar' => array( |
1042 'tar' => array( |
1023 '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}', |
1043 '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}', |
1024 'group' => 'archive', |
1044 'group' => 'archive', |
1025 'module' => 'tar', |
1045 'module' => 'tar', |
1026 'mime_type' => 'application/x-tar', |
1046 'mime_type' => 'application/x-tar', |
1027 'fail_id3' => 'ERROR', |
1047 'fail_id3' => 'ERROR', |
1028 'fail_ape' => 'ERROR', |
1048 'fail_ape' => 'ERROR', |
1029 ), |
1049 ), |
1030 |
1050 |
1031 // GZIP - data - GZIP compressed data |
1051 // GZIP - data - GZIP compressed data |
1032 'gz' => array( |
1052 'gz' => array( |
1033 'pattern' => '^\x1F\x8B\x08', |
1053 'pattern' => '^\\x1F\\x8B\\x08', |
1034 'group' => 'archive', |
1054 'group' => 'archive', |
1035 'module' => 'gzip', |
1055 'module' => 'gzip', |
1036 'mime_type' => 'application/x-gzip', |
1056 'mime_type' => 'application/x-gzip', |
1037 'fail_id3' => 'ERROR', |
1057 'fail_id3' => 'ERROR', |
1038 'fail_ape' => 'ERROR', |
1058 'fail_ape' => 'ERROR', |
1039 ), |
1059 ), |
1040 |
1060 |
1041 // ZIP - data - ZIP compressed data |
1061 // ZIP - data - ZIP compressed data |
1042 'zip' => array( |
1062 'zip' => array( |
1043 'pattern' => '^PK\x03\x04', |
1063 'pattern' => '^PK\\x03\\x04', |
1044 'group' => 'archive', |
1064 'group' => 'archive', |
1045 'module' => 'zip', |
1065 'module' => 'zip', |
1046 'mime_type' => 'application/zip', |
1066 'mime_type' => 'application/zip', |
1047 'fail_id3' => 'ERROR', |
1067 'fail_id3' => 'ERROR', |
1048 'fail_ape' => 'ERROR', |
1068 'fail_ape' => 'ERROR', |
1051 |
1071 |
1052 // Misc other formats |
1072 // Misc other formats |
1053 |
1073 |
1054 // PAR2 - data - Parity Volume Set Specification 2.0 |
1074 // PAR2 - data - Parity Volume Set Specification 2.0 |
1055 'par2' => array ( |
1075 'par2' => array ( |
1056 'pattern' => '^PAR2\x00PKT', |
1076 'pattern' => '^PAR2\\x00PKT', |
1057 'group' => 'misc', |
1077 'group' => 'misc', |
1058 'module' => 'par2', |
1078 'module' => 'par2', |
1059 'mime_type' => 'application/octet-stream', |
1079 'mime_type' => 'application/octet-stream', |
1060 'fail_id3' => 'ERROR', |
1080 'fail_id3' => 'ERROR', |
1061 'fail_ape' => 'ERROR', |
1081 'fail_ape' => 'ERROR', |
1062 ), |
1082 ), |
1063 |
1083 |
1064 // PDF - data - Portable Document Format |
1084 // PDF - data - Portable Document Format |
1065 'pdf' => array( |
1085 'pdf' => array( |
1066 'pattern' => '^\x25PDF', |
1086 'pattern' => '^\\x25PDF', |
1067 'group' => 'misc', |
1087 'group' => 'misc', |
1068 'module' => 'pdf', |
1088 'module' => 'pdf', |
1069 'mime_type' => 'application/pdf', |
1089 'mime_type' => 'application/pdf', |
1070 'fail_id3' => 'ERROR', |
1090 'fail_id3' => 'ERROR', |
1071 'fail_ape' => 'ERROR', |
1091 'fail_ape' => 'ERROR', |
1072 ), |
1092 ), |
1073 |
1093 |
1074 // MSOFFICE - data - ZIP compressed data |
1094 // MSOFFICE - data - ZIP compressed data |
1075 'msoffice' => array( |
1095 'msoffice' => array( |
1076 'pattern' => '^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document |
1096 'pattern' => '^\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1', // D0CF11E == DOCFILE == Microsoft Office Document |
1077 'group' => 'misc', |
1097 'group' => 'misc', |
1078 'module' => 'msoffice', |
1098 'module' => 'msoffice', |
1079 'mime_type' => 'application/octet-stream', |
1099 'mime_type' => 'application/octet-stream', |
1080 'fail_id3' => 'ERROR', |
1100 'fail_id3' => 'ERROR', |
1081 'fail_ape' => 'ERROR', |
1101 'fail_ape' => 'ERROR', |
1112 return $info; |
1132 return $info; |
1113 } |
1133 } |
1114 } |
1134 } |
1115 |
1135 |
1116 |
1136 |
1117 if (preg_match('#\.mp[123a]$#i', $filename)) { |
1137 if (preg_match('#\\.mp[123a]$#i', $filename)) { |
1118 // Too many mp3 encoders on the market put gabage in front of mpeg files |
1138 // Too many mp3 encoders on the market put gabage in front of mpeg files |
1119 // use assume format on these if format detection failed |
1139 // use assume format on these if format detection failed |
1120 $GetFileFormatArray = $this->GetFileFormatArray(); |
1140 $GetFileFormatArray = $this->GetFileFormatArray(); |
1121 $info = $GetFileFormatArray['mp3']; |
1141 $info = $GetFileFormatArray['mp3']; |
1122 $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php'; |
1142 $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php'; |
1123 return $info; |
1143 return $info; |
1124 } elseif (preg_match('/\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) { |
1144 } elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) { |
1125 // there's not really a useful consistent "magic" at the beginning of .cue files to identify them |
1145 // there's not really a useful consistent "magic" at the beginning of .cue files to identify them |
1126 // so until I think of something better, just go by filename if all other format checks fail |
1146 // so until I think of something better, just go by filename if all other format checks fail |
1127 // and verify there's at least one instance of "TRACK xx AUDIO" in the file |
1147 // and verify there's at least one instance of "TRACK xx AUDIO" in the file |
1128 $GetFileFormatArray = $this->GetFileFormatArray(); |
1148 $GetFileFormatArray = $this->GetFileFormatArray(); |
1129 $info = $GetFileFormatArray['cue']; |
1149 $info = $GetFileFormatArray['cue']; |
1659 } |
1691 } |
1660 $pos = $this->ftell() + $bytes; |
1692 $pos = $this->ftell() + $bytes; |
1661 if (!getid3_lib::intValueSupported($pos)) { |
1693 if (!getid3_lib::intValueSupported($pos)) { |
1662 throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10); |
1694 throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10); |
1663 } |
1695 } |
1664 return fread($this->getid3->fp, $bytes); |
1696 |
|
1697 //return fread($this->getid3->fp, $bytes); |
|
1698 /* |
|
1699 * http://www.getid3.org/phpBB3/viewtopic.php?t=1930 |
|
1700 * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread(). |
|
1701 * It seems to assume that fread() would always return as many bytes as were requested. |
|
1702 * However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes. |
|
1703 * The call may return only part of the requested data and a new call is needed to get more." |
|
1704 */ |
|
1705 $contents = ''; |
|
1706 do { |
|
1707 $part = fread($this->getid3->fp, $bytes); |
|
1708 $partLength = strlen($part); |
|
1709 $bytes -= $partLength; |
|
1710 $contents .= $part; |
|
1711 } while (($bytes > 0) && ($partLength > 0)); |
|
1712 return $contents; |
1665 } |
1713 } |
1666 |
1714 |
1667 protected function fseek($bytes, $whence=SEEK_SET) { |
1715 protected function fseek($bytes, $whence=SEEK_SET) { |
1668 if ($this->data_string_flag) { |
1716 if ($this->data_string_flag) { |
1669 switch ($whence) { |
1717 switch ($whence) { |