1 /*
2 +----------------------------------------------------------------------+
3 | phar php single-file executable PHP extension |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2005-2017 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 | http://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 /* $Id$ */
20
21 #include "phar_internal.h"
22
23 #define PHAR_FUNC(name) \
24 static PHP_NAMED_FUNCTION(name)
25
PHAR_FUNC(phar_opendir)26 PHAR_FUNC(phar_opendir) /* {{{ */
27 {
28 char *filename;
29 size_t filename_len;
30 zval *zcontext = NULL;
31
32 if (!PHAR_G(intercepted)) {
33 goto skip_phar;
34 }
35
36 if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
37 && !cached_phars.u.flags) {
38 goto skip_phar;
39 }
40
41 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z", &filename, &filename_len, &zcontext) == FAILURE) {
42 return;
43 }
44
45 if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
46 char *arch, *entry, *fname;
47 int arch_len, entry_len, fname_len;
48 fname = (char*)zend_get_executed_filename();
49
50 /* we are checking for existence of a file within the relative path. Chances are good that this is
51 retrieving something from within the phar archive */
52
53 if (strncasecmp(fname, "phar://", 7)) {
54 goto skip_phar;
55 }
56 fname_len = strlen(fname);
57 if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
58 php_stream_context *context = NULL;
59 php_stream *stream;
60 char *name;
61
62 efree(entry);
63 entry = estrndup(filename, filename_len);
64 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
65 entry_len = filename_len;
66 /* retrieving a file within the current directory, so use this if possible */
67 entry = phar_fix_filepath(entry, &entry_len, 1);
68
69 if (entry[0] == '/') {
70 spprintf(&name, 4096, "phar://%s%s", arch, entry);
71 } else {
72 spprintf(&name, 4096, "phar://%s/%s", arch, entry);
73 }
74 efree(entry);
75 efree(arch);
76 if (zcontext) {
77 context = php_stream_context_from_zval(zcontext, 0);
78 }
79 stream = php_stream_opendir(name, REPORT_ERRORS, context);
80 efree(name);
81 if (!stream) {
82 RETURN_FALSE;
83 }
84 php_stream_to_zval(stream, return_value);
85 return;
86 }
87 }
88 skip_phar:
89 PHAR_G(orig_opendir)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
90 return;
91 }
92 /* }}} */
93
PHAR_FUNC(phar_file_get_contents)94 PHAR_FUNC(phar_file_get_contents) /* {{{ */
95 {
96 char *filename;
97 size_t filename_len;
98 zend_string *contents;
99 zend_bool use_include_path = 0;
100 php_stream *stream;
101 zend_long offset = -1;
102 zend_long maxlen = PHP_STREAM_COPY_ALL;
103 zval *zcontext = NULL;
104
105 if (!PHAR_G(intercepted)) {
106 goto skip_phar;
107 }
108
109 if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
110 && !cached_phars.u.flags) {
111 goto skip_phar;
112 }
113
114 /* Parse arguments */
115 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
116 goto skip_phar;
117 }
118
119 if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
120 char *arch, *entry, *fname;
121 zend_string *entry_str = NULL;
122 int arch_len, entry_len, fname_len;
123 php_stream_context *context = NULL;
124
125 fname = (char*)zend_get_executed_filename();
126
127 if (strncasecmp(fname, "phar://", 7)) {
128 goto skip_phar;
129 }
130 fname_len = strlen(fname);
131 if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
132 char *name;
133 phar_archive_data *phar;
134
135 efree(entry);
136 entry = filename;
137 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
138 entry_len = filename_len;
139
140 if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
141 efree(arch);
142 php_error_docref(NULL, E_WARNING, "length must be greater than or equal to zero");
143 RETURN_FALSE;
144 }
145
146 /* retrieving a file defaults to within the current directory, so use this if possible */
147 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
148 efree(arch);
149 goto skip_phar;
150 }
151 if (use_include_path) {
152 if ((entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
153 name = ZSTR_VAL(entry_str);
154 goto phar_it;
155 } else {
156 /* this file is not in the phar, use the original path */
157 efree(arch);
158 goto skip_phar;
159 }
160 } else {
161 entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
162 if (entry[0] == '/') {
163 if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
164 /* this file is not in the phar, use the original path */
165 notfound:
166 efree(arch);
167 efree(entry);
168 goto skip_phar;
169 }
170 } else {
171 if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
172 goto notfound;
173 }
174 }
175 /* auto-convert to phar:// */
176 if (entry[0] == '/') {
177 spprintf(&name, 4096, "phar://%s%s", arch, entry);
178 } else {
179 spprintf(&name, 4096, "phar://%s/%s", arch, entry);
180 }
181 if (entry != filename) {
182 efree(entry);
183 }
184 }
185
186 phar_it:
187 efree(arch);
188 if (zcontext) {
189 context = php_stream_context_from_zval(zcontext, 0);
190 }
191 stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
192 if (entry_str) {
193 zend_string_release(entry_str);
194 } else {
195 efree(name);
196 }
197
198 if (!stream) {
199 RETURN_FALSE;
200 }
201
202 if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
203 php_error_docref(NULL, E_WARNING, "Failed to seek to position %pd in the stream", offset);
204 php_stream_close(stream);
205 RETURN_FALSE;
206 }
207
208 /* uses mmap if possible */
209 contents = php_stream_copy_to_mem(stream, maxlen, 0);
210 if (contents && ZSTR_LEN(contents) > 0) {
211 RETVAL_STR(contents);
212 } else if (contents) {
213 zend_string_release(contents);
214 RETVAL_EMPTY_STRING();
215 } else {
216 RETVAL_FALSE;
217 }
218
219 php_stream_close(stream);
220 return;
221 }
222 }
223 skip_phar:
224 PHAR_G(orig_file_get_contents)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
225 return;
226 }
227 /* }}} */
228
PHAR_FUNC(phar_readfile)229 PHAR_FUNC(phar_readfile) /* {{{ */
230 {
231 char *filename;
232 size_t filename_len;
233 int size = 0;
234 zend_bool use_include_path = 0;
235 zval *zcontext = NULL;
236 php_stream *stream;
237
238 if (!PHAR_G(intercepted)) {
239 goto skip_phar;
240 }
241
242 if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
243 && !cached_phars.u.flags) {
244 goto skip_phar;
245 }
246 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
247 goto skip_phar;
248 }
249 if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
250 char *arch, *entry, *fname;
251 zend_string *entry_str = NULL;
252 int arch_len, entry_len, fname_len;
253 php_stream_context *context = NULL;
254 char *name;
255 phar_archive_data *phar;
256 fname = (char*)zend_get_executed_filename();
257
258 if (strncasecmp(fname, "phar://", 7)) {
259 goto skip_phar;
260 }
261 fname_len = strlen(fname);
262 if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
263 goto skip_phar;
264 }
265
266 efree(entry);
267 entry = filename;
268 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
269 entry_len = filename_len;
270 /* retrieving a file defaults to within the current directory, so use this if possible */
271 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
272 efree(arch);
273 goto skip_phar;
274 }
275 if (use_include_path) {
276 if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
277 /* this file is not in the phar, use the original path */
278 efree(arch);
279 goto skip_phar;
280 } else {
281 name = ZSTR_VAL(entry_str);
282 }
283 } else {
284 entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
285 if (entry[0] == '/') {
286 if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
287 /* this file is not in the phar, use the original path */
288 notfound:
289 efree(entry);
290 efree(arch);
291 goto skip_phar;
292 }
293 } else {
294 if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
295 goto notfound;
296 }
297 }
298 /* auto-convert to phar:// */
299 if (entry[0] == '/') {
300 spprintf(&name, 4096, "phar://%s%s", arch, entry);
301 } else {
302 spprintf(&name, 4096, "phar://%s/%s", arch, entry);
303 }
304 efree(entry);
305 }
306
307 efree(arch);
308 context = php_stream_context_from_zval(zcontext, 0);
309 stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
310 if (entry_str) {
311 zend_string_release(entry_str);
312 } else {
313 efree(name);
314 }
315 if (stream == NULL) {
316 RETURN_FALSE;
317 }
318 size = php_stream_passthru(stream);
319 php_stream_close(stream);
320 RETURN_LONG(size);
321 }
322
323 skip_phar:
324 PHAR_G(orig_readfile)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
325 return;
326
327 }
328 /* }}} */
329
PHAR_FUNC(phar_fopen)330 PHAR_FUNC(phar_fopen) /* {{{ */
331 {
332 char *filename, *mode;
333 size_t filename_len, mode_len;
334 zend_bool use_include_path = 0;
335 zval *zcontext = NULL;
336 php_stream *stream;
337
338 if (!PHAR_G(intercepted)) {
339 goto skip_phar;
340 }
341
342 if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
343 && !cached_phars.u.flags) {
344 /* no need to check, include_path not even specified in fopen/ no active phars */
345 goto skip_phar;
346 }
347 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "ps|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
348 goto skip_phar;
349 }
350 if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
351 char *arch, *entry, *fname;
352 zend_string *entry_str = NULL;
353 int arch_len, entry_len, fname_len;
354 php_stream_context *context = NULL;
355 char *name;
356 phar_archive_data *phar;
357 fname = (char*)zend_get_executed_filename();
358
359 if (strncasecmp(fname, "phar://", 7)) {
360 goto skip_phar;
361 }
362 fname_len = strlen(fname);
363 if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
364 goto skip_phar;
365 }
366
367 efree(entry);
368 entry = filename;
369 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
370 entry_len = filename_len;
371 /* retrieving a file defaults to within the current directory, so use this if possible */
372 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
373 efree(arch);
374 goto skip_phar;
375 }
376 if (use_include_path) {
377 if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
378 /* this file is not in the phar, use the original path */
379 efree(arch);
380 goto skip_phar;
381 } else {
382 name = ZSTR_VAL(entry_str);
383 }
384 } else {
385 entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
386 if (entry[0] == '/') {
387 if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
388 /* this file is not in the phar, use the original path */
389 notfound:
390 efree(entry);
391 efree(arch);
392 goto skip_phar;
393 }
394 } else {
395 if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
396 /* this file is not in the phar, use the original path */
397 goto notfound;
398 }
399 }
400 /* auto-convert to phar:// */
401 if (entry[0] == '/') {
402 spprintf(&name, 4096, "phar://%s%s", arch, entry);
403 } else {
404 spprintf(&name, 4096, "phar://%s/%s", arch, entry);
405 }
406 efree(entry);
407 }
408
409 efree(arch);
410 context = php_stream_context_from_zval(zcontext, 0);
411 stream = php_stream_open_wrapper_ex(name, mode, 0 | REPORT_ERRORS, NULL, context);
412 if (entry_str) {
413 zend_string_release(entry_str);
414 } else {
415 efree(name);
416 }
417 if (stream == NULL) {
418 RETURN_FALSE;
419 }
420 php_stream_to_zval(stream, return_value);
421 if (zcontext) {
422 Z_ADDREF_P(zcontext);
423 }
424 return;
425 }
426 skip_phar:
427 PHAR_G(orig_fopen)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
428 return;
429 }
430 /* }}} */
431
432 #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
433 #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)
434 #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
435 #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
436
437 /* {{{ php_stat
438 */
phar_fancy_stat(zend_stat_t * stat_sb,int type,zval * return_value)439 static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value)
440 {
441 zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev,
442 stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks;
443 int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
444 char *stat_sb_names[13] = {
445 "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
446 "size", "atime", "mtime", "ctime", "blksize", "blocks"
447 };
448
449 #ifndef NETWARE
450 if (type >= FS_IS_W && type <= FS_IS_X) {
451 if(stat_sb->st_uid==getuid()) {
452 rmask=S_IRUSR;
453 wmask=S_IWUSR;
454 xmask=S_IXUSR;
455 } else if(stat_sb->st_gid==getgid()) {
456 rmask=S_IRGRP;
457 wmask=S_IWGRP;
458 xmask=S_IXGRP;
459 } else {
460 int groups, n, i;
461 gid_t *gids;
462
463 groups = getgroups(0, NULL);
464 if(groups > 0) {
465 gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
466 n=getgroups(groups, gids);
467 for(i=0;i<n;++i){
468 if(stat_sb->st_gid==gids[i]) {
469 rmask=S_IRGRP;
470 wmask=S_IWGRP;
471 xmask=S_IXGRP;
472 break;
473 }
474 }
475 efree(gids);
476 }
477 }
478 }
479 #endif
480
481 switch (type) {
482 case FS_PERMS:
483 RETURN_LONG((zend_long)stat_sb->st_mode);
484 case FS_INODE:
485 RETURN_LONG((zend_long)stat_sb->st_ino);
486 case FS_SIZE:
487 RETURN_LONG((zend_long)stat_sb->st_size);
488 case FS_OWNER:
489 RETURN_LONG((zend_long)stat_sb->st_uid);
490 case FS_GROUP:
491 RETURN_LONG((zend_long)stat_sb->st_gid);
492 case FS_ATIME:
493 #ifdef NETWARE
494 RETURN_LONG((zend_long)stat_sb->st_atime.tv_sec);
495 #else
496 RETURN_LONG((zend_long)stat_sb->st_atime);
497 #endif
498 case FS_MTIME:
499 #ifdef NETWARE
500 RETURN_LONG((zend_long)stat_sb->st_mtime.tv_sec);
501 #else
502 RETURN_LONG((zend_long)stat_sb->st_mtime);
503 #endif
504 case FS_CTIME:
505 #ifdef NETWARE
506 RETURN_LONG((zend_long)stat_sb->st_ctime.tv_sec);
507 #else
508 RETURN_LONG((zend_long)stat_sb->st_ctime);
509 #endif
510 case FS_TYPE:
511 if (S_ISLNK(stat_sb->st_mode)) {
512 RETURN_STRING("link");
513 }
514 switch(stat_sb->st_mode & S_IFMT) {
515 case S_IFDIR: RETURN_STRING("dir");
516 case S_IFREG: RETURN_STRING("file");
517 }
518 php_error_docref(NULL, E_NOTICE, "Unknown file type (%u)", stat_sb->st_mode & S_IFMT);
519 RETURN_STRING("unknown");
520 case FS_IS_W:
521 RETURN_BOOL((stat_sb->st_mode & wmask) != 0);
522 case FS_IS_R:
523 RETURN_BOOL((stat_sb->st_mode&rmask)!=0);
524 case FS_IS_X:
525 RETURN_BOOL((stat_sb->st_mode&xmask)!=0 && !S_ISDIR(stat_sb->st_mode));
526 case FS_IS_FILE:
527 RETURN_BOOL(S_ISREG(stat_sb->st_mode));
528 case FS_IS_DIR:
529 RETURN_BOOL(S_ISDIR(stat_sb->st_mode));
530 case FS_IS_LINK:
531 RETURN_BOOL(S_ISLNK(stat_sb->st_mode));
532 case FS_EXISTS:
533 RETURN_TRUE; /* the false case was done earlier */
534 case FS_LSTAT:
535 /* FALLTHROUGH */
536 case FS_STAT:
537 array_init(return_value);
538
539 ZVAL_LONG(&stat_dev, stat_sb->st_dev);
540 ZVAL_LONG(&stat_ino, stat_sb->st_ino);
541 ZVAL_LONG(&stat_mode, stat_sb->st_mode);
542 ZVAL_LONG(&stat_nlink, stat_sb->st_nlink);
543 ZVAL_LONG(&stat_uid, stat_sb->st_uid);
544 ZVAL_LONG(&stat_gid, stat_sb->st_gid);
545 #ifdef HAVE_ST_RDEV
546 ZVAL_LONG(&stat_rdev, stat_sb->st_rdev);
547 #else
548 ZVAL_LONG(&stat_rdev, -1);
549 #endif
550 ZVAL_LONG(&stat_size, stat_sb->st_size);
551 #ifdef NETWARE
552 ZVAL_LONG(&stat_atime, (stat_sb->st_atime).tv_sec);
553 ZVAL_LONG(&stat_mtime, (stat_sb->st_mtime).tv_sec);
554 ZVAL_LONG(&stat_ctime, (stat_sb->st_ctime).tv_sec);
555 #else
556 ZVAL_LONG(&stat_atime, stat_sb->st_atime);
557 ZVAL_LONG(&stat_mtime, stat_sb->st_mtime);
558 ZVAL_LONG(&stat_ctime, stat_sb->st_ctime);
559 #endif
560 #ifdef HAVE_ST_BLKSIZE
561 ZVAL_LONG(&stat_blksize, stat_sb->st_blksize);
562 #else
563 ZVAL_LONG(&stat_blksize,-1);
564 #endif
565 #ifdef HAVE_ST_BLOCKS
566 ZVAL_LONG(&stat_blocks, stat_sb->st_blocks);
567 #else
568 ZVAL_LONG(&stat_blocks,-1);
569 #endif
570 /* Store numeric indexes in proper order */
571 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_dev);
572 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ino);
573 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mode);
574 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_nlink);
575 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_uid);
576 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_gid);
577
578 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_rdev);
579 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_size);
580 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_atime);
581 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mtime);
582 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ctime);
583 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blksize);
584 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blocks);
585
586 /* Store string indexes referencing the same zval*/
587 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[0], strlen(stat_sb_names[0]), &stat_dev);
588 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[1], strlen(stat_sb_names[1]), &stat_ino);
589 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[2], strlen(stat_sb_names[2]), &stat_mode);
590 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[3], strlen(stat_sb_names[3]), &stat_nlink);
591 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[4], strlen(stat_sb_names[4]), &stat_uid);
592 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[5], strlen(stat_sb_names[5]), &stat_gid);
593 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[6], strlen(stat_sb_names[6]), &stat_rdev);
594 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[7], strlen(stat_sb_names[7]), &stat_size);
595 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[8], strlen(stat_sb_names[8]), &stat_atime);
596 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[9], strlen(stat_sb_names[9]), &stat_mtime);
597 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[10], strlen(stat_sb_names[10]), &stat_ctime);
598 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[11], strlen(stat_sb_names[11]), &stat_blksize);
599 zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[12], strlen(stat_sb_names[12]), &stat_blocks);
600
601 return;
602 }
603 php_error_docref(NULL, E_WARNING, "Didn't understand stat call");
604 RETURN_FALSE;
605 }
606 /* }}} */
607
phar_file_stat(const char * filename,php_stat_len filename_length,int type,void (* orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS),INTERNAL_FUNCTION_PARAMETERS)608 static void phar_file_stat(const char *filename, php_stat_len filename_length, int type, void (*orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS), INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
609 {
610 if (!filename_length) {
611 RETURN_FALSE;
612 }
613
614 if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
615 char *arch, *entry, *fname;
616 int arch_len, entry_len, fname_len;
617 zend_stat_t sb = {0};
618 phar_entry_info *data = NULL;
619 phar_archive_data *phar;
620
621 fname = (char*)zend_get_executed_filename();
622
623 /* we are checking for existence of a file within the relative path. Chances are good that this is
624 retrieving something from within the phar archive */
625
626 if (strncasecmp(fname, "phar://", 7)) {
627 goto skip_phar;
628 }
629 fname_len = strlen(fname);
630 if (PHAR_G(last_phar) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
631 arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
632 arch_len = PHAR_G(last_phar_name_len);
633 entry = estrndup(filename, filename_length);
634 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
635 entry_len = (int) filename_length;
636 phar = PHAR_G(last_phar);
637 goto splitted;
638 }
639 if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
640
641 efree(entry);
642 entry = estrndup(filename, filename_length);
643 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
644 entry_len = (int) filename_length;
645 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
646 efree(arch);
647 efree(entry);
648 goto skip_phar;
649 }
650 splitted:
651 entry = phar_fix_filepath(entry, &entry_len, 1);
652 if (entry[0] == '/') {
653 if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
654 efree(entry);
655 goto stat_entry;
656 }
657 goto notfound;
658 }
659 if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
660 efree(entry);
661 goto stat_entry;
662 }
663 if (zend_hash_str_exists(&(phar->virtual_dirs), entry, entry_len)) {
664 efree(entry);
665 efree(arch);
666 if (IS_EXISTS_CHECK(type)) {
667 RETURN_TRUE;
668 }
669 sb.st_size = 0;
670 sb.st_mode = 0777;
671 sb.st_mode |= S_IFDIR; /* regular directory */
672 #ifdef NETWARE
673 sb.st_mtime.tv_sec = phar->max_timestamp;
674 sb.st_atime.tv_sec = phar->max_timestamp;
675 sb.st_ctime.tv_sec = phar->max_timestamp;
676 #else
677 sb.st_mtime = phar->max_timestamp;
678 sb.st_atime = phar->max_timestamp;
679 sb.st_ctime = phar->max_timestamp;
680 #endif
681 goto statme_baby;
682 } else {
683 char *save;
684 int save_len;
685
686 notfound:
687 efree(entry);
688 save = PHAR_G(cwd);
689 save_len = PHAR_G(cwd_len);
690 /* this file is not in the current directory, use the original path */
691 entry = estrndup(filename, filename_length);
692 entry_len = filename_length;
693 PHAR_G(cwd) = "/";
694 PHAR_G(cwd_len) = 0;
695 /* clean path without cwd */
696 entry = phar_fix_filepath(entry, &entry_len, 1);
697 if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
698 PHAR_G(cwd) = save;
699 PHAR_G(cwd_len) = save_len;
700 efree(entry);
701 if (IS_EXISTS_CHECK(type)) {
702 efree(arch);
703 RETURN_TRUE;
704 }
705 goto stat_entry;
706 }
707 if (zend_hash_str_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
708 PHAR_G(cwd) = save;
709 PHAR_G(cwd_len) = save_len;
710 efree(entry);
711 efree(arch);
712 if (IS_EXISTS_CHECK(type)) {
713 RETURN_TRUE;
714 }
715 sb.st_size = 0;
716 sb.st_mode = 0777;
717 sb.st_mode |= S_IFDIR; /* regular directory */
718 #ifdef NETWARE
719 sb.st_mtime.tv_sec = phar->max_timestamp;
720 sb.st_atime.tv_sec = phar->max_timestamp;
721 sb.st_ctime.tv_sec = phar->max_timestamp;
722 #else
723 sb.st_mtime = phar->max_timestamp;
724 sb.st_atime = phar->max_timestamp;
725 sb.st_ctime = phar->max_timestamp;
726 #endif
727 goto statme_baby;
728 }
729 PHAR_G(cwd) = save;
730 PHAR_G(cwd_len) = save_len;
731 efree(entry);
732 efree(arch);
733 /* Error Occurred */
734 if (!IS_EXISTS_CHECK(type)) {
735 php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
736 }
737 RETURN_FALSE;
738 }
739 stat_entry:
740 efree(arch);
741 if (!data->is_dir) {
742 sb.st_size = data->uncompressed_filesize;
743 sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
744 if (data->link) {
745 sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
746 } else {
747 sb.st_mode |= S_IFREG; /* regular file */
748 }
749 /* timestamp is just the timestamp when this was added to the phar */
750 #ifdef NETWARE
751 sb.st_mtime.tv_sec = data->timestamp;
752 sb.st_atime.tv_sec = data->timestamp;
753 sb.st_ctime.tv_sec = data->timestamp;
754 #else
755 sb.st_mtime = data->timestamp;
756 sb.st_atime = data->timestamp;
757 sb.st_ctime = data->timestamp;
758 #endif
759 } else {
760 sb.st_size = 0;
761 sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
762 sb.st_mode |= S_IFDIR; /* regular directory */
763 if (data->link) {
764 sb.st_mode |= S_IFLNK;
765 }
766 /* timestamp is just the timestamp when this was added to the phar */
767 #ifdef NETWARE
768 sb.st_mtime.tv_sec = data->timestamp;
769 sb.st_atime.tv_sec = data->timestamp;
770 sb.st_ctime.tv_sec = data->timestamp;
771 #else
772 sb.st_mtime = data->timestamp;
773 sb.st_atime = data->timestamp;
774 sb.st_ctime = data->timestamp;
775 #endif
776 }
777
778 statme_baby:
779 if (!phar->is_writeable) {
780 sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
781 }
782
783 sb.st_nlink = 1;
784 sb.st_rdev = -1;
785 /* this is only for APC, so use /dev/null device - no chance of conflict there! */
786 sb.st_dev = 0xc;
787 /* generate unique inode number for alias/filename, so no phars will conflict */
788 if (data) {
789 sb.st_ino = data->inode;
790 }
791 #ifndef PHP_WIN32
792 sb.st_blksize = -1;
793 sb.st_blocks = -1;
794 #endif
795 phar_fancy_stat(&sb, type, return_value);
796 return;
797 }
798 }
799 skip_phar:
800 orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
801 return;
802 }
803 /* }}} */
804
805 #define PharFileFunction(fname, funcnum, orig) \
806 void fname(INTERNAL_FUNCTION_PARAMETERS) { \
807 if (!PHAR_G(intercepted)) { \
808 PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
809 } else { \
810 char *filename; \
811 size_t filename_len; \
812 \
813 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { \
814 return; \
815 } \
816 \
817 phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
818 } \
819 }
820 /* }}} */
821
822 /* {{{ proto int fileperms(string filename)
823 Get file permissions */
PharFileFunction(phar_fileperms,FS_PERMS,orig_fileperms)824 PharFileFunction(phar_fileperms, FS_PERMS, orig_fileperms)
825 /* }}} */
826
827 /* {{{ proto int fileinode(string filename)
828 Get file inode */
829 PharFileFunction(phar_fileinode, FS_INODE, orig_fileinode)
830 /* }}} */
831
832 /* {{{ proto int filesize(string filename)
833 Get file size */
834 PharFileFunction(phar_filesize, FS_SIZE, orig_filesize)
835 /* }}} */
836
837 /* {{{ proto int fileowner(string filename)
838 Get file owner */
839 PharFileFunction(phar_fileowner, FS_OWNER, orig_fileowner)
840 /* }}} */
841
842 /* {{{ proto int filegroup(string filename)
843 Get file group */
844 PharFileFunction(phar_filegroup, FS_GROUP, orig_filegroup)
845 /* }}} */
846
847 /* {{{ proto int fileatime(string filename)
848 Get last access time of file */
849 PharFileFunction(phar_fileatime, FS_ATIME, orig_fileatime)
850 /* }}} */
851
852 /* {{{ proto int filemtime(string filename)
853 Get last modification time of file */
854 PharFileFunction(phar_filemtime, FS_MTIME, orig_filemtime)
855 /* }}} */
856
857 /* {{{ proto int filectime(string filename)
858 Get inode modification time of file */
859 PharFileFunction(phar_filectime, FS_CTIME, orig_filectime)
860 /* }}} */
861
862 /* {{{ proto string filetype(string filename)
863 Get file type */
864 PharFileFunction(phar_filetype, FS_TYPE, orig_filetype)
865 /* }}} */
866
867 /* {{{ proto bool is_writable(string filename)
868 Returns true if file can be written */
869 PharFileFunction(phar_is_writable, FS_IS_W, orig_is_writable)
870 /* }}} */
871
872 /* {{{ proto bool is_readable(string filename)
873 Returns true if file can be read */
874 PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
875 /* }}} */
876
877 /* {{{ proto bool is_executable(string filename)
878 Returns true if file is executable */
879 PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
880 /* }}} */
881
882 /* {{{ proto bool file_exists(string filename)
883 Returns true if filename exists */
884 PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
885 /* }}} */
886
887 /* {{{ proto bool is_dir(string filename)
888 Returns true if file is directory */
889 PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir)
890 /* }}} */
891
892 PHAR_FUNC(phar_is_file) /* {{{ */
893 {
894 char *filename;
895 size_t filename_len;
896
897 if (!PHAR_G(intercepted)) {
898 goto skip_phar;
899 }
900
901 if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
902 && !cached_phars.u.flags) {
903 goto skip_phar;
904 }
905 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
906 goto skip_phar;
907 }
908 if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
909 char *arch, *entry, *fname;
910 int arch_len, entry_len, fname_len;
911 fname = (char*)zend_get_executed_filename();
912
913 /* we are checking for existence of a file within the relative path. Chances are good that this is
914 retrieving something from within the phar archive */
915
916 if (strncasecmp(fname, "phar://", 7)) {
917 goto skip_phar;
918 }
919 fname_len = strlen(fname);
920 if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
921 phar_archive_data *phar;
922
923 efree(entry);
924 entry = filename;
925 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
926 entry_len = filename_len;
927 /* retrieving a file within the current directory, so use this if possible */
928 if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
929 phar_entry_info *etemp;
930
931 entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
932 if (entry[0] == '/') {
933 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
934 /* this file is not in the current directory, use the original path */
935 found_it:
936 efree(entry);
937 efree(arch);
938 RETURN_BOOL(!etemp->is_dir);
939 }
940 } else {
941 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
942 goto found_it;
943 }
944 }
945 }
946 if (entry != filename) {
947 efree(entry);
948 }
949 efree(arch);
950 RETURN_FALSE;
951 }
952 }
953 skip_phar:
954 PHAR_G(orig_is_file)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
955 return;
956 }
957 /* }}} */
958
PHAR_FUNC(phar_is_link)959 PHAR_FUNC(phar_is_link) /* {{{ */
960 {
961 char *filename;
962 size_t filename_len;
963
964 if (!PHAR_G(intercepted)) {
965 goto skip_phar;
966 }
967
968 if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
969 && !cached_phars.u.flags) {
970 goto skip_phar;
971 }
972 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
973 goto skip_phar;
974 }
975 if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
976 char *arch, *entry, *fname;
977 int arch_len, entry_len, fname_len;
978 fname = (char*)zend_get_executed_filename();
979
980 /* we are checking for existence of a file within the relative path. Chances are good that this is
981 retrieving something from within the phar archive */
982
983 if (strncasecmp(fname, "phar://", 7)) {
984 goto skip_phar;
985 }
986 fname_len = strlen(fname);
987 if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
988 phar_archive_data *phar;
989
990 efree(entry);
991 entry = filename;
992 /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
993 entry_len = filename_len;
994 /* retrieving a file within the current directory, so use this if possible */
995 if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
996 phar_entry_info *etemp;
997
998 entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
999 if (entry[0] == '/') {
1000 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
1001 /* this file is not in the current directory, use the original path */
1002 found_it:
1003 efree(entry);
1004 efree(arch);
1005 RETURN_BOOL(etemp->link);
1006 }
1007 } else {
1008 if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
1009 goto found_it;
1010 }
1011 }
1012 }
1013 efree(entry);
1014 efree(arch);
1015 RETURN_FALSE;
1016 }
1017 }
1018 skip_phar:
1019 PHAR_G(orig_is_link)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1020 return;
1021 }
1022 /* }}} */
1023
1024 /* {{{ proto array lstat(string filename)
1025 Give information about a file or symbolic link */
PharFileFunction(phar_lstat,FS_LSTAT,orig_lstat)1026 PharFileFunction(phar_lstat, FS_LSTAT, orig_lstat)
1027 /* }}} */
1028
1029 /* {{{ proto array stat(string filename)
1030 Give information about a file */
1031 PharFileFunction(phar_stat, FS_STAT, orig_stat)
1032 /* }}} */
1033
1034 /* {{{ void phar_intercept_functions(void) */
1035 void phar_intercept_functions(void)
1036 {
1037 if (!PHAR_G(request_init)) {
1038 PHAR_G(cwd) = NULL;
1039 PHAR_G(cwd_len) = 0;
1040 }
1041 PHAR_G(intercepted) = 1;
1042 }
1043 /* }}} */
1044
1045 /* {{{ void phar_release_functions(void) */
phar_release_functions(void)1046 void phar_release_functions(void)
1047 {
1048 PHAR_G(intercepted) = 0;
1049 }
1050 /* }}} */
1051
1052 /* {{{ void phar_intercept_functions_init(void) */
1053 #define PHAR_INTERCEPT(func) \
1054 PHAR_G(orig_##func) = NULL; \
1055 if (NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
1056 PHAR_G(orig_##func) = orig->internal_function.handler; \
1057 orig->internal_function.handler = phar_##func; \
1058 }
1059
phar_intercept_functions_init(void)1060 void phar_intercept_functions_init(void)
1061 {
1062 zend_function *orig;
1063
1064 PHAR_INTERCEPT(fopen);
1065 PHAR_INTERCEPT(file_get_contents);
1066 PHAR_INTERCEPT(is_file);
1067 PHAR_INTERCEPT(is_link);
1068 PHAR_INTERCEPT(is_dir);
1069 PHAR_INTERCEPT(opendir);
1070 PHAR_INTERCEPT(file_exists);
1071 PHAR_INTERCEPT(fileperms);
1072 PHAR_INTERCEPT(fileinode);
1073 PHAR_INTERCEPT(filesize);
1074 PHAR_INTERCEPT(fileowner);
1075 PHAR_INTERCEPT(filegroup);
1076 PHAR_INTERCEPT(fileatime);
1077 PHAR_INTERCEPT(filemtime);
1078 PHAR_INTERCEPT(filectime);
1079 PHAR_INTERCEPT(filetype);
1080 PHAR_INTERCEPT(is_writable);
1081 PHAR_INTERCEPT(is_readable);
1082 PHAR_INTERCEPT(is_executable);
1083 PHAR_INTERCEPT(lstat);
1084 PHAR_INTERCEPT(stat);
1085 PHAR_INTERCEPT(readfile);
1086 PHAR_G(intercepted) = 0;
1087 }
1088 /* }}} */
1089
1090 /* {{{ void phar_intercept_functions_shutdown(void) */
1091 #define PHAR_RELEASE(func) \
1092 if (PHAR_G(orig_##func) && NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
1093 orig->internal_function.handler = PHAR_G(orig_##func); \
1094 } \
1095 PHAR_G(orig_##func) = NULL;
1096
phar_intercept_functions_shutdown(void)1097 void phar_intercept_functions_shutdown(void)
1098 {
1099 zend_function *orig;
1100
1101 PHAR_RELEASE(fopen);
1102 PHAR_RELEASE(file_get_contents);
1103 PHAR_RELEASE(is_file);
1104 PHAR_RELEASE(is_dir);
1105 PHAR_RELEASE(opendir);
1106 PHAR_RELEASE(file_exists);
1107 PHAR_RELEASE(fileperms);
1108 PHAR_RELEASE(fileinode);
1109 PHAR_RELEASE(filesize);
1110 PHAR_RELEASE(fileowner);
1111 PHAR_RELEASE(filegroup);
1112 PHAR_RELEASE(fileatime);
1113 PHAR_RELEASE(filemtime);
1114 PHAR_RELEASE(filectime);
1115 PHAR_RELEASE(filetype);
1116 PHAR_RELEASE(is_writable);
1117 PHAR_RELEASE(is_readable);
1118 PHAR_RELEASE(is_executable);
1119 PHAR_RELEASE(lstat);
1120 PHAR_RELEASE(stat);
1121 PHAR_RELEASE(readfile);
1122 PHAR_G(intercepted) = 0;
1123 }
1124 /* }}} */
1125
1126 static struct _phar_orig_functions {
1127 void (*orig_fopen)(INTERNAL_FUNCTION_PARAMETERS);
1128 void (*orig_file_get_contents)(INTERNAL_FUNCTION_PARAMETERS);
1129 void (*orig_is_file)(INTERNAL_FUNCTION_PARAMETERS);
1130 void (*orig_is_link)(INTERNAL_FUNCTION_PARAMETERS);
1131 void (*orig_is_dir)(INTERNAL_FUNCTION_PARAMETERS);
1132 void (*orig_opendir)(INTERNAL_FUNCTION_PARAMETERS);
1133 void (*orig_file_exists)(INTERNAL_FUNCTION_PARAMETERS);
1134 void (*orig_fileperms)(INTERNAL_FUNCTION_PARAMETERS);
1135 void (*orig_fileinode)(INTERNAL_FUNCTION_PARAMETERS);
1136 void (*orig_filesize)(INTERNAL_FUNCTION_PARAMETERS);
1137 void (*orig_fileowner)(INTERNAL_FUNCTION_PARAMETERS);
1138 void (*orig_filegroup)(INTERNAL_FUNCTION_PARAMETERS);
1139 void (*orig_fileatime)(INTERNAL_FUNCTION_PARAMETERS);
1140 void (*orig_filemtime)(INTERNAL_FUNCTION_PARAMETERS);
1141 void (*orig_filectime)(INTERNAL_FUNCTION_PARAMETERS);
1142 void (*orig_filetype)(INTERNAL_FUNCTION_PARAMETERS);
1143 void (*orig_is_writable)(INTERNAL_FUNCTION_PARAMETERS);
1144 void (*orig_is_readable)(INTERNAL_FUNCTION_PARAMETERS);
1145 void (*orig_is_executable)(INTERNAL_FUNCTION_PARAMETERS);
1146 void (*orig_lstat)(INTERNAL_FUNCTION_PARAMETERS);
1147 void (*orig_readfile)(INTERNAL_FUNCTION_PARAMETERS);
1148 void (*orig_stat)(INTERNAL_FUNCTION_PARAMETERS);
1149 } phar_orig_functions = {NULL};
1150
phar_save_orig_functions(void)1151 void phar_save_orig_functions(void) /* {{{ */
1152 {
1153 phar_orig_functions.orig_fopen = PHAR_G(orig_fopen);
1154 phar_orig_functions.orig_file_get_contents = PHAR_G(orig_file_get_contents);
1155 phar_orig_functions.orig_is_file = PHAR_G(orig_is_file);
1156 phar_orig_functions.orig_is_link = PHAR_G(orig_is_link);
1157 phar_orig_functions.orig_is_dir = PHAR_G(orig_is_dir);
1158 phar_orig_functions.orig_opendir = PHAR_G(orig_opendir);
1159 phar_orig_functions.orig_file_exists = PHAR_G(orig_file_exists);
1160 phar_orig_functions.orig_fileperms = PHAR_G(orig_fileperms);
1161 phar_orig_functions.orig_fileinode = PHAR_G(orig_fileinode);
1162 phar_orig_functions.orig_filesize = PHAR_G(orig_filesize);
1163 phar_orig_functions.orig_fileowner = PHAR_G(orig_fileowner);
1164 phar_orig_functions.orig_filegroup = PHAR_G(orig_filegroup);
1165 phar_orig_functions.orig_fileatime = PHAR_G(orig_fileatime);
1166 phar_orig_functions.orig_filemtime = PHAR_G(orig_filemtime);
1167 phar_orig_functions.orig_filectime = PHAR_G(orig_filectime);
1168 phar_orig_functions.orig_filetype = PHAR_G(orig_filetype);
1169 phar_orig_functions.orig_is_writable = PHAR_G(orig_is_writable);
1170 phar_orig_functions.orig_is_readable = PHAR_G(orig_is_readable);
1171 phar_orig_functions.orig_is_executable = PHAR_G(orig_is_executable);
1172 phar_orig_functions.orig_lstat = PHAR_G(orig_lstat);
1173 phar_orig_functions.orig_readfile = PHAR_G(orig_readfile);
1174 phar_orig_functions.orig_stat = PHAR_G(orig_stat);
1175 }
1176 /* }}} */
1177
phar_restore_orig_functions(void)1178 void phar_restore_orig_functions(void) /* {{{ */
1179 {
1180 PHAR_G(orig_fopen) = phar_orig_functions.orig_fopen;
1181 PHAR_G(orig_file_get_contents) = phar_orig_functions.orig_file_get_contents;
1182 PHAR_G(orig_is_file) = phar_orig_functions.orig_is_file;
1183 PHAR_G(orig_is_link) = phar_orig_functions.orig_is_link;
1184 PHAR_G(orig_is_dir) = phar_orig_functions.orig_is_dir;
1185 PHAR_G(orig_opendir) = phar_orig_functions.orig_opendir;
1186 PHAR_G(orig_file_exists) = phar_orig_functions.orig_file_exists;
1187 PHAR_G(orig_fileperms) = phar_orig_functions.orig_fileperms;
1188 PHAR_G(orig_fileinode) = phar_orig_functions.orig_fileinode;
1189 PHAR_G(orig_filesize) = phar_orig_functions.orig_filesize;
1190 PHAR_G(orig_fileowner) = phar_orig_functions.orig_fileowner;
1191 PHAR_G(orig_filegroup) = phar_orig_functions.orig_filegroup;
1192 PHAR_G(orig_fileatime) = phar_orig_functions.orig_fileatime;
1193 PHAR_G(orig_filemtime) = phar_orig_functions.orig_filemtime;
1194 PHAR_G(orig_filectime) = phar_orig_functions.orig_filectime;
1195 PHAR_G(orig_filetype) = phar_orig_functions.orig_filetype;
1196 PHAR_G(orig_is_writable) = phar_orig_functions.orig_is_writable;
1197 PHAR_G(orig_is_readable) = phar_orig_functions.orig_is_readable;
1198 PHAR_G(orig_is_executable) = phar_orig_functions.orig_is_executable;
1199 PHAR_G(orig_lstat) = phar_orig_functions.orig_lstat;
1200 PHAR_G(orig_readfile) = phar_orig_functions.orig_readfile;
1201 PHAR_G(orig_stat) = phar_orig_functions.orig_stat;
1202 }
1203 /* }}} */
1204
1205 /*
1206 * Local variables:
1207 * tab-width: 4
1208 * c-basic-offset: 4
1209 * End:
1210 * vim600: noet sw=4 ts=4 fdm=marker
1211 * vim<600: noet sw=4 ts=4
1212 */
1213
1214