From: Greg Beaver Date: Wed, 9 Jan 2008 00:58:37 +0000 (+0000) Subject: fix empty directories in phar, add test X-Git-Tag: RELEASE_2_0_0a1~980 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9f5b3a229f34cf4d52565b5b977b9249b306782d;p=php fix empty directories in phar, add test --- diff --git a/ext/phar/Makefile.frag b/ext/phar/Makefile.frag index 3e79356fa1..d693e8dd86 100755 --- a/ext/phar/Makefile.frag +++ b/ext/phar/Makefile.frag @@ -1,6 +1,6 @@ $(srcdir)/phar_path_check.c: $(srcdir)/phar_path_check.re - $(RE2C) -b -o $(srcdir)/phar_path_check.c $(srcdir)/phar_path_check.re) + $(RE2C) -b -o $(srcdir)/phar_path_check.c $(srcdir)/phar_path_check.re pharcmd: $(builddir)/phar.php $(builddir)/phar.phar diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 74d3e7177c..d52eb7ca39 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -397,7 +397,7 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char */ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ { - phar_entry_info entry; + phar_entry_info entry, *e; phar_archive_data *phar; char *error; char *plain_map; @@ -436,8 +436,10 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in return FAILURE; } - if (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); php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", directory already exists", resource->path+1, resource->host); php_url_free(resource); return FAILURE; @@ -495,5 +497,65 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in */ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ { + phar_entry_info *entry; + phar_archive_data *phar; + char *error; + char *plain_map; + php_url *resource = NULL; + uint host_len; + + if ((resource = phar_open_url(wrapper, url, "w", options TSRMLS_CC)) == NULL) { + return FAILURE; + } + + /* we must have at the very least phar://alias.phar/internalfile.php */ + if (!resource->scheme || !resource->host || !resource->path) { + php_url_free(resource); + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url \"%s\"", url); + return FAILURE; + } + + if (strcasecmp("phar", resource->scheme)) { + php_url_free(resource); + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: not a phar stream url \"%s\"", url); + return FAILURE; + } + + host_len = strlen(resource->host); + phar_request_initialize(TSRMLS_C); + if (zend_hash_find(&(PHAR_GLOBALS->phar_plain_map), resource->host, host_len+1, (void **)&plain_map) == SUCCESS) { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: directory \"%s\" cannot be removed in phar \"%s\", phar is extracted in plain map", resource->path+1, resource->host); + php_url_free(resource); + return FAILURE; + } + + if (FAILURE == phar_get_archive(&phar, resource->host, host_len, NULL, 0, &error TSRMLS_CC)) { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s", resource->path+1, resource->host, error); + efree(error); + php_url_free(resource); + return FAILURE; + } + + if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 1, &error TSRMLS_CC))) { + if (error) { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error); + efree(error); + } else { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", directory does not exist", resource->path+1, resource->host); + } + php_url_free(resource); + return FAILURE; + } + + /* now for the easy part */ + entry->is_deleted = 1; + phar_flush(phar, 0, 0, &error TSRMLS_CC); + if (error) { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", entry->filename, phar->fname, error); + zend_hash_del(&phar->manifest, entry->filename, entry->filename_len); + efree(error); + return FAILURE; + } + return SUCCESS; } /* }}} */ diff --git a/ext/phar/dirstream.h b/ext/phar/dirstream.h index 9326d9e0ec..9528c4da27 100644 --- a/ext/phar/dirstream.h +++ b/ext/phar/dirstream.h @@ -20,7 +20,6 @@ /* $Id$ */ BEGIN_EXTERN_C() -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); int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, int options, php_stream_context *context TSRMLS_DC); int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); diff --git a/ext/phar/phar.c b/ext/phar/phar.c index f637ec861e..04b8908068 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -22,7 +22,6 @@ #define PHAR_MAIN 1 #include "phar_internal.h" #include "SAPI.h" -#include "php_stream_unlink.h" ZEND_DECLARE_MODULE_GLOBALS(phar) @@ -398,11 +397,14 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int pa /* }}} */ /** * retrieve information on a file or directory contained within a phar, or null if none found + * allow_dir is 0 for none, 1 for both empty directories in the phar and temp directories, and 2 for only + * valid pre-existing empty directory entries */ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error TSRMLS_DC) /* {{{ */ { const char *pcr_error; phar_entry_info *entry; + char is_dir = (path[path_len - 1] == '/'); if (error) { *error = NULL; @@ -424,6 +426,9 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in if (!&phar->manifest.arBuckets) { return NULL; } + if (is_dir) { + path_len--; + } if (SUCCESS == zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) { if (entry->is_deleted) { /* entry is deleted, but has not been flushed to disk yet */ @@ -435,9 +440,16 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in } return NULL; } + if (!entry->is_dir && is_dir) { + /* user requested a directory, we must return one */ + if (error) { + spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path); + } + return NULL; + } return entry; } - if (dir) { + if (dir == 1) { /* try to find a directory */ HashTable *manifest; char *key; @@ -525,7 +537,7 @@ static int phar_open_entry_file(phar_archive_data *phar, phar_entry_info *entry, * appended, truncated, or read. For read, if the entry is marked unmodified, it is * assumed that the file pointer, if present, is opened for reading */ -int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */ +int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry; @@ -556,11 +568,20 @@ int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char } 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; + if (allow_dir) { + if ((entry = phar_get_entry_info_dir(phar, path, path_len, 2, for_create && !PHAR_G(readonly) ? NULL : error TSRMLS_CC)) == NULL) { + if (for_create && !PHAR_G(readonly)) { + return SUCCESS; + } + return FAILURE; + } + } else { + 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; + } + return FAILURE; } - return FAILURE; } if (entry->is_modified && !for_write) { if (error) { @@ -588,6 +609,11 @@ int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char (*ret)->internal_file = entry; (*ret)->is_zip = entry->is_zip; (*ret)->is_tar = entry->is_tar; + if (entry->is_dir) { + entry->phar->refcount++; + entry->fp_refcount++; + return SUCCESS; + } if (entry->fp) { /* make a copy */ if (for_trunc) { @@ -712,18 +738,19 @@ void phar_entry_remove(phar_entry_data *idata, char **error TSRMLS_DC) /* {{{ */ /** * Create a new dummy file slot within a writeable phar for a newly created file */ -phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */ +phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry, etemp; phar_entry_data *ret; const char *pcr_error; + char is_dir = path[path_len - 1] == '/'; if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) { return NULL; } - if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, error TSRMLS_CC)) { + if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, allow_dir, error TSRMLS_CC)) { return NULL; } else if (ret) { return ret; @@ -749,13 +776,22 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char } return NULL; } - etemp.fp_refcount = 1; + if (is_dir) { + etemp.fp_refcount = 1; + etemp.is_dir = 1; + etemp.flags = PHAR_ENT_PERM_DEF_DIR; + etemp.old_flags = PHAR_ENT_PERM_DEF_DIR; + etemp.filename_len--; /* strip trailing / */ + path_len--; + } else { + etemp.fp_refcount = 1; + etemp.flags = PHAR_ENT_PERM_DEF_FILE; + etemp.old_flags = PHAR_ENT_PERM_DEF_FILE; + } etemp.is_modified = 1; etemp.timestamp = time(0); etemp.offset_within_phar = -1; etemp.is_crc_checked = 1; - etemp.flags = PHAR_ENT_PERM_DEF_FILE; - etemp.old_flags = PHAR_ENT_PERM_DEF_FILE; etemp.phar = phar; #if HAVE_PHAR_ZIP if (phar->is_zip) { @@ -1298,7 +1334,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int entry.is_dir = 0; } entry.filename = estrndup(buffer, entry.filename_len); - buffer += entry.filename_len + entry.is_dir; + buffer += entry.filename_len + (entry.is_dir ? 1 : 0); PHAR_GET_32(buffer, entry.uncompressed_filesize); PHAR_GET_32(buffer, entry.timestamp); if (offset == 0) { diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index fe98c6061e..2b7c7b185c 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -332,8 +332,8 @@ int phar_entry_delref(phar_entry_data *idata TSRMLS_DC); phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC); phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error TSRMLS_DC); -phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC); -int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC); +phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC); +int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC); int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC); int phar_detect_phar_fname_ext(const char *filename, int check_length, char **ext_str, int *ext_len); int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index f2f7a3aa0b..3b2b7b2361 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -307,7 +307,7 @@ void phar_do_404(char *fname, int fname_len, char *f404, int f404_len, char *ent phar_entry_data *phar; char *error; if (f404_len) { - if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, f404, f404_len, "r", &error TSRMLS_CC)) { + if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, f404, f404_len, "r", 0, &error TSRMLS_CC)) { if (error) { efree(error); } @@ -412,7 +412,7 @@ PHP_METHOD(Phar, webPhar) entry = estrndup("/index.php", sizeof("/index.php")); entry_len = sizeof("/index.php")-1; } - if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, entry, entry_len, "r", &error TSRMLS_CC)) { + if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, entry, entry_len, "r", 0, &error TSRMLS_CC)) { if (error) { efree(error); } @@ -465,7 +465,7 @@ PHP_METHOD(Phar, webPhar) } } - if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, entry, entry_len, "r", &error TSRMLS_CC)) { + if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, entry, entry_len, "r", 0, &error TSRMLS_CC)) { phar_do_404(fname, fname_len, f404, f404_len, entry, entry_len TSRMLS_CC); #ifdef PHP_WIN32 efree(fname); @@ -1096,7 +1096,7 @@ phar_spl_fileinfo: } after_open_fp: - if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, str_key, str_key_len, "w+b", &error TSRMLS_CC))) { + if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, str_key, str_key_len, "w+b", 0, &error TSRMLS_CC))) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s cannot be created: %s", str_key, error); efree(error); if (save) { @@ -1871,7 +1871,7 @@ PHP_METHOD(Phar, offsetGet) return; } - if (!phar_get_entry_info_dir(phar_obj->arc.archive, fname, fname_len, 1, &error TSRMLS_CC)) { + if (!phar_get_entry_info_dir(phar_obj->arc.archive, fname, fname_len, 2, &error TSRMLS_CC)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:""); } else { fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname); @@ -1907,7 +1907,7 @@ PHP_METHOD(Phar, offsetSet) return; } - if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len, "w+b", &error TSRMLS_CC))) { + if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len, "w+b", 2, &error TSRMLS_CC))) { if (error) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created: %s", fname, error); efree(error); @@ -1918,18 +1918,20 @@ PHP_METHOD(Phar, offsetSet) if (error) { efree(error); } - if (cont_str) { - contents_len = php_stream_write(data->fp, cont_str, cont_len); - if (contents_len != cont_len) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname); - } - } else { - if (!(php_stream_from_zval_no_verify(contents_file, &zresource))) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname); + if (!data->internal_file->is_dir) { + if (cont_str) { + contents_len = php_stream_write(data->fp, cont_str, cont_len); + if (contents_len != cont_len) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname); + } + } else { + if (!(php_stream_from_zval_no_verify(contents_file, &zresource))) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname); + } + contents_len = php_stream_copy_to_stream(contents_file, data->fp, PHP_STREAM_COPY_ALL); } - contents_len = php_stream_copy_to_stream(contents_file, data->fp, PHP_STREAM_COPY_ALL); + data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len; } - data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len; phar_entry_delref(data TSRMLS_CC); phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); if (error) { diff --git a/ext/phar/phar_path_check.c b/ext/phar/phar_path_check.c index 2d436a5702..03a85b6783 100755 --- a/ext/phar/phar_path_check.c +++ b/ext/phar/phar_path_check.c @@ -1,5 +1,5 @@ -/* Generated by re2c 0.10.5 on Thu Feb 8 23:49:41 2007 */ -#line 1 "ext/phar/phar_path_check.re" +/* Generated by re2c 0.12.3 on Tue Jan 8 18:41:21 2008 */ +#line 1 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" /* +----------------------------------------------------------------------+ | phar php single-file executable PHP extension | @@ -44,7 +44,7 @@ phar_path_check_result phar_path_check(char **s, int *len, const char **error) loop: { -#line 48 "ext/phar/phar_path_check.c" +#line 48 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" { YYCTYPE yych; @@ -73,35 +73,34 @@ loop: } yy2: yych = *(YYMARKER = ++YYCURSOR); - if(yych <= 0x00) goto yy16; if(yych <= '-') goto yy3; - if(yych <= '.') goto yy18; - if(yych <= '/') goto yy20; + if(yych <= '.') goto yy16; + if(yych <= '/') goto yy18; yy3: -#line 97 "ext/phar/phar_path_check.re" +#line 93 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { goto loop; } -#line 86 "ext/phar/phar_path_check.c" +#line 85 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" yy4: ++YYCURSOR; -#line 60 "ext/phar/phar_path_check.re" +#line 60 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { *error = "back-slash"; return pcr_err_back_slash; } -#line 94 "ext/phar/phar_path_check.c" +#line 93 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" yy6: ++YYCURSOR; -#line 68 "ext/phar/phar_path_check.re" +#line 64 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { *error = "star"; return pcr_err_star; } -#line 102 "ext/phar/phar_path_check.c" +#line 101 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" yy8: ++YYCURSOR; -#line 72 "ext/phar/phar_path_check.re" +#line 68 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { if (**s == '/') { (*s)++; @@ -110,22 +109,22 @@ yy8: *error = NULL; return pcr_use_query; } -#line 114 "ext/phar/phar_path_check.c" +#line 113 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" yy10: ++YYCURSOR; yy11: -#line 80 "ext/phar/phar_path_check.re" +#line 76 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { *error ="illegal character"; return pcr_err_illegal_char; } -#line 123 "ext/phar/phar_path_check.c" +#line 122 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" yy12: yych = *++YYCURSOR; goto yy11; yy13: ++YYCURSOR; -#line 84 "ext/phar/phar_path_check.re" +#line 80 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { if (**s == '/') { (*s)++; @@ -139,58 +138,50 @@ yy13: *error = NULL; return pcr_is_ok; } -#line 143 "ext/phar/phar_path_check.c" +#line 142 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" yy15: yych = *++YYCURSOR; goto yy3; yy16: - ++YYCURSOR; -#line 64 "ext/phar/phar_path_check.re" - { - *error = "empty directory"; - return pcr_err_empty_entry; - } -#line 154 "ext/phar/phar_path_check.c" -yy18: yych = *++YYCURSOR; - if(yych <= 0x00) goto yy23; - if(yych <= '-') goto yy19; - if(yych <= '.') goto yy22; - if(yych <= '/') goto yy23; -yy19: + if(yych <= 0x00) goto yy21; + if(yych <= '-') goto yy17; + if(yych <= '.') goto yy20; + if(yych <= '/') goto yy21; +yy17: YYCURSOR = YYMARKER; goto yy3; -yy20: +yy18: ++YYCURSOR; -#line 48 "ext/phar/phar_path_check.re" +#line 48 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { *error = "double slash"; return pcr_err_double_slash; } -#line 171 "ext/phar/phar_path_check.c" -yy22: +#line 162 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" +yy20: yych = *++YYCURSOR; - if(yych <= 0x00) goto yy25; - if(yych == '/') goto yy25; - goto yy19; -yy23: + if(yych <= 0x00) goto yy23; + if(yych == '/') goto yy23; + goto yy17; +yy21: ++YYCURSOR; -#line 56 "ext/phar/phar_path_check.re" +#line 56 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { *error = "current directory reference"; return pcr_err_curr_dir; } -#line 184 "ext/phar/phar_path_check.c" -yy25: +#line 175 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" +yy23: ++YYCURSOR; -#line 52 "ext/phar/phar_path_check.re" +#line 52 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" { *error = "upper directory reference"; return pcr_err_up_dir; } -#line 192 "ext/phar/phar_path_check.c" +#line 183 "/home/cellog/workspace/php5/ext/phar/phar_path_check.c" } } -#line 100 "ext/phar/phar_path_check.re" +#line 96 "/home/cellog/workspace/php5/ext/phar/phar_path_check.re" } diff --git a/ext/phar/phar_path_check.re b/ext/phar/phar_path_check.re index 6702cdd68d..97a6b5d565 100755 --- a/ext/phar/phar_path_check.re +++ b/ext/phar/phar_path_check.re @@ -61,10 +61,6 @@ ANY = .; *error = "back-slash"; return pcr_err_back_slash; } -"/" END { - *error = "empty directory"; - return pcr_err_empty_entry; - } "*" { *error = "star"; return pcr_err_star; diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 047483c99e..52c8442e5b 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -187,7 +187,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat /* strip leading "/" */ internal_file = estrdup(resource->path + 1); if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) { - if (NULL == (idata = phar_get_or_create_entry_data(resource->host, host_len, internal_file, strlen(internal_file), mode, &error TSRMLS_CC))) { + if (NULL == (idata = phar_get_or_create_entry_data(resource->host, host_len, internal_file, strlen(internal_file), mode, 0, &error TSRMLS_CC))) { if (error) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error); efree(error); @@ -229,7 +229,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat } return fpf; } else { - if ((FAILURE == phar_get_entry_data(&idata, resource->host, host_len, internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) || !idata) { + if ((FAILURE == phar_get_entry_data(&idata, resource->host, host_len, internal_file, strlen(internal_file), "r", 0, &error TSRMLS_CC)) || !idata) { if (error) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error); efree(error); @@ -689,7 +689,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio /* need to copy to strip leading "/", will get touched again */ internal_file = estrdup(resource->path + 1); - if (FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) { + if (FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", 0, &error TSRMLS_CC)) { /* constraints of fp refcount were not met */ if (error) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error); diff --git a/ext/phar/tests/033.phpt b/ext/phar/tests/033.phpt index ceae7ea681..4866e9978d 100644 --- a/ext/phar/tests/033.phpt +++ b/ext/phar/tests/033.phpt @@ -13,6 +13,7 @@ $file = ''; $files = array(); $files['a.php'] = ''; +$files['dir/'] = ''; include 'phar_test.inc'; $a = new Phar($fname); var_dump($a['a.php']->isExecutable()); @@ -20,6 +21,13 @@ $a['a.php']->chmod(0777); var_dump($a['a.php']->isExecutable()); $a['a.php']->chmod(0666); var_dump($a['a.php']->isExecutable()); +echo "test dir\n"; +var_dump($a['dir']->isDir()); +var_dump($a['dir']->isReadable()); +$a['dir']->chmod(000); +var_dump($a['dir']->isReadable()); +$a['dir']->chmod(0666); +var_dump($a['dir']->isReadable()); ?> ===DONE=== --CLEAN-- @@ -30,4 +38,9 @@ unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.1.phar.php bool(false) bool(true) bool(false) +test dir +bool(true) +bool(true) +bool(false) +bool(true) ===DONE=== diff --git a/ext/phar/tests/dir.phpt b/ext/phar/tests/dir.phpt new file mode 100644 index 0000000000..f642d6ddac --- /dev/null +++ b/ext/phar/tests/dir.phpt @@ -0,0 +1,25 @@ +--TEST-- +Phar: mkdir test +--SKIPIF-- + +--INI-- +phar.readonly=0 +phar.require_hash=0 +--FILE-- +isDir()); +var_dump($phar['test/']->isDir()); +mkdir($pname . '/another/dir/'); +var_dump($phar['another/dir']->isDir()); +?> +--CLEAN-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) diff --git a/ext/phar/tests/phar_copy.phpt b/ext/phar/tests/phar_copy.phpt index b3a7f9784d..372d850cf7 100644 --- a/ext/phar/tests/phar_copy.phpt +++ b/ext/phar/tests/phar_copy.phpt @@ -15,7 +15,7 @@ $fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '2.phar.php'; $pname = 'phar://'.$fname; $iname = '/file.txt'; -$ename = '/error/'; +$ename = '/error/..'; $p = new Phar($fname); @@ -49,6 +49,6 @@ echo 'c: ' ,file_get_contents($p2['c']->getPathName()), $p2['c']->getMetaData(); --EXPECTF-- -hihifile "/error/" contains invalid characters empty directory, cannot be copied from "a" in phar %s +hihifile "/error/.." contains invalid characters upper directory reference, cannot be copied from "a" in phar %s a: hib: hic: hia===DONE=== \ No newline at end of file diff --git a/ext/phar/tests/phar_offset_get_error.phpt b/ext/phar/tests/phar_offset_get_error.phpt index 50e12f0199..ad0223697d 100755 --- a/ext/phar/tests/phar_offset_get_error.phpt +++ b/ext/phar/tests/phar_offset_get_error.phpt @@ -12,7 +12,7 @@ phar.require_hash=1 $fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; $pname = 'phar://'.$fname; $iname = '/file.txt'; -$ename = '/error/'; +$ename = '/error/..'; $p = new Phar($fname); $p[$iname] = "foobar\n"; @@ -32,6 +32,6 @@ include($pname . $iname); --CLEAN-- --EXPECT-- -Entry /error/ does not exist and cannot be created: phar error: invalid path "/error/" contains empty directory +Entry /error/.. does not exist and cannot be created: phar error: invalid path "/error/.." contains upper directory reference foobar ===DONE=== diff --git a/ext/phar/tests/tar/phar_copy.phpt b/ext/phar/tests/tar/phar_copy.phpt index 2750e85344..fcb3f498aa 100644 --- a/ext/phar/tests/tar/phar_copy.phpt +++ b/ext/phar/tests/tar/phar_copy.phpt @@ -15,7 +15,7 @@ $fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '2.phar.php'; $pname = 'phar://'.$fname; $iname = '/file.txt'; -$ename = '/error/'; +$ename = '/error/..'; $p = new Phar($fname); @@ -50,7 +50,7 @@ echo 'c: ' ,file_get_contents($p2['c']->getPathName()); --EXPECTF-- hihibool(true) -file "/error/" contains invalid characters empty directory, cannot be copied from "a" in phar %s +file "/error/.." contains invalid characters upper directory reference, cannot be copied from "a" in phar %s bool(true) a: hib: hic: hi===DONE=== \ No newline at end of file diff --git a/ext/phar/tests/zip/phar_copy.phpt b/ext/phar/tests/zip/phar_copy.phpt index d5a234fdc5..9cb14b14fc 100644 --- a/ext/phar/tests/zip/phar_copy.phpt +++ b/ext/phar/tests/zip/phar_copy.phpt @@ -15,7 +15,7 @@ $fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '2.phar.php'; $pname = 'phar://'.$fname; $iname = '/file.txt'; -$ename = '/error/'; +$ename = '/error/..'; $p = new Phar($fname); @@ -50,7 +50,7 @@ echo 'c: ' ,file_get_contents($p2['c']->getPathName()); --EXPECTF-- hihibool(true) -file "/error/" contains invalid characters empty directory, cannot be copied from "a" in phar %s +file "/error/.." contains invalid characters upper directory reference, cannot be copied from "a" in phar %s bool(true) a: hib: hic: hi===DONE=== \ No newline at end of file