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