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

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