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