diff --git a/ChangeLog b/ChangeLog index e5e5b59..29a328e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ ChangeLog * closes #2: auto disable caching on crash * closes #73: warn for improper PHP_FCGI_CHILDREN setting fcgi mode (>=PHP_5_3) * closes #174: updates api to support "clear all cache" + * closes #198: support for caching protocol url * fixes #39: ini_set never work for xcache.coverager setting. use API instead * code refactor * uses extension= to load XCache. loading via zend_extension= is unsupported diff --git a/mod_cacher/xc_cacher.c b/mod_cacher/xc_cacher.c index 69d384f..e9306c2 100644 --- a/mod_cacher/xc_cacher.c +++ b/mod_cacher/xc_cacher.c @@ -242,8 +242,8 @@ static inline int xc_entry_equal_unlocked(xc_entry_type_t type, const xc_entry_t } } - assert(IS_ABSOLUTE_PATH(entry1->name.str.val, entry1->name.str.len)); - assert(IS_ABSOLUTE_PATH(entry2->name.str.val, entry2->name.str.len)); + assert(strstr(entry1->name.str.val, "://") != NULL || IS_ABSOLUTE_PATH(entry1->name.str.val, entry1->name.str.len)); + assert(strstr(entry1->name.str.val, "://") != NULL || IS_ABSOLUTE_PATH(entry2->name.str.val, entry2->name.str.len)); return entry1->name.str.len == entry2->name.str.len && memcmp(entry1->name.str.val, entry2->name.str.val, entry1->name.str.len + 1) == 0; @@ -946,9 +946,9 @@ static char *xc_expand_url(const char *filepath, char *real_path TSRMLS_DC) /* { } /* }}} */ -#define XC_RESOLVE_PATH_CHECKER(name) zend_bool name(const char *filepath, size_t filepath_len, void *data TSRMLS_DC) +#define XC_RESOLVE_PATH_CHECKER(name) int name(const char *filepath, size_t filepath_len, void *data TSRMLS_DC) typedef XC_RESOLVE_PATH_CHECKER((*xc_resolve_path_checker_func_t)); -static zend_bool xc_resolve_path(const char *filepath, char *path_buffer, xc_resolve_path_checker_func_t checker_func, void *data TSRMLS_DC) /* {{{ */ +static int xc_resolve_path(const char *filepath, char *path_buffer, xc_resolve_path_checker_func_t checker_func, void *data TSRMLS_DC) /* {{{ */ { char *paths, *path; char *tokbuf; @@ -966,12 +966,7 @@ static zend_bool xc_resolve_path(const char *filepath, char *path_buffer, xc_res !path || !*path) { - if (checker_func(path_buffer, path_buffer_len, data TSRMLS_CC)) { - ret = 1; - } - else { - ret = FAILURE; - } + ret = checker_func(path_buffer, path_buffer_len, data TSRMLS_CC); goto finish; } #endif @@ -983,8 +978,8 @@ static zend_bool xc_resolve_path(const char *filepath, char *path_buffer, xc_res for (path = php_strtok_r(paths, tokens, &tokbuf); path; path = php_strtok_r(NULL, tokens, &tokbuf)) { path_buffer_len = snprintf(path_buffer, MAXPATHLEN, "%s/%s", path, filepath); if (path_buffer_len < MAXPATHLEN - 1) { - if (checker_func(path_buffer, path_buffer_len, data TSRMLS_CC)) { - ret = 1; + ret = checker_func(path_buffer, path_buffer_len, data TSRMLS_CC); + if (ret == SUCCESS) { goto finish; } } @@ -992,31 +987,24 @@ static zend_bool xc_resolve_path(const char *filepath, char *path_buffer, xc_res /* fall back to current directory */ if (zend_is_executing(TSRMLS_C)) { - const char *executed_filename = zend_get_executed_filename(TSRMLS_C); - if (executed_filename && executed_filename[0] && executed_filename[0] != '[') { - size_t filename_len = strlen(filepath); - size_t dirname_len; - - for (dirname_len = strlen(executed_filename) - 1; dirname_len > 0; --dirname_len) { - if (IS_SLASH(executed_filename[dirname_len])) { - if (dirname_len + filename_len < MAXPATHLEN - 1) { - ++dirname_len; /* include tailing slash */ - memcpy(path_buffer, executed_filename, dirname_len); - memcpy(path_buffer + dirname_len, filepath, filename_len); - path_buffer_len = dirname_len + filename_len; - path_buffer[path_buffer_len] = '\0'; - if (checker_func(path_buffer, path_buffer_len, data TSRMLS_CC)) { - ret = 1; - goto finish; - } - } - break; - } + const char *executing_filename = zend_get_executed_filename(TSRMLS_C); + int dirname_len = strlen(executing_filename); + size_t filename_len = strlen(filepath); + + while ((--dirname_len >= 0) && !IS_SLASH(executing_filename[dirname_len])); + if (executing_filename && dirname_len > 0 && executing_filename[0] && executing_filename[0] != '[' + && dirname_len + 1 + filename_len + 1 < MAXPATHLEN) { + memcpy(path_buffer, executing_filename, dirname_len + 1); + memcpy(path_buffer + dirname_len + 1, filepath, filename_len + 1); + path_buffer_len = dirname_len + 1 + filename_len; + ret = checker_func(path_buffer, path_buffer_len, data TSRMLS_CC); + if (ret == SUCCESS) { + goto finish; } } } - ret = 0; + ret = FAILURE; finish: my_free_alloca(paths, use_heap); @@ -1024,17 +1012,53 @@ finish: return ret; } /* }}} */ -#ifndef ZEND_ENGINE_2_3 -static XC_RESOLVE_PATH_CHECKER(xc_stat_file) /* {{{ */ + +static zend_bool xc_is_absolute(const char *filepath, size_t filepath_len) /* {{{ */ +{ + const char *p; + + if (IS_ABSOLUTE_PATH(filepath, filepath_len)) { + return 1; + } + + for (p = filepath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + if ((*p == ':') && (p - filepath > 1) && (p[1] == '/') && (p[2] == '/')) { + return 1; + } + + return 0; +} +/* }}} */ +static int xc_stat(const char *filepath, struct stat *statbuf TSRMLS_DC) /* {{{ */ +{ + if (strstr(filepath, "://") != NULL) { + php_stream_statbuf ssb; + php_stream_wrapper *wrapper = NULL; + char *path_for_open = NULL; + + wrapper = php_stream_locate_url_wrapper(filepath, &path_for_open, 0 TSRMLS_CC); + if (wrapper && wrapper->wops->url_stat + && wrapper != &php_plain_files_wrapper + && wrapper->wops->url_stat(wrapper, path_for_open, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL TSRMLS_CC) == SUCCESS) { + *statbuf = ssb.sb; + return SUCCESS; + } + + return FAILURE; + } + + return VCWD_STAT(filepath, statbuf); +} +/* }}} */ +static XC_RESOLVE_PATH_CHECKER(xc_resolve_path_stat_checker) /* {{{ */ { - return VCWD_STAT(filepath, (struct stat *) data) == 0 ? 1 : 0; + return xc_stat(filepath, (struct stat *) data TSRMLS_CC); } /* }}} */ +#ifndef ZEND_ENGINE_2_3 static int xc_resolve_path_stat(const char *filepath, char *path_buffer, struct stat *pbuf TSRMLS_DC) /* {{{ */ { - return xc_resolve_path(filepath, path_buffer, xc_stat_file, (void *) pbuf TSRMLS_CC) - ? SUCCESS - : FAILURE; + return xc_resolve_path(filepath, path_buffer, xc_resolve_path_stat_checker, (void *) pbuf TSRMLS_CC); } /* }}} */ #endif @@ -1050,39 +1074,37 @@ typedef struct xc_compiler_t { /* {{{ */ xc_entry_data_php_t new_php; } xc_compiler_t; /* }}} */ -typedef struct xc_entry_resolve_path_data_t { /* {{{ */ +typedef struct xc_resolve_path_entry_checker_t { /* {{{ */ xc_compiler_t *compiler; xc_entry_php_t **stored_entry; -} xc_entry_resolve_path_data_t; +} xc_resolve_path_entry_checker_data_t; /* }}} */ -static XC_RESOLVE_PATH_CHECKER(xc_entry_resolve_path_func_unlocked) /* {{{ */ +static XC_RESOLVE_PATH_CHECKER(xc_resolve_path_entry_checker) /* {{{ */ { - xc_entry_resolve_path_data_t *entry_resolve_path_data = (xc_entry_resolve_path_data_t *) data; - xc_compiler_t *compiler = entry_resolve_path_data->compiler; + xc_resolve_path_entry_checker_data_t *entry_checker_data = (xc_resolve_path_entry_checker_data_t *) data; + xc_compiler_t *compiler = entry_checker_data->compiler; compiler->new_entry.entry.name.str.val = xc_expand_url(filepath, compiler->opened_path_buffer TSRMLS_CC); compiler->new_entry.entry.name.str.len = strlen(compiler->new_entry.entry.name.str.val); - *entry_resolve_path_data->stored_entry = (xc_entry_php_t *) xc_entry_find_unlocked( + *entry_checker_data->stored_entry = (xc_entry_php_t *) xc_entry_find_unlocked( XC_TYPE_PHP , &xc_php_caches[compiler->entry_hash.cacheid] , compiler->entry_hash.entryslotid , (xc_entry_t *) &compiler->new_entry TSRMLS_CC); - return *entry_resolve_path_data->stored_entry ? 1 : 0; + return *entry_checker_data->stored_entry ? SUCCESS : FAILURE; } /* }}} */ -static int xc_entry_resolve_path_unlocked(xc_compiler_t *compiler, const char *filepath, xc_entry_php_t **stored_entry TSRMLS_DC) /* {{{ */ +static int xc_resolve_path_check_entry_unlocked(xc_compiler_t *compiler, const char *filepath, xc_entry_php_t **stored_entry TSRMLS_DC) /* {{{ */ { char path_buffer[MAXPATHLEN]; - xc_entry_resolve_path_data_t entry_resolve_path_data; - entry_resolve_path_data.compiler = compiler; - entry_resolve_path_data.stored_entry = stored_entry; + xc_resolve_path_entry_checker_data_t entry_checker_data; + entry_checker_data.compiler = compiler; + entry_checker_data.stored_entry = stored_entry; - return xc_resolve_path(filepath, path_buffer, xc_entry_resolve_path_func_unlocked, (void *) &entry_resolve_path_data TSRMLS_CC) - ? SUCCESS - : FAILURE; + return xc_resolve_path(filepath, path_buffer, xc_resolve_path_entry_checker, (void *) &entry_checker_data TSRMLS_CC); } /* }}} */ static int xc_entry_php_quick_resolve_opened_path(xc_compiler_t *compiler, struct stat *statbuf TSRMLS_DC) /* {{{ */ @@ -1103,8 +1125,8 @@ static int xc_entry_php_quick_resolve_opened_path(xc_compiler_t *compiler, struc giveupsapistat: /* absolute path */ - if (IS_ABSOLUTE_PATH(compiler->filename, strlen(compiler->filename))) { - if (statbuf && VCWD_STAT(compiler->filename, statbuf) != 0) { + if (xc_is_absolute(compiler->filename, strlen(compiler->filename))) { + if (statbuf && xc_stat(compiler->filename, statbuf TSRMLS_CC) != SUCCESS) { return FAILURE; } compiler->opened_path = xc_expand_url(compiler->filename, compiler->opened_path_buffer TSRMLS_CC); @@ -1146,7 +1168,7 @@ static int xc_entry_php_resolve_opened_path(xc_compiler_t *compiler, struct stat strcpy(compiler->opened_path_buffer, opened_path); efree(opened_path); compiler->opened_path = compiler->opened_path_buffer; - if (!statbuf || VCWD_STAT(compiler->opened_path, statbuf) == 0) { + if (!statbuf || xc_stat(compiler->opened_path, statbuf TSRMLS_CC) == SUCCESS) { return SUCCESS; } } @@ -1168,7 +1190,7 @@ static int xc_entry_php_init_key(xc_compiler_t *compiler TSRMLS_DC) /* {{{ */ time_t delta; if (compiler->opened_path) { - if (VCWD_STAT(compiler->opened_path, &buf) != 0) { + if (xc_stat(compiler->opened_path, &buf TSRMLS_CC) != SUCCESS) { return FAILURE; } } @@ -2074,7 +2096,7 @@ static zend_op_array *xc_compile_file_cached(xc_compiler_t *compiler, zend_file_ stored_php = NULL; ENTER_LOCK_EX(cache) { - if (!compiler->opened_path && xc_entry_resolve_path_unlocked(compiler, compiler->filename, &stored_entry TSRMLS_CC) == SUCCESS) { + if (!compiler->opened_path && xc_resolve_path_check_entry_unlocked(compiler, compiler->filename, &stored_entry TSRMLS_CC) == SUCCESS) { compiler->opened_path = compiler->new_entry.entry.name.str.val; } else { @@ -2177,14 +2199,8 @@ static zend_op_array *xc_compile_file(zend_file_handle *h, int type TSRMLS_DC) / if (!XG(cacher) || !h->filename || !SG(request_info).path_translated - || strstr(h->filename, "://") != NULL -#ifdef ZEND_ENGINE_2_3 - /* supported by php_resolve_path */ - || (!XG(stat) && strstr(PG(include_path), "://") != NULL) -#else - || strstr(PG(include_path), "://") != NULL -#endif - ) { + + ) { TRACE("%s", "cacher not enabled"); return old_compile_file(h, type TSRMLS_CC); }