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