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