php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
fileinfo.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Ilia Alshanetsky <ilia@php.net> |
14 +----------------------------------------------------------------------+
15*/
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20#include "php.h"
21
22#include "libmagic/magic.h"
23/*
24 * HOWMANY specifies the maximum offset libmagic will look at
25 * this is currently hardcoded in the libmagic source but not exported
26 */
27#ifndef HOWMANY
28#define HOWMANY 65536
29#endif
30
31#include "php_ini.h"
32#include "ext/standard/info.h"
33#include "ext/standard/file.h" /* needed for context stuff */
34#include "php_fileinfo.h"
35#include "fileinfo_arginfo.h"
36#include "fopen_wrappers.h" /* needed for is_url */
38
39/* {{{ macros and type definitions */
44
45static zend_object_handlers finfo_object_handlers;
47
52
53static inline finfo_object *php_finfo_fetch_object(zend_object *obj) {
54 return (finfo_object *)((char*)(obj) - XtOffsetOf(finfo_object, zo));
55}
56
57#define Z_FINFO_P(zv) php_finfo_fetch_object(Z_OBJ_P((zv)))
58
59#define FILEINFO_FROM_OBJECT(finfo, object) \
60{ \
61 finfo_object *obj = Z_FINFO_P(object); \
62 finfo = obj->ptr; \
63 if (!finfo) { \
64 zend_throw_error(NULL, "Invalid finfo object"); \
65 RETURN_THROWS(); \
66 } \
67}
68
69/* {{{ finfo_objects_free */
70static void finfo_objects_free(zend_object *object)
71{
72 finfo_object *intern = php_finfo_fetch_object(object);
73
74 if (intern->ptr) {
75 magic_close(intern->ptr->magic);
76 efree(intern->ptr);
77 }
78
79 zend_object_std_dtor(&intern->zo);
80}
81/* }}} */
82
83/* {{{ finfo_objects_new */
85{
86 finfo_object *intern;
87
88 intern = zend_object_alloc(sizeof(finfo_object), class_type);
89
90 zend_object_std_init(&intern->zo, class_type);
91 object_properties_init(&intern->zo, class_type);
92
93 return &intern->zo;
94}
95/* }}} */
96
97#define FINFO_SET_OPTION(magic, options) \
98 if (magic_setflags(magic, options) == -1) { \
99 php_error_docref(NULL, E_WARNING, "Failed to set option '" ZEND_LONG_FMT "' %d:%s", \
100 options, magic_errno(magic), magic_error(magic)); \
101 RETURN_FALSE; \
102 }
103/* }}} */
104
105/* {{{ PHP_MINIT_FUNCTION */
107{
108 finfo_class_entry = register_class_finfo();
109 finfo_class_entry->create_object = finfo_objects_new;
110 finfo_class_entry->default_object_handlers = &finfo_object_handlers;
111
112 /* copy the standard object handlers to you handler table */
113 memcpy(&finfo_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
114 finfo_object_handlers.offset = XtOffsetOf(finfo_object, zo);
115 finfo_object_handlers.free_obj = finfo_objects_free;
116 finfo_object_handlers.clone_obj = NULL;
117
118 register_fileinfo_symbols(module_number);
119
120 return SUCCESS;
121}
122/* }}} */
123
124/* {{{ fileinfo_module_entry */
127 "fileinfo",
128 ext_functions,
130 NULL,
131 NULL,
132 NULL,
133 PHP_MINFO(fileinfo),
136};
137/* }}} */
138
139#ifdef COMPILE_DL_FILEINFO
140ZEND_GET_MODULE(fileinfo)
141#endif
142
143/* {{{ PHP_MINFO_FUNCTION */
145{
146 char magic_ver[5];
147
148 (void)snprintf(magic_ver, 4, "%d", magic_version());
149 magic_ver[4] = '\0';
150
152 php_info_print_table_row(2, "fileinfo support", "enabled");
153 php_info_print_table_row(2, "libmagic", magic_ver);
155}
156/* }}} */
157
158/* {{{ Construct a new fileinfo object. */
160{
162 char *file = NULL;
163 size_t file_len = 0;
165 zval *object = getThis();
166 char resolved_path[MAXPATHLEN];
168
169 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lp!", &options, &file, &file_len) == FAILURE) {
171 }
172
173 if (object) {
174 finfo_object *finfo_obj = Z_FINFO_P(object);
175
177
178 if (finfo_obj->ptr) {
179 magic_close(finfo_obj->ptr->magic);
180 efree(finfo_obj->ptr);
181 finfo_obj->ptr = NULL;
182 }
183 }
184
185 if (file_len == 0) {
186 file = NULL;
187 } else if (file && *file) { /* user specified file, perform open_basedir checks */
188
190 if (object) {
192 if (!EG(exception)) {
193 zend_throw_exception(NULL, "Constructor failed", 0);
194 }
195 }
197 }
198 if (!expand_filepath_with_mode(file, resolved_path, NULL, 0, CWD_EXPAND)) {
199 if (object) {
201 if (!EG(exception)) {
202 zend_throw_exception(NULL, "Constructor failed", 0);
203 }
204 }
206 }
207 file = resolved_path;
208 }
209
210 finfo = emalloc(sizeof(php_fileinfo));
211
212 finfo->options = options;
213 finfo->magic = magic_open(options);
214
215 if (finfo->magic == NULL) {
216 efree(finfo);
217 php_error_docref(NULL, E_WARNING, "Invalid mode '" ZEND_LONG_FMT "'.", options);
218 if (object) {
220 if (!EG(exception)) {
221 zend_throw_exception(NULL, "Constructor failed", 0);
222 }
223 }
225 }
226
227 if (magic_load(finfo->magic, file) == -1) {
228 php_error_docref(NULL, E_WARNING, "Failed to load magic database at \"%s\"", file);
229 magic_close(finfo->magic);
230 efree(finfo);
231 if (object) {
233 if (!EG(exception)) {
234 zend_throw_exception(NULL, "Constructor failed", 0);
235 }
236 }
238 }
239
240 if (object) {
241 finfo_object *obj;
243 obj = Z_FINFO_P(object);
244 obj->ptr = finfo;
245 } else {
247 finfo_object *obj = php_finfo_fetch_object(zobj);
248 obj->ptr = finfo;
250 }
251}
252/* }}} */
253
254/* {{{ Close fileinfo object - a NOP. */
256{
257 zval *self;
258
261 }
262
264}
265/* }}} */
266
267/* {{{ Set libmagic configuration options. */
269{
272 zval *self;
273
276 }
278
280 finfo->options = options;
281
283}
284/* }}} */
285
286#define FILEINFO_MODE_BUFFER 0
287#define FILEINFO_MODE_STREAM 1
288#define FILEINFO_MODE_FILE 2
289
290static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mimetype_emu) /* {{{ */
291{
292 zend_long options = 0;
293 char *ret_val = NULL, *buffer = NULL;
294 size_t buffer_len;
296 zval *zcontext = NULL;
297 zval *what;
298 char mime_directory[] = "directory";
299 struct magic_set *magic = NULL;
300
301 if (mimetype_emu) {
302
303 /* mime_content_type(..) emulation */
304 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &what) == FAILURE) {
306 }
307
308 switch (Z_TYPE_P(what)) {
309 case IS_STRING:
310 buffer = Z_STRVAL_P(what);
311 buffer_len = Z_STRLEN_P(what);
313 break;
314
315 case IS_RESOURCE:
317 break;
318
319 default:
320 zend_argument_type_error(1, "must be of type resource|string, %s given", zend_zval_value_name(what));
322 }
323
325 if (magic_load(magic, NULL) == -1) {
326 php_error_docref(NULL, E_WARNING, "Failed to load magic database");
327 goto common;
328 }
329 } else {
330 zval *self;
331 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|lr!", &self, finfo_class_entry, &buffer, &buffer_len, &options, &zcontext) == FAILURE) {
333 }
335 magic = finfo->magic;
336 }
337
338 /* Set options for the current file/buffer. */
339 if (options) {
341 }
342
343 switch (mode) {
345 {
346 ret_val = (char *) magic_buffer(magic, buffer, buffer_len);
347 break;
348 }
349
351 {
352 php_stream *stream;
353 zend_off_t streampos;
354
355 php_stream_from_zval_no_verify(stream, what);
356 if (!stream) {
357 goto common;
358 }
359
360 streampos = php_stream_tell(stream); /* remember stream position for restoration */
361 php_stream_seek(stream, 0, SEEK_SET);
362
363 ret_val = (char *) magic_stream(magic, stream);
364
365 php_stream_seek(stream, streampos, SEEK_SET);
366 break;
367 }
368
370 {
371 /* determine if the file is a local file or remote URL */
372 const char *tmp2;
373 php_stream_wrapper *wrap;
375
376 // Implementation is used for both finfo_file() and mimetype_emu()
377 int buffer_param_num = (mimetype_emu ? 1 : 2);
378 if (buffer == NULL || buffer_len == 0) {
380 goto clean;
381 }
382 if (CHECK_NULL_PATH(buffer, buffer_len)) {
383 zend_argument_type_error(buffer_param_num, "must not contain any null bytes");
384 goto clean;
385 }
386
387 wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0);
388
389 if (wrap) {
390 php_stream *stream;
392
393#ifdef PHP_WIN32
394 if (php_stream_stat_path_ex(buffer, 0, &ssb, context) == SUCCESS) {
395 if (ssb.sb.st_mode & S_IFDIR) {
396 ret_val = mime_directory;
397 goto common;
398 }
399 }
400#endif
401
403
404 if (!stream) {
406 goto clean;
407 }
408
409 if (php_stream_stat(stream, &ssb) == SUCCESS) {
410 if (ssb.sb.st_mode & S_IFDIR) {
411 ret_val = mime_directory;
412 } else {
413 ret_val = (char *)magic_stream(magic, stream);
414 }
415 }
416
417 php_stream_close(stream);
418 }
419 break;
420 }
422 }
423
424common:
425 if (ret_val) {
426 RETVAL_STRING(ret_val);
427 } else {
428 php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic));
430 }
431
432clean:
433 if (mimetype_emu) {
435 }
436
437 /* Restore options */
438 if (options) {
439 FINFO_SET_OPTION(magic, finfo->options)
440 }
441 return;
442}
443/* }}} */
444
445/* {{{ Return information about a file. */
450/* }}} */
451
452/* {{{ Return information about a string buffer. */
457/* }}} */
458
459/* {{{ Return content-type for file */
461{
462 _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1, 1);
463}
464/* }}} */
bool exception
Definition assert.c:30
file(string $filename, int $flags=0, $context=null)
memcpy(ptr1, ptr2, size)
zend_module_entry fileinfo_module_entry
Definition fileinfo.c:125
#define FILEINFO_MODE_BUFFER
Definition fileinfo.c:286
struct _php_fileinfo php_fileinfo
struct _finfo_object finfo_object
zend_class_entry * finfo_class_entry
Definition fileinfo.c:46
#define FILEINFO_MODE_FILE
Definition fileinfo.c:288
#define FILEINFO_MODE_STREAM
Definition fileinfo.c:287
#define FINFO_SET_OPTION(magic, options)
Definition fileinfo.c:97
#define FILEINFO_FROM_OBJECT(finfo, object)
Definition fileinfo.c:59
#define Z_FINFO_P(zv)
Definition fileinfo.c:57
PHP_FILEINFO_API zend_object * finfo_objects_new(zend_class_entry *class_type)
Definition fileinfo.c:84
finfo_close(finfo $finfo)
finfo_buffer(finfo $finfo, string $string, int $flags=FILEINFO_NONE, $context=null)
finfo_open(int $flags=FILEINFO_NONE, ?string $magic_database=null)
finfo_file(finfo $finfo, string $filename, int $flags=FILEINFO_NONE, $context=null)
finfo_set_flags(finfo $finfo, int $flags)
mime_content_type($filename)
PHPAPI char * expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode)
PHPAPI int php_check_open_basedir(const char *path)
zval * zcontext
char * mode
#define SEEK_SET
Definition gd_io_file.c:20
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
file_public int magic_version(void)
Definition magic.c:328
file_public int magic_load(struct magic_set *ms, const char *magicfile)
Definition magic.c:132
file_public const char * magic_stream(struct magic_set *ms, php_stream *stream)
Definition magic.c:188
file_public int magic_errno(struct magic_set *ms)
Definition magic.c:298
file_public const char * magic_error(struct magic_set *ms)
Definition magic.c:290
file_public const char * magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
Definition magic.c:272
file_public void magic_close(struct magic_set *ms)
Definition magic.c:121
file_public struct magic_set * magic_open(int flags)
Definition magic.c:82
#define MAGIC_MIME_TYPE
Definition magic.h:37
#define MAGIC_NONE
Definition magic.h:32
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_MINIT
Definition php.h:392
#define PHP_FILEINFO_VERSION
#define PHP_FILEINFO_API
PHP_JSON_API size_t int options
Definition php_json.h:102
#define php_stream_context_from_zval(zcontext, nocontext)
struct _php_stream php_stream
Definition php_streams.h:96
struct _php_stream_context php_stream_context
Definition php_streams.h:98
#define php_stream_stat_path_ex(path, flags, ssb, context)
#define REPORT_ERRORS
#define php_stream_seek(stream, offset, whence)
#define php_stream_open_wrapper_ex(path, mode, options, opened, context)
#define php_stream_close(stream)
#define php_stream_tell(stream)
#define php_stream_stat(stream, ssb)
#define php_stream_from_zval_no_verify(xstr, pzval)
struct _php_stream_wrapper php_stream_wrapper
Definition php_streams.h:97
PHPAPI php_stream_wrapper * php_stream_locate_url_wrapper(const char *path, const char **path_for_open, int options)
Definition streams.c:1964
struct _php_stream_statbuf php_stream_statbuf
php_fileinfo * ptr
Definition fileinfo.c:49
zend_object zo
Definition fileinfo.c:50
struct magic_set * magic
Definition fileinfo.c:42
zend_long options
Definition fileinfo.c:41
Definition file.h:177
Definition dce.c:49
Definition file.h:202
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
@ EH_THROW
Definition zend.h:433
ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current)
Definition zend_API.c:5242
ZEND_API void zend_restore_error_handling(zend_error_handling *saved)
Definition zend_API.c:5253
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num)
Definition zend_API.c:443
ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec,...)
Definition zend_API.c:1314
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
#define CHECK_NULL_PATH(p, l)
Definition zend_API.h:950
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_OBJ(r)
Definition zend_API.h:1052
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETVAL_STRING(s)
Definition zend_API.h:1017
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define RETURN_THROWS()
Definition zend_API.h:1060
#define getThis()
Definition zend_API.h:526
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define efree(ptr)
Definition zend_alloc.h:155
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
#define snprintf
#define E_WARNING
Definition zend_errors.h:24
ZEND_API ZEND_COLD zend_object * zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define EG(v)
int32_t zend_long
Definition zend_long.h:42
int32_t zend_off_t
Definition zend_long.h:44
#define ZEND_LONG_FMT
Definition zend_long.h:87
#define STANDARD_MODULE_HEADER
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
#define XtOffsetOf(s_type, field)
#define EMPTY_SWITCH_DEFAULT_CASE()
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define IS_STRING
Definition zend_types.h:606
#define IS_RESOURCE
Definition zend_types.h:609
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
@ FAILURE
Definition zend_types.h:61
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define CWD_EXPAND
#define MAXPATHLEN
zend_object * zobj