]> granicus.if.org Git - php/commitdiff
fix empty directories in phar, add test
authorGreg Beaver <cellog@php.net>
Wed, 9 Jan 2008 00:58:37 +0000 (00:58 +0000)
committerGreg Beaver <cellog@php.net>
Wed, 9 Jan 2008 00:58:37 +0000 (00:58 +0000)
15 files changed:
ext/phar/Makefile.frag
ext/phar/dirstream.c
ext/phar/dirstream.h
ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/phar/phar_path_check.c
ext/phar/phar_path_check.re
ext/phar/stream.c
ext/phar/tests/033.phpt
ext/phar/tests/dir.phpt [new file with mode: 0644]
ext/phar/tests/phar_copy.phpt
ext/phar/tests/phar_offset_get_error.phpt
ext/phar/tests/tar/phar_copy.phpt
ext/phar/tests/zip/phar_copy.phpt

index 3e79356fa1457f960fba9bdedcb39bfc6b6b8ab3..d693e8dd86ae966ccf996dcca33a3e17c7d87074 100755 (executable)
@@ -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
 
index 74d3e7177c245324db31eef0270786a33e3ea420..d52eb7ca39311ee24e5a68807b286ce464661143 100644 (file)
@@ -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;
 }
 /* }}} */
index 9326d9e0ec082de0e7c1be2ebc9c649bbbbfb6aa..9528c4da27a3279783bf6a0f6dbcd1886930a37a 100644 (file)
@@ -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);
 
index f637ec861eed0d23e464d9ab2bd741f972fa649d..04b89080685c28f8545a1a57477981a1375c1cff 100644 (file)
@@ -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) {
index fe98c6061ea88cbffe0f44e42ed21c32bd38227f..2b7c7b185c2fb149cc710f7d6b0305d83f4c7f95 100755 (executable)
@@ -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);
index f2f7a3aa0b301cdcff5315b79867871742c3cee6..3b2b7b2361873406f65f5ccccfef636c349b1bbd 100755 (executable)
@@ -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) {
index 2d436a5702091534e6b527129d103bdf2e77c9d5..03a85b678387fd41083d97c2b34d0ff72b913d67 100755 (executable)
@@ -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"
 
 }
index 6702cdd68de66b5152c2cf4ad3e4f50e774bd698..97a6b5d565f1f6f619b92f297f0676ed3124c46e 100755 (executable)
@@ -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;
index 047483c99e0746baba1d8257fa30e7651faa1f8a..52c8442e5bdacd58a19cf2597bf0ac75a304f662 100644 (file)
@@ -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);
index ceae7ea681a0679e01e8c4e9193277abb1604d1d..4866e9978df5fd86c78f7a977a2926a976fb9de5 100644 (file)
@@ -13,6 +13,7 @@ $file = '<?php include "' . $pname . '/a.php"; __HALT_COMPILER(); ?>';
 
 $files = array();
 $files['a.php']   = '<?php echo "This is a\n"; include "'.$pname.'/b.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 (file)
index 0000000..f642d6d
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Phar: mkdir test
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$phar = new Phar($fname);
+
+$phar['test/'] = '';
+var_dump($phar['test']->isDir());
+var_dump($phar['test/']->isDir());
+mkdir($pname . '/another/dir/');
+var_dump($phar['another/dir']->isDir());
+?>
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
index b3a7f9784dbcba4e02ce59a5486084d2a4a47845..372d850cf724a85c8734804f3dd4557e39eca9c0 100644 (file)
@@ -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();
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '2.phar.php'); ?>
 --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
index 50e12f0199a6b1d89c7c18711fca13c67a0ba291..ad0223697d8f835149c716b6b6cbd78d8d5d4f1b 100755 (executable)
@@ -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--
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
 --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===
index 2750e8534413d2016e7befc60ad3dc64e9d50068..fcb3f498aad8bc737d0909d818afd36372680ce4 100644 (file)
@@ -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());
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '2.phar.php'); ?>
 --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
index d5a234fdc5810eda3f4006962776da39fc5be15d..9cb14b14fc59f5abc5906360418de5a824c902e8 100644 (file)
@@ -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());
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '2.phar.php'); ?>
 --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