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