]> granicus.if.org Git - php/commitdiff
fix Bug #12124: Phar object cannot be iterated over
authorGreg Beaver <cellog@php.net>
Thu, 4 Oct 2007 03:33:21 +0000 (03:33 +0000)
committerGreg Beaver <cellog@php.net>
Thu, 4 Oct 2007 03:33:21 +0000 (03:33 +0000)
remove unused variables
fix jit file open sprintf calls

ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c

index c1086f7ee37b9da0da803f97a288f02c89b43149..2d956d18502c1decdf5f00e0026ce241e6bfe804 100644 (file)
@@ -331,6 +331,14 @@ static int phar_get_archive(phar_archive_data **archive, char *fname, int fname_
  * retrieve information on a file contained within a phar, or null if it ain't there
  */
 phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC) /* {{{ */
+{
+       return phar_get_entry_info_dir(phar, path, path_len, 0, error TSRMLS_CC);
+}
+/* }}} */
+/**
+ * retrieve information on a file or directory contained within a phar, or null if none found
+ */
+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;
@@ -356,6 +364,41 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int pa
                }
                return entry;
        }
+       if (dir) {
+               /* try to find a directory */
+               HashTable *manifest;
+               char *key;
+               uint keylen;
+               ulong unused;
+
+               manifest = &phar->manifest;
+               zend_hash_internal_pointer_reset(manifest);
+               while (FAILURE != zend_hash_has_more_elements(manifest)) {
+                       if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) {
+                               break;
+                       }
+                       if (0 != memcmp(key, path, path_len)) {
+                               /* entry in directory not found */
+                               if (SUCCESS != zend_hash_move_forward(manifest)) {
+                                       break;
+                               }
+                               continue;
+                       } else {
+                               if (key[path_len] != '/') {
+                                       if (SUCCESS != zend_hash_move_forward(manifest)) {
+                                               break;
+                                       }
+                                       continue;
+                               }
+                               /* found a file in this path */
+                               entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info));
+                               entry->is_dir = 1;
+                               entry->filename = (char *) estrndup(path, path_len + 1);
+                               entry->filename_len = path_len;
+                               return entry;
+                       }
+               }
+       }
        return NULL;
 }
 /* }}} */
@@ -1707,7 +1750,7 @@ static phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info
        offset = phar->internal_file_start + entry->offset_within_phar;
        if (-1 == php_stream_seek(fp, offset, SEEK_SET)) {
                spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (cannot seek to start of file \"%s\" at offset \"%d\")",
-                       phar->fname, entry, offset);
+                       phar->fname, entry->filename, offset);
                return NULL;
        }
 
@@ -1724,7 +1767,7 @@ static phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info
                        filter = NULL;
                }
                if (!filter) {
-                       spprintf(error, 0, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry);
+                       spprintf(error, 0, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry->filename);
                        return NULL;                    
                }
                /* now we can safely use proper decompression */
@@ -1791,16 +1834,11 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
 {
        phar_entry_data *idata;
        char *internal_file;
-       char *buffer;
        char *error;
-       char *filter_name;
        char *plain_map;
-       char tmpbuf[8];
        HashTable *pharcontext;
        php_url *resource = NULL;
        php_stream *fp, *fpf;
-       php_stream_filter *filter/*,  *consumed */;
-       php_uint32 offset, read, total, toread;
        zval **pzoption, *metadata;
        uint host_len;
 
@@ -2220,7 +2258,7 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err
        long offset;
        size_t wrote;
        php_uint32 manifest_len, mytime, loc, new_manifest_count;
-       php_uint32 newcrc32, save;
+       php_uint32 newcrc32;
        php_stream *file, *oldfile, *newfile, *stubfile;
        php_stream_filter *filter;
        php_serialize_data_t metadata_hash;
index e591ea31f561f8aa03c1a299617f7bdbb70a1c98..f2f2e55be85c89f442b2eb479d65a653ecce3bd4 100755 (executable)
@@ -159,6 +159,8 @@ typedef struct _phar_entry_info {
        int                      is_crc_checked:1;
        int                      is_modified:1;
        int                      is_deleted:1;
+       /* used when iterating */
+       int                      is_dir:1;
        phar_archive_data        *phar;
        smart_str                metadata_str;
 } phar_entry_info;
@@ -271,6 +273,7 @@ int phar_archive_delref(phar_archive_data *phar TSRMLS_DC);
 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_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);
index d2b7e963a7c812f45d1ef36675704904c3e20266..64b3a77f1cb1aa54e7ae9d4d3365f9d1df46e8e7 100755 (executable)
@@ -1083,10 +1083,10 @@ PHP_METHOD(PharFileInfo, __construct)
                return;
        }
 
-       if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len, &error TSRMLS_CC)) == NULL) {
-               efree(arch);
+       if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error TSRMLS_CC)) == NULL) {
                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                        "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error?", ":"", error?error:"");
+               efree(arch);
                efree(entry);
                return;
        }
@@ -1112,13 +1112,31 @@ PHP_METHOD(PharFileInfo, __construct)
                return; \
        }
 
+/* {{{ proto void PharFileInfo::__destruct()
+ * clean up directory-based entry objects
+ */
+PHP_METHOD(PharFileInfo, __destruct)
+{
+       PHAR_ENTRY_OBJECT();
+
+       if (entry_obj->ent.entry->is_dir) {
+               if (entry_obj->ent.entry->filename) {
+                       efree(entry_obj->ent.entry->filename);
+                       entry_obj->ent.entry->filename = NULL;
+               }
+               efree(entry_obj->ent.entry);
+               entry_obj->ent.entry = NULL;
+       }
+}
+/* }}} */
+
 /* {{{ proto int PharFileInfo::getCompressedSize()
  * Returns the compressed size
  */
 PHP_METHOD(PharFileInfo, getCompressedSize)
 {
        PHAR_ENTRY_OBJECT();
-       
+
        RETURN_LONG(entry_obj->ent.entry->compressed_filesize);
 }
 /* }}} */
@@ -1163,6 +1181,10 @@ PHP_METHOD(PharFileInfo, getCRC32)
 {
        PHAR_ENTRY_OBJECT();
 
+       if (entry_obj->ent.entry->is_dir) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry is a directory, does not have a CRC"); \
+       }
        if (entry_obj->ent.entry->is_crc_checked) {
                RETURN_LONG(entry_obj->ent.entry->crc32);
        } else {
@@ -1203,6 +1225,10 @@ PHP_METHOD(PharFileInfo, chmod)
        long perms;
        PHAR_ENTRY_OBJECT();
 
+       if (entry_obj->ent.entry->is_dir) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry is a directory, cannot chmod"); \
+       }
        if (PHAR_G(readonly)) {
                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Cannot modify permissions for file \"%s\" write operations are prohibited", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
        }
@@ -1268,6 +1294,10 @@ PHP_METHOD(PharFileInfo, setMetadata)
        zval *metadata;
        PHAR_ENTRY_OBJECT();
 
+       if (entry_obj->ent.entry->is_dir) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry is a directory, cannot set metadata"); \
+       }
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &metadata) == FAILURE) {
                return;
        }
@@ -1296,6 +1326,10 @@ PHP_METHOD(PharFileInfo, delMetadata)
        char *error;
        PHAR_ENTRY_OBJECT();
 
+       if (entry_obj->ent.entry->is_dir) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry is a directory, cannot delete metadata"); \
+       }
        if (entry_obj->ent.entry->metadata) {
                zval_ptr_dtor(&entry_obj->ent.entry->metadata);
                entry_obj->ent.entry->metadata = NULL;
@@ -1323,6 +1357,10 @@ PHP_METHOD(PharFileInfo, setCompressedGZ)
        char *error;
        PHAR_ENTRY_OBJECT();
 
+       if (entry_obj->ent.entry->is_dir) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry is a directory, cannot set compression"); \
+       }
        if (entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) {
                RETURN_TRUE;
                return;
@@ -1363,6 +1401,10 @@ PHP_METHOD(PharFileInfo, setCompressedBZIP2)
        char *error;
        PHAR_ENTRY_OBJECT();
 
+       if (entry_obj->ent.entry->is_dir) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry is a directory, cannot set compression"); \
+       }
        if (entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
                RETURN_TRUE;
                return;
@@ -1403,6 +1445,10 @@ PHP_METHOD(PharFileInfo, setUncompressed)
        int fname_len;
        PHAR_ENTRY_OBJECT();
 
+       if (entry_obj->ent.entry->is_dir) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry is a directory, cannot set compression"); \
+       }
        if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) {
                RETURN_TRUE;
                return;
@@ -1544,6 +1590,7 @@ ZEND_END_ARG_INFO();
 
 zend_function_entry php_entry_methods[] = {
        PHP_ME(PharFileInfo, __construct,        arginfo_entry___construct,  0)
+       PHP_ME(PharFileInfo, __destruct,         NULL,                       0)
        PHP_ME(PharFileInfo, getCompressedSize,  NULL,                       0)
        PHP_ME(PharFileInfo, isCompressed,       NULL,                       0)
        PHP_ME(PharFileInfo, isCompressedGZ,     NULL,                       0)