From: Greg Beaver Date: Thu, 10 Jan 2008 15:13:00 +0000 (+0000) Subject: add interception of is_dir(), file_exists() and file_get_contents() - will make these... X-Git-Tag: RELEASE_2_0_0a1~958 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ab4c2caf4b4f1584e70a92a5687783f13dc9b2b2;p=php add interception of is_dir(), file_exists() and file_get_contents() - will make these optional shortly --- diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 3b20144b05..1ff835aa3b 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -269,7 +269,9 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) keylen = keylen - dirlen - 1; } PHAR_ADD_ENTRY: - phar_add_empty(data, entry, keylen); + if (keylen) { + phar_add_empty(data, entry, keylen); + } efree(entry); if (SUCCESS != zend_hash_move_forward(manifest)) { break; @@ -436,7 +438,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in return FAILURE; } - if (e = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 1, &error TSRMLS_CC)) { + if ((e = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 1, &error TSRMLS_CC))) { /* directory exists, or is a subdirectory of an existing file */ efree(e->filename); efree(e); diff --git a/ext/phar/dirstream.h b/ext/phar/dirstream.h index 9528c4da27..f3f95c5659 100644 --- a/ext/phar/dirstream.h +++ b/ext/phar/dirstream.h @@ -33,6 +33,8 @@ static int phar_dir_close(php_stream *stream, int close_handle TSRMLS_DC); static int phar_dir_flush(php_stream *stream TSRMLS_DC); static int phar_dir_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC); static int phar_dir_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); +#else +php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); #endif END_EXTERN_C() diff --git a/ext/phar/phar.c b/ext/phar/phar.c index c61e404bd5..8707957b98 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1870,14 +1870,20 @@ char *tsrm_strtok_r(char *s, const char *delim, char **last) /** * Remove .. and . references within a phar filename */ -static char *phar_fix_filepath(char *path, int *new_len) /* {{{ */ +static char *phar_fix_filepath(char *path, int *new_len, int cwd) /* {{{ */ { char *ptr, *free_path, *new_phar; char *tok; int ptr_length, new_phar_len = 1, path_length = *new_len; - free_path = path; - new_phar = estrndup("/\0", 2); + if (cwd) { + free_path = path = estrndup(path, path_length); + new_phar_len = PHAR_G(cwd_len); + new_phar = estrndup(PHAR_G(cwd), new_phar_len); + } else { + free_path = path; + new_phar = estrndup("/\0", 2); + } tok = NULL; ptr = tsrm_strtok_r(path, "/", &tok); while (ptr) { @@ -1919,7 +1925,9 @@ static char *phar_fix_filepath(char *path, int *new_len) /* {{{ */ ptr = tsrm_strtok_r(NULL, "/", &tok); } - efree(free_path); + if (free_path) { + efree(free_path); + } if (path[path_length-1] == '/' && new_phar_len > 1) { new_phar = (char*)erealloc(new_phar, new_phar_len + 2); @@ -1984,7 +1992,7 @@ int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_le #ifdef PHP_WIN32 phar_unixify_path_separators(*entry, *entry_len); #endif - *entry = phar_fix_filepath(*entry, entry_len); + *entry = phar_fix_filepath(*entry, entry_len, 0); } else { *entry_len = 1; *entry = estrndup("/", 1); @@ -3069,7 +3077,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type zend_op_array *res; char *name = NULL; char *fname = NULL; - int fname_len, failed; + int failed; zend_op_array *(*save)(zend_file_handle *file_handle, int type TSRMLS_DC); phar_archive_data *phar; @@ -3077,7 +3085,6 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type zend_compile_file = phar_orig_compile_file; fname = zend_get_executed_filename(TSRMLS_C); - fname_len = strlen(fname); if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, "://")) { if (SUCCESS == phar_open_filename(file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL TSRMLS_CC)) { if (phar->is_zip || phar->is_tar) { @@ -3085,7 +3092,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type /* zip or tar-based phar */ spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php"); - if (SUCCESS == zend_stream_open_function((const char *)name, file_handle TSRMLS_CC)) { + if (SUCCESS == phar_orig_zend_open((const char *)name, file_handle TSRMLS_CC)) { efree(name); name = NULL; file_handle->filename = f.filename; @@ -3109,51 +3116,328 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type } } } +skip_phar: + zend_try { + failed = 0; + res = zend_compile_file(file_handle, type TSRMLS_CC); + } zend_catch { + failed = 1; + } zend_end_try(); + if (name) { + efree(name); + } + zend_compile_file = save; + if (failed) { + zend_bailout(); + } + return res; +} +/* }}} */ + +ZEND_API int phar_zend_open(const char *filename, zend_file_handle *handle TSRMLS_DC) /* {{{ */ +{ + char *arch, *entry; + + entry = (char *) filename; if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) { - char *arch, *entry; int arch_len, entry_len; + char *fname = NULL; + int fname_len; + + fname = zend_get_executed_filename(TSRMLS_C); if (strncasecmp(fname, "phar://", 7)) { goto skip_phar; } fname_len = strlen(fname); if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + char *name; + efree(entry); - entry = file_handle->filename; + entry = (char *) filename; /* include within phar, if :// is not in the url, then prepend phar:/// */ if (strstr(entry, "://")) { efree(arch); goto skip_phar; } entry_len = strlen(entry); + if (!IS_ABSOLUTE_PATH(entry, entry_len)) { + phar_archive_data **pphar; + /* retrieving an include within the current directory, so use this if possible */ + if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + entry = phar_fix_filepath(entry, &entry_len, 1); + if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) { + /* this file is not in the current directory, use the original path */ + efree(entry); + entry = (char *) filename; + } + } + } /* auto-convert to phar:// */ spprintf(&name, 4096, "phar://%s/%s", arch, entry); efree(arch); - if (file_handle->type == ZEND_HANDLE_FP) { - // clean up - fclose(file_handle->handle.fp); + if (SUCCESS == phar_orig_zend_open(name, handle TSRMLS_CC)) { + if (!handle->opened_path) { + handle->opened_path = name; + } + if (entry != filename) { + efree(entry); + } + return SUCCESS; } - file_handle->type = ZEND_HANDLE_FILENAME; - file_handle->free_filename = 1; - file_handle->filename = name; + return FAILURE; } } skip_phar: - zend_try { - failed = 0; - res = zend_compile_file(file_handle, type TSRMLS_CC); - } zend_catch { - failed = 1; - } zend_end_try(); - if (name) { - efree(name); + return phar_orig_zend_open(filename, handle TSRMLS_CC); +} +/* }}} */ + +static void phar_is_dir(INTERNAL_FUNCTION_PARAMETERS) +{ + char *filename; + int filename_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { + return; } - zend_compile_file = save; - if (failed) { - zend_bailout(); + + if (!IS_ABSOLUTE_PATH(filename, filename_len)) { + char *arch, *entry, *fname; + int arch_len, entry_len, fname_len, free_filename = 0; + fname = zend_get_executed_filename(TSRMLS_C); + + /* we are checking for existence of a file within the relative path. Chances are good that this is + retrieving something from within the phar archive */ + + if (strncasecmp(fname, "phar://", 7)) { + goto skip_phar; + } + fname_len = strlen(fname); + if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + phar_archive_data **pphar; + + efree(entry); + entry = filename; + /* fopen within phar, if :// is not in the url, then prepend phar:/// */ + entry_len = filename_len; + if (strstr(entry, "://")) { + efree(arch); + if (free_filename) { + efree(filename); + } + goto skip_phar; + } + /* retrieving a file within the current directory, so use this if possible */ + if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + phar_entry_info *etemp; + + entry = phar_fix_filepath(entry, &entry_len, 1); + if (zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &etemp)) { + /* this file is not in the current directory, use the original path */ + efree(entry); + efree(arch); + RETURN_BOOL(etemp->is_dir); + } else { + char *key; + uint keylen; + ulong unused; + HashTable *manifest; + + efree(arch); + manifest = &(*pphar)->manifest; + zend_hash_internal_pointer_reset(manifest); + while (FAILURE != zend_hash_has_more_elements(manifest)) { + if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) { + break; + } + if (0 != memcmp(key, entry, entry_len)) { + /* entry in directory not found */ + if (SUCCESS != zend_hash_move_forward(manifest)) { + break; + } + continue; + } else { + if (key[entry_len] != '/') { + if (SUCCESS != zend_hash_move_forward(manifest)) { + break; + } + continue; + } + /* found a file in this path */ + efree(entry); + RETURN_TRUE; + } + } + efree(entry); + RETURN_FALSE; + } + } + } } - return res; +skip_phar: + PHAR_G(orig_is_dir)(INTERNAL_FUNCTION_PARAM_PASSTHRU); + return; +} + +static void phar_fgc(INTERNAL_FUNCTION_PARAMETERS) +{ + char *filename; + int filename_len; + char *contents; + zend_bool use_include_path = 0; + php_stream *stream; + int len, newlen; + long offset = -1; + long maxlen = PHP_STREAM_COPY_ALL; + zval *zcontext = NULL; + + /* Parse arguments */ + 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) { + return; + } + if (use_include_path || !IS_ABSOLUTE_PATH(filename, filename_len)) { + char *arch, *entry, *fname; + int arch_len, entry_len, fname_len, free_filename = 0; + php_stream_context *context = NULL; + fname = zend_get_executed_filename(TSRMLS_C); + + if (strncasecmp(fname, "phar://", 7)) { + goto skip_phar; + } + fname_len = strlen(fname); + if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + char *name; + phar_archive_data **pphar; + + efree(entry); + entry = filename; + /* fopen within phar, if :// is not in the url, then prepend phar:/// */ + entry_len = filename_len; + if (strstr(entry, "://")) { + efree(arch); + if (free_filename) { + efree(filename); + } + goto skip_phar; + } + + if (ZEND_NUM_ARGS() == 5 && maxlen < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero"); + RETURN_FALSE; + } + + if (!IS_ABSOLUTE_PATH(filename, filename_len)) { + /* retrieving a file defaults to within the current directory, so use this if possible */ + if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + name = entry; + entry = phar_fix_filepath(entry, &entry_len, 1); + if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) { + /* this file is not in the current directory, use the original path */ + efree(entry); + entry = name; + } + } + } + /* auto-convert to phar:// */ + spprintf(&name, 4096, "phar://%s/%s", arch, entry); + if (entry != filename) { + efree(entry); + } + efree(arch); + context = php_stream_context_from_zval(zcontext, 0); + stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context); + if (free_filename) { + efree(filename); + } + efree(name); + + + if (!stream) { + RETURN_FALSE; + } + + if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek to position %ld in the stream", offset); + php_stream_close(stream); + RETURN_FALSE; + } + + /* uses mmap if possible */ + if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) { + + if (PG(magic_quotes_runtime)) { + contents = php_addslashes(contents, len, &newlen, 1 TSRMLS_CC); /* 1 = free source string */ + len = newlen; + } + + RETVAL_STRINGL(contents, len, 0); + } else if (len == 0) { + RETVAL_EMPTY_STRING(); + } else { + RETVAL_FALSE; + } + + php_stream_close(stream); + return; + } + } +skip_phar: + PHAR_G(orig_fgc)(INTERNAL_FUNCTION_PARAM_PASSTHRU); + return; +} + +static void phar_file_exists(INTERNAL_FUNCTION_PARAMETERS) +{ + char *filename; + int filename_len; + + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { + goto skip_phar; + } + if (!IS_ABSOLUTE_PATH(filename, filename_len)) { + char *arch, *entry, *fname; + int arch_len, entry_len, fname_len, free_filename = 0; + fname = zend_get_executed_filename(TSRMLS_C); + + /* we are checking for existence of a file within the relative path. Chances are good that this is + retrieving something from within the phar archive */ + + if (strncasecmp(fname, "phar://", 7)) { + goto skip_phar; + } + fname_len = strlen(fname); + if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + phar_archive_data **pphar; + + efree(entry); + entry = filename; + /* fopen within phar, if :// is not in the url, then prepend phar:/// */ + entry_len = filename_len; + if (strstr(entry, "://")) { + efree(arch); + if (free_filename) { + efree(filename); + } + goto skip_phar; + } + /* retrieving a file within the current directory, so use this if possible */ + if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + entry = phar_fix_filepath(entry, &entry_len, 1); + if (zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) { + /* this file is not in the current directory, use the original path */ + efree(entry); + efree(arch); + RETURN_TRUE; + } + } + efree(entry); + efree(arch); + } + } +skip_phar: + PHAR_G(file_exists)(INTERNAL_FUNCTION_PARAM_PASSTHRU); + return; } -/* }}} */ static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS) { @@ -3163,42 +3447,63 @@ static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS) zval *zcontext = NULL; php_stream *stream; - if (ht < 3 || !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) { + if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) { /* no need to check, include_path not even specified in fopen/ no active phars */ goto skip_phar; } - 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 || !use_include_path) { + 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) { goto skip_phar; } - { + if (use_include_path || !IS_ABSOLUTE_PATH(filename, filename_len)) { char *arch, *entry, *fname; - int arch_len, entry_len, fname_len; + int arch_len, entry_len, fname_len, free_filename = 0; php_stream_context *context = NULL; fname = zend_get_executed_filename(TSRMLS_C); + if (strncasecmp(fname, "phar://", 7)) { goto skip_phar; } fname_len = strlen(fname); if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { - char *s, *name; + char *name; + phar_archive_data **pphar; efree(entry); entry = filename; /* fopen within phar, if :// is not in the url, then prepend phar:/// */ entry_len = filename_len; - for (s = entry; s < (entry + entry_len - 4); s++) { - if (*s == ':' && *(s + 1) == '/' && *(s + 2) == '/') { - efree(arch); - goto skip_phar; + if (strstr(entry, "://")) { + efree(arch); + if (free_filename) { + efree(filename); + } + goto skip_phar; + } + if (!IS_ABSOLUTE_PATH(filename, filename_len)) { + /* retrieving a file defaults to within the current directory, so use this if possible */ + if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + name = entry; + entry = phar_fix_filepath(entry, &entry_len, 1); + if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) { + /* this file is not in the current directory, use the original path */ + efree(entry); + entry = name; + } } } /* auto-convert to phar:// */ spprintf(&name, 4096, "phar://%s/%s", arch, entry); + if (entry != filename) { + efree(entry); + } efree(arch); context = php_stream_context_from_zval(zcontext, 0); stream = php_stream_open_wrapper_ex(name, mode, 0 | REPORT_ERRORS, NULL, context); efree(name); php_stream_to_zval(stream, return_value); + if (free_filename) { + efree(filename); + } return; } } @@ -3213,6 +3518,8 @@ PHP_MINIT_FUNCTION(phar) /* {{{ */ REGISTER_INI_ENTRIES(); PHAR_G(orig_fopen) = NULL; + PHAR_G(orig_fgc) = NULL; + PHAR_G(file_exists) = NULL; phar_has_gnupg = zend_hash_exists(&module_registry, "gnupg", sizeof("gnupg")); phar_has_bz2 = zend_hash_exists(&module_registry, "bz2", sizeof("bz2")); phar_has_zlib = zend_hash_exists(&module_registry, "zlib", sizeof("zlib")); @@ -3220,6 +3527,9 @@ PHP_MINIT_FUNCTION(phar) /* {{{ */ phar_orig_compile_file = zend_compile_file; zend_compile_file = phar_compile_file; + phar_orig_zend_open = zend_stream_open_function; + zend_stream_open_function = phar_zend_open; + phar_object_init(TSRMLS_C); return php_register_url_stream_wrapper("phar", &php_stream_phar_wrapper TSRMLS_CC); @@ -3232,6 +3542,9 @@ PHP_MSHUTDOWN_FUNCTION(phar) /* {{{ */ if (zend_compile_file == phar_compile_file) { zend_compile_file = phar_orig_compile_file; } + if (zend_stream_open_function == phar_zend_open) { + zend_stream_open_function = phar_orig_zend_open; + } } /* }}} */ @@ -3252,6 +3565,19 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */ PHAR_G(orig_fopen) = orig->internal_function.handler; orig->internal_function.handler = phar_fopen; } + if (SUCCESS == zend_hash_find(CG(function_table), "file_get_contents", 18, (void **)&orig)) { + PHAR_G(orig_fgc) = orig->internal_function.handler; + orig->internal_function.handler = phar_fgc; + } + if (SUCCESS == zend_hash_find(CG(function_table), "file_exists", 12, (void **)&orig)) { + PHAR_G(file_exists) = orig->internal_function.handler; + orig->internal_function.handler = phar_file_exists; + } + if (SUCCESS == zend_hash_find(CG(function_table), "is_dir", 7, (void **)&orig)) { + PHAR_G(file_exists) = orig->internal_function.handler; + orig->internal_function.handler = phar_is_dir; + } + PHAR_G(cwd) = NULL; } } /* }}} */ @@ -3265,6 +3591,19 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */ if (PHAR_G(orig_fopen) && SUCCESS == zend_hash_find(CG(function_table), "fopen", 6, (void **)&orig)) { orig->internal_function.handler = PHAR_G(orig_fopen); } + PHAR_G(orig_fopen) = NULL; + if (PHAR_G(file_exists) && SUCCESS == zend_hash_find(CG(function_table), "file_exists", 12, (void **)&orig)) { + orig->internal_function.handler = PHAR_G(file_exists); + } + PHAR_G(file_exists) = NULL; + if (PHAR_G(orig_fgc) && SUCCESS == zend_hash_find(CG(function_table), "file_get_contents", 18, (void **)&orig)) { + orig->internal_function.handler = PHAR_G(orig_fgc); + } + PHAR_G(orig_fgc) = NULL; + if (PHAR_G(orig_is_dir) && SUCCESS == zend_hash_find(CG(function_table), "is_dir", 7, (void **)&orig)) { + orig->internal_function.handler = PHAR_G(orig_is_dir); + } + PHAR_G(orig_is_dir) = NULL; zend_hash_destroy(&(PHAR_GLOBALS->phar_alias_map)); PHAR_GLOBALS->phar_alias_map.arBuckets = NULL; zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map)); @@ -3274,6 +3613,11 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */ zend_hash_destroy(&(PHAR_GLOBALS->phar_SERVER_mung_list)); PHAR_GLOBALS->phar_SERVER_mung_list.arBuckets = NULL; PHAR_GLOBALS->request_init = 0; + if (PHAR_G(cwd)) { + efree(PHAR_G(cwd)); + } + PHAR_G(cwd) = NULL; + PHAR_G(cwd_len) = 0; } PHAR_GLOBALS->request_done = 1; return SUCCESS; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index e13899ac4d..16261c5dd7 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -42,6 +42,7 @@ #include "ext/standard/info.h" #include "ext/standard/basic_functions.h" #include "ext/standard/file.h" +#include "ext/standard/php_string.h" #include "ext/standard/url.h" #include "ext/standard/crc32.h" #include "ext/standard/md5.h" @@ -51,6 +52,7 @@ #ifndef PHP_WIN32 #include "TSRM/tsrm_strtok_r.h" #endif +#include "TSRM/tsrm_virtual_cwd.h" #if HAVE_PHAR_ZIP #include "lib/zip.h" #include "lib/zipint.h" @@ -141,6 +143,12 @@ ZEND_BEGIN_MODULE_GLOBALS(phar) int request_done; int request_ends; void (*orig_fopen)(INTERNAL_FUNCTION_PARAMETERS); + void (*orig_fgc)(INTERNAL_FUNCTION_PARAMETERS); + void (*orig_is_dir)(INTERNAL_FUNCTION_PARAMETERS); + void (*file_exists)(INTERNAL_FUNCTION_PARAMETERS); + /* used for includes with . in them inside front controller */ + char* cwd; + int cwd_len; ZEND_END_MODULE_GLOBALS(phar) ZEND_EXTERN_MODULE_GLOBALS(phar) @@ -149,6 +157,7 @@ int phar_has_bz2; int phar_has_gnupg; int phar_has_zlib; zend_op_array *(*phar_orig_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); +ZEND_API int (*phar_orig_zend_open)(const char *filename, zend_file_handle *handle TSRMLS_DC); #ifdef ZTS # include "TSRM.h" diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 2266de075c..16e0a8dd22 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -165,7 +165,7 @@ static void phar_mung_server_vars(char *fname, char *entry, char *basename, int static int phar_file_action(phar_entry_data *phar, char *mime_type, int code, char *entry, int entry_len, char *arch, int arch_len, char *basename, int basename_len TSRMLS_DC) { - char *name = NULL, buf[8192]; + char *name = NULL, buf[8192], *cwd; zend_syntax_highlighter_ini syntax_highlighter_ini; sapi_header_line ctr = {0}; size_t got; @@ -269,7 +269,18 @@ static int phar_file_action(phar_entry_data *phar, char *mime_type, int code, ch if (!file_handle.opened_path) { file_handle.opened_path = estrndup(name, name_len); } + PHAR_G(cwd) = NULL; + PHAR_G(cwd_len) = 0; if (zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) { + if ((cwd = strrchr(entry, '/'))) { + if (entry[0] == '/') { + PHAR_G(cwd_len) = cwd - (entry + 1); + PHAR_G(cwd) = estrndup(entry + 1, PHAR_G(cwd_len)); + } else { + PHAR_G(cwd_len) = cwd - entry; + PHAR_G(cwd) = estrndup(entry, PHAR_G(cwd_len)); + } + } new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); zend_destroy_file_handle(&file_handle TSRMLS_CC); } else { @@ -282,18 +293,24 @@ static int phar_file_action(phar_entry_data *phar, char *mime_type, int code, ch if (new_op_array) { EG(return_value_ptr_ptr) = &result; EG(active_op_array) = new_op_array; - - zend_execute(new_op_array TSRMLS_CC); - - destroy_op_array(new_op_array TSRMLS_CC); - efree(new_op_array); - if (!EG(exception)) { - if (EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); + + zend_try { + zend_execute(new_op_array TSRMLS_CC); + destroy_op_array(new_op_array TSRMLS_CC); + efree(new_op_array); + if (!EG(exception)) { + if (EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } } - } - - efree(name); + } zend_catch { + if (PHAR_G(cwd)) { + efree(PHAR_G(cwd)); + PHAR_G(cwd) = NULL; + PHAR_G(cwd_len) = 0; + } + efree(name); + } zend_end_try(); zend_bailout(); } return PHAR_MIME_PHP; diff --git a/ext/phar/stream.h b/ext/phar/stream.h index b9cf92a250..7eb39fa3bf 100644 --- a/ext/phar/stream.h +++ b/ext/phar/stream.h @@ -26,7 +26,6 @@ php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char *mode, void phar_entry_remove(phar_entry_data *idata, char **error TSRMLS_DC); static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); -static php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC); static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);