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)) {
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;
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,
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;
}
} 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;
+ }
}
}
}
$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/');
--- /dev/null
+--TEST--
+opendir test, subdirectory
+--SKIPIF--
+<?php if (!extension_loaded("phar")) print "skip"; ?>
+--FILE--
+<?php
+function cleanup() { unlink(dirname(__FILE__) . '/008_phar.php'); }
+register_shutdown_function('cleanup');
+$file = "<?php
+PHP_Archive::mapPhar(5, 'hio', true);
+__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', 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