xref: /PHP-7.0/ext/phar/func_interceptors.c (revision 478f119a)
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