From dd8e3dd4df8c6ffffd1aa6f0b0068b9585b48a3b Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Sun, 11 Dec 2005 08:14:44 +0000 Subject: [PATCH] fix opendir, add test for subdirectory, revert stupid addition to 018.phpt --- ext/phar/phar.c | 77 +++++++++++++++++++++++++++++------------ ext/phar/tests/018.phpt | 2 -- ext/phar/tests/019.phpt | 35 +++++++++++++++++++ 3 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 ext/phar/tests/019.phpt diff --git a/ext/phar/phar.c b/ext/phar/phar.c index cb69335bf1..99de4122bc 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -949,8 +949,10 @@ PHP_PHAR_API int phar_stream_stat(php_stream_wrapper *wrapper, char *url, int fl data->manifest, &key, &keylen, &unused, 0, NULL)) { if (0 == memcmp(internal_file, key, strlen(internal_file))) { /* directory found, all dirs have the same stat */ - phar_dostat(NULL, ssb, 1 TSRMLS_CC); - break; + if (key[strlen(internal_file)] == '/') { + phar_dostat(NULL, ssb, 1 TSRMLS_CC); + break; + } } } if (SUCCESS != zend_hash_move_forward(data->manifest)) { @@ -984,23 +986,38 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) zend_hash_init(data, 64, zend_get_hash_value, NULL, 0); zend_hash_internal_pointer_reset(manifest); - while (SUCCESS == zend_hash_has_more_elements(manifest)) { + while (HASH_KEY_NON_EXISTANT != zend_hash_has_more_elements(manifest)) { if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) { - return NULL; + break; } if (*dir == '/') { - /* not root directory */ + /* root directory */ if (NULL != (found = (char *) memchr(key, '/', keylen))) { /* the entry has a path separator and is a subdirectory */ - save = key; - goto PHAR_DIR_SUBDIR; + entry = (char *) emalloc (found - key + 1); + memcpy(entry, key, found - key); + keylen = found - key; + entry[keylen] = '\0'; + } else { + entry = (char *) emalloc (keylen + 1); + memcpy(entry, key, keylen); + entry[keylen] = '\0'; } - dirlen = 0; + goto PHAR_ADD_ENTRY; } else { if (0 != memcmp(key, dir, dirlen)) { /* entry in directory not found */ - zend_hash_move_forward(manifest); + if (SUCCESS != zend_hash_move_forward(manifest)) { + break; + } continue; + } else { + if (key[dirlen] != '/') { + if (SUCCESS != zend_hash_move_forward(manifest)) { + break; + } + continue; + } } } save = key; @@ -1008,24 +1025,33 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) if (NULL != (found = (char *) memchr(save, '/', keylen - dirlen - 1))) { /* is subdirectory */ save -= dirlen + 1; -PHAR_DIR_SUBDIR: - entry = (char *) emalloc (found - save + 2); - memcpy(entry, save, found - save); - keylen = found - save; - entry[found - save + 1] = '\0'; + entry = (char *) emalloc (found - save + dirlen + 1); + memcpy(entry, save + dirlen + 1, found - save - dirlen - 1); + keylen = found - save - dirlen - 1; + entry[keylen] = '\0'; } else { /* is file */ save -= dirlen + 1; entry = (char *) emalloc (keylen - dirlen + 1); - memcpy(entry, save, keylen - dirlen); - entry[keylen - dirlen] = '\0'; - keylen = keylen - dirlen; + memcpy(entry, save + dirlen + 1, keylen - dirlen - 1); + entry[keylen - dirlen - 1] = '\0'; + keylen = keylen - dirlen - 1; } +PHAR_ADD_ENTRY: phar_add_empty(data, entry, keylen); efree(entry); - zend_hash_move_forward(manifest); + if (SUCCESS != zend_hash_move_forward(manifest)) { + break; + } + } + if (HASH_KEY_NON_EXISTANT != zend_hash_has_more_elements(data)) { + efree(dir); + return php_stream_alloc(&phar_dir_ops, data, NULL, "r"); + } else { + efree(dir); + FREE_HASHTABLE(data); + return NULL; } - return php_stream_alloc(&phar_dir_ops, data, NULL, "r"); } PHP_PHAR_API php_stream *phar_opendir(php_stream_wrapper *wrapper, char *filename, char *mode, @@ -1062,7 +1088,8 @@ PHP_PHAR_API php_stream *phar_opendir(php_stream_wrapper *wrapper, char *filenam if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_data), resource->host, strlen(resource->host), (void **) &data)) { if (*internal_file == '\0') { /* root directory requested */ - ret = phar_make_dirstream("/", data->manifest TSRMLS_CC); + internal_file = estrndup(internal_file - 1, 1); + ret = phar_make_dirstream(internal_file, data->manifest TSRMLS_CC); php_url_free(resource); return ret; } @@ -1072,17 +1099,21 @@ PHP_PHAR_API php_stream *phar_opendir(php_stream_wrapper *wrapper, char *filenam } else { /* search for directory */ zend_hash_internal_pointer_reset(data->manifest); - while (zend_hash_has_more_elements(data->manifest)) { + while (HASH_KEY_NON_EXISTANT != zend_hash_has_more_elements(data->manifest)) { if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key_ex( data->manifest, &key, &keylen, &unused, 0, NULL)) { - if (0 == memcmp(key, internal_file, keylen)) { + if (0 == memcmp(key, internal_file, strlen(internal_file))) { /* directory found */ + internal_file = estrndup(internal_file, + strlen(internal_file)); php_url_free(resource); return phar_make_dirstream(internal_file, data->manifest TSRMLS_CC); } } - zend_hash_move_forward(data->manifest); + if (SUCCESS != zend_hash_move_forward(data->manifest)) { + break; + } } } } diff --git a/ext/phar/tests/018.phpt b/ext/phar/tests/018.phpt index 39fa4c49b1..be5eb8bf92 100644 --- a/ext/phar/tests/018.phpt +++ b/ext/phar/tests/018.phpt @@ -12,12 +12,10 @@ __HALT_COMPILER(); ?>"; $manifest = ''; $manifest .= pack('V', 1) . 'a' . pack('VVVV', 1, time(), 0, 9); $manifest .= pack('V', 3) . 'b/a' . pack('VVVV', 1, time(), 0, 9); -$manifest .= pack('V', 3) . 'c/a' . pack('VVVV', 1, time(), 0, 9); $file .= pack('VV', strlen($manifest) + 4, 2) . $manifest . pack('VV', crc32('a'), 1) . 'a' . pack('VV', crc32('b'), 1) . 'b'; - pack('VV', crc32('c'), 1) . 'c'; file_put_contents(dirname(__FILE__) . '/008_phar.php', $file); include dirname(__FILE__) . '/008_phar.php'; $dir = opendir('phar://hio/'); diff --git a/ext/phar/tests/019.phpt b/ext/phar/tests/019.phpt new file mode 100644 index 0000000000..ce2f599ae8 --- /dev/null +++ b/ext/phar/tests/019.phpt @@ -0,0 +1,35 @@ +--TEST-- +opendir test, subdirectory +--SKIPIF-- + +--FILE-- +"; +$manifest = ''; +$manifest .= pack('V', 1) . 'a' . pack('VVVV', 1, time(), 0, 9); +$manifest .= pack('V', 3) . 'b/a' . pack('VVVV', 1, time(), 0, 9); +$manifest .= pack('V', 5) . 'b/c/d' . pack('VVVV', 1, time(), 0, 9); +$manifest .= pack('V', 5) . 'bad/c' . pack('VVVV', 1, time(), 0, 9); +$file .= pack('VV', strlen($manifest) + 4, 4) . + $manifest . + pack('VV', crc32('a'), 1) . 'a' . + pack('VV', crc32('b'), 1) . 'b'; + pack('VV', crc32('c'), 1) . 'c'; + pack('VV', crc32('d'), 1) . 'd'; +file_put_contents(dirname(__FILE__) . '/008_phar.php', $file); +include dirname(__FILE__) . '/008_phar.php'; +$dir = opendir('phar://hio/b'); +while (false !== ($a = readdir($dir))) { + var_dump($a); + var_dump(is_dir('phar://hio/b/' . $a)); +} +?> +--EXPECT-- +string(1) "a" +bool(false) +string(1) "c" +bool(true) \ No newline at end of file -- 2.50.1