Back to index

php5  5.3.10
func_interceptors.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | phar php single-file executable PHP extension                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 2005-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt.                                 |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Gregory Beaver <cellog@php.net>                             |
00016   +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id: func_interceptors.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include "phar_internal.h"
00022 
00023 #define PHAR_FUNC(name) \
00024        static PHP_NAMED_FUNCTION(name)
00025 
00026 PHAR_FUNC(phar_opendir) /* {{{ */
00027 {
00028        char *filename;
00029        int filename_len;
00030        zval *zcontext = NULL;
00031 
00032        if (!PHAR_G(intercepted)) {
00033               goto skip_phar;
00034        }
00035 
00036        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
00037               && !cached_phars.arBuckets) {
00038               goto skip_phar;
00039        }
00040 
00041        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &zcontext) == FAILURE) {
00042               return;
00043        }
00044 
00045        if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
00046               char *arch, *entry, *fname;
00047               int arch_len, entry_len, fname_len;
00048               fname = zend_get_executed_filename(TSRMLS_C);
00049 
00050               /* we are checking for existence of a file within the relative path.  Chances are good that this is
00051                  retrieving something from within the phar archive */
00052 
00053               if (strncasecmp(fname, "phar://", 7)) {
00054                      goto skip_phar;
00055               }
00056               fname_len = strlen(fname);
00057               if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
00058                      php_stream_context *context = NULL;
00059                      php_stream *stream;
00060                      char *name;
00061 
00062                      efree(entry);
00063                      entry = estrndup(filename, filename_len);
00064                      /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00065                      entry_len = filename_len;
00066                      /* retrieving a file within the current directory, so use this if possible */
00067                      entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
00068 
00069                      if (entry[0] == '/') {
00070                             spprintf(&name, 4096, "phar://%s%s", arch, entry);
00071                      } else {
00072                             spprintf(&name, 4096, "phar://%s/%s", arch, entry);
00073                      }
00074                      efree(entry);
00075                      efree(arch);
00076                      if (zcontext) {
00077                             context = php_stream_context_from_zval(zcontext, 0);
00078                      }
00079                      stream = php_stream_opendir(name, REPORT_ERRORS, context);
00080                      efree(name);
00081                      if (!stream) {
00082                             RETURN_FALSE;
00083                      }
00084                      php_stream_to_zval(stream, return_value);
00085                      return;
00086               }
00087        }
00088 skip_phar:
00089        PHAR_G(orig_opendir)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00090        return;
00091 }
00092 /* }}} */
00093 
00094 PHAR_FUNC(phar_file_get_contents) /* {{{ */
00095 {
00096        char *filename;
00097        int filename_len;
00098        char *contents;
00099        zend_bool use_include_path = 0;
00100        php_stream *stream;
00101        int len;
00102        long offset = -1;
00103        long maxlen = PHP_STREAM_COPY_ALL;
00104        zval *zcontext = NULL;
00105 
00106        if (!PHAR_G(intercepted)) {
00107               goto skip_phar;
00108        }
00109 
00110        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
00111               && !cached_phars.arBuckets) {
00112               goto skip_phar;
00113        }
00114 
00115        /* Parse arguments */
00116        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) {
00117               goto skip_phar;
00118        }
00119 
00120        if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
00121               char *arch, *entry, *fname;
00122               int arch_len, entry_len, fname_len;
00123               php_stream_context *context = NULL;
00124 
00125               fname = zend_get_executed_filename(TSRMLS_C);
00126 
00127               if (strncasecmp(fname, "phar://", 7)) {
00128                      goto skip_phar;
00129               }
00130               fname_len = strlen(fname);
00131               if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
00132                      char *name;
00133                      phar_archive_data *phar;
00134 
00135                      efree(entry);
00136                      entry = filename;
00137                      /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00138                      entry_len = filename_len;
00139 
00140                      if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
00141                             efree(arch);
00142                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero");
00143                             RETURN_FALSE;
00144                      }
00145 
00146                      /* retrieving a file defaults to within the current directory, so use this if possible */
00147                      if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
00148                             efree(arch);
00149                             goto skip_phar;
00150                      }
00151                      if (use_include_path) {
00152                             if ((entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) {
00153                                    name = entry;
00154                                    goto phar_it;
00155                             } else {
00156                                    /* this file is not in the phar, use the original path */
00157                                    efree(arch);
00158                                    goto skip_phar;
00159                             }
00160                      } else {
00161                             entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
00162                             if (entry[0] == '/') {
00163                                    if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
00164                                           /* this file is not in the phar, use the original path */
00165 notfound:
00166                                           efree(arch);
00167                                           efree(entry);
00168                                           goto skip_phar;
00169                                    }
00170                             } else {
00171                                    if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
00172                                           goto notfound;
00173                                    }
00174                             }
00175                             /* auto-convert to phar:// */
00176                             if (entry[0] == '/') {
00177                                    spprintf(&name, 4096, "phar://%s%s", arch, entry);
00178                             } else {
00179                                    spprintf(&name, 4096, "phar://%s/%s", arch, entry);
00180                             }
00181                             if (entry != filename) {
00182                                    efree(entry);
00183                             }
00184                      }
00185 
00186 phar_it:
00187                      efree(arch);
00188                      if (zcontext) {
00189                             context = php_stream_context_from_zval(zcontext, 0);
00190                      }
00191                      stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
00192                      efree(name);
00193 
00194                      if (!stream) {
00195                             RETURN_FALSE;
00196                      }
00197 
00198                      if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
00199                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek to position %ld in the stream", offset);
00200                             php_stream_close(stream);
00201                             RETURN_FALSE;
00202                      }
00203 
00204                      /* uses mmap if possible */
00205                      if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) {
00206 #if PHP_MAJOR_VERSION < 6
00207                             if (PG(magic_quotes_runtime)) {
00208                                    int newlen;
00209                                    contents = php_addslashes(contents, len, &newlen, 1 TSRMLS_CC); /* 1 = free source string */
00210                                    len = newlen;
00211                             }
00212 #endif
00213                             RETVAL_STRINGL(contents, len, 0);
00214                      } else if (len == 0) {
00215                             RETVAL_EMPTY_STRING();
00216                      } else {
00217                             RETVAL_FALSE;
00218                      }
00219 
00220                      php_stream_close(stream);
00221                      return;
00222               }
00223        }
00224 skip_phar:
00225        PHAR_G(orig_file_get_contents)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00226        return;
00227 }
00228 /* }}} */
00229 
00230 PHAR_FUNC(phar_readfile) /* {{{ */
00231 {
00232        char *filename;
00233        int filename_len;
00234        int size = 0;
00235        zend_bool use_include_path = 0;
00236        zval *zcontext = NULL;
00237        php_stream *stream;
00238 
00239        if (!PHAR_G(intercepted)) {
00240               goto skip_phar;
00241        }
00242 
00243        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
00244               && !cached_phars.arBuckets) {
00245               goto skip_phar;
00246        }
00247        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
00248               goto skip_phar;
00249        }
00250        if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
00251               char *arch, *entry, *fname;
00252               int arch_len, entry_len, fname_len;
00253               php_stream_context *context = NULL;
00254               char *name;
00255               phar_archive_data *phar;
00256               fname = zend_get_executed_filename(TSRMLS_C);
00257 
00258               if (strncasecmp(fname, "phar://", 7)) {
00259                      goto skip_phar;
00260               }
00261               fname_len = strlen(fname);
00262               if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
00263                      goto skip_phar;
00264               }
00265 
00266               efree(entry);
00267               entry = filename;
00268               /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00269               entry_len = filename_len;
00270               /* retrieving a file defaults to within the current directory, so use this if possible */
00271               if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
00272                      efree(arch);
00273                      goto skip_phar;
00274               }
00275               if (use_include_path) {
00276                      if (!(entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) {
00277                             /* this file is not in the phar, use the original path */
00278                             efree(arch);
00279                             goto skip_phar;
00280                      } else {
00281                             name = entry;
00282                      }
00283               } else {
00284                      entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
00285                      if (entry[0] == '/') {
00286                             if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
00287                                    /* this file is not in the phar, use the original path */
00288 notfound:
00289                                    efree(entry);
00290                                    efree(arch);
00291                                    goto skip_phar;
00292                             }
00293                      } else {
00294                             if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
00295                                    goto notfound;
00296                             }
00297                      }
00298                      /* auto-convert to phar:// */
00299                      if (entry[0] == '/') {
00300                             spprintf(&name, 4096, "phar://%s%s", arch, entry);
00301                      } else {
00302                             spprintf(&name, 4096, "phar://%s/%s", arch, entry);
00303                      }
00304                      efree(entry);
00305               }
00306 
00307               efree(arch);
00308               context = php_stream_context_from_zval(zcontext, 0);
00309               stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
00310               efree(name);
00311               if (stream == NULL) {
00312                      RETURN_FALSE;
00313               }
00314               size = php_stream_passthru(stream);
00315               php_stream_close(stream);
00316               RETURN_LONG(size);
00317        }
00318 
00319 skip_phar:
00320        PHAR_G(orig_readfile)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00321        return;
00322 
00323 }
00324 /* }}} */
00325 
00326 PHAR_FUNC(phar_fopen) /* {{{ */
00327 {
00328        char *filename, *mode;
00329        int filename_len, mode_len;
00330        zend_bool use_include_path = 0;
00331        zval *zcontext = NULL;
00332        php_stream *stream;
00333 
00334        if (!PHAR_G(intercepted)) {
00335               goto skip_phar;
00336        }
00337 
00338        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
00339               && !cached_phars.arBuckets) {
00340               /* no need to check, include_path not even specified in fopen/ no active phars */
00341               goto skip_phar;
00342        }
00343        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) {
00344               goto skip_phar;
00345        }
00346        if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
00347               char *arch, *entry, *fname;
00348               int arch_len, entry_len, fname_len;
00349               php_stream_context *context = NULL;
00350               char *name;
00351               phar_archive_data *phar;
00352               fname = zend_get_executed_filename(TSRMLS_C);
00353 
00354               if (strncasecmp(fname, "phar://", 7)) {
00355                      goto skip_phar;
00356               }
00357               fname_len = strlen(fname);
00358               if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
00359                      goto skip_phar;
00360               }
00361 
00362               efree(entry);
00363               entry = filename;
00364               /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00365               entry_len = filename_len;
00366               /* retrieving a file defaults to within the current directory, so use this if possible */
00367               if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
00368                      efree(arch);
00369                      goto skip_phar;
00370               }
00371               if (use_include_path) {
00372                      if (!(entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) {
00373                             /* this file is not in the phar, use the original path */
00374                             efree(arch);
00375                             goto skip_phar;
00376                      } else {
00377                             name = entry;
00378                      }
00379               } else {
00380                      entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
00381                      if (entry[0] == '/') {
00382                             if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
00383                                    /* this file is not in the phar, use the original path */
00384 notfound:
00385                                    efree(entry);
00386                                    efree(arch);
00387                                    goto skip_phar;
00388                             }
00389                      } else {
00390                             if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
00391                                    /* this file is not in the phar, use the original path */
00392                                    goto notfound;
00393                             }
00394                      }
00395                      /* auto-convert to phar:// */
00396                      if (entry[0] == '/') {
00397                             spprintf(&name, 4096, "phar://%s%s", arch, entry);
00398                      } else {
00399                             spprintf(&name, 4096, "phar://%s/%s", arch, entry);
00400                      }
00401                      efree(entry);
00402               }
00403 
00404               efree(arch);
00405               context = php_stream_context_from_zval(zcontext, 0);
00406               stream = php_stream_open_wrapper_ex(name, mode, 0 | REPORT_ERRORS, NULL, context);
00407               efree(name);
00408               if (stream == NULL) {
00409                      RETURN_FALSE;
00410               }
00411               php_stream_to_zval(stream, return_value);
00412               if (zcontext) {
00413                      zend_list_addref(Z_RESVAL_P(zcontext));
00414               }
00415               return;
00416        }
00417 skip_phar:
00418        PHAR_G(orig_fopen)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00419        return;
00420 }
00421 /* }}} */
00422 
00423 #ifndef S_ISDIR
00424 #define S_ISDIR(mode)       (((mode)&S_IFMT) == S_IFDIR)
00425 #endif
00426 #ifndef S_ISREG
00427 #define S_ISREG(mode)       (((mode)&S_IFMT) == S_IFREG)
00428 #endif
00429 #ifndef S_ISLNK
00430 #define S_ISLNK(mode)       (((mode)&S_IFMT) == S_IFLNK)
00431 #endif
00432 
00433 #define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
00434 
00435 #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
00436 #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)
00437 #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
00438 #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
00439 
00440 /* {{{ php_stat
00441  */
00442 static void phar_fancy_stat(struct stat *stat_sb, int type, zval *return_value TSRMLS_DC)
00443 {
00444        zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
00445                *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
00446        int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
00447        char *stat_sb_names[13] = {
00448               "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
00449               "size", "atime", "mtime", "ctime", "blksize", "blocks"
00450        };
00451 
00452 #ifndef NETWARE
00453        if (type >= FS_IS_W && type <= FS_IS_X) {
00454               if(stat_sb->st_uid==getuid()) {
00455                      rmask=S_IRUSR;
00456                      wmask=S_IWUSR;
00457                      xmask=S_IXUSR;
00458               } else if(stat_sb->st_gid==getgid()) {
00459                      rmask=S_IRGRP;
00460                      wmask=S_IWGRP;
00461                      xmask=S_IXGRP;
00462               } else {
00463                      int   groups, n, i;
00464                      gid_t *gids;
00465 
00466                      groups = getgroups(0, NULL);
00467                      if(groups > 0) {
00468                             gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
00469                             n=getgroups(groups, gids);
00470                             for(i=0;i<n;++i){
00471                                    if(stat_sb->st_gid==gids[i]) {
00472                                           rmask=S_IRGRP;
00473                                           wmask=S_IWGRP;
00474                                           xmask=S_IXGRP;
00475                                           break;
00476                                    }
00477                             }
00478                             efree(gids);
00479                      }
00480               }
00481        }
00482 #endif
00483 
00484        switch (type) {
00485        case FS_PERMS:
00486               RETURN_LONG((long)stat_sb->st_mode);
00487        case FS_INODE:
00488               RETURN_LONG((long)stat_sb->st_ino);
00489        case FS_SIZE:
00490               RETURN_LONG((long)stat_sb->st_size);
00491        case FS_OWNER:
00492               RETURN_LONG((long)stat_sb->st_uid);
00493        case FS_GROUP:
00494               RETURN_LONG((long)stat_sb->st_gid);
00495        case FS_ATIME:
00496 #ifdef NETWARE
00497               RETURN_LONG((long)stat_sb->st_atime.tv_sec);
00498 #else
00499               RETURN_LONG((long)stat_sb->st_atime);
00500 #endif
00501        case FS_MTIME:
00502 #ifdef NETWARE
00503               RETURN_LONG((long)stat_sb->st_mtime.tv_sec);
00504 #else
00505               RETURN_LONG((long)stat_sb->st_mtime);
00506 #endif
00507        case FS_CTIME:
00508 #ifdef NETWARE
00509               RETURN_LONG((long)stat_sb->st_ctime.tv_sec);
00510 #else
00511               RETURN_LONG((long)stat_sb->st_ctime);
00512 #endif
00513        case FS_TYPE:
00514               if (S_ISLNK(stat_sb->st_mode)) {
00515                      RETURN_STRING("link", 1);
00516               }
00517               switch(stat_sb->st_mode & S_IFMT) {
00518               case S_IFDIR: RETURN_STRING("dir", 1);
00519               case S_IFREG: RETURN_STRING("file", 1);
00520               }
00521               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%u)", stat_sb->st_mode & S_IFMT);
00522               RETURN_STRING("unknown", 1);
00523        case FS_IS_W:
00524               RETURN_BOOL((stat_sb->st_mode & wmask) != 0);
00525        case FS_IS_R:
00526               RETURN_BOOL((stat_sb->st_mode&rmask)!=0);
00527        case FS_IS_X:
00528               RETURN_BOOL((stat_sb->st_mode&xmask)!=0 && !S_ISDIR(stat_sb->st_mode));
00529        case FS_IS_FILE:
00530               RETURN_BOOL(S_ISREG(stat_sb->st_mode));
00531        case FS_IS_DIR:
00532               RETURN_BOOL(S_ISDIR(stat_sb->st_mode));
00533        case FS_IS_LINK:
00534               RETURN_BOOL(S_ISLNK(stat_sb->st_mode));
00535        case FS_EXISTS:
00536               RETURN_TRUE; /* the false case was done earlier */
00537        case FS_LSTAT:
00538               /* FALLTHROUGH */
00539        case FS_STAT:
00540               array_init(return_value);
00541 
00542               MAKE_LONG_ZVAL_INCREF(stat_dev, stat_sb->st_dev);
00543               MAKE_LONG_ZVAL_INCREF(stat_ino, stat_sb->st_ino);
00544               MAKE_LONG_ZVAL_INCREF(stat_mode, stat_sb->st_mode);
00545               MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_sb->st_nlink);
00546               MAKE_LONG_ZVAL_INCREF(stat_uid, stat_sb->st_uid);
00547               MAKE_LONG_ZVAL_INCREF(stat_gid, stat_sb->st_gid);
00548 #ifdef HAVE_ST_RDEV
00549               MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_sb->st_rdev);
00550 #else
00551               MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
00552 #endif
00553               MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
00554 #ifdef NETWARE
00555               MAKE_LONG_ZVAL_INCREF(stat_atime, (stat_sb->st_atime).tv_sec);
00556               MAKE_LONG_ZVAL_INCREF(stat_mtime, (stat_sb->st_mtime).tv_sec);
00557               MAKE_LONG_ZVAL_INCREF(stat_ctime, (stat_sb->st_ctime).tv_sec);
00558 #else
00559               MAKE_LONG_ZVAL_INCREF(stat_atime, stat_sb->st_atime);
00560               MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_sb->st_mtime);
00561               MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_sb->st_ctime);
00562 #endif
00563 #ifdef HAVE_ST_BLKSIZE
00564               MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_sb->st_blksize);
00565 #else
00566               MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
00567 #endif
00568 #ifdef HAVE_ST_BLOCKS
00569               MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_sb->st_blocks);
00570 #else
00571               MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
00572 #endif
00573               /* Store numeric indexes in propper order */
00574               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
00575               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
00576               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
00577               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
00578               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
00579               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
00580 
00581               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
00582               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
00583               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
00584               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
00585               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
00586               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
00587               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
00588 
00589               /* Store string indexes referencing the same zval*/
00590               zend_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *) &stat_dev, sizeof(zval *), NULL);
00591               zend_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *) &stat_ino, sizeof(zval *), NULL);
00592               zend_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *) &stat_mode, sizeof(zval *), NULL);
00593               zend_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *) &stat_nlink, sizeof(zval *), NULL);
00594               zend_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *) &stat_uid, sizeof(zval *), NULL);
00595               zend_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *) &stat_gid, sizeof(zval *), NULL);
00596               zend_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *) &stat_rdev, sizeof(zval *), NULL);
00597               zend_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *) &stat_size, sizeof(zval *), NULL);
00598               zend_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *) &stat_atime, sizeof(zval *), NULL);
00599               zend_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *) &stat_mtime, sizeof(zval *), NULL);
00600               zend_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *) &stat_ctime, sizeof(zval *), NULL);
00601               zend_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *) &stat_blksize, sizeof(zval *), NULL);
00602               zend_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *) &stat_blocks, sizeof(zval *), NULL);
00603 
00604               return;
00605        }
00606        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Didn't understand stat call");
00607        RETURN_FALSE;
00608 }
00609 /* }}} */
00610 
00611 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) /* {{{ */
00612 {
00613        if (!filename_length) {
00614               RETURN_FALSE;
00615        }
00616 
00617        if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
00618               char *arch, *entry, *fname;
00619               int arch_len, entry_len, fname_len;
00620               struct stat sb = {0};
00621               phar_entry_info *data = NULL;
00622               phar_archive_data *phar;
00623 
00624               fname = zend_get_executed_filename(TSRMLS_C);
00625 
00626               /* we are checking for existence of a file within the relative path.  Chances are good that this is
00627                  retrieving something from within the phar archive */
00628 
00629               if (strncasecmp(fname, "phar://", 7)) {
00630                      goto skip_phar;
00631               }
00632               fname_len = strlen(fname);
00633               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))) {
00634                      arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
00635                      arch_len = PHAR_G(last_phar_name_len);
00636                      entry = estrndup(filename, filename_length);
00637                      /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00638                      entry_len = (int) filename_length;
00639                      phar = PHAR_G(last_phar);
00640                      goto splitted;
00641               }
00642               if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
00643 
00644                      efree(entry);
00645                      entry = estrndup(filename, filename_length);
00646                      /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00647                      entry_len = (int) filename_length;
00648                      if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
00649                             efree(arch);
00650                             efree(entry);
00651                             goto skip_phar;
00652                      }
00653 splitted:
00654                      entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
00655                      if (entry[0] == '/') {
00656                             if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &data)) {
00657                                    efree(entry);
00658                                    goto stat_entry;
00659                             }
00660                             goto notfound;
00661                      }
00662                      if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &data)) {
00663                             efree(entry);
00664                             goto stat_entry;
00665                      }
00666                      if (zend_hash_exists(&(phar->virtual_dirs), entry, entry_len)) {
00667                             efree(entry);
00668                             efree(arch);
00669                             if (IS_EXISTS_CHECK(type)) {
00670                                    RETURN_TRUE;
00671                             }
00672                             sb.st_size = 0;
00673                             sb.st_mode = 0777;
00674                             sb.st_mode |= S_IFDIR; /* regular directory */
00675 #ifdef NETWARE
00676                             sb.st_mtime.tv_sec = phar->max_timestamp;
00677                             sb.st_atime.tv_sec = phar->max_timestamp;
00678                             sb.st_ctime.tv_sec = phar->max_timestamp;
00679 #else
00680                             sb.st_mtime = phar->max_timestamp;
00681                             sb.st_atime = phar->max_timestamp;
00682                             sb.st_ctime = phar->max_timestamp;
00683 #endif
00684                             goto statme_baby;
00685                      } else {
00686                             char *save;
00687                             int save_len;
00688 
00689 notfound:
00690                             efree(entry);
00691                             save = PHAR_G(cwd);
00692                             save_len = PHAR_G(cwd_len);
00693                             /* this file is not in the current directory, use the original path */
00694                             entry = estrndup(filename, filename_length);
00695                             entry_len = filename_length;
00696                             PHAR_G(cwd) = "/";
00697                             PHAR_G(cwd_len) = 0;
00698                             /* clean path without cwd */
00699                             entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
00700                             if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &data)) {
00701                                    PHAR_G(cwd) = save;
00702                                    PHAR_G(cwd_len) = save_len;
00703                                    efree(entry);
00704                                    if (IS_EXISTS_CHECK(type)) {
00705                                           efree(arch);
00706                                           RETURN_TRUE;
00707                                    }
00708                                    goto stat_entry;
00709                             }
00710                             if (zend_hash_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
00711                                    PHAR_G(cwd) = save;
00712                                    PHAR_G(cwd_len) = save_len;
00713                                    efree(entry);
00714                                    efree(arch);
00715                                    if (IS_EXISTS_CHECK(type)) {
00716                                           RETURN_TRUE;
00717                                    }
00718                                    sb.st_size = 0;
00719                                    sb.st_mode = 0777;
00720                                    sb.st_mode |= S_IFDIR; /* regular directory */
00721 #ifdef NETWARE
00722                                    sb.st_mtime.tv_sec = phar->max_timestamp;
00723                                    sb.st_atime.tv_sec = phar->max_timestamp;
00724                                    sb.st_ctime.tv_sec = phar->max_timestamp;
00725 #else
00726                                    sb.st_mtime = phar->max_timestamp;
00727                                    sb.st_atime = phar->max_timestamp;
00728                                    sb.st_ctime = phar->max_timestamp;
00729 #endif
00730                                    goto statme_baby;
00731                             }
00732                             PHAR_G(cwd) = save;
00733                             PHAR_G(cwd_len) = save_len;
00734                             efree(entry);
00735                             efree(arch);
00736                             /* Error Occured */
00737                             if (!IS_EXISTS_CHECK(type)) {
00738                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
00739                             }
00740                             RETURN_FALSE;
00741                      }
00742 stat_entry:
00743                      efree(arch);
00744                      if (!data->is_dir) {
00745                             sb.st_size = data->uncompressed_filesize;
00746                             sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
00747                             if (data->link) {
00748                                    sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
00749                             } else {
00750                                    sb.st_mode |= S_IFREG; /* regular file */
00751                             }
00752                             /* timestamp is just the timestamp when this was added to the phar */
00753 #ifdef NETWARE
00754                             sb.st_mtime.tv_sec = data->timestamp;
00755                             sb.st_atime.tv_sec = data->timestamp;
00756                             sb.st_ctime.tv_sec = data->timestamp;
00757 #else
00758                             sb.st_mtime = data->timestamp;
00759                             sb.st_atime = data->timestamp;
00760                             sb.st_ctime = data->timestamp;
00761 #endif
00762                      } else {
00763                             sb.st_size = 0;
00764                             sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
00765                             sb.st_mode |= S_IFDIR; /* regular directory */
00766                             if (data->link) {
00767                                    sb.st_mode |= S_IFLNK;
00768                             }
00769                             /* timestamp is just the timestamp when this was added to the phar */
00770 #ifdef NETWARE
00771                             sb.st_mtime.tv_sec = data->timestamp;
00772                             sb.st_atime.tv_sec = data->timestamp;
00773                             sb.st_ctime.tv_sec = data->timestamp;
00774 #else
00775                             sb.st_mtime = data->timestamp;
00776                             sb.st_atime = data->timestamp;
00777                             sb.st_ctime = data->timestamp;
00778 #endif
00779                      }
00780 
00781 statme_baby:
00782                      if (!phar->is_writeable) {
00783                             sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
00784                      }
00785 
00786                      sb.st_nlink = 1;
00787                      sb.st_rdev = -1;
00788                      /* this is only for APC, so use /dev/null device - no chance of conflict there! */
00789                      sb.st_dev = 0xc;
00790                      /* generate unique inode number for alias/filename, so no phars will conflict */
00791                      if (data) {
00792                             sb.st_ino = data->inode;
00793                      }
00794 #ifndef PHP_WIN32
00795                      sb.st_blksize = -1;
00796                      sb.st_blocks = -1;
00797 #endif
00798                      phar_fancy_stat(&sb, type, return_value TSRMLS_CC);
00799                      return;
00800               }
00801        }
00802 skip_phar:
00803        orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00804        return;
00805 }
00806 /* }}} */
00807 
00808 #define PharFileFunction(fname, funcnum, orig) \
00809 void fname(INTERNAL_FUNCTION_PARAMETERS) { \
00810        if (!PHAR_G(intercepted)) { \
00811               PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
00812        } else { \
00813               char *filename; \
00814               int filename_len; \
00815               \
00816               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
00817                      return; \
00818               } \
00819               \
00820               phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
00821        } \
00822 }
00823 /* }}} */
00824 
00825 /* {{{ proto int fileperms(string filename)
00826    Get file permissions */
00827 PharFileFunction(phar_fileperms, FS_PERMS, orig_fileperms)
00828 /* }}} */
00829 
00830 /* {{{ proto int fileinode(string filename)
00831    Get file inode */
00832 PharFileFunction(phar_fileinode, FS_INODE, orig_fileinode)
00833 /* }}} */
00834 
00835 /* {{{ proto int filesize(string filename)
00836    Get file size */
00837 PharFileFunction(phar_filesize, FS_SIZE, orig_filesize)
00838 /* }}} */
00839 
00840 /* {{{ proto int fileowner(string filename)
00841    Get file owner */
00842 PharFileFunction(phar_fileowner, FS_OWNER, orig_fileowner)
00843 /* }}} */
00844 
00845 /* {{{ proto int filegroup(string filename)
00846    Get file group */
00847 PharFileFunction(phar_filegroup, FS_GROUP, orig_filegroup)
00848 /* }}} */
00849 
00850 /* {{{ proto int fileatime(string filename)
00851    Get last access time of file */
00852 PharFileFunction(phar_fileatime, FS_ATIME, orig_fileatime)
00853 /* }}} */
00854 
00855 /* {{{ proto int filemtime(string filename)
00856    Get last modification time of file */
00857 PharFileFunction(phar_filemtime, FS_MTIME, orig_filemtime)
00858 /* }}} */
00859 
00860 /* {{{ proto int filectime(string filename)
00861    Get inode modification time of file */
00862 PharFileFunction(phar_filectime, FS_CTIME, orig_filectime)
00863 /* }}} */
00864 
00865 /* {{{ proto string filetype(string filename)
00866    Get file type */
00867 PharFileFunction(phar_filetype, FS_TYPE, orig_filetype)
00868 /* }}} */
00869 
00870 /* {{{ proto bool is_writable(string filename)
00871    Returns true if file can be written */
00872 PharFileFunction(phar_is_writable, FS_IS_W, orig_is_writable)
00873 /* }}} */
00874 
00875 /* {{{ proto bool is_readable(string filename)
00876    Returns true if file can be read */
00877 PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
00878 /* }}} */
00879 
00880 /* {{{ proto bool is_executable(string filename)
00881    Returns true if file is executable */
00882 PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
00883 /* }}} */
00884 
00885 /* {{{ proto bool file_exists(string filename)
00886    Returns true if filename exists */
00887 PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
00888 /* }}} */
00889 
00890 /* {{{ proto bool is_dir(string filename)
00891    Returns true if file is directory */
00892 PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir)
00893 /* }}} */
00894 
00895 PHAR_FUNC(phar_is_file) /* {{{ */
00896 {
00897        char *filename;
00898        int filename_len;
00899 
00900        if (!PHAR_G(intercepted)) {
00901               goto skip_phar;
00902        }
00903 
00904        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
00905               && !cached_phars.arBuckets) {
00906               goto skip_phar;
00907        }
00908        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
00909               goto skip_phar;
00910        }
00911        if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
00912               char *arch, *entry, *fname;
00913               int arch_len, entry_len, fname_len;
00914               fname = zend_get_executed_filename(TSRMLS_C);
00915 
00916               /* we are checking for existence of a file within the relative path.  Chances are good that this is
00917                  retrieving something from within the phar archive */
00918 
00919               if (strncasecmp(fname, "phar://", 7)) {
00920                      goto skip_phar;
00921               }
00922               fname_len = strlen(fname);
00923               if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
00924                      phar_archive_data *phar;
00925 
00926                      efree(entry);
00927                      entry = filename;
00928                      /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00929                      entry_len = filename_len;
00930                      /* retrieving a file within the current directory, so use this if possible */
00931                      if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
00932                             phar_entry_info *etemp;
00933 
00934                             entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
00935                             if (entry[0] == '/') {
00936                                    if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
00937                                           /* this file is not in the current directory, use the original path */
00938 found_it:
00939                                           efree(entry);
00940                                           efree(arch);
00941                                           RETURN_BOOL(!etemp->is_dir);
00942                                    }
00943                             } else {
00944                                    if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &etemp)) {
00945                                           goto found_it;
00946                                    }
00947                             }
00948                      }
00949                      if (entry != filename) {
00950                             efree(entry);
00951                      }
00952                      efree(arch);
00953                      RETURN_FALSE;
00954               }
00955        }
00956 skip_phar:
00957        PHAR_G(orig_is_file)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00958        return;
00959 }
00960 /* }}} */
00961 
00962 PHAR_FUNC(phar_is_link) /* {{{ */
00963 {
00964        char *filename;
00965        int filename_len;
00966 
00967        if (!PHAR_G(intercepted)) {
00968               goto skip_phar;
00969        }
00970 
00971        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
00972               && !cached_phars.arBuckets) {
00973               goto skip_phar;
00974        }
00975        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
00976               goto skip_phar;
00977        }
00978        if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
00979               char *arch, *entry, *fname;
00980               int arch_len, entry_len, fname_len;
00981               fname = zend_get_executed_filename(TSRMLS_C);
00982 
00983               /* we are checking for existence of a file within the relative path.  Chances are good that this is
00984                  retrieving something from within the phar archive */
00985 
00986               if (strncasecmp(fname, "phar://", 7)) {
00987                      goto skip_phar;
00988               }
00989               fname_len = strlen(fname);
00990               if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
00991                      phar_archive_data *phar;
00992 
00993                      efree(entry);
00994                      entry = filename;
00995                      /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
00996                      entry_len = filename_len;
00997                      /* retrieving a file within the current directory, so use this if possible */
00998                      if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
00999                             phar_entry_info *etemp;
01000 
01001                             entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
01002                             if (entry[0] == '/') {
01003                                    if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
01004                                           /* this file is not in the current directory, use the original path */
01005 found_it:
01006                                           efree(entry);
01007                                           efree(arch);
01008                                           RETURN_BOOL(etemp->link);
01009                                    }
01010                             } else {
01011                                    if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &etemp)) {
01012                                           goto found_it;
01013                                    }
01014                             }
01015                      }
01016                      efree(entry);
01017                      efree(arch);
01018                      RETURN_FALSE;
01019               }
01020        }
01021 skip_phar:
01022        PHAR_G(orig_is_link)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01023        return;
01024 }
01025 /* }}} */
01026 
01027 /* {{{ proto array lstat(string filename)
01028    Give information about a file or symbolic link */
01029 PharFileFunction(phar_lstat, FS_LSTAT, orig_lstat)
01030 /* }}} */
01031 
01032 /* {{{ proto array stat(string filename)
01033    Give information about a file */
01034 PharFileFunction(phar_stat, FS_STAT, orig_stat)
01035 /* }}} */
01036 
01037 /* {{{ void phar_intercept_functions(TSRMLS_D) */
01038 void phar_intercept_functions(TSRMLS_D)
01039 {
01040        if (!PHAR_G(request_init)) {
01041               PHAR_G(cwd) = NULL;
01042               PHAR_G(cwd_len) = 0;
01043        }
01044        PHAR_G(intercepted) = 1;
01045 }
01046 /* }}} */
01047 
01048 /* {{{ void phar_release_functions(TSRMLS_D) */
01049 void phar_release_functions(TSRMLS_D)
01050 {
01051        PHAR_G(intercepted) = 0;
01052 }
01053 /* }}} */
01054 
01055 /* {{{ void phar_intercept_functions_init(TSRMLS_D) */
01056 #define PHAR_INTERCEPT(func) \
01057        PHAR_G(orig_##func) = NULL; \
01058        if (SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \
01059               PHAR_G(orig_##func) = orig->internal_function.handler; \
01060               orig->internal_function.handler = phar_##func; \
01061        }
01062 
01063 void phar_intercept_functions_init(TSRMLS_D)
01064 {
01065        zend_function *orig;
01066 
01067        PHAR_INTERCEPT(fopen);
01068        PHAR_INTERCEPT(file_get_contents);
01069        PHAR_INTERCEPT(is_file);
01070        PHAR_INTERCEPT(is_link);
01071        PHAR_INTERCEPT(is_dir);
01072        PHAR_INTERCEPT(opendir);
01073        PHAR_INTERCEPT(file_exists);
01074        PHAR_INTERCEPT(fileperms);
01075        PHAR_INTERCEPT(fileinode);
01076        PHAR_INTERCEPT(filesize);
01077        PHAR_INTERCEPT(fileowner);
01078        PHAR_INTERCEPT(filegroup);
01079        PHAR_INTERCEPT(fileatime);
01080        PHAR_INTERCEPT(filemtime);
01081        PHAR_INTERCEPT(filectime);
01082        PHAR_INTERCEPT(filetype);
01083        PHAR_INTERCEPT(is_writable);
01084        PHAR_INTERCEPT(is_readable);
01085        PHAR_INTERCEPT(is_executable);
01086        PHAR_INTERCEPT(lstat);
01087        PHAR_INTERCEPT(stat);
01088        PHAR_INTERCEPT(readfile);
01089        PHAR_G(intercepted) = 0;
01090 }
01091 /* }}} */
01092 
01093 /* {{{ void phar_intercept_functions_shutdown(TSRMLS_D) */
01094 #define PHAR_RELEASE(func) \
01095        if (PHAR_G(orig_##func) && SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \
01096               orig->internal_function.handler = PHAR_G(orig_##func); \
01097        } \
01098        PHAR_G(orig_##func) = NULL;
01099 
01100 void phar_intercept_functions_shutdown(TSRMLS_D)
01101 {
01102        zend_function *orig;
01103 
01104        PHAR_RELEASE(fopen);
01105        PHAR_RELEASE(file_get_contents);
01106        PHAR_RELEASE(is_file);
01107        PHAR_RELEASE(is_dir);
01108        PHAR_RELEASE(opendir);
01109        PHAR_RELEASE(file_exists);
01110        PHAR_RELEASE(fileperms);
01111        PHAR_RELEASE(fileinode);
01112        PHAR_RELEASE(filesize);
01113        PHAR_RELEASE(fileowner);
01114        PHAR_RELEASE(filegroup);
01115        PHAR_RELEASE(fileatime);
01116        PHAR_RELEASE(filemtime);
01117        PHAR_RELEASE(filectime);
01118        PHAR_RELEASE(filetype);
01119        PHAR_RELEASE(is_writable);
01120        PHAR_RELEASE(is_readable);
01121        PHAR_RELEASE(is_executable);
01122        PHAR_RELEASE(lstat);
01123        PHAR_RELEASE(stat);
01124        PHAR_RELEASE(readfile);
01125        PHAR_G(intercepted) = 0;
01126 }
01127 /* }}} */
01128 
01129 static struct _phar_orig_functions {
01130        void        (*orig_fopen)(INTERNAL_FUNCTION_PARAMETERS);
01131        void        (*orig_file_get_contents)(INTERNAL_FUNCTION_PARAMETERS);
01132        void        (*orig_is_file)(INTERNAL_FUNCTION_PARAMETERS);
01133        void        (*orig_is_link)(INTERNAL_FUNCTION_PARAMETERS);
01134        void        (*orig_is_dir)(INTERNAL_FUNCTION_PARAMETERS);
01135        void        (*orig_opendir)(INTERNAL_FUNCTION_PARAMETERS);
01136        void        (*orig_file_exists)(INTERNAL_FUNCTION_PARAMETERS);
01137        void        (*orig_fileperms)(INTERNAL_FUNCTION_PARAMETERS);
01138        void        (*orig_fileinode)(INTERNAL_FUNCTION_PARAMETERS);
01139        void        (*orig_filesize)(INTERNAL_FUNCTION_PARAMETERS);
01140        void        (*orig_fileowner)(INTERNAL_FUNCTION_PARAMETERS);
01141        void        (*orig_filegroup)(INTERNAL_FUNCTION_PARAMETERS);
01142        void        (*orig_fileatime)(INTERNAL_FUNCTION_PARAMETERS);
01143        void        (*orig_filemtime)(INTERNAL_FUNCTION_PARAMETERS);
01144        void        (*orig_filectime)(INTERNAL_FUNCTION_PARAMETERS);
01145        void        (*orig_filetype)(INTERNAL_FUNCTION_PARAMETERS);
01146        void        (*orig_is_writable)(INTERNAL_FUNCTION_PARAMETERS);
01147        void        (*orig_is_readable)(INTERNAL_FUNCTION_PARAMETERS);
01148        void        (*orig_is_executable)(INTERNAL_FUNCTION_PARAMETERS);
01149        void        (*orig_lstat)(INTERNAL_FUNCTION_PARAMETERS);
01150        void        (*orig_readfile)(INTERNAL_FUNCTION_PARAMETERS);
01151        void        (*orig_stat)(INTERNAL_FUNCTION_PARAMETERS);
01152 } phar_orig_functions = {NULL};
01153 
01154 void phar_save_orig_functions(TSRMLS_D) /* {{{ */
01155 {
01156        phar_orig_functions.orig_fopen             = PHAR_G(orig_fopen);
01157        phar_orig_functions.orig_file_get_contents = PHAR_G(orig_file_get_contents);
01158        phar_orig_functions.orig_is_file           = PHAR_G(orig_is_file);
01159        phar_orig_functions.orig_is_link           = PHAR_G(orig_is_link);
01160        phar_orig_functions.orig_is_dir            = PHAR_G(orig_is_dir);
01161        phar_orig_functions.orig_opendir           = PHAR_G(orig_opendir);
01162        phar_orig_functions.orig_file_exists       = PHAR_G(orig_file_exists);
01163        phar_orig_functions.orig_fileperms         = PHAR_G(orig_fileperms);
01164        phar_orig_functions.orig_fileinode         = PHAR_G(orig_fileinode);
01165        phar_orig_functions.orig_filesize          = PHAR_G(orig_filesize);
01166        phar_orig_functions.orig_fileowner         = PHAR_G(orig_fileowner);
01167        phar_orig_functions.orig_filegroup         = PHAR_G(orig_filegroup);
01168        phar_orig_functions.orig_fileatime         = PHAR_G(orig_fileatime);
01169        phar_orig_functions.orig_filemtime         = PHAR_G(orig_filemtime);
01170        phar_orig_functions.orig_filectime         = PHAR_G(orig_filectime);
01171        phar_orig_functions.orig_filetype          = PHAR_G(orig_filetype);
01172        phar_orig_functions.orig_is_writable       = PHAR_G(orig_is_writable);
01173        phar_orig_functions.orig_is_readable       = PHAR_G(orig_is_readable);
01174        phar_orig_functions.orig_is_executable     = PHAR_G(orig_is_executable);
01175        phar_orig_functions.orig_lstat             = PHAR_G(orig_lstat);
01176        phar_orig_functions.orig_readfile          = PHAR_G(orig_readfile);
01177        phar_orig_functions.orig_stat              = PHAR_G(orig_stat);
01178 }
01179 /* }}} */
01180 
01181 void phar_restore_orig_functions(TSRMLS_D) /* {{{ */
01182 {
01183        PHAR_G(orig_fopen)             = phar_orig_functions.orig_fopen;
01184        PHAR_G(orig_file_get_contents) = phar_orig_functions.orig_file_get_contents;
01185        PHAR_G(orig_is_file)           = phar_orig_functions.orig_is_file;
01186        PHAR_G(orig_is_link)           = phar_orig_functions.orig_is_link;
01187        PHAR_G(orig_is_dir)            = phar_orig_functions.orig_is_dir;
01188        PHAR_G(orig_opendir)           = phar_orig_functions.orig_opendir;
01189        PHAR_G(orig_file_exists)       = phar_orig_functions.orig_file_exists;
01190        PHAR_G(orig_fileperms)         = phar_orig_functions.orig_fileperms;
01191        PHAR_G(orig_fileinode)         = phar_orig_functions.orig_fileinode;
01192        PHAR_G(orig_filesize)          = phar_orig_functions.orig_filesize;
01193        PHAR_G(orig_fileowner)         = phar_orig_functions.orig_fileowner;
01194        PHAR_G(orig_filegroup)         = phar_orig_functions.orig_filegroup;
01195        PHAR_G(orig_fileatime)         = phar_orig_functions.orig_fileatime;
01196        PHAR_G(orig_filemtime)         = phar_orig_functions.orig_filemtime;
01197        PHAR_G(orig_filectime)         = phar_orig_functions.orig_filectime;
01198        PHAR_G(orig_filetype)          = phar_orig_functions.orig_filetype;
01199        PHAR_G(orig_is_writable)       = phar_orig_functions.orig_is_writable;
01200        PHAR_G(orig_is_readable)       = phar_orig_functions.orig_is_readable;
01201        PHAR_G(orig_is_executable)     = phar_orig_functions.orig_is_executable;
01202        PHAR_G(orig_lstat)             = phar_orig_functions.orig_lstat;
01203        PHAR_G(orig_readfile)          = phar_orig_functions.orig_readfile;
01204        PHAR_G(orig_stat)              = phar_orig_functions.orig_stat;
01205 }
01206 /* }}} */
01207 
01208 /*
01209  * Local variables:
01210  * tab-width: 4
01211  * c-basic-offset: 4
01212  * End:
01213  * vim600: noet sw=4 ts=4 fdm=marker
01214  * vim<600: noet sw=4 ts=4
01215  */
01216