root/ext/phar/func_interceptors.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHAR_FUNC
  2. PHAR_FUNC
  3. PHAR_FUNC
  4. PHAR_FUNC
  5. phar_fancy_stat
  6. phar_file_stat
  7. PharFileFunction
  8. PHAR_FUNC
  9. PharFileFunction
  10. phar_release_functions
  11. phar_intercept_functions_init
  12. phar_intercept_functions_shutdown
  13. phar_save_orig_functions
  14. phar_restore_orig_functions

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

/* [<][>][^][v][top][bottom][index][help] */