1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 The PHP Group | |
6 | +----------------------------------------------------------------------+ |
7 | | This source file is subject to version 3.0 of the PHP license, | |
8 | | that is bundled with this package in the file LICENSE, and is | |
9 | | available through the world-wide-web at the following url: | |
10 | | http://www.php.net/license/3_0.txt. | |
11 | | If you did not receive a copy of the PHP license and are unable to | |
12 | | obtain it through the world-wide-web, please send a note to | |
13 | | license@php.net so we can mail you a copy immediately. | |
14 | +----------------------------------------------------------------------+ |
15 | | Author: Ilia Alshanetsky <ilia@php.net> | |
16 | +----------------------------------------------------------------------+ |
17 | */ |
18 | |
19 | /* $Id$ */ |
20 | |
21 | #ifdef HAVE_CONFIG_H |
22 | #include "config.h" |
23 | #endif |
24 | #include "php.h" |
25 | |
26 | #include <magic.h> |
27 | /* |
28 | * HOWMANY specifies the maximum offset libmagic will look at |
29 | * this is currently hardcoded in the libmagic source but not exported |
30 | */ |
31 | #ifndef HOWMANY |
32 | #define HOWMANY 65536 |
33 | #endif |
34 | |
35 | #include "php_ini.h" |
36 | #include "ext/standard/info.h" |
37 | #include "ext/standard/file.h" /* needed for context stuff */ |
38 | #include "php_fileinfo.h" |
39 | #include "fopen_wrappers.h" /* needed for is_url */ |
40 | |
41 | #ifndef _S_IFDIR |
42 | # define _S_IFDIR S_IFDIR |
43 | #endif |
44 | |
45 | /* {{{ macros and type definitions */ |
46 | struct php_fileinfo { |
47 | long options; |
48 | struct magic_set *magic; |
49 | }; |
50 | |
51 | static zend_object_handlers finfo_object_handlers; |
52 | zend_class_entry *finfo_class_entry; |
53 | |
54 | struct finfo_object { |
55 | zend_object zo; |
56 | struct php_fileinfo *ptr; |
57 | }; |
58 | |
59 | #define FILEINFO_DECLARE_INIT_OBJECT(object) \ |
60 | zval *object = getThis(); |
61 | |
62 | #define FILEINFO_REGISTER_OBJECT(_object, _ptr) \ |
63 | { \ |
64 | struct finfo_object *obj; \ |
65 | obj = (struct finfo_object*)zend_object_store_get_object(_object TSRMLS_CC); \ |
66 | obj->ptr = _ptr; \ |
67 | } |
68 | |
69 | #define FILEINFO_FROM_OBJECT(finfo, object) \ |
70 | { \ |
71 | struct finfo_object *obj = zend_object_store_get_object(object TSRMLS_CC); \ |
72 | finfo = obj->ptr; \ |
73 | if (!finfo) { \ |
74 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "The invalid fileinfo object."); \ |
75 | RETURN_FALSE; \ |
76 | } \ |
77 | } |
78 | |
79 | /* {{{ finfo_objects_free |
80 | */ |
81 | static void finfo_objects_free(void *object TSRMLS_DC) |
82 | { |
83 | struct finfo_object *intern = (struct finfo_object *) object; |
84 | |
85 | if (intern->ptr) { |
86 | magic_close(intern->ptr->magic); |
87 | efree(intern->ptr); |
88 | } |
89 | |
90 | zend_object_std_dtor(&intern->zo TSRMLS_CC); |
91 | efree(intern); |
92 | } |
93 | /* }}} */ |
94 | |
95 | /* {{{ finfo_objects_new |
96 | */ |
97 | PHP_FILEINFO_API zend_object_value finfo_objects_new(zend_class_entry *class_type TSRMLS_DC) |
98 | { |
99 | zend_object_value retval; |
100 | struct finfo_object *intern; |
101 | |
102 | intern = emalloc(sizeof(struct finfo_object)); |
103 | memset(intern, 0, sizeof(struct finfo_object)); |
104 | |
105 | zend_object_std_init(&intern->zo, class_type TSRMLS_CC); |
106 | object_properties_init(&intern->zo, class_type); |
107 | |
108 | intern->ptr = NULL; |
109 | |
110 | retval.handle = zend_objects_store_put(intern, NULL, |
111 | finfo_objects_free, NULL TSRMLS_CC); |
112 | retval.handlers = (zend_object_handlers *) &finfo_object_handlers; |
113 | |
114 | return retval; |
115 | } |
116 | /* }}} */ |
117 | |
118 | /* {{{ arginfo */ |
119 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_open, 0, 0, 0) |
120 | ZEND_ARG_INFO(0, options) |
121 | ZEND_ARG_INFO(0, arg) |
122 | ZEND_END_ARG_INFO() |
123 | |
124 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_close, 0, 0, 1) |
125 | ZEND_ARG_INFO(0, finfo) |
126 | ZEND_END_ARG_INFO() |
127 | |
128 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_set_flags, 0, 0, 2) |
129 | ZEND_ARG_INFO(0, finfo) |
130 | ZEND_ARG_INFO(0, options) |
131 | ZEND_END_ARG_INFO() |
132 | |
133 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_method_set_flags, 0, 0, 1) |
134 | ZEND_ARG_INFO(0, options) |
135 | ZEND_END_ARG_INFO() |
136 | |
137 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_file, 0, 0, 2) |
138 | ZEND_ARG_INFO(0, finfo) |
139 | ZEND_ARG_INFO(0, filename) |
140 | ZEND_ARG_INFO(0, options) |
141 | ZEND_ARG_INFO(0, context) |
142 | ZEND_END_ARG_INFO() |
143 | |
144 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_method_file, 0, 0, 1) |
145 | ZEND_ARG_INFO(0, filename) |
146 | ZEND_ARG_INFO(0, options) |
147 | ZEND_ARG_INFO(0, context) |
148 | ZEND_END_ARG_INFO() |
149 | |
150 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_buffer, 0, 0, 2) |
151 | ZEND_ARG_INFO(0, finfo) |
152 | ZEND_ARG_INFO(0, string) |
153 | ZEND_ARG_INFO(0, options) |
154 | ZEND_ARG_INFO(0, context) |
155 | ZEND_END_ARG_INFO() |
156 | |
157 | ZEND_BEGIN_ARG_INFO_EX(arginfo_finfo_method_buffer, 0, 0, 1) |
158 | ZEND_ARG_INFO(0, string) |
159 | ZEND_ARG_INFO(0, options) |
160 | ZEND_ARG_INFO(0, context) |
161 | ZEND_END_ARG_INFO() |
162 | |
163 | ZEND_BEGIN_ARG_INFO_EX(arginfo_mime_content_type, 0, 0, 1) |
164 | ZEND_ARG_INFO(0, string) |
165 | ZEND_END_ARG_INFO() |
166 | /* }}} */ |
167 | |
168 | /* {{{ finfo_class_functions |
169 | */ |
170 | zend_function_entry finfo_class_functions[] = { |
171 | ZEND_ME_MAPPING(finfo, finfo_open, arginfo_finfo_open, ZEND_ACC_PUBLIC) |
172 | ZEND_ME_MAPPING(set_flags, finfo_set_flags,arginfo_finfo_method_set_flags, ZEND_ACC_PUBLIC) |
173 | ZEND_ME_MAPPING(file, finfo_file, arginfo_finfo_method_file, ZEND_ACC_PUBLIC) |
174 | ZEND_ME_MAPPING(buffer, finfo_buffer, arginfo_finfo_method_buffer, ZEND_ACC_PUBLIC) |
175 | PHP_FE_END |
176 | }; |
177 | /* }}} */ |
178 | |
179 | #define FINFO_SET_OPTION(magic, options) \ |
180 | if (magic_setflags(magic, options) == -1) { \ |
181 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to set option '%ld' %d:%s", \ |
182 | options, magic_errno(magic), magic_error(magic)); \ |
183 | RETURN_FALSE; \ |
184 | } |
185 | |
186 | /* True global resources - no need for thread safety here */ |
187 | static int le_fileinfo; |
188 | /* }}} */ |
189 | |
190 | void finfo_resource_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ |
191 | { |
192 | if (rsrc->ptr) { |
193 | struct php_fileinfo *finfo = (struct php_fileinfo *) rsrc->ptr; |
194 | magic_close(finfo->magic); |
195 | efree(rsrc->ptr); |
196 | rsrc->ptr = NULL; |
197 | } |
198 | } |
199 | /* }}} */ |
200 | |
201 | |
202 | /* {{{ fileinfo_functions[] |
203 | */ |
204 | zend_function_entry fileinfo_functions[] = { |
205 | PHP_FE(finfo_open, arginfo_finfo_open) |
206 | PHP_FE(finfo_close, arginfo_finfo_close) |
207 | PHP_FE(finfo_set_flags, arginfo_finfo_set_flags) |
208 | PHP_FE(finfo_file, arginfo_finfo_file) |
209 | PHP_FE(finfo_buffer, arginfo_finfo_buffer) |
210 | PHP_FE(mime_content_type, arginfo_mime_content_type) |
211 | {NULL, NULL, NULL} |
212 | }; |
213 | /* }}} */ |
214 | |
215 | /* {{{ PHP_MINIT_FUNCTION |
216 | */ |
217 | PHP_MINIT_FUNCTION(finfo) |
218 | { |
219 | zend_class_entry _finfo_class_entry; |
220 | INIT_CLASS_ENTRY(_finfo_class_entry, "finfo" , finfo_class_functions); |
221 | _finfo_class_entry.create_object = finfo_objects_new; |
222 | finfo_class_entry = zend_register_internal_class(&_finfo_class_entry TSRMLS_CC); |
223 | |
224 | /* copy the standard object handlers to you handler table */ |
225 | memcpy(&finfo_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); |
226 | |
227 | le_fileinfo = zend_register_list_destructors_ex(finfo_resource_destructor, NULL, "file_info" , module_number); |
228 | |
229 | REGISTER_LONG_CONSTANT("FILEINFO_NONE" , MAGIC_NONE, CONST_CS|CONST_PERSISTENT); |
230 | REGISTER_LONG_CONSTANT("FILEINFO_SYMLINK" , MAGIC_SYMLINK, CONST_CS|CONST_PERSISTENT); |
231 | REGISTER_LONG_CONSTANT("FILEINFO_MIME" , MAGIC_MIME, CONST_CS|CONST_PERSISTENT); |
232 | REGISTER_LONG_CONSTANT("FILEINFO_MIME_TYPE" , MAGIC_MIME_TYPE, CONST_CS|CONST_PERSISTENT); |
233 | REGISTER_LONG_CONSTANT("FILEINFO_MIME_ENCODING" ,MAGIC_MIME_ENCODING, CONST_CS|CONST_PERSISTENT); |
234 | /* REGISTER_LONG_CONSTANT("FILEINFO_COMPRESS", MAGIC_COMPRESS, CONST_CS|CONST_PERSISTENT); disabled, as it does fork now */ |
235 | REGISTER_LONG_CONSTANT("FILEINFO_DEVICES" , MAGIC_DEVICES, CONST_CS|CONST_PERSISTENT); |
236 | REGISTER_LONG_CONSTANT("FILEINFO_CONTINUE" , MAGIC_CONTINUE, CONST_CS|CONST_PERSISTENT); |
237 | #ifdef MAGIC_PRESERVE_ATIME |
238 | REGISTER_LONG_CONSTANT("FILEINFO_PRESERVE_ATIME" , MAGIC_PRESERVE_ATIME, CONST_CS|CONST_PERSISTENT); |
239 | #endif |
240 | #ifdef MAGIC_RAW |
241 | REGISTER_LONG_CONSTANT("FILEINFO_RAW" , MAGIC_RAW, CONST_CS|CONST_PERSISTENT); |
242 | #endif |
243 | |
244 | return SUCCESS; |
245 | } |
246 | /* }}} */ |
247 | |
248 | /* {{{ fileinfo_module_entry |
249 | */ |
250 | zend_module_entry fileinfo_module_entry = { |
251 | STANDARD_MODULE_HEADER, |
252 | "fileinfo" , |
253 | fileinfo_functions, |
254 | PHP_MINIT(finfo), |
255 | NULL, |
256 | NULL, |
257 | NULL, |
258 | PHP_MINFO(fileinfo), |
259 | PHP_FILEINFO_VERSION, |
260 | STANDARD_MODULE_PROPERTIES |
261 | }; |
262 | /* }}} */ |
263 | |
264 | #ifdef COMPILE_DL_FILEINFO |
265 | ZEND_GET_MODULE(fileinfo) |
266 | #endif |
267 | |
268 | /* {{{ PHP_MINFO_FUNCTION |
269 | */ |
270 | PHP_MINFO_FUNCTION(fileinfo) |
271 | { |
272 | char magic_ver[5]; |
273 | |
274 | (void)snprintf(magic_ver, 4, "%d" , magic_version()); |
275 | magic_ver[4] = '\0'; |
276 | |
277 | php_info_print_table_start(); |
278 | php_info_print_table_row(2, "fileinfo support" , "enabled" ); |
279 | php_info_print_table_row(2, "version" , PHP_FILEINFO_VERSION); |
280 | php_info_print_table_row(2, "libmagic" , magic_ver); |
281 | php_info_print_table_end(); |
282 | } |
283 | /* }}} */ |
284 | |
285 | #define FILEINFO_DESTROY_OBJECT(object) \ |
286 | do { \ |
287 | if (object) { \ |
288 | zend_object_store_ctor_failed(object TSRMLS_CC); \ |
289 | zval_dtor(object); \ |
290 | ZVAL_NULL(object); \ |
291 | } \ |
292 | } while (0) |
293 | |
294 | /* {{{ proto resource finfo_open([int options [, string arg]]) |
295 | Create a new fileinfo resource. */ |
296 | PHP_FUNCTION(finfo_open) |
297 | { |
298 | long options = MAGIC_NONE; |
299 | char *file = NULL; |
300 | int file_len = 0; |
301 | struct php_fileinfo *finfo; |
302 | FILEINFO_DECLARE_INIT_OBJECT(object) |
303 | char resolved_path[MAXPATHLEN]; |
304 | |
305 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lp" , &options, &file, &file_len) == FAILURE) { |
306 | FILEINFO_DESTROY_OBJECT(object); |
307 | RETURN_FALSE; |
308 | } |
309 | |
310 | if (object) { |
311 | struct finfo_object *finfo_obj = (struct finfo_object*)zend_object_store_get_object(object TSRMLS_CC); |
312 | |
313 | if (finfo_obj->ptr) { |
314 | magic_close(finfo_obj->ptr->magic); |
315 | efree(finfo_obj->ptr); |
316 | finfo_obj->ptr = NULL; |
317 | } |
318 | } |
319 | |
320 | if (file_len == 0) { |
321 | file = NULL; |
322 | } else if (file && *file) { /* user specified file, perform open_basedir checks */ |
323 | |
324 | if (php_check_open_basedir(file TSRMLS_CC)) { |
325 | FILEINFO_DESTROY_OBJECT(object); |
326 | RETURN_FALSE; |
327 | } |
328 | if (!expand_filepath_with_mode(file, resolved_path, NULL, 0, CWD_EXPAND TSRMLS_CC)) { |
329 | FILEINFO_DESTROY_OBJECT(object); |
330 | RETURN_FALSE; |
331 | } |
332 | file = resolved_path; |
333 | } |
334 | |
335 | finfo = emalloc(sizeof(struct php_fileinfo)); |
336 | |
337 | finfo->options = options; |
338 | finfo->magic = magic_open(options); |
339 | |
340 | if (finfo->magic == NULL) { |
341 | efree(finfo); |
342 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid mode '%ld'." , options); |
343 | FILEINFO_DESTROY_OBJECT(object); |
344 | RETURN_FALSE; |
345 | } |
346 | |
347 | if (magic_load(finfo->magic, file) == -1) { |
348 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database at '%s'." , file); |
349 | magic_close(finfo->magic); |
350 | efree(finfo); |
351 | FILEINFO_DESTROY_OBJECT(object); |
352 | RETURN_FALSE; |
353 | } |
354 | |
355 | if (object) { |
356 | FILEINFO_REGISTER_OBJECT(object, finfo); |
357 | } else { |
358 | ZEND_REGISTER_RESOURCE(return_value, finfo, le_fileinfo); |
359 | } |
360 | } |
361 | /* }}} */ |
362 | |
363 | /* {{{ proto resource finfo_close(resource finfo) |
364 | Close fileinfo resource. */ |
365 | PHP_FUNCTION(finfo_close) |
366 | { |
367 | struct php_fileinfo *finfo; |
368 | zval *zfinfo; |
369 | |
370 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r" , &zfinfo) == FAILURE) { |
371 | RETURN_FALSE; |
372 | } |
373 | ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info" , le_fileinfo); |
374 | |
375 | zend_list_delete(Z_RESVAL_P(zfinfo)); |
376 | |
377 | RETURN_TRUE; |
378 | } |
379 | /* }}} */ |
380 | |
381 | /* {{{ proto bool finfo_set_flags(resource finfo, int options) |
382 | Set libmagic configuration options. */ |
383 | PHP_FUNCTION(finfo_set_flags) |
384 | { |
385 | long options; |
386 | struct php_fileinfo *finfo; |
387 | zval *zfinfo; |
388 | FILEINFO_DECLARE_INIT_OBJECT(object) |
389 | |
390 | if (object) { |
391 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l" , &options) == FAILURE) { |
392 | RETURN_FALSE; |
393 | } |
394 | FILEINFO_FROM_OBJECT(finfo, object); |
395 | } else { |
396 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl" , &zfinfo, &options) == FAILURE) { |
397 | RETURN_FALSE; |
398 | } |
399 | ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info" , le_fileinfo); |
400 | } |
401 | |
402 | FINFO_SET_OPTION(finfo->magic, options) |
403 | finfo->options = options; |
404 | |
405 | RETURN_TRUE; |
406 | } |
407 | /* }}} */ |
408 | |
409 | #define FILEINFO_MODE_BUFFER 0 |
410 | #define FILEINFO_MODE_STREAM 1 |
411 | #define FILEINFO_MODE_FILE 2 |
412 | |
413 | static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mimetype_emu) /* {{{ */ |
414 | { |
415 | long options = 0; |
416 | char *ret_val = NULL, *buffer = NULL; |
417 | int buffer_len; |
418 | struct php_fileinfo *finfo = NULL; |
419 | zval *zfinfo, *zcontext = NULL; |
420 | zval *what; |
421 | char mime_directory[] = "directory" ; |
422 | |
423 | struct magic_set *magic = NULL; |
424 | FILEINFO_DECLARE_INIT_OBJECT(object) |
425 | |
426 | if (mimetype_emu) { |
427 | |
428 | /* mime_content_type(..) emulation */ |
429 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z" , &what) == FAILURE) { |
430 | return; |
431 | } |
432 | |
433 | switch (Z_TYPE_P(what)) { |
434 | case IS_STRING: |
435 | buffer = Z_STRVAL_P(what); |
436 | buffer_len = Z_STRLEN_P(what); |
437 | mode = FILEINFO_MODE_FILE; |
438 | break; |
439 | |
440 | case IS_RESOURCE: |
441 | mode = FILEINFO_MODE_STREAM; |
442 | break; |
443 | |
444 | default: |
445 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments" ); |
446 | RETURN_FALSE; |
447 | } |
448 | |
449 | magic = magic_open(MAGIC_MIME_TYPE); |
450 | if (magic_load(magic, NULL) == -1) { |
451 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database." ); |
452 | goto common; |
453 | } |
454 | } else if (object) { |
455 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr" , &buffer, &buffer_len, &options, &zcontext) == FAILURE) { |
456 | RETURN_FALSE; |
457 | } |
458 | FILEINFO_FROM_OBJECT(finfo, object); |
459 | magic = finfo->magic; |
460 | } else { |
461 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lr" , &zfinfo, &buffer, &buffer_len, &options, &zcontext) == FAILURE) { |
462 | RETURN_FALSE; |
463 | } |
464 | ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info" , le_fileinfo); |
465 | magic = finfo->magic; |
466 | } |
467 | |
468 | /* Set options for the current file/buffer. */ |
469 | if (options) { |
470 | FINFO_SET_OPTION(magic, options) |
471 | } |
472 | |
473 | switch (mode) { |
474 | case FILEINFO_MODE_BUFFER: |
475 | { |
476 | ret_val = (char *) magic_buffer(magic, buffer, buffer_len); |
477 | break; |
478 | } |
479 | |
480 | case FILEINFO_MODE_STREAM: |
481 | { |
482 | php_stream *stream; |
483 | off_t streampos; |
484 | |
485 | php_stream_from_zval_no_verify(stream, &what); |
486 | if (!stream) { |
487 | goto common; |
488 | } |
489 | |
490 | streampos = php_stream_tell(stream); /* remember stream position for restoration */ |
491 | php_stream_seek(stream, 0, SEEK_SET); |
492 | |
493 | ret_val = (char *) magic_stream(magic, stream); |
494 | |
495 | php_stream_seek(stream, streampos, SEEK_SET); |
496 | break; |
497 | } |
498 | |
499 | case FILEINFO_MODE_FILE: |
500 | { |
501 | /* determine if the file is a local file or remote URL */ |
502 | const char *tmp2; |
503 | php_stream_wrapper *wrap; |
504 | php_stream_statbuf ssb; |
505 | |
506 | if (buffer == NULL || !*buffer) { |
507 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty filename or path" ); |
508 | RETVAL_FALSE; |
509 | goto clean; |
510 | } |
511 | if (CHECK_NULL_PATH(buffer, buffer_len)) { |
512 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path" ); |
513 | RETVAL_FALSE; |
514 | goto clean; |
515 | } |
516 | |
517 | wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0 TSRMLS_CC); |
518 | |
519 | if (wrap) { |
520 | php_stream *stream; |
521 | php_stream_context *context = php_stream_context_from_zval(zcontext, 0); |
522 | |
523 | #ifdef PHP_WIN32 |
524 | if (php_stream_stat_path_ex(buffer, 0, &ssb, context) == SUCCESS) { |
525 | if (ssb.sb.st_mode & S_IFDIR) { |
526 | ret_val = mime_directory; |
527 | goto common; |
528 | } |
529 | } |
530 | #endif |
531 | |
532 | #if PHP_API_VERSION < 20100412 |
533 | stream = php_stream_open_wrapper_ex(buffer, "rb" , ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context); |
534 | #else |
535 | stream = php_stream_open_wrapper_ex(buffer, "rb" , REPORT_ERRORS, NULL, context); |
536 | #endif |
537 | |
538 | if (!stream) { |
539 | RETVAL_FALSE; |
540 | goto clean; |
541 | } |
542 | |
543 | if (php_stream_stat(stream, &ssb) == SUCCESS) { |
544 | if (ssb.sb.st_mode & S_IFDIR) { |
545 | ret_val = mime_directory; |
546 | } else { |
547 | ret_val = (char *)magic_stream(magic, stream); |
548 | } |
549 | } |
550 | |
551 | php_stream_close(stream); |
552 | } |
553 | break; |
554 | } |
555 | |
556 | default: |
557 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments" ); |
558 | } |
559 | |
560 | common: |
561 | if (ret_val) { |
562 | RETVAL_STRING(ret_val, 1); |
563 | } else { |
564 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s" , magic_errno(magic), magic_error(magic)); |
565 | RETVAL_FALSE; |
566 | } |
567 | |
568 | clean: |
569 | if (mimetype_emu) { |
570 | magic_close(magic); |
571 | } |
572 | |
573 | /* Restore options */ |
574 | if (options) { |
575 | FINFO_SET_OPTION(magic, finfo->options) |
576 | } |
577 | return; |
578 | } |
579 | /* }}} */ |
580 | |
581 | /* {{{ proto string finfo_file(resource finfo, char *file_name [, int options [, resource context]]) |
582 | Return information about a file. */ |
583 | PHP_FUNCTION(finfo_file) |
584 | { |
585 | _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_FILE, 0); |
586 | } |
587 | /* }}} */ |
588 | |
589 | /* {{{ proto string finfo_buffer(resource finfo, char *string [, int options [, resource context]]) |
590 | Return infromation about a string buffer. */ |
591 | PHP_FUNCTION(finfo_buffer) |
592 | { |
593 | _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_BUFFER, 0); |
594 | } |
595 | /* }}} */ |
596 | |
597 | /* {{{ proto string mime_content_type(string filename|resource stream) |
598 | Return content-type for file */ |
599 | PHP_FUNCTION(mime_content_type) |
600 | { |
601 | _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1, 1); |
602 | } |
603 | /* }}} */ |
604 | |
605 | |
606 | /* |
607 | * Local variables: |
608 | * tab-width: 4 |
609 | * c-basic-offset: 4 |
610 | * End: |
611 | * vim600: noet sw=4 ts=4 fdm=marker |
612 | * vim<600: noet sw=4 ts=4 |
613 | */ |
614 | |