diff options
author | Greg Beaver <cellog@php.net> | 2007-12-22 07:46:53 +0000 |
---|---|---|
committer | Greg Beaver <cellog@php.net> | 2007-12-22 07:46:53 +0000 |
commit | 8e4cc4b3dd81b184da2229782cd65547a674956f (patch) | |
tree | 68b75095b7693ce472a73c27ee1c0a7ff274251c | |
parent | 2bbd4be65ef988f1c548dc95df5c1b077834bdb3 (diff) | |
download | php-git-8e4cc4b3dd81b184da2229782cd65547a674956f.tar.gz |
first attempt at major new feature: default front controller for web
Currently, an entire phar entry is leaked for no obvious reason, otherwise it works. Sample code:
The phar has to be created using Phar->useFrontController(); and the stub performs actual resolution of which file to load:
<?php
Phar::mapPhar();
include 'phar://' . __FILE__ . '/' . substr($_SERVER['REQUEST_URI'], strlen(basename(__FILE__)));
__HALT_COMPILER();
?>
Phar automatically determines mime type from the file extension and either parses or displays the file. Modification of REQUEST_URI
and other variables should happen in the stub
[DOC]
-rw-r--r-- | ext/phar/phar.c | 236 | ||||
-rwxr-xr-x | ext/phar/phar_internal.h | 27 | ||||
-rwxr-xr-x | ext/phar/phar_object.c | 26 | ||||
-rw-r--r-- | ext/phar/tests/001.phpt | 2 | ||||
-rwxr-xr-x | ext/phar/tests/create_path_error.phpt | 10 | ||||
-rwxr-xr-x | ext/phar/tests/phar_test.inc | 2 |
6 files changed, 280 insertions, 23 deletions
diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 44baaef34c..1f8dd4d162 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -185,6 +185,11 @@ PHP_INI_END() */ static void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC) /* {{{ */ { + if (!PHAR_G(request_ends)) { + if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_web_map))) { + zend_hash_del(&(PHAR_GLOBALS->phar_web_map), data->fname, data->fname_len); + } + } if (data->alias && data->alias != data->fname) { efree(data->alias); data->alias = NULL; @@ -390,6 +395,12 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in *error = NULL; } + if (!path_len && !dir) { + if (error) { + spprintf(error, 0, "phar error: invalid path \"%s\" must not be empty", path); + } + return NULL; + } if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) { if (error) { spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error); @@ -414,6 +425,9 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in uint keylen; ulong unused; + if (!path_len) { + path = "/"; + } manifest = &phar->manifest; zend_hash_internal_pointer_reset(manifest); while (FAILURE != zend_hash_has_more_elements(manifest)) { @@ -515,6 +529,12 @@ static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) { return FAILURE; } + if (!path_len) { + if (error) { + spprintf(error, 0, "phar error: file \"\" cannot be empty"); + } + return FAILURE; + } if ((entry = phar_get_entry_info(phar, path, path_len, for_create && !PHAR_G(readonly) ? NULL : error TSRMLS_CC)) == NULL) { if (for_create && !PHAR_G(readonly)) { return SUCCESS; @@ -1314,6 +1334,13 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int mydata->sig_len = sig_len; mydata->signature = signature; phar_request_initialize(TSRMLS_C); + if ((manifest_flags & PHAR_HDR_WEB) != 0) { + mydata->is_web = 1; + if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_mimes))) { + phar_init_mime_list(TSRMLS_C); + } + zend_hash_add(&(PHAR_GLOBALS->phar_web_map), mydata->fname, fname_len, (void*)&mydata, sizeof(void*), NULL); + } zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL); if (register_alias) { mydata->is_explicit_alias = 1; @@ -1564,9 +1591,12 @@ int phar_detect_phar_fname_ext(const char *filename, int check_length, char **ex static int php_check_dots(const char *element, int n) { - while (n-- > 0) if (element[n] != '.') break; - - return (n != -1); + for(n--; n >= 0; --n) { + if (element[n] != '.') { + return 1; + } + } + return 0; } #define IS_DIRECTORY_UP(element, len) \ @@ -1631,7 +1661,7 @@ static char *phar_fix_filepath(char *path, int *new_len) /* {{{ */ efree(free_path); - if (path[path_length-1] == '/') { + if (path[path_length-1] == '/' && new_phar_len > 1) { new_phar = (char*)erealloc(new_phar, new_phar_len + 2); new_phar[new_phar_len++] = '/'; new_phar[new_phar_len] = 0; @@ -1694,7 +1724,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); } else { *entry_len = 1; *entry = estrndup("/", 1); @@ -2264,7 +2294,7 @@ static size_t phar_stream_read(php_stream *stream, char *buf, size_t count TSRML /* use our proxy position */ php_stream_seek(data->fp, data->position + data->zero, SEEK_SET); - + if (!data->zero) { got = php_stream_read(data->fp, buf, count); if (data->fp->eof) { @@ -2750,8 +2780,13 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err manifest_len = offset + archive->alias_len + sizeof(manifest) + main_metadata_str.len; phar_set_32(manifest, manifest_len); phar_set_32(manifest+4, new_manifest_count); - *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF); - *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION) & 0xF0)); + if (archive->is_web) { + *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION_NOWEB) >> 8) & 0xFF); + *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION_NOWEB) & 0xF0)); + } else { + *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF); + *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION) & 0xF0)); + } phar_set_32(manifest+10, global_flags); phar_set_32(manifest+14, archive->alias_len); @@ -3831,12 +3866,166 @@ static void php_phar_init_globals_module(zend_phar_globals *phar_globals) phar_globals->readonly = 1; } /* }}} */ + +static void phar_init_mime_list(TSRMLS_D) +{ + phar_mime_type mime; +#define PHAR_SET_MIME(mimetype, ret, ...) \ + mime.mime = mimetype; \ + mime.len = sizeof((mimetype))+1; \ + mime.type = ret; \ + { \ + char mimes[][5] = {__VA_ARGS__, "\0"}; \ + int i = 0; \ + for (; mimes[i][0]; i++) { \ + zend_hash_add(&(PHAR_GLOBALS->phar_mimes), mimes[i], strlen(mimes[i]), (void *)&mime, sizeof(phar_mime_type), NULL); \ + } \ + } + + PHAR_SET_MIME("text/html", PHAR_MIME_PHPS, "phps") + PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "c", "cc", "cpp", "c++", "dtd", "h", "log", "rng", "txt", "xsd") + PHAR_SET_MIME("", PHAR_MIME_PHP, "php", "inc") + PHAR_SET_MIME("video/avi", PHAR_MIME_OTHER, "avi") + PHAR_SET_MIME("image/bmp", PHAR_MIME_OTHER, "bmp") + PHAR_SET_MIME("text/css", PHAR_MIME_OTHER, "css") + PHAR_SET_MIME("image/gif", PHAR_MIME_OTHER, "gif") + PHAR_SET_MIME("text/html", PHAR_MIME_OTHER, "htm", "html", "htmls") + PHAR_SET_MIME("image/x-ico", PHAR_MIME_OTHER, "ico") + PHAR_SET_MIME("image/jpeg", PHAR_MIME_OTHER, "jpe", "jpg", "jpeg") + PHAR_SET_MIME("application/x-javascript", PHAR_MIME_OTHER, "js") + PHAR_SET_MIME("audio/midi", PHAR_MIME_OTHER, "mid", "midi") + PHAR_SET_MIME("audio/mod", PHAR_MIME_OTHER, "mod") + PHAR_SET_MIME("movie/quicktime", PHAR_MIME_OTHER, "mov") + PHAR_SET_MIME("audio/mp3", PHAR_MIME_OTHER, "mp3") + PHAR_SET_MIME("video/mpeg", PHAR_MIME_OTHER, "mpg", "mpeg") + PHAR_SET_MIME("application/pdf", PHAR_MIME_OTHER, "pdf") + PHAR_SET_MIME("image/png", PHAR_MIME_OTHER, "png") + PHAR_SET_MIME("application/shockwave-flash", PHAR_MIME_OTHER, "swf") + PHAR_SET_MIME("image/tiff", PHAR_MIME_OTHER, "tif", "tiff") + PHAR_SET_MIME("audio/wav", PHAR_MIME_OTHER, "wav") + PHAR_SET_MIME("image/xbm", PHAR_MIME_OTHER, "xbm") + PHAR_SET_MIME("text/xml", PHAR_MIME_OTHER, "xml") +} + +static int phar_file_type(char *file, char **mime_type TSRMLS_DC) +{ + char *ext; + phar_mime_type *mime; + if (!mime_type) { + /* assume PHP */ + return 0; + } + ext = strrchr(file, '.'); + if (!ext) { + *mime_type = "text/plain"; + /* no file extension = assume text/plain */ + return PHAR_MIME_OTHER; + } + ext++; + if (SUCCESS != zend_hash_find(&(PHAR_GLOBALS->phar_mimes), ext, strlen(ext), (void **) &mime)) { + *mime_type = "application/octet-stream"; + return PHAR_MIME_OTHER; + } + *mime_type = mime->mime; + return mime->type; +} +/* }}} */ + +static zend_op_array *phar_file_action(char *entry, int entry_len, char *arch, int arch_len, char **ourname TSRMLS_DC) +{ + char *mime_type, *name = NULL, buf[8192], *error; + zend_syntax_highlighter_ini syntax_highlighter_ini; + sapi_header_line ctr = {0}; + zend_op_array *nada; + zend_op *opline; + phar_entry_data *phar; + size_t got; + + *ourname = name; + +#define PHAR_NOP() \ + nada = (zend_op_array *) emalloc(sizeof(zend_op_array)); \ + init_op_array(nada, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); \ + opline = get_next_op(nada TSRMLS_CC); \ + opline->opcode = ZEND_RETURN; \ + opline->op1.op_type = IS_CONST; \ + INIT_ZVAL(opline->op1.u.constant); \ + SET_UNUSED(opline->op2); \ + ZEND_VM_SET_OPCODE_HANDLER(opline); \ + nada->done_pass_two = 1; \ + return nada; + + switch (phar_file_type(entry, &mime_type TSRMLS_CC)) { + case PHAR_MIME_PHPS: + /* highlight source */ + spprintf(&name, 4096, "phar://%s/%s", arch, entry); + efree(arch); + php_get_highlight_struct(&syntax_highlighter_ini); + + if (highlight_file(name, &syntax_highlighter_ini TSRMLS_CC) == FAILURE) { + } + + PHAR_NOP(); + case PHAR_MIME_OTHER: + /* send headers, output file contents */ + if (FAILURE == phar_get_entry_data(&phar, arch, arch_len, entry, entry_len, "r", &error TSRMLS_CC)) { + ctr.response_code = 404; + ctr.line_len = sizeof("HTTP/1.0 404")+1; + ctr.line = "HTTP/1.0 404"; + sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); + + PHAR_NOP(); + } + ctr.line_len = spprintf(&(ctr.line), 0, "Content-type: %s", mime_type); + sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); + efree(ctr.line); + ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %d", phar->internal_file->uncompressed_filesize); + sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); + efree(ctr.line); + if (FAILURE == sapi_send_headers(TSRMLS_C)) { + phar_entry_delref(phar TSRMLS_CC); + zend_bailout(); + } + + /* prepare to output */ + if (!phar->fp) { + phar->internal_file->fp_refcount++; + phar->fp = phar->phar->fp; + phar->zero = phar->phar->internal_file_start + phar->internal_file->offset_within_phar; + } + php_stream_seek(phar->fp, phar->position + phar->zero, SEEK_SET); + do { + if (!phar->zero) { + got = php_stream_read(phar->fp, buf, 8192); + PHPWRITE(buf, got); + if (phar->fp->eof) { + break; + } + } else { + got = php_stream_read(phar->fp, buf, MIN(8192, phar->internal_file->uncompressed_filesize - phar->position)); + PHPWRITE(buf, got); + phar->position = php_stream_tell(phar->fp) - phar->zero; + if (phar->position == (off_t) phar->internal_file->uncompressed_filesize) { + break; + } + } + } while (1); + + phar_entry_delref(phar TSRMLS_CC); + PHAR_NOP(); + case PHAR_MIME_PHP: + /* fall through */ + break; + } + return NULL; +} + static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) /* {{{ */ { zend_op_array *res; char *s, *name = NULL; char *fname = NULL; - int fname_len; + int fname_len, failed; zend_op_array *(*save)(zend_file_handle *file_handle, int type TSRMLS_DC); save = zend_compile_file; /* restore current handler or we cause trouble */ @@ -3845,12 +4034,25 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type char *arch, *entry; int arch_len, entry_len; fname = zend_get_executed_filename(TSRMLS_C); + fname_len = strlen(fname); + /* check for web front controller phars */ + if (zend_hash_exists(&(PHAR_GLOBALS->phar_web_map), fname, fname_len)) { + zend_op_array *retval; + if (strncasecmp(file_handle->filename, "phar://", 7)) { + goto skip_phar; + } + fname_len = strlen(file_handle->filename); + if (SUCCESS == phar_split_fname(file_handle->filename, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + if ((retval = phar_file_action(entry, entry_len, arch, arch_len, &name TSRMLS_CC))) { + return retval; + } + } + } 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)) { - efree(entry); entry = file_handle->filename; /* include within phar, if :// is not in the url, then prepend phar://<archive>/ */ @@ -3870,11 +4072,19 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type } } skip_phar: - res = zend_compile_file(file_handle, type TSRMLS_CC); + 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; } /* }}} */ @@ -3969,6 +4179,8 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */ PHAR_GLOBALS->request_done = 0; zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data, 0); zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 0); + zend_hash_init(&(PHAR_GLOBALS->phar_web_map), sizeof(void *), zend_get_hash_value, NULL, 0); + zend_hash_init(&(PHAR_GLOBALS->phar_mimes), sizeof(phar_mime_type *), zend_get_hash_value, NULL, 0); zend_hash_init(&(PHAR_GLOBALS->phar_plain_map), sizeof(const char *), zend_get_hash_value, NULL, 0); phar_split_extract_list(TSRMLS_C); if (SUCCESS == zend_hash_find(CG(function_table), "fopen", 6, (void **)&orig)) { @@ -3990,6 +4202,8 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */ } zend_hash_destroy(&(PHAR_GLOBALS->phar_alias_map)); zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map)); + zend_hash_destroy(&(PHAR_GLOBALS->phar_web_map)); + zend_hash_destroy(&(PHAR_GLOBALS->phar_mimes)); zend_hash_destroy(&(PHAR_GLOBALS->phar_plain_map)); PHAR_GLOBALS->request_init = 0; } diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 0682cc2d82..fe6bfcc74f 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -33,6 +33,7 @@ #include "zend_interfaces.h" #include "zend_operators.h" #include "zend_qsort.h" +#include "zend_vm.h" #include "main/php_streams.h" #include "main/streams/php_stream_plain_wrapper.h" #include "ext/standard/info.h" @@ -69,9 +70,11 @@ #endif #define PHAR_EXT_VERSION_STR "1.3.0" -#define PHAR_API_VERSION_STR "1.1.0" +#define PHAR_API_VERSION_STR "1.2.0" /* x.y.z maps to 0xyz0 */ -#define PHAR_API_VERSION 0x1100 +#define PHAR_API_VERSION 0x1200 +/* API version to use for is_web=0 in phar creation */ +#define PHAR_API_VERSION_NOWEB 0x1100 #define PHAR_API_MIN_READ 0x1000 #define PHAR_API_MAJORVERSION 0x1000 #define PHAR_API_MAJORVER_MASK 0xF000 @@ -82,6 +85,7 @@ #define PHAR_HDR_COMPRESSED_GZ 0x00001000 #define PHAR_HDR_COMPRESSED_BZ2 0x00002000 #define PHAR_HDR_SIGNATURE 0x00010000 +#define PHAR_HDR_WEB 0x00020000 #define PHAR_SIG_MD5 0x0001 #define PHAR_SIG_SHA1 0x0002 @@ -109,6 +113,10 @@ ZEND_BEGIN_MODULE_GLOBALS(phar) HashTable phar_fname_map; HashTable phar_alias_map; HashTable phar_plain_map; + /* phar archives that have is_web = 1, used for fast lookup in phar_compile_file */ + HashTable phar_web_map; + /* mapping of file extension to MIME type */ + HashTable phar_mimes; char* extract_list; int readonly; zend_bool readonly_orig; @@ -202,8 +210,20 @@ struct _phar_archive_data { int is_brandnew:1; /* defer phar creation */ int donotflush:1; + /* this phar is intended to use a web front controller with non-CLI SAPI */ + int is_web:1; }; +#define PHAR_MIME_PHP '\0' +#define PHAR_MIME_PHPS '\1' +#define PHAR_MIME_OTHER '\2' + +typedef struct _phar_mime_type { + char *mime; + int len; + /* one of PHAR_MIME_* */ + char type; +} phar_mime_type; /* stream access data for one file entry in a phar file */ typedef struct _phar_entry_data { @@ -251,10 +271,9 @@ int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, i int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC); int phar_open_compiled_file(char *alias, int alias_len, char **error TSRMLS_DC); -static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS); -static void phar_getcwd(INTERNAL_FUNCTION_PARAMETERS); #ifdef PHAR_MAIN +static void phar_init_mime_list(TSRMLS_D); static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS); static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index e7dfcb0fbf..96b9e68f8c 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -342,6 +342,31 @@ PHP_METHOD(Phar, getSupportedCompression) return; \ } +/* {{{ proto void Phar::useWebFrontController() + * This method is used in Phar creation to specify that this phar + * is intended to be executed as a self-contained website, and the + * built-in fast front controller should be used. + */ +PHP_METHOD(Phar, useWebFrontController) +{ + char *error; + PHAR_ARCHIVE_OBJECT(); + + if (PHAR_G(readonly)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, + "Cannot specify use of default front controller, phar is read-only"); + return; + } + + phar_obj->arc.archive->is_web = 1; + phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + if (error) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); + efree(error); + } +} +/* }}} */ + static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) { zval **value; @@ -1982,6 +2007,7 @@ zend_function_entry php_archive_methods[] = { PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC) PHP_ME(Phar, uncompressAllFiles, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC) + PHP_ME(Phar, useWebFrontController, NULL, ZEND_ACC_PUBLIC) #endif /* static member functions */ PHP_ME(Phar, apiVersion, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) diff --git a/ext/phar/tests/001.phpt b/ext/phar/tests/001.phpt index 397501e8e4..26c225deb0 100644 --- a/ext/phar/tests/001.phpt +++ b/ext/phar/tests/001.phpt @@ -8,5 +8,5 @@ var_dump(Phar::apiVersion()); ?> ===DONE=== --EXPECT-- -string(5) "1.1.0" +string(5) "1.2.0" ===DONE=== diff --git a/ext/phar/tests/create_path_error.phpt b/ext/phar/tests/create_path_error.phpt index eb2dbe43ca..cdb5b5f6da 100755 --- a/ext/phar/tests/create_path_error.phpt +++ b/ext/phar/tests/create_path_error.phpt @@ -54,11 +54,9 @@ foreach($checks as $check) --EXPECTF-- string(5) "query" string(5) "query" -Error: file_put_contents(phar://%s//): failed to open stream: phar error: invalid path "/" contains empty directory -Error: file_put_contents(phar://%s/.): failed to open stream: phar error: invalid path "." contains current directory reference -Error: file_put_contents(phar://%s/../): failed to open stream: phar error: invalid path "../" contains empty directory -Error: file_put_contents(phar://%s/a/..): failed to open stream: phar error: invalid path "a/.." contains upper directory reference -Error: file_put_contents(phar://%s/a/): failed to open stream: phar error: invalid path "a/" contains empty directory -Error: file_put_contents(phar://%s/b//a.php): failed to open stream: phar error: invalid path "b//a.php" contains double slash +Error: file_put_contents(phar://%s//): failed to open stream: phar error: file "" cannot be empty +Error: file_put_contents(phar://%s/.): failed to open stream: phar error: file "" cannot be empty +Error: file_put_contents(phar://%s/../): failed to open stream: phar error: file "" cannot be empty +Error: file_put_contents(phar://%s/a/..): failed to open stream: phar error: file "" cannot be empty Exception: Entry a does not exist and cannot be created: phar error: invalid path "a" contains illegal character ===DONE=== diff --git a/ext/phar/tests/phar_test.inc b/ext/phar/tests/phar_test.inc index 213e95558c..af5d227f66 100755 --- a/ext/phar/tests/phar_test.inc +++ b/ext/phar/tests/phar_test.inc @@ -51,7 +51,7 @@ foreach($files as $name => $cont) $alias = 'hio'; if (isset($pmeta)) $pmeta = serialize($pmeta); else $pmeta = ''; -$manifest = pack('VnVV', count($files), 0x1000, $glags, strlen($alias)) . $alias . pack('V', strlen($pmeta)) . $pmeta . $manifest; +$manifest = pack('VnVV', count($files), 0x1000, $gflags, strlen($alias)) . $alias . pack('V', strlen($pmeta)) . $pmeta . $manifest; $file .= pack('V', strlen($manifest)) . $manifest; foreach($files as $cont) |