php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
func_interceptors.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | phar php single-file executable PHP extension |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 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 | https://www.php.net/license/3_01.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 | Authors: Gregory Beaver <cellog@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#include "phar_internal.h"
21#include "ext/standard/file.h" /* For php_le_stream_context() */
22
23PHP_FUNCTION(phar_opendir) /* {{{ */
24{
25 char *filename;
28
30 goto skip_phar;
31 }
32
33 if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
35 goto skip_phar;
36 }
37
40 }
41
42 if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
43 char *arch, *entry;
44 size_t arch_len, entry_len;
46
47 /* we are checking for existence of a file within the relative path. Chances are good that this is
48 retrieving something from within the phar archive */
49 if (!fname || !zend_string_starts_with_literal_ci(fname, "phar://")) {
50 goto skip_phar;
51 }
52
53 if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) {
55 php_stream *stream;
56 char *name;
57
58 efree(entry);
59 entry = estrndup(filename, filename_len);
60 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
61 entry_len = filename_len;
62 /* retrieving a file within the current directory, so use this if possible */
63 entry = phar_fix_filepath(entry, &entry_len, 1);
64
65 if (entry[0] == '/') {
66 spprintf(&name, 4096, "phar://%s%s", arch, entry);
67 } else {
68 spprintf(&name, 4096, "phar://%s/%s", arch, entry);
69 }
70 efree(entry);
71 efree(arch);
72 if (zcontext) {
74 }
76 efree(name);
77 if (!stream) {
79 }
81 return;
82 }
83 }
84skip_phar:
86 return;
87}
88/* }}} */
89
90static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool using_include_path)
91{
92 char *arch, *entry;
93 size_t arch_len, entry_len;
95
96 /* we are checking for existence of a file within the relative path. Chances are good that this is
97 retrieving something from within the phar archive */
98 if (!fname || !zend_string_starts_with_literal_ci(fname, "phar://")) {
99 return NULL;
100 }
101
102 if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) {
103 return NULL;
104 }
105
106 efree(entry);
107 entry = NULL;
108 entry_len = 0;
109 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
110 /* retrieving a file defaults to within the current directory, so use this if possible */
111 phar_archive_data *phar;
112 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
113 efree(arch);
114 return NULL;
115 }
116
118 if (using_include_path) {
119 if (!(name = phar_find_in_include_path(filename, NULL))) {
120 /* this file is not in the phar, use the original path */
121 efree(arch);
122 return NULL;
123 }
124 } else {
125 entry_len = ZSTR_LEN(filename);
126 entry = phar_fix_filepath(estrndup(ZSTR_VAL(filename), ZSTR_LEN(filename)), &entry_len, 1);
127 if (entry[0] == '/') {
128 if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
129 /* this file is not in the phar, use the original path */
130notfound:
131 efree(entry);
132 efree(arch);
133 return NULL;
134 }
135 } else {
136 if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
137 goto notfound;
138 }
139 }
140 /* auto-convert to phar:// */
141 if (entry[0] == '/') {
142 ZEND_ASSERT(strlen("phar://") + arch_len + entry_len < 4096);
144 "phar://", strlen("phar://"),
145 arch, arch_len,
146 entry, entry_len
147 );
148 } else {
149 name = strpprintf(4096, "phar://%s/%s", arch, entry);
150 }
151 efree(entry);
152 }
153
154 efree(arch);
155 return name;
156}
157
158PHP_FUNCTION(phar_file_get_contents) /* {{{ */
159{
160 zend_string *filename;
166 zval *zcontext = NULL;
167
168 if (!PHAR_G(intercepted)) {
169 goto skip_phar;
170 }
171
172 if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
174 goto skip_phar;
175 }
176
177 /* Parse arguments */
179 goto skip_phar;
180 }
181
183 maxlen = (ssize_t) PHP_STREAM_COPY_ALL;
184 } else if (maxlen < 0) {
185 zend_argument_value_error(5, "must be greater than or equal to 0");
187 }
188
189 if (use_include_path || (!IS_ABSOLUTE_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename)) && !strstr(ZSTR_VAL(filename), "://"))) {
190 zend_string *name = phar_get_name_for_relative_paths(filename, use_include_path);
191 if (!name) {
192 goto skip_phar;
193 }
194
196 php_stream *stream;
197
198 if (zcontext) {
200 }
202
204
205 if (!stream) {
207 }
208
209 if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
210 php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", offset);
211 php_stream_close(stream);
213 }
214
215 /* uses mmap if possible */
217 if (contents && ZSTR_LEN(contents) > 0) {
219 } else if (contents) {
222 } else {
224 }
225
226 php_stream_close(stream);
227 return;
228 }
229skip_phar:
231 return;
232}
233/* }}} */
234
235PHP_FUNCTION(phar_readfile) /* {{{ */
236{
237 zend_string *filename;
238 bool use_include_path = 0;
239 zval *zcontext = NULL;
240
241 if (!PHAR_G(intercepted)) {
242 goto skip_phar;
243 }
244
245 if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
247 goto skip_phar;
248 }
250 goto skip_phar;
251 }
252 if (use_include_path || (!IS_ABSOLUTE_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename)) && !strstr(ZSTR_VAL(filename), "://"))) {
253 zend_string *name = phar_get_name_for_relative_paths(filename, use_include_path);
254 if (!name) {
255 goto skip_phar;
256 }
257
258 php_stream *stream;
260
262
264 if (stream == NULL) {
266 }
267 ssize_t size = php_stream_passthru(stream);
268 php_stream_close(stream);
270 }
271
272skip_phar:
274 return;
275
276}
277/* }}} */
278
279PHP_FUNCTION(phar_fopen) /* {{{ */
280{
281 zend_string *filename;
282 char *mode;
283 size_t mode_len;
284 bool use_include_path = 0;
285 zval *zcontext = NULL;
286
287 if (!PHAR_G(intercepted)) {
288 goto skip_phar;
289 }
290
291 if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
293 /* no need to check, include_path not even specified in fopen/ no active phars */
294 goto skip_phar;
295 }
297 goto skip_phar;
298 }
299 if (use_include_path || (!IS_ABSOLUTE_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename)) && !strstr(ZSTR_VAL(filename), "://"))) {
300 zend_string *name = phar_get_name_for_relative_paths(filename, use_include_path);
301 if (!name) {
302 goto skip_phar;
303 }
304
305 php_stream *stream;
307
309
311 if (stream == NULL) {
313 }
315 if (zcontext) {
317 }
318 return;
319 }
320skip_phar:
322 return;
323}
324/* }}} */
325
326#define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
327#define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK)
328#define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
329#define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
330
331/* {{{ php_stat */
332static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value)
333{
334 zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev,
335 stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks;
336 int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
337 char *stat_sb_names[13] = {
338 "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
339 "size", "atime", "mtime", "ctime", "blksize", "blocks"
340 };
341
342 if (type >= FS_IS_W && type <= FS_IS_X) {
343 if(stat_sb->st_uid==getuid()) {
344 rmask=S_IRUSR;
345 wmask=S_IWUSR;
346 xmask=S_IXUSR;
347 } else if(stat_sb->st_gid==getgid()) {
348 rmask=S_IRGRP;
349 wmask=S_IWGRP;
350 xmask=S_IXGRP;
351 } else {
352 int groups, n, i;
353 gid_t *gids;
354
355 groups = getgroups(0, NULL);
356 if(groups > 0) {
357 gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
358 n=getgroups(groups, gids);
359 for(i=0;i<n;++i){
360 if(stat_sb->st_gid==gids[i]) {
361 rmask=S_IRGRP;
362 wmask=S_IWGRP;
363 xmask=S_IXGRP;
364 break;
365 }
366 }
367 efree(gids);
368 }
369 }
370 }
371
372 switch (type) {
373 case FS_PERMS:
374 RETURN_LONG((zend_long)stat_sb->st_mode);
375 case FS_INODE:
376 RETURN_LONG((zend_long)stat_sb->st_ino);
377 case FS_SIZE:
378 RETURN_LONG((zend_long)stat_sb->st_size);
379 case FS_OWNER:
380 RETURN_LONG((zend_long)stat_sb->st_uid);
381 case FS_GROUP:
382 RETURN_LONG((zend_long)stat_sb->st_gid);
383 case FS_ATIME:
384 RETURN_LONG((zend_long)stat_sb->st_atime);
385 case FS_MTIME:
386 RETURN_LONG((zend_long)stat_sb->st_mtime);
387 case FS_CTIME:
388 RETURN_LONG((zend_long)stat_sb->st_ctime);
389 case FS_TYPE:
390 if (S_ISLNK(stat_sb->st_mode)) {
391 RETURN_STRING("link");
392 }
393 switch(stat_sb->st_mode & S_IFMT) {
394 case S_IFDIR: RETURN_STRING("dir");
395 case S_IFREG: RETURN_STRING("file");
396 }
397 php_error_docref(NULL, E_NOTICE, "Unknown file type (%u)", stat_sb->st_mode & S_IFMT);
398 RETURN_STRING("unknown");
399 case FS_IS_W:
400 RETURN_BOOL((stat_sb->st_mode & wmask) != 0);
401 case FS_IS_R:
402 RETURN_BOOL((stat_sb->st_mode&rmask)!=0);
403 case FS_IS_X:
404 RETURN_BOOL((stat_sb->st_mode&xmask)!=0 && !S_ISDIR(stat_sb->st_mode));
405 case FS_IS_FILE:
406 RETURN_BOOL(S_ISREG(stat_sb->st_mode));
407 case FS_IS_DIR:
408 RETURN_BOOL(S_ISDIR(stat_sb->st_mode));
409 case FS_IS_LINK:
410 RETURN_BOOL(S_ISLNK(stat_sb->st_mode));
411 case FS_EXISTS:
412 RETURN_TRUE; /* the false case was done earlier */
413 case FS_LSTAT:
414 /* FALLTHROUGH */
415 case FS_STAT:
417
418 ZVAL_LONG(&stat_dev, stat_sb->st_dev);
419 ZVAL_LONG(&stat_ino, stat_sb->st_ino);
420 ZVAL_LONG(&stat_mode, stat_sb->st_mode);
421 ZVAL_LONG(&stat_nlink, stat_sb->st_nlink);
422 ZVAL_LONG(&stat_uid, stat_sb->st_uid);
423 ZVAL_LONG(&stat_gid, stat_sb->st_gid);
424#ifdef HAVE_STRUCT_STAT_ST_RDEV
425 ZVAL_LONG(&stat_rdev, stat_sb->st_rdev);
426#else
427 ZVAL_LONG(&stat_rdev, -1);
428#endif
429 ZVAL_LONG(&stat_size, stat_sb->st_size);
430 ZVAL_LONG(&stat_atime, stat_sb->st_atime);
431 ZVAL_LONG(&stat_mtime, stat_sb->st_mtime);
432 ZVAL_LONG(&stat_ctime, stat_sb->st_ctime);
433#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
434 ZVAL_LONG(&stat_blksize, stat_sb->st_blksize);
435#else
436 ZVAL_LONG(&stat_blksize,-1);
437#endif
438#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
439 ZVAL_LONG(&stat_blocks, stat_sb->st_blocks);
440#else
441 ZVAL_LONG(&stat_blocks,-1);
442#endif
443 /* Store numeric indexes in proper order */
450
458
459 /* Store string indexes referencing the same zval*/
460 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[0], strlen(stat_sb_names[0]), &stat_dev);
461 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[1], strlen(stat_sb_names[1]), &stat_ino);
462 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[2], strlen(stat_sb_names[2]), &stat_mode);
463 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[3], strlen(stat_sb_names[3]), &stat_nlink);
464 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[4], strlen(stat_sb_names[4]), &stat_uid);
465 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[5], strlen(stat_sb_names[5]), &stat_gid);
466 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[6], strlen(stat_sb_names[6]), &stat_rdev);
467 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[7], strlen(stat_sb_names[7]), &stat_size);
468 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[8], strlen(stat_sb_names[8]), &stat_atime);
469 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[9], strlen(stat_sb_names[9]), &stat_mtime);
470 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[10], strlen(stat_sb_names[10]), &stat_ctime);
471 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[11], strlen(stat_sb_names[11]), &stat_blksize);
472 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[12], strlen(stat_sb_names[12]), &stat_blocks);
473
474 return;
475 }
476 php_error_docref(NULL, E_WARNING, "Didn't understand stat call");
478}
479/* }}} */
480
481static void phar_file_stat(const char *filename, size_t filename_length, int type, zif_handler orig_stat_func, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
482{
483 if (!filename_length) {
485 }
486
487 if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
488 char *arch, *entry;
489 size_t arch_len, entry_len;
490 zend_string *fname;
491 zend_stat_t sb = {0};
493 phar_archive_data *phar;
494
496
497 /* we are checking for existence of a file within the relative path. Chances are good that this is
498 retrieving something from within the phar archive */
499 if (!fname || !zend_string_starts_with_literal_ci(fname, "phar://")) {
500 goto skip_phar;
501 }
502
503 if (PHAR_G(last_phar) && ZSTR_LEN(fname) - 7 >= PHAR_G(last_phar_name_len) && !memcmp(ZSTR_VAL(fname) + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
505 arch_len = PHAR_G(last_phar_name_len);
506 entry = estrndup(filename, filename_length);
507 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
508 entry_len = filename_length;
509 phar = PHAR_G(last_phar);
510 goto splitted;
511 }
512 if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) {
513
514 efree(entry);
515 entry = estrndup(filename, filename_length);
516 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
517 entry_len = filename_length;
518 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
519 efree(arch);
520 efree(entry);
521 goto skip_phar;
522 }
523splitted:
524 entry = phar_fix_filepath(entry, &entry_len, 1);
525 if (entry[0] == '/') {
526 if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
527 efree(entry);
528 goto stat_entry;
529 }
530 goto notfound;
531 }
532 if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
533 efree(entry);
534 goto stat_entry;
535 }
536 if (zend_hash_str_exists(&(phar->virtual_dirs), entry, entry_len)) {
537 efree(entry);
538 efree(arch);
539 if (IS_EXISTS_CHECK(type)) {
541 }
542 sb.st_size = 0;
543 sb.st_mode = 0777;
544 sb.st_mode |= S_IFDIR; /* regular directory */
545 sb.st_mtime = phar->max_timestamp;
546 sb.st_atime = phar->max_timestamp;
547 sb.st_ctime = phar->max_timestamp;
548 goto statme_baby;
549 } else {
550 char *save;
551 size_t save_len;
552
553notfound:
554 efree(entry);
555 save = PHAR_G(cwd);
556 save_len = PHAR_G(cwd_len);
557 /* this file is not in the current directory, use the original path */
558 entry = estrndup(filename, filename_length);
559 entry_len = filename_length;
560 PHAR_G(cwd) = "/";
561 PHAR_G(cwd_len) = 0;
562 /* clean path without cwd */
563 entry = phar_fix_filepath(entry, &entry_len, 1);
564 if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
565 PHAR_G(cwd) = save;
566 PHAR_G(cwd_len) = save_len;
567 efree(entry);
568 if (IS_EXISTS_CHECK(type)) {
569 efree(arch);
571 }
572 goto stat_entry;
573 }
574 if (zend_hash_str_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
575 PHAR_G(cwd) = save;
576 PHAR_G(cwd_len) = save_len;
577 efree(entry);
578 efree(arch);
579 if (IS_EXISTS_CHECK(type)) {
581 }
582 sb.st_size = 0;
583 sb.st_mode = 0777;
584 sb.st_mode |= S_IFDIR; /* regular directory */
585 sb.st_mtime = phar->max_timestamp;
586 sb.st_atime = phar->max_timestamp;
587 sb.st_ctime = phar->max_timestamp;
588 goto statme_baby;
589 }
590 PHAR_G(cwd) = save;
591 PHAR_G(cwd_len) = save_len;
592 efree(entry);
593 efree(arch);
594 /* Error Occurred */
595 if (!IS_EXISTS_CHECK(type)) {
596 php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
597 }
599 }
600stat_entry:
601 efree(arch);
602 if (!data->is_dir) {
603 sb.st_size = data->uncompressed_filesize;
604 sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
605 if (data->link) {
606 sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
607 } else {
608 sb.st_mode |= S_IFREG; /* regular file */
609 }
610 /* timestamp is just the timestamp when this was added to the phar */
611 sb.st_mtime = data->timestamp;
612 sb.st_atime = data->timestamp;
613 sb.st_ctime = data->timestamp;
614 } else {
615 sb.st_size = 0;
616 sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
617 sb.st_mode |= S_IFDIR; /* regular directory */
618 if (data->link) {
619 sb.st_mode |= S_IFLNK;
620 }
621 /* timestamp is just the timestamp when this was added to the phar */
622 sb.st_mtime = data->timestamp;
623 sb.st_atime = data->timestamp;
624 sb.st_ctime = data->timestamp;
625 }
626
627statme_baby:
628 if (!phar->is_writeable) {
629 sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
630 }
631
632 sb.st_nlink = 1;
633 sb.st_rdev = -1;
634 /* this is only for APC, so use /dev/null device - no chance of conflict there! */
635 sb.st_dev = 0xc;
636 /* generate unique inode number for alias/filename, so no phars will conflict */
637 if (data) {
638 sb.st_ino = data->inode;
639 }
640#ifndef PHP_WIN32
641 sb.st_blksize = -1;
642 sb.st_blocks = -1;
643#endif
644 phar_fancy_stat(&sb, type, return_value);
645 return;
646 }
647 }
648skip_phar:
649 orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
650 return;
651}
652/* }}} */
653
654#define PharFileFunction(fname, funcnum, orig) \
655PHP_FUNCTION(fname) { \
656 if (!PHAR_G(intercepted)) { \
657 PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
658 } else { \
659 char *filename; \
660 size_t filename_len; \
661 \
662 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { \
663 RETURN_THROWS(); \
664 } \
665 \
666 phar_file_stat(filename, filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
667 } \
668}
669/* }}} */
670
671/* {{{ Get file permissions */
673/* }}} */
674
675/* {{{ Get file inode */
677/* }}} */
678
679/* {{{ Get file size */
681/* }}} */
682
683/* {{{ Get file owner */
685/* }}} */
686
687/* {{{ Get file group */
689/* }}} */
690
691/* {{{ Get last access time of file */
693/* }}} */
694
695/* {{{ Get last modification time of file */
697/* }}} */
698
699/* {{{ Get inode modification time of file */
701/* }}} */
702
703/* {{{ Get file type */
705/* }}} */
706
707/* {{{ Returns true if file can be written */
708PharFileFunction(phar_is_writable, FS_IS_W, orig_is_writable)
709/* }}} */
710
711/* {{{ Returns true if file can be read */
712PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
713/* }}} */
714
715/* {{{ Returns true if file is executable */
716PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
717/* }}} */
718
719/* {{{ Returns true if filename exists */
720PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
721/* }}} */
722
723/* {{{ Returns true if file is directory */
725/* }}} */
726
727PHP_FUNCTION(phar_is_file) /* {{{ */
728{
729 char *filename;
730 size_t filename_len;
731
732 if (!PHAR_G(intercepted)) {
733 goto skip_phar;
734 }
735
736 if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
738 goto skip_phar;
739 }
741 goto skip_phar;
742 }
743 if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
744 char *arch, *entry;
745 size_t arch_len, entry_len;
747
748 /* we are checking for existence of a file within the relative path. Chances are good that this is
749 retrieving something from within the phar archive */
750 if (!fname || !zend_string_starts_with_literal_ci(fname, "phar://")) {
751 goto skip_phar;
752 }
753
754 if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) {
755 phar_archive_data *phar;
756
757 efree(entry);
758 entry = filename;
759 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
760 entry_len = filename_len;
761 /* retrieving a file within the current directory, so use this if possible */
762 if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
763 phar_entry_info *etemp;
764
765 entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
766 if (entry[0] == '/') {
767 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
768 /* this file is not in the current directory, use the original path */
769found_it:
770 efree(entry);
771 efree(arch);
772 RETURN_BOOL(!etemp->is_dir);
773 }
774 } else {
775 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
776 goto found_it;
777 }
778 }
779 }
780 if (entry != filename) {
781 efree(entry);
782 }
783 efree(arch);
785 }
786 }
787skip_phar:
789 return;
790}
791/* }}} */
792
793PHP_FUNCTION(phar_is_link) /* {{{ */
794{
795 char *filename;
796 size_t filename_len;
797
798 if (!PHAR_G(intercepted)) {
799 goto skip_phar;
800 }
801
802 if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
804 goto skip_phar;
805 }
807 goto skip_phar;
808 }
809 if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
810 char *arch, *entry;
811 size_t arch_len, entry_len;
813
814 /* we are checking for existence of a file within the relative path. Chances are good that this is
815 retrieving something from within the phar archive */
816 if (!fname || !zend_string_starts_with_literal_ci(fname, "phar://")) {
817 goto skip_phar;
818 }
819
820 if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) {
821 phar_archive_data *phar;
822
823 efree(entry);
824 entry = filename;
825 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
826 entry_len = filename_len;
827 /* retrieving a file within the current directory, so use this if possible */
828 if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
829 phar_entry_info *etemp;
830
831 entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
832 if (entry[0] == '/') {
833 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
834 /* this file is not in the current directory, use the original path */
835found_it:
836 efree(entry);
837 efree(arch);
838 RETURN_BOOL(etemp->link);
839 }
840 } else {
841 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
842 goto found_it;
843 }
844 }
845 }
846 efree(entry);
847 efree(arch);
849 }
850 }
851skip_phar:
853 return;
854}
855/* }}} */
856
857/* {{{ Give information about a file or symbolic link */
859/* }}} */
860
861/* {{{ Give information about a file */
863/* }}} */
864
865/* {{{ void phar_intercept_functions(void) */
867{
868 if (!PHAR_G(request_init)) {
869 PHAR_G(cwd) = NULL;
870 PHAR_G(cwd_len) = 0;
871 }
872 PHAR_G(intercepted) = 1;
873}
874/* }}} */
875
876/* {{{ void phar_release_functions(void) */
878{
879 PHAR_G(intercepted) = 0;
880}
881/* }}} */
882
883/* {{{ void phar_intercept_functions_init(void) */
884#define PHAR_INTERCEPT(func) \
885 PHAR_G(orig_##func) = NULL; \
886 if (NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
887 PHAR_G(orig_##func) = orig->internal_function.handler; \
888 orig->internal_function.handler = PHP_FN(phar_##func); \
889 }
890
919/* }}} */
920
921/* {{{ void phar_intercept_functions_shutdown(void) */
922#define PHAR_RELEASE(func) \
923 if (PHAR_G(orig_##func) && NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
924 orig->internal_function.handler = PHAR_G(orig_##func); \
925 } \
926 PHAR_G(orig_##func) = NULL;
927
955/* }}} */
956
957static struct _phar_orig_functions {
958 zif_handler orig_fopen;
959 zif_handler orig_file_get_contents;
960 zif_handler orig_is_file;
961 zif_handler orig_is_link;
962 zif_handler orig_is_dir;
963 zif_handler orig_opendir;
964 zif_handler orig_file_exists;
965 zif_handler orig_fileperms;
966 zif_handler orig_fileinode;
967 zif_handler orig_filesize;
968 zif_handler orig_fileowner;
969 zif_handler orig_filegroup;
970 zif_handler orig_fileatime;
971 zif_handler orig_filemtime;
972 zif_handler orig_filectime;
973 zif_handler orig_filetype;
974 zif_handler orig_is_writable;
975 zif_handler orig_is_readable;
976 zif_handler orig_is_executable;
977 zif_handler orig_lstat;
978 zif_handler orig_readfile;
979 zif_handler orig_stat;
980} phar_orig_functions = {0};
981
982void phar_save_orig_functions(void) /* {{{ */
983{
984 phar_orig_functions.orig_fopen = PHAR_G(orig_fopen);
985 phar_orig_functions.orig_file_get_contents = PHAR_G(orig_file_get_contents);
986 phar_orig_functions.orig_is_file = PHAR_G(orig_is_file);
987 phar_orig_functions.orig_is_link = PHAR_G(orig_is_link);
988 phar_orig_functions.orig_is_dir = PHAR_G(orig_is_dir);
989 phar_orig_functions.orig_opendir = PHAR_G(orig_opendir);
990 phar_orig_functions.orig_file_exists = PHAR_G(orig_file_exists);
991 phar_orig_functions.orig_fileperms = PHAR_G(orig_fileperms);
992 phar_orig_functions.orig_fileinode = PHAR_G(orig_fileinode);
993 phar_orig_functions.orig_filesize = PHAR_G(orig_filesize);
994 phar_orig_functions.orig_fileowner = PHAR_G(orig_fileowner);
995 phar_orig_functions.orig_filegroup = PHAR_G(orig_filegroup);
996 phar_orig_functions.orig_fileatime = PHAR_G(orig_fileatime);
997 phar_orig_functions.orig_filemtime = PHAR_G(orig_filemtime);
998 phar_orig_functions.orig_filectime = PHAR_G(orig_filectime);
999 phar_orig_functions.orig_filetype = PHAR_G(orig_filetype);
1000 phar_orig_functions.orig_is_writable = PHAR_G(orig_is_writable);
1001 phar_orig_functions.orig_is_readable = PHAR_G(orig_is_readable);
1002 phar_orig_functions.orig_is_executable = PHAR_G(orig_is_executable);
1003 phar_orig_functions.orig_lstat = PHAR_G(orig_lstat);
1004 phar_orig_functions.orig_readfile = PHAR_G(orig_readfile);
1005 phar_orig_functions.orig_stat = PHAR_G(orig_stat);
1006}
1007/* }}} */
1008
1010{
1011 PHAR_G(orig_fopen) = phar_orig_functions.orig_fopen;
1012 PHAR_G(orig_file_get_contents) = phar_orig_functions.orig_file_get_contents;
1013 PHAR_G(orig_is_file) = phar_orig_functions.orig_is_file;
1014 PHAR_G(orig_is_link) = phar_orig_functions.orig_is_link;
1015 PHAR_G(orig_is_dir) = phar_orig_functions.orig_is_dir;
1016 PHAR_G(orig_opendir) = phar_orig_functions.orig_opendir;
1017 PHAR_G(orig_file_exists) = phar_orig_functions.orig_file_exists;
1018 PHAR_G(orig_fileperms) = phar_orig_functions.orig_fileperms;
1019 PHAR_G(orig_fileinode) = phar_orig_functions.orig_fileinode;
1020 PHAR_G(orig_filesize) = phar_orig_functions.orig_filesize;
1021 PHAR_G(orig_fileowner) = phar_orig_functions.orig_fileowner;
1022 PHAR_G(orig_filegroup) = phar_orig_functions.orig_filegroup;
1023 PHAR_G(orig_fileatime) = phar_orig_functions.orig_fileatime;
1024 PHAR_G(orig_filemtime) = phar_orig_functions.orig_filemtime;
1025 PHAR_G(orig_filectime) = phar_orig_functions.orig_filectime;
1026 PHAR_G(orig_filetype) = phar_orig_functions.orig_filetype;
1027 PHAR_G(orig_is_writable) = phar_orig_functions.orig_is_writable;
1028 PHAR_G(orig_is_readable) = phar_orig_functions.orig_is_readable;
1029 PHAR_G(orig_is_executable) = phar_orig_functions.orig_is_executable;
1030 PHAR_G(orig_lstat) = phar_orig_functions.orig_lstat;
1031 PHAR_G(orig_readfile) = phar_orig_functions.orig_readfile;
1032 PHAR_G(orig_stat) = phar_orig_functions.orig_stat;
1033}
1034/* }}} */
is_executable(string $filename)
filegroup(string $filename)
readfile(string $filename, bool $use_include_path=false, $context=null)
fileowner(string $filename)
filemtime(string $filename)
is_link(string $filename)
is_dir(string $filename)
file_exists(string $filename)
file_get_contents(string $filename, bool $use_include_path=false, $context=null, int $offset=0, ?int $length=null)
is_readable(string $filename)
fileatime(string $filename)
opendir(string $directory, $context=null)
is_writable(string $filename)
is_file(string $filename)
fileperms(string $filename)
fopen(string $filename, string $mode, bool $use_include_path=false, $context=null)
filectime(string $filename)
fileinode(string $filename)
strstr(string $haystack, string $needle, bool $before_needle=false)
filetype(string $filename)
stat(string $filename)
filesize(string $filename)
lstat(string $filename)
zend_ffi_type * type
Definition ffi.c:3812
zend_long n
Definition ffi.c:4979
new_type size
Definition ffi.c:4365
void phar_intercept_functions_shutdown(void)
void phar_restore_orig_functions(void)
size_t mode_len
#define PHAR_INTERCEPT(func)
zval * zcontext
bool use_include_path
zend_long offset
char * mode
#define IS_LINK_OPERATION(__t)
void phar_release_functions(void)
#define PHAR_RELEASE(func)
zend_string * contents
#define PharFileFunction(fname, funcnum, orig)
void phar_intercept_functions_init(void)
#define IS_EXISTS_CHECK(__t)
zend_long maxlen
bool maxlen_is_null
size_t filename_len
void phar_save_orig_functions(void)
void phar_intercept_functions(void)
#define SEEK_SET
Definition gd_io_file.c:20
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
HashTable cached_phars
Definition phar.c:90
char * phar_fix_filepath(char *path, size_t *new_len, int use_cwd)
Definition phar.c:2128
zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, char **entry, size_t *entry_len, int executable, int for_create)
Definition phar.c:2240
zif_handler orig_lstat
zif_handler orig_filectime
zif_handler orig_is_writable
zif_handler orig_opendir
bool request_init
zif_handler orig_is_dir
#define PHAR_ENT_PERM_MASK
zif_handler orig_stat
zif_handler orig_is_link
phar_archive_data * last_phar
zif_handler orig_fileperms
zif_handler orig_fopen
bool intercepted
zif_handler orig_filegroup
zif_handler orig_fileinode
HashTable phar_fname_map
uint32_t last_phar_name_len
char * cwd
#define PHAR_G(v)
zif_handler orig_filetype
struct _phar_archive_data phar_archive_data
uint32_t cwd_len
zif_handler orig_file_get_contents
struct _phar_entry_info phar_entry_info
zend_string * phar_find_in_include_path(zend_string *file, phar_archive_data **pphar)
Definition util.c:266
zif_handler orig_readfile
zif_handler orig_fileowner
zif_handler orig_filesize
char * last_phar_name
zif_handler orig_is_executable
zend_result phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error)
Definition util.c:1013
zif_handler orig_filemtime
zif_handler orig_fileatime
#define PHP_FUNCTION
Definition php.h:364
#define FS_EXISTS
#define FS_IS_W
#define FS_SIZE
#define FS_GROUP
#define FS_IS_X
#define FS_TYPE
#define FS_INODE
#define FS_IS_DIR
#define FS_IS_R
#define FS_MTIME
#define FS_OWNER
#define FS_PERMS
#define FS_IS_FILE
#define FS_LSTAT
#define FS_ATIME
#define FS_CTIME
#define FS_IS_LINK
#define FS_STAT
#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 REPORT_ERRORS
#define PHP_STREAM_COPY_ALL
#define php_stream_seek(stream, offset, whence)
#define php_stream_to_zval(stream, zval)
#define php_stream_opendir(path, options, context)
#define php_stream_open_wrapper_ex(path, mode, options, opened, context)
#define php_stream_close(stream)
#define php_stream_copy_to_mem(src, maxlen, persistent)
#define php_stream_passthru(stream)
zend_constant * data
#define strpprintf
Definition spprintf.h:30
#define spprintf
Definition spprintf.h:29
uint32_t is_dir
char * link
Definition dce.c:49
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1287
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define ZEND_PARSE_PARAMS_QUIET
Definition zend_API.h:361
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETVAL_EMPTY_STRING()
Definition zend_API.h:1021
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_BOOL(b)
Definition zend_API.h:1035
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETVAL_STR(s)
Definition zend_API.h:1013
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define array_init(arg)
Definition zend_API.h:537
#define estrndup(s, length)
Definition zend_alloc.h:165
#define efree(ptr)
Definition zend_alloc.h:155
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
struct _zval_struct zval
strlen(string $string)
zend_string_release_ex(func->internal_function.function_name, 0)
void(ZEND_FASTCALL * zif_handler)(INTERNAL_FUNCTION_PARAMETERS)
#define E_NOTICE
Definition zend_errors.h:26
#define E_WARNING
Definition zend_errors.h:24
ZEND_API zend_string * zend_get_executed_filename_ex(void)
union _zend_function zend_function
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
Definition zend_hash.c:1224
ZEND_API zval *ZEND_FASTCALL zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData)
Definition zend_hash.c:1031
#define HT_IS_INITIALIZED(ht)
Definition zend_hash.h:56
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
#define ZEND_ASSERT(c)
struct stat zend_stat_t
Definition zend_stream.h:94
ZEND_API zend_string * zend_string_concat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define zend_string_starts_with_literal_ci(str, prefix)
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_LONG(z, l)
#define Z_ADDREF_P(pz)
@ FAILURE
Definition zend_types.h:61
#define S_ISDIR(mode)
#define IS_ABSOLUTE_PATH(path, len)
#define S_ISLNK(mode)
#define S_ISREG(mode)
#define S_IFLNK
zval * return_value
zend_string * name