diff options
| author | Greg Beaver <cellog@php.net> | 2008-03-20 23:59:07 +0000 |
|---|---|---|
| committer | Greg Beaver <cellog@php.net> | 2008-03-20 23:59:07 +0000 |
| commit | d02dff1363a3e9030f2ac78541ab3642574e07a5 (patch) | |
| tree | 929c5fc3dddaab699407d79fe6ad9d12cfb1d15d /ext/phar/util.c | |
| parent | b986dfaaaea377d607c9f33326da917c9c5984d7 (diff) | |
| download | php-git-d02dff1363a3e9030f2ac78541ab3642574e07a5.tar.gz | |
save work - sandbox is completely f**ed up, have to rm -rf and start again
This *SHOULD* fix issues, but I can't get run-tests to work reliably to be absolutely sure
Diffstat (limited to 'ext/phar/util.c')
| -rw-r--r-- | ext/phar/util.c | 316 |
1 files changed, 231 insertions, 85 deletions
diff --git a/ext/phar/util.c b/ext/phar/util.c index f965c03317..6f38a17c8a 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -241,115 +241,261 @@ int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, return FAILURE; } -char *phar_find_in_include_path(char *file, phar_archive_data **pphar TSRMLS_DC) /* {{{ */ +char *phar_find_in_include_path(char *filename, int filename_len, phar_archive_data **pphar TSRMLS_DC) /* {{{ */ { - char *path = PG(include_path), *pathbuf, *ptr, *end; - char *trypath; - phar_archive_data *blank = NULL, *self; +#if PHP_VERSION_ID >= 50300 + char *path, *fname, *arch, *entry, *ret, *test; + int arch_len, entry_len; - if (!pphar) { - pphar = ␣ - self = NULL; - } else { - self = *pphar; + if (pphar) { + *pphar = NULL; + } + + if (!zend_is_executing(TSRMLS_C) || !PHAR_G(cwd)) { + return phar_save_resolve_path(filename, filename_len TSRMLS_CC); } - if (!path || (path && !*path)) { - return file; + fname = zend_get_executed_filename(TSRMLS_C); + if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + return phar_save_resolve_path(filename, filename_len TSRMLS_CC); } + if (*filename == '.') { + int try_len; - /* check in provided path */ - /* append the calling scripts' current working directory - * as a fall back case - */ - spprintf(&pathbuf, 0, "%s%c.", path, DEFAULT_DIR_SEPARATOR); + if (SUCCESS != (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + efree(arch); + efree(entry); + return phar_save_resolve_path(filename, filename_len TSRMLS_CC); + } + efree(entry); + test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC); + if (zend_hash_exists(&((*pphar)->manifest), test + 1, try_len - 1)) { + spprintf(&ret, 0, "phar://%s%s", arch, test); + efree(arch); + efree(test); + return ret; + } + } + efree(entry); + spprintf(&path, MAXPATHLEN, "phar://%s/%s%c%s", arch, PHAR_G(cwd), DEFAULT_DIR_SEPARATOR, PG(include_path)); + efree(arch); + ret = php_resolve_path(filename, filename_len, path TSRMLS_CC); + efree(path); + if (ret && strlen(ret) > 8 && !strncmp(ret, "phar://", 7)) { + char *arch, *entry; + int arch_len, entry_len, ret_len; - ptr = pathbuf; + ret_len = strlen(ret); + /* found phar:// */ - while (ptr && *ptr) { + if (SUCCESS != phar_split_fname(ret, ret_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + return ret; + } + zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar); + efree(arch); + efree(entry); + } + return ret; +#else /* PHP 5.2 */ + char resolved_path[MAXPATHLEN]; + char trypath[MAXPATHLEN]; + char *ptr, *end, *path = PG(include_path); + php_stream_wrapper *wrapper; + const char *p; + int n = 0; + char *fname, *arch, *entry, *ret, *test; + int arch_len, entry_len; + + if (!filename) { + return NULL; + } + + if (!zend_is_executing(TSRMLS_C) || !PHAR_G(cwd)) { + goto doit; + } + fname = zend_get_executed_filename(TSRMLS_C); + if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + goto doit; + } + + if (*filename == '.') { + phar_archive_data **pphar; int try_len; - char *test; + + if (SUCCESS != (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + efree(arch); + efree(entry); + goto doit; + } + efree(entry); + test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC); + if (zend_hash_exists(&((*pphar)->manifest), test + 1, try_len - 1)) { + spprintf(&ret, 0, "phar://%s%s", arch, test); + efree(arch); + efree(test); + return ret; + } + efree(test); + } + efree(arch); + efree(entry); + +doit: + if (*filename == '.' || + IS_ABSOLUTE_PATH(filename, filename_len) || + !path || + !*path) { + if (tsrm_realpath(filename, resolved_path TSRMLS_CC)) { + return estrdup(resolved_path); + } else { + return NULL; + } + } + /* test for stream wrappers and return */ + for (p = filename; p - filename < filename_len && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); p++) { + n++; + } + + if (n < filename_len - 3 && (*p == ':') && (!strncmp("//", p+1, 2) || ( filename_len > 4 && !memcmp("data", filename, 4)))) { + /* found stream wrapper, this is an absolute path until stream wrappers implement realpath */ + return estrndup(filename, filename_len); + } + + ptr = (char *) path; + while (ptr && *ptr) { + int len, is_stream_wrapper = 0, maybe_stream = 1; end = strchr(ptr, DEFAULT_DIR_SEPARATOR); - /* check for phar:// */ - if (end - ptr == 4 && !strncmp(ptr, "phar", 4)) { - char *arch, *entry; - int arch_len, entry_len; +#ifndef PHP_WIN32 + /* search for stream wrapper */ + if (end - ptr <= 1) { + maybe_stream = 0; + goto not_stream; + } + for (p = ptr, n = 0; p < end && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); p++) { + n++; + } - /* found phar:// */ + if (n == end - ptr && *p && !strncmp("//", p+1, 2)) { + is_stream_wrapper = 1; + /* seek to real end of include_path portion */ end = strchr(end + 1, DEFAULT_DIR_SEPARATOR); - if (end != NULL) { - *end = '\0'; - end++; - } - - if (SUCCESS != phar_split_fname(ptr, end - ptr, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + } else { + maybe_stream = 0; + } +not_stream: +#endif + if (end) { + if ((end-ptr) + 1 + filename_len + 1 >= MAXPATHLEN) { + ptr = end + 1; continue; } - if (SUCCESS != (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { - efree(arch); - efree(entry); - continue; + memcpy(trypath, ptr, end-ptr); + len = end-ptr; + trypath[end-ptr] = '/'; + memcpy(trypath+(end-ptr)+1, filename, filename_len+1); + ptr = end+1; + } else { + len = strlen(ptr); + + if (len + 1 + filename_len + 1 >= MAXPATHLEN) { + break; } - try_len = spprintf(&trypath, MAXPATHLEN, "%s/%s", entry, file); - efree(entry); - test = phar_fix_filepath(trypath, &try_len, 0 TSRMLS_CC); - if (zend_hash_exists(&((*pphar)->manifest), test + 1, try_len - 1)) { - efree(pathbuf); - spprintf(&trypath, 0, "phar://%s%s", arch, test); - efree(arch); - efree(test); - return trypath; + memcpy(trypath, ptr, len); + trypath[len] = '/'; + memcpy(trypath+len+1, filename, filename_len+1); + ptr = NULL; + } + + if (!is_stream_wrapper && maybe_stream) { + /* search for stream wrapper */ + for (p = trypath, n = 0; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + n++; } - if (zend_hash_num_elements(&((*pphar)->mounted_dirs))) { - if (phar_get_entry_info_dir(*pphar, test + 1, try_len - 1, 0, NULL TSRMLS_CC)) { - spprintf(&trypath, 0, "phar://%s%s", arch, test); - efree(arch); - efree(test); - return trypath; + } + + if (is_stream_wrapper || (n < len - 3 && (*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4)))) { + char *actual; + + wrapper = php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); + if (wrapper == &php_plain_files_wrapper) { + strncpy(trypath, actual, MAXPATHLEN); + } else if (!wrapper) { + /* if wrapper is NULL, there was a mal-formed include_path stream wrapper, so skip this ptr */ + continue; + } else { + if (wrapper->wops->url_stat) { + php_stream_statbuf ssb; + + if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL TSRMLS_CC)) { + if (wrapper == &php_stream_phar_wrapper) { + char *arch, *entry; + int arch_len, entry_len, ret_len; + + ret_len = strlen(trypath); + /* found phar:// */ + + if (SUCCESS != phar_split_fname(trypath, ret_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + return estrndup(trypath, ret_len); + } + zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar); + efree(arch); + efree(entry); + return estrndup(trypath, ret_len); + } + return estrdup(trypath); + } } + continue; } - efree(test); - *pphar = self; - ptr = end; - continue; - } - if (end != NULL) { - *end = '\0'; - end++; - } - if (*ptr == '\0') { - goto stream_skip; } - if (!*pphar || ptr[0] != '.') { - ptr = end; - continue; - } - /* relative path in include_path starting with ".", look inside current phar, if any */ - try_len = spprintf(&trypath, MAXPATHLEN, "%s/%s", ptr, file); - test = phar_fix_filepath(trypath, &try_len, 1 TSRMLS_CC); - if (zend_hash_exists(&((*pphar)->manifest), test + 1, try_len - 1)) { - char *save = test; - efree(pathbuf); - test = estrndup(test + 1, try_len - 1); - efree(save); - return test; + + if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) { + return estrdup(resolved_path); } - if (zend_hash_num_elements(&((*pphar)->mounted_dirs))) { - if (phar_get_entry_info_dir(*pphar, test + 1, try_len - 1, 0, NULL TSRMLS_CC)) { - char *save = test; - efree(pathbuf); - test = estrndup(test + 1, try_len - 1); - efree(save); - return test; + } /* end provided path */ + + /* check in calling scripts' current working directory as a fall back case + */ + if (zend_is_executing(TSRMLS_C)) { + char *exec_fname = zend_get_executed_filename(TSRMLS_C); + int exec_fname_length = strlen(exec_fname); + const char *p; + int n = 0; + + while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])); + if (exec_fname && exec_fname[0] != '[' && + exec_fname_length > 0 && + exec_fname_length + 1 + filename_len + 1 < MAXPATHLEN) { + memcpy(trypath, exec_fname, exec_fname_length + 1); + memcpy(trypath+exec_fname_length + 1, filename, filename_len+1); + + /* search for stream wrapper */ + for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + n++; + } + if (n < exec_fname_length - 3 && (*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4))) { + char *actual; + + wrapper = php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); + if (wrapper == &php_plain_files_wrapper) { + /* this should never technically happen, but we'll leave it here for completeness */ + strncpy(trypath, actual, MAXPATHLEN); + } else if (!wrapper) { + /* if wrapper is NULL, there was a mal-formed include_path stream wrapper + this also should be impossible */ + return NULL; + } else { + return estrdup(trypath); + } + } + if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) { + return estrdup(resolved_path); } } - efree(test); -stream_skip: - ptr = end; - } /* end provided path */ + } - efree(pathbuf); return NULL; +#endif /* PHP 5.2 */ } /* }}} */ |
