diff --git a/ext/phar/build_precommand.php b/ext/phar/build_precommand.php
index 8904afdf054..c2fe9c8e523 100755
--- a/ext/phar/build_precommand.php
+++ b/ext/phar/build_precommand.php
@@ -5,14 +5,12 @@
* @ingroup Phar
* @brief class Phar Pre Command
* @author Marcus Boerger
- * @date 2007 - 2007
+ * @date 2007 - 2008
*
* Phar Command
*/
-foreach(array("SPL", "Reflection", "Phar") as $ext)
-{
- if (!extension_loaded($ext))
- {
+foreach(array("SPL", "Reflection", "Phar") as $ext) {
+ if (!extension_loaded($ext)) {
echo "$argv[0] requires PHP extension $ext.\n";
exit(1);
}
@@ -28,14 +26,12 @@ $classes = array(
'PharCommand',
);
-foreach($classes as $name)
-{
+foreach($classes as $name) {
echo "if (!class_exists('$name', 0))\n{\n";
$f = file(dirname(__FILE__) . '/phar/' . strtolower($name) . '.inc');
unset($f[0]);
$c = count($f);
- while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n"))
- {
+ while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n")) {
unset($f[$c--]);
}
if (substr($f[$c], -2) == "\r\n") {
@@ -47,8 +43,7 @@ foreach($classes as $name)
if (substr($f[$c], -2) == '?>') {
$f[$c] = substr($f[$c], 0,-2);
}
- while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n"))
- {
+ while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n")) {
unset($f[$c--]);
}
echo join('', $f);
diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c
index 8218c9ca715..e72bd5b2d2b 100644
--- a/ext/phar/dirstream.c
+++ b/ext/phar/dirstream.c
@@ -45,13 +45,13 @@ static int phar_dir_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{
{
HashTable *data = (HashTable *)stream->abstract;
- if (data && data->arBuckets)
- {
+ if (data && data->arBuckets) {
zend_hash_destroy(data);
data->arBuckets = 0;
FREE_HASHTABLE(data);
stream->abstract = NULL;
}
+
return 0;
}
/* }}} */
@@ -63,14 +63,15 @@ static int phar_dir_seek(php_stream *stream, off_t offset, int whence, off_t *ne
{
HashTable *data = (HashTable *)stream->abstract;
- if (!data)
- {
+ if (!data) {
return -1;
}
+
if (whence == SEEK_END) {
whence = SEEK_SET;
offset = zend_hash_num_elements(data) + offset;
}
+
if (whence == SEEK_SET) {
zend_hash_internal_pointer_reset(data);
}
@@ -102,15 +103,19 @@ static size_t phar_dir_read(php_stream *stream, char *buf, size_t count TSRMLS_D
if (FAILURE == zend_hash_has_more_elements(data)) {
return 0;
}
+
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(data, &key, &keylen, &unused, 0, NULL)) {
return 0;
}
+
PHAR_STR(key, str_key);
zend_hash_move_forward(data);
to_read = MIN(keylen, count);
+
if (to_read == 0 || count < keylen) {
return 0;
}
+
memset(buf, 0, sizeof(php_stream_dirent));
memcpy(((php_stream_dirent *) buf)->d_name, str_key, to_read);
((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0';
@@ -159,10 +164,9 @@ static int phar_compare_dir_name(const void *a, const void *b TSRMLS_DC) /* {{{
Bucket *f;
Bucket *s;
int result;
-
+
f = *((Bucket **) a);
s = *((Bucket **) b);
-
#if (PHP_MAJOR_VERSION < 6)
result = zend_binary_strcmp(f->arKey, f->nKeyLength, s->arKey, s->nKeyLength);
#else
@@ -202,12 +206,16 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
efree(dir);
return php_stream_alloc(&phar_dir_ops, data, NULL, "r");
}
+
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;
}
+
PHAR_STR(key, str_key);
+
if (keylen <= (uint)dirlen) {
if (keylen < (uint)dirlen || !strncmp(str_key, dir, dirlen)) {
if (SUCCESS != zend_hash_move_forward(manifest)) {
@@ -216,6 +224,7 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
continue;
}
}
+
if (*dir == '/') {
/* root directory */
if (keylen >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
@@ -225,6 +234,7 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
}
continue;
}
+
if (NULL != (found = (char *) memchr(str_key, '/', keylen))) {
/* the entry has a path separator and is a subdirectory */
entry = (char *) safe_emalloc(found - str_key, 1, 1);
@@ -236,6 +246,7 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
memcpy(entry, str_key, keylen);
entry[keylen] = '\0';
}
+
goto PHAR_ADD_ENTRY;
} else {
if (0 != memcmp(str_key, dir, dirlen)) {
@@ -253,8 +264,10 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
}
}
}
+
save = str_key;
save += dirlen + 1; /* seek to just past the path separator */
+
if (NULL != (found = (char *) memchr(save, '/', keylen - dirlen - 1))) {
/* is subdirectory */
save -= dirlen + 1;
@@ -274,11 +287,14 @@ PHAR_ADD_ENTRY:
if (keylen) {
phar_add_empty(data, entry, keylen);
}
+
efree(entry);
+
if (SUCCESS != zend_hash_move_forward(manifest)) {
break;
}
}
+
if (FAILURE != zend_hash_has_more_elements(data)) {
efree(dir);
if (zend_hash_sort(data, zend_qsort, phar_compare_dir_name, 0 TSRMLS_CC) == FAILURE) {
@@ -296,8 +312,7 @@ PHAR_ADD_ENTRY:
/**
* Open a directory handle within a phar archive
*/
-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) /* {{{ */
+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) /* {{{ */
{
php_url *resource = NULL;
php_stream *ret;
@@ -334,8 +349,8 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
host_len = strlen(resource->host);
phar_request_initialize(TSRMLS_C);
-
internal_file = resource->path + 1; /* strip leading "/" */
+
if (FAILURE == phar_get_archive(&phar, resource->host, host_len, NULL, 0, &error TSRMLS_CC)) {
if (error) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
@@ -346,9 +361,11 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
php_url_free(resource);
return NULL;
}
+
if (error) {
efree(error);
}
+
if (*internal_file == '\0') {
/* root directory requested */
internal_file = estrndup(internal_file - 1, 1);
@@ -356,10 +373,12 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
php_url_free(resource);
return ret;
}
+
if (!phar->manifest.arBuckets) {
php_url_free(resource);
return NULL;
}
+
if (SUCCESS == zend_hash_find(&phar->manifest, internal_file, strlen(internal_file), (void**)&entry) && !entry->is_dir) {
php_url_free(resource);
return NULL;
@@ -389,6 +408,7 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
return phar_make_dirstream(internal_file, &phar->manifest TSRMLS_CC);
}
}
+
if (SUCCESS != zend_hash_move_forward(&phar->manifest)) {
break;
}
@@ -417,11 +437,14 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\", no phar archive specified", url_from);
return 0;
}
+
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
phar = NULL;
}
+
efree(arch);
efree(entry2);
+
if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\", write operations disabled", url_from);
return 0;
@@ -463,18 +486,21 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
php_url_free(resource);
return 0;
}
+
if (error) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
efree(error);
php_url_free(resource);
return 0;
}
+
if ((e = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 0, &error, 1 TSRMLS_CC))) {
/* entry exists as a file */
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", file already exists", resource->path+1, resource->host);
php_url_free(resource);
return 0;
}
+
if (error) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
efree(error);
@@ -494,11 +520,14 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
if (phar->is_zip) {
entry.is_zip = 1;
}
+
entry.filename = estrdup(resource->path + 1);
+
if (phar->is_tar) {
entry.is_tar = 1;
entry.tar_type = TAR_DIR;
}
+
entry.filename_len = strlen(resource->path + 1);
php_url_free(resource);
entry.is_dir = 1;
@@ -507,19 +536,23 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
entry.is_crc_checked = 1;
entry.flags = PHAR_ENT_PERM_DEF_DIR;
entry.old_flags = PHAR_ENT_PERM_DEF_DIR;
+
if (SUCCESS != zend_hash_add(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", entry.filename, phar->fname);
efree(error);
efree(entry.filename);
return 0;
}
+
phar_flush(phar, 0, 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 0;
}
+
phar_add_virtual_dirs(phar, entry.filename, entry.filename_len TSRMLS_CC);
return 1;
}
@@ -547,11 +580,14 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
return 0;
}
+
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
phar = NULL;
}
+
efree(arch);
efree(entry2);
+
if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot rmdir directory \"%s\", write operations disabled", url);
return 0;
@@ -584,7 +620,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
}
path_len = strlen(resource->path+1);
-
+
if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, path_len, 2, &error, 1 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);
@@ -604,13 +640,13 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
}
for (zend_hash_internal_pointer_reset(&phar->manifest);
- HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL));
- zend_hash_move_forward(&phar->manifest)) {
+ HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL));
+ zend_hash_move_forward(&phar->manifest)) {
- if (!entry->is_deleted &&
- key_len > path_len &&
- memcmp(key, resource->path+1, path_len) == 0 &&
- IS_SLASH(key[path_len])) {
+ if (!entry->is_deleted &&
+ key_len > path_len &&
+ memcmp(key, resource->path+1, path_len) == 0 &&
+ IS_SLASH(key[path_len])) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty");
if (entry->is_temp_dir) {
efree(entry->filename);
@@ -622,13 +658,13 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
}
for (zend_hash_internal_pointer_reset(&phar->virtual_dirs);
- HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL));
- zend_hash_move_forward(&phar->virtual_dirs)) {
+ HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL));
+ zend_hash_move_forward(&phar->virtual_dirs)) {
- if (!entry->is_deleted &&
- key_len > path_len &&
- memcmp(key, resource->path+1, path_len) == 0 &&
- IS_SLASH(key[path_len])) {
+ if (!entry->is_deleted &&
+ key_len > path_len &&
+ memcmp(key, resource->path+1, path_len) == 0 &&
+ IS_SLASH(key[path_len])) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty");
if (entry->is_temp_dir) {
efree(entry->filename);
diff --git a/ext/phar/dirstream.h b/ext/phar/dirstream.h
index 6467b55bcee..b6b49699b97 100644
--- a/ext/phar/dirstream.h
+++ b/ext/phar/dirstream.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2006-2007 The PHP Group |
+ | Copyright (c) 2006-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c
index 266bbb0d8ad..d3308b571a8 100644
--- a/ext/phar/func_interceptors.c
+++ b/ext/phar/func_interceptors.c
@@ -37,6 +37,7 @@ PHAR_FUNC(phar_opendir) /* {{{ */
&& !cached_phars.arBuckets) {
goto skip_phar;
}
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &zcontext) == FAILURE) {
return;
}
@@ -110,10 +111,12 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
&& !cached_phars.arBuckets) {
goto skip_phar;
}
+
/* Parse arguments */
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
goto skip_phar;
}
+
if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
char *arch, *entry, *fname;
int arch_len, entry_len, fname_len;
@@ -783,7 +786,7 @@ statme_baby:
if (!phar->is_writeable) {
sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
}
-
+
sb.st_nlink = 1;
sb.st_rdev = -1;
/* this is only for APC, so use /dev/null device - no chance of conflict there! */
diff --git a/ext/phar/func_interceptors.h b/ext/phar/func_interceptors.h
index e161df6d345..d67d5f63803 100644
--- a/ext/phar/func_interceptors.h
+++ b/ext/phar/func_interceptors.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2006-2007 The PHP Group |
+ | Copyright (c) 2006-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/phar/makestub.php b/ext/phar/makestub.php
index f1e7b46dc34..2bb30e96d83 100644
--- a/ext/phar/makestub.php
+++ b/ext/phar/makestub.php
@@ -34,7 +34,7 @@ $stub = '/*
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension generated stub |
+----------------------------------------------------------------------+
- | Copyright (c) 2005-' . date('Y') . ' The PHP Group |
+ | Copyright (c) 2005-' . date('Y') . ' The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index f9126c7dd05..9cb0b749162 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -42,12 +42,12 @@ static int phar_set_writeable_bit(void *pDest, void *argument TSRMLS_DC) /* {{{
if (!phar->is_data) {
phar->is_writeable = !keep;
}
+
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
-/* if the original value is 0 (disabled), then allow setting/unsetting at will
- otherwise, only allow 1 (enabled), and error on disabling */
+/* if the original value is 0 (disabled), then allow setting/unsetting at will. Otherwise only allow 1 (enabled), and error on disabling */
ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */
{
zend_bool old, ini;
@@ -56,7 +56,7 @@ ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */
old = PHAR_G(readonly_orig);
} else {
old = PHAR_G(require_hash_orig);
- }
+ }
if (new_value_length == 2 && !strcasecmp("on", new_value)) {
ini = (zend_bool) 1;
@@ -74,10 +74,10 @@ ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */
/* do not allow unsetting in runtime */
if (stage == ZEND_INI_STAGE_STARTUP) {
if (entry->name_length == 14) {
- PHAR_G(readonly_orig) = ini;
+ PHAR_G(readonly_orig) = ini;
} else {
PHAR_G(require_hash_orig) = ini;
- }
+ }
} else if (old && !ini) {
return FAILURE;
}
@@ -89,7 +89,8 @@ ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */
}
} else {
PHAR_G(require_hash) = ini;
- }
+ }
+
return SUCCESS;
}
/* }}}*/
@@ -119,6 +120,7 @@ static void phar_split_cache_list(TSRMLS_D) /* {{{ */
if (zend_hash_init(&EG(regular_list), 0, NULL, NULL, 0) == SUCCESS) {
EG(regular_list).nNextFreeElement=1; /* we don't want resource id 0 */
}
+
PHAR_G(has_bz2) = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
PHAR_G(has_zlib) = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
/* these two are dummies and will be destroyed later */
@@ -132,9 +134,9 @@ static void phar_split_cache_list(TSRMLS_D) /* {{{ */
for (key = php_strtok_r(tmp, ds, &lasts);
key;
- key = php_strtok_r(NULL, ds, &lasts))
- {
+ key = php_strtok_r(NULL, ds, &lasts)) {
end = strchr(key, DEFAULT_DIR_SEPARATOR);
+
if (end) {
if (SUCCESS == phar_open_from_filename(key, end - key, NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
finish_up:
@@ -166,6 +168,7 @@ finish_error:
}
}
}
+
PHAR_GLOBALS->persist = 0;
PHAR_GLOBALS->request_init = 0;
/* destroy dummy values from before */
@@ -194,9 +197,9 @@ ZEND_INI_MH(phar_ini_cache_list) /* {{{ */
/* }}} */
PHP_INI_BEGIN()
- STD_PHP_INI_BOOLEAN( "phar.readonly", "1", PHP_INI_ALL, phar_ini_modify_handler, readonly, zend_phar_globals, phar_globals)
+ STD_PHP_INI_BOOLEAN( "phar.readonly", "1", PHP_INI_ALL, phar_ini_modify_handler, readonly, zend_phar_globals, phar_globals)
STD_PHP_INI_BOOLEAN( "phar.require_hash", "1", PHP_INI_ALL, phar_ini_modify_handler, require_hash, zend_phar_globals, phar_globals)
- STD_PHP_INI_ENTRY("phar.cache_list", "", PHP_INI_SYSTEM, phar_ini_cache_list, cache_list, zend_phar_globals, phar_globals)
+ STD_PHP_INI_ENTRY("phar.cache_list", "", PHP_INI_SYSTEM, phar_ini_cache_list, cache_list, zend_phar_globals, phar_globals)
PHP_INI_END()
/**
@@ -209,26 +212,32 @@ void phar_destroy_phar_data(phar_archive_data *phar TSRMLS_DC) /* {{{ */
pefree(phar->alias, phar->is_persistent);
phar->alias = NULL;
}
+
if (phar->fname) {
pefree(phar->fname, phar->is_persistent);
phar->fname = NULL;
}
+
if (phar->signature) {
pefree(phar->signature, phar->is_persistent);
phar->signature = NULL;
}
+
if (phar->manifest.arBuckets) {
zend_hash_destroy(&phar->manifest);
phar->manifest.arBuckets = NULL;
}
+
if (phar->mounted_dirs.arBuckets) {
zend_hash_destroy(&phar->mounted_dirs);
phar->mounted_dirs.arBuckets = NULL;
}
+
if (phar->virtual_dirs.arBuckets) {
zend_hash_destroy(&phar->virtual_dirs);
phar->virtual_dirs.arBuckets = NULL;
}
+
if (phar->metadata) {
if (phar->is_persistent) {
if (phar->metadata_len) {
@@ -243,14 +252,17 @@ void phar_destroy_phar_data(phar_archive_data *phar TSRMLS_DC) /* {{{ */
phar->metadata_len = 0;
phar->metadata = 0;
}
+
if (phar->fp) {
php_stream_close(phar->fp);
phar->fp = 0;
}
+
if (phar->ufp) {
php_stream_close(phar->ufp);
phar->ufp = 0;
}
+
pefree(phar, phar->is_persistent);
}
/* }}}*/
@@ -260,7 +272,10 @@ void phar_destroy_phar_data(phar_archive_data *phar TSRMLS_DC) /* {{{ */
*/
int phar_archive_delref(phar_archive_data *phar TSRMLS_DC) /* {{{ */
{
- if (phar->is_persistent) return 0;
+ if (phar->is_persistent) {
+ return 0;
+ }
+
if (--phar->refcount < 0) {
if (PHAR_GLOBALS->request_done
|| zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), phar->fname, phar->fname_len) != SUCCESS) {
@@ -271,6 +286,7 @@ int phar_archive_delref(phar_archive_data *phar TSRMLS_DC) /* {{{ */
/* invalidate phar cache */
PHAR_G(last_phar) = NULL;
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
+
if (phar->fp && !(phar->flags & PHAR_FILE_COMPRESSION_MASK)) {
/* close open file handle - allows removal or rename of
the file on windows, which has greedy locking
@@ -279,6 +295,7 @@ int phar_archive_delref(phar_archive_data *phar TSRMLS_DC) /* {{{ */
php_stream_close(phar->fp);
phar->fp = NULL;
}
+
if (!zend_hash_num_elements(&phar->manifest)) {
/* this is a new phar that has perhaps had an alias/metadata set, but has never
been flushed */
@@ -325,10 +342,12 @@ static int phar_tmpclose_apply(void *pDest TSRMLS_DC) /* {{{ */
if (entry->fp_type != PHAR_TMP) {
return ZEND_HASH_APPLY_KEEP;
}
+
if (entry->fp && !entry->fp_refcount) {
php_stream_close(entry->fp);
entry->fp = NULL;
}
+
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
@@ -348,7 +367,9 @@ static void destroy_phar_data(void *pDest) /* {{{ */
destroy_phar_data_only(pDest);
return;
}
+
zend_hash_apply_with_argument(&(PHAR_GLOBALS->phar_alias_map), phar_unalias_apply, phar_data TSRMLS_CC);
+
if (--phar_data->refcount < 0) {
phar_destroy_phar_data(phar_data TSRMLS_CC);
}
@@ -367,10 +388,12 @@ void destroy_phar_manifest_entry(void *pDest) /* {{{ */
php_stream_close(entry->cfp);
entry->cfp = 0;
}
+
if (entry->fp) {
php_stream_close(entry->fp);
entry->fp = 0;
}
+
if (entry->metadata) {
if (entry->is_persistent) {
if (entry->metadata_len) {
@@ -385,15 +408,19 @@ void destroy_phar_manifest_entry(void *pDest) /* {{{ */
entry->metadata_len = 0;
entry->metadata = 0;
}
+
if (entry->metadata_str.c) {
smart_str_free(&entry->metadata_str);
entry->metadata_str.c = 0;
}
+
pefree(entry->filename, entry->is_persistent);
+
if (entry->link) {
pefree(entry->link, entry->is_persistent);
entry->link = 0;
}
+
if (entry->tmp) {
pefree(entry->tmp, entry->is_persistent);
entry->tmp = 0;
@@ -409,10 +436,12 @@ int phar_entry_delref(phar_entry_data *idata TSRMLS_DC) /* {{{ */
if (--idata->internal_file->fp_refcount < 0) {
idata->internal_file->fp_refcount = 0;
}
+
if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
php_stream_close(idata->fp);
}
}
+
phar_archive_delref(idata->phar TSRMLS_CC);
efree(idata);
return ret;
@@ -427,6 +456,7 @@ void phar_entry_remove(phar_entry_data *idata, char **error TSRMLS_DC) /* {{{ */
phar_archive_data *phar;
phar = idata->phar;
+
if (idata->internal_file->fp_refcount < 2) {
if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
php_stream_close(idata->fp);
@@ -508,6 +538,7 @@ int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len
#ifdef PHP_WIN32
unixfname = estrndup(fname, fname_len);
phar_unixify_path_separators(unixfname, fname_len);
+
if (SUCCESS == phar_get_archive(&phar, unixfname, fname_len, alias, alias_len, error TSRMLS_CC)
&& ((alias && fname_len == phar->fname_len
&& !strncmp(unixfname, phar->fname, fname_len)) || !alias)
@@ -538,9 +569,11 @@ int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len
}
}
}
+
if (pphar) {
*pphar = phar;
}
+
return SUCCESS;
} else {
#ifdef PHP_WIN32
@@ -549,9 +582,11 @@ int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len
if (pphar) {
*pphar = NULL;
}
+
if (phar && error && !(options & REPORT_ERRORS)) {
efree(error);
}
+
return FAILURE;
}
}
@@ -582,13 +617,16 @@ int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSR
INIT_ZVAL(**metadata);
p = (const unsigned char*) *buffer;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(metadata, &p, p + buf_len, &var_hash TSRMLS_CC)) {
+
+ if (!php_var_unserialize(metadata, &p, p + buf_len, &var_hash TSRMLS_CC)) {
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
zval_ptr_dtor(metadata);
*metadata = NULL;
return FAILURE;
}
+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
if (PHAR_G(persist)) {
/* lazy init metadata */
zval_ptr_dtor(metadata);
@@ -602,9 +640,11 @@ int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSR
} else {
*metadata = NULL;
}
+
if (!zip_metadata_len) {
*buffer += buf_len;
}
+
return SUCCESS;
}
/* }}}*/
@@ -612,7 +652,7 @@ int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSR
/**
* Does not check for a previously opened phar in the cache.
*
- * Parse a new one and add it to the cache, returning either SUCCESS or
+ * Parse a new one and add it to the cache, returning either SUCCESS or
* FAILURE, and setting pphar to the pointer to the manifest entry
*
* This is used by phar_open_from_filename to process the manifest, but can be called
@@ -632,6 +672,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
if (pphar) {
*pphar = NULL;
}
+
if (error) {
*error = NULL;
}
@@ -642,15 +683,18 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
}
buffer = b32;
+
if (3 != php_stream_read(fp, buffer, 3)) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at stub end)")
}
+
if ((*buffer == ' ' || *buffer == '\n') && *(buffer + 1) == '?' && *(buffer + 2) == '>') {
int nextchar;
halt_offset += 3;
if (EOF == (nextchar = php_stream_getc(fp))) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at stub end)")
}
+
if ((char) nextchar == '\r') {
/* if we have an \r we require an \n as well */
if (EOF == (nextchar = php_stream_getc(fp)) || (char)nextchar != '\n') {
@@ -658,10 +702,12 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
}
++halt_offset;
}
+
if ((char) nextchar == '\n') {
++halt_offset;
}
}
+
/* make sure we are at the right location to read the manifest */
if (-1 == php_stream_seek(fp, halt_offset, SEEK_SET)) {
MAPPHAR_ALLOC_FAIL("cannot seek to __HALT_COMPILER(); location in phar \"%s\"")
@@ -669,31 +715,38 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
/* read in manifest */
buffer = b32;
+
if (4 != php_stream_read(fp, buffer, 4)) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at manifest length)")
}
+
PHAR_GET_32(buffer, manifest_len);
+
if (manifest_len > 1048576 * 100) {
/* prevent serious memory issues by limiting manifest to at most 100 MB in length */
MAPPHAR_ALLOC_FAIL("manifest cannot be larger than 100 MB in phar \"%s\"")
}
+
buffer = (char *)emalloc(manifest_len);
savebuf = buffer;
endbuffer = buffer + manifest_len;
+
if (manifest_len < 10 || manifest_len != php_stream_read(fp, buffer, manifest_len)) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
}
/* extract the number of entries */
PHAR_GET_32(buffer, manifest_count);
+
if (manifest_count == 0) {
MAPPHAR_FAIL("in phar \"%s\", manifest claims to have zero entries. Phars must have at least 1 entry");
}
/* extract API version, lowest nibble currently unused */
- manifest_ver = (((unsigned char)buffer[0]) << 8)
- + ((unsigned char)buffer[1]);
+ manifest_ver = (((unsigned char)buffer[0]) << 8)
+ + ((unsigned char)buffer[1]);
buffer += 2;
+
if ((manifest_ver & PHAR_API_VER_MASK) < PHAR_API_MIN_READ) {
efree(savebuf);
php_stream_close(fp);
@@ -706,7 +759,6 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
PHAR_GET_32(buffer, manifest_flags);
manifest_flags &= ~PHAR_HDR_COMPRESSION_MASK;
-
manifest_flags &= ~PHAR_FILE_COMPRESSION_MASK;
/* remember whether this entire phar was compressed with gz/bzip2 */
manifest_flags |= compression;
@@ -720,7 +772,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
if (-1 == php_stream_seek(fp, -8, SEEK_END)
|| (read_len = php_stream_tell(fp)) < 20
- || 8 != php_stream_read(fp, sig_buf, 8)
+ || 8 != php_stream_read(fp, sig_buf, 8)
|| memcmp(sig_buf+4, "GBMB", 4)) {
efree(savebuf);
php_stream_close(fp);
@@ -729,185 +781,191 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
}
return FAILURE;
}
+
PHAR_GET_32(sig_ptr, sig_flags);
+
switch(sig_flags) {
- case PHAR_SIG_OPENSSL: {
- php_uint32 signature_len;
- char *sig;
- off_t whence;
+ case PHAR_SIG_OPENSSL: {
+ php_uint32 signature_len;
+ char *sig;
+ off_t whence;
- /* we store the signature followed by the signature length */
- if (-1 == php_stream_seek(fp, -12, SEEK_CUR)
- || 4 != php_stream_read(fp, sig_buf, 4)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" openssl signature length could not be read", fname);
+ /* we store the signature followed by the signature length */
+ if (-1 == php_stream_seek(fp, -12, SEEK_CUR)
+ || 4 != php_stream_read(fp, sig_buf, 4)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" openssl signature length could not be read", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- sig_ptr = sig_buf;
- PHAR_GET_32(sig_ptr, signature_len);
+ sig_ptr = sig_buf;
+ PHAR_GET_32(sig_ptr, signature_len);
+ sig = (char *) emalloc(signature_len);
+ whence = signature_len + 4;
+ whence = -whence;
- sig = (char *) emalloc(signature_len);
+ if (-1 == php_stream_seek(fp, whence, SEEK_CUR)
+ || !(end_of_phar = php_stream_tell(fp))
+ || signature_len != php_stream_read(fp, sig, signature_len)) {
+ efree(savebuf);
+ efree(sig);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" openssl signature could not be read", fname);
+ }
+ return FAILURE;
+ }
- whence = signature_len + 4;
- whence = -whence;
- if (-1 == php_stream_seek(fp, whence, SEEK_CUR)
- || !(end_of_phar = php_stream_tell(fp))
- || signature_len != php_stream_read(fp, sig, signature_len)) {
- efree(savebuf);
+ if (FAILURE == phar_verify_signature(fp, end_of_phar, PHAR_SIG_OPENSSL, sig, signature_len, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ efree(sig);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" openssl signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
+ }
efree(sig);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" openssl signature could not be read", fname);
- }
- return FAILURE;
}
- if (FAILURE == phar_verify_signature(fp, end_of_phar, PHAR_SIG_OPENSSL, sig, signature_len, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
- efree(sig);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" openssl signature could not be verified: %s", fname, *error);
- efree(save);
- }
- return FAILURE;
- }
- efree(sig);
- }
- break;
+ break;
#if HAVE_HASH_EXT
- case PHAR_SIG_SHA512: {
- unsigned char digest[64];
+ case PHAR_SIG_SHA512: {
+ unsigned char digest[64];
- php_stream_seek(fp, -(8 + 64), SEEK_END);
- read_len = php_stream_tell(fp);
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ php_stream_seek(fp, -(8 + 64), SEEK_END);
+ read_len = php_stream_tell(fp);
+
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA512, (char *)digest, 64, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" SHA512 signature could not be verified: %s", fname, *error);
- efree(save);
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA512, (char *)digest, 64, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA512 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
}
- return FAILURE;
+ break;
}
- break;
- }
- case PHAR_SIG_SHA256: {
- unsigned char digest[32];
+ case PHAR_SIG_SHA256: {
+ unsigned char digest[32];
- php_stream_seek(fp, -(8 + 32), SEEK_END);
- read_len = php_stream_tell(fp);
+ php_stream_seek(fp, -(8 + 32), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA256, (char *)digest, 32, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" SHA256 signature could not be verified: %s", fname, *error);
- efree(save);
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA256, (char *)digest, 32, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA256 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
}
- return FAILURE;
+ break;
}
- break;
- }
#else
- case PHAR_SIG_SHA512:
- case PHAR_SIG_SHA256:
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a unsupported signature", fname);
- }
- return FAILURE;
+ case PHAR_SIG_SHA512:
+ case PHAR_SIG_SHA256:
+ efree(savebuf);
+ php_stream_close(fp);
+
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a unsupported signature", fname);
+ }
+ return FAILURE;
#endif
- case PHAR_SIG_SHA1: {
- unsigned char digest[20];
+ case PHAR_SIG_SHA1: {
+ unsigned char digest[20];
- php_stream_seek(fp, -(8 + 20), SEEK_END);
- read_len = php_stream_tell(fp);
+ php_stream_seek(fp, -(8 + 20), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
+ }
+
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA1, (char *)digest, 20, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA1 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
+ }
+ break;
+ }
+ case PHAR_SIG_MD5: {
+ unsigned char digest[16];
+
+ php_stream_seek(fp, -(8 + 16), SEEK_END);
+ read_len = php_stream_tell(fp);
+
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
+ }
+
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_MD5, (char *)digest, 16, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" MD5 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
+ }
+ break;
+ }
+ default:
efree(savebuf);
php_stream_close(fp);
+
if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ spprintf(error, 0, "phar \"%s\" has a broken or unsupported signature", fname);
}
return FAILURE;
- }
-
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA1, (char *)digest, 20, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" SHA1 signature could not be verified: %s", fname, *error);
- efree(save);
- }
- return FAILURE;
- }
- break;
- }
- case PHAR_SIG_MD5: {
- unsigned char digest[16];
-
- php_stream_seek(fp, -(8 + 16), SEEK_END);
- read_len = php_stream_tell(fp);
-
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
- }
- return FAILURE;
- }
-
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_MD5, (char *)digest, 16, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" MD5 signature could not be verified: %s", fname, *error);
- efree(save);
- }
- return FAILURE;
- }
- break;
- }
- default:
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken or unsupported signature", fname);
- }
- return FAILURE;
}
} else if (PHAR_G(require_hash)) {
efree(savebuf);
php_stream_close(fp);
+
if (error) {
spprintf(error, 0, "phar \"%s\" does not have a signature", fname);
}
@@ -919,12 +977,15 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
/* extract alias */
PHAR_GET_32(buffer, tmp_len);
+
if (buffer + tmp_len > endbuffer) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (buffer overrun)");
}
+
if (manifest_len < 10 + tmp_len) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
}
+
/* tmp_len = 0 says alias length is 0, which means the alias is not stored in the phar */
if (tmp_len) {
/* if the alias is stored we enforce it (implicit overrides explicit) */
@@ -932,15 +993,19 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
{
buffer[tmp_len] = '\0';
php_stream_close(fp);
+
if (signature) {
efree(signature);
}
+
if (error) {
spprintf(error, 0, "cannot load phar \"%s\" with implicit alias \"%s\" under different alias \"%s\"", fname, buffer, alias);
}
+
efree(savebuf);
return FAILURE;
}
+
alias_len = tmp_len;
alias = buffer;
buffer += tmp_len;
@@ -1000,24 +1065,33 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
if (buffer + 4 > endbuffer) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)")
}
+
PHAR_GET_32(buffer, entry.filename_len);
+
if (entry.filename_len == 0) {
MAPPHAR_FAIL("zero-length filename encountered in phar \"%s\"");
}
- if (entry.is_persistent) entry.manifest_pos = manifest_index;
+
+ if (entry.is_persistent) {
+ entry.manifest_pos = manifest_index;
+ }
+
if (buffer + entry.filename_len + 20 > endbuffer) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)");
}
+
if ((manifest_ver & PHAR_API_VER_MASK) >= PHAR_API_MIN_DIR && buffer[entry.filename_len - 1] == '/') {
entry.is_dir = 1;
} else {
entry.is_dir = 0;
}
+
phar_add_virtual_dirs(mydata, buffer, entry.filename_len TSRMLS_CC);
entry.filename = pestrndup(buffer, entry.filename_len, entry.is_persistent);
buffer += entry.filename_len;
PHAR_GET_32(buffer, entry.uncompressed_filesize);
PHAR_GET_32(buffer, entry.timestamp);
+
if (offset == halt_offset + (int)manifest_len + 4) {
mydata->min_timestamp = entry.timestamp;
mydata->max_timestamp = entry.timestamp;
@@ -1028,13 +1102,16 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
mydata->max_timestamp = entry.timestamp;
}
}
+
PHAR_GET_32(buffer, entry.compressed_filesize);
PHAR_GET_32(buffer, entry.crc32);
PHAR_GET_32(buffer, entry.flags);
+
if (entry.is_dir) {
entry.filename_len--;
entry.flags |= PHAR_ENT_PERM_DEF_DIR;
}
+
if (entry.is_persistent) {
if (phar_parse_metadata(&buffer, &entry.metadata, 0 TSRMLS_CC) == FAILURE) {
pefree(entry.filename, entry.is_persistent);
@@ -1046,49 +1123,52 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
}
}
+
entry.offset = entry.offset_abs = offset;
offset += entry.compressed_filesize;
+
switch (entry.flags & PHAR_ENT_COMPRESSION_MASK) {
- case PHAR_ENT_COMPRESSED_GZ:
- if (!PHAR_G(has_zlib)) {
- if (entry.metadata) {
- if (entry.is_persistent) {
- free(entry.metadata);
- } else {
- zval_ptr_dtor(&entry.metadata);
+ case PHAR_ENT_COMPRESSED_GZ:
+ if (!PHAR_G(has_zlib)) {
+ if (entry.metadata) {
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
}
- pefree(entry.filename, entry.is_persistent);
- MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
- }
- break;
- case PHAR_ENT_COMPRESSED_BZ2:
- if (!PHAR_G(has_bz2)) {
- if (entry.metadata) {
- if (entry.is_persistent) {
- free(entry.metadata);
- } else {
- zval_ptr_dtor(&entry.metadata);
+ break;
+ case PHAR_ENT_COMPRESSED_BZ2:
+ if (!PHAR_G(has_bz2)) {
+ if (entry.metadata) {
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
}
- pefree(entry.filename, entry.is_persistent);
- MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
- }
- break;
- default:
- if (entry.uncompressed_filesize != entry.compressed_filesize) {
- if (entry.metadata) {
- if (entry.is_persistent) {
- free(entry.metadata);
- } else {
- zval_ptr_dtor(&entry.metadata);
+ break;
+ default:
+ if (entry.uncompressed_filesize != entry.compressed_filesize) {
+ if (entry.metadata) {
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)");
}
- pefree(entry.filename, entry.is_persistent);
- MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)");
- }
- break;
+ break;
}
+
manifest_flags |= (entry.flags & PHAR_ENT_COMPRESSION_MASK);
/* if signature matched, no need to check CRC32 for each file */
entry.is_crc_checked = (manifest_flags & PHAR_HDR_SIGNATURE ? 1 : 0);
@@ -1101,6 +1181,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
mydata->halt_offset = halt_offset;
mydata->flags = manifest_flags;
endbuffer = strrchr(mydata->fname, '/');
+
if (endbuffer) {
mydata->ext = memchr(endbuffer, '.', (mydata->fname + fname_len) - endbuffer);
if (mydata->ext == endbuffer) {
@@ -1110,6 +1191,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
mydata->ext_len = (mydata->fname + mydata->fname_len) - mydata->ext;
}
}
+
mydata->alias = alias ?
pestrndup(alias, alias_len, mydata->is_persistent) :
pestrndup(mydata->fname, fname_len, mydata->is_persistent);
@@ -1119,15 +1201,18 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
mydata->sig_len = sig_len;
mydata->signature = signature;
phar_request_initialize(TSRMLS_C);
+
if (register_alias) {
phar_archive_data **fd_ptr;
mydata->is_temporary_alias = temp_alias;
+
if (!phar_validate_alias(mydata->alias, mydata->alias_len)) {
signature = NULL;
fp = NULL;
MAPPHAR_FAIL("Cannot open archive \"%s\", invalid alias");
}
+
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
signature = NULL;
@@ -1135,10 +1220,12 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
MAPPHAR_FAIL("Cannot open archive \"%s\", alias is already in use by existing archive");
}
}
+
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
} else {
mydata->is_temporary_alias = 1;
}
+
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
efree(savebuf);
@@ -1161,6 +1248,7 @@ int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int al
phar_archive_data **test, *unused = NULL;
test = &unused;
+
if (error) {
*error = NULL;
}
@@ -1169,6 +1257,7 @@ int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int al
if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, 1 TSRMLS_CC) == SUCCESS) {
goto check_file;
}
+
/* next try to create a new file */
if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, 1 TSRMLS_CC)) {
if (error) {
@@ -1176,18 +1265,19 @@ int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int al
}
return FAILURE;
}
-
check_file:
if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, test, &my_error TSRMLS_CC) == SUCCESS) {
if (pphar) {
*pphar = *test;
}
+
if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) {
if (error) {
spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname);
}
return FAILURE;
}
+
if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) {
phar_entry_info *stub;
if (FAILURE == zend_hash_find(&((*test)->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
@@ -1195,6 +1285,7 @@ check_file:
return FAILURE;
}
}
+
if (!PHAR_G(readonly) || (*test)->is_data) {
(*test)->is_writeable = 1;
}
@@ -1219,7 +1310,6 @@ check_file:
}
return phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC);
-
}
/* }}} */
@@ -1237,13 +1327,13 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
return FAILURE;
}
#endif
-
if (php_check_open_basedir(fname TSRMLS_CC)) {
return FAILURE;
}
/* first open readonly so it won't be created if not present */
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual);
+
if (actual) {
fname = actual;
fname_len = strlen(actual);
@@ -1266,6 +1356,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
return FAILURE;
}
}
+
if (actual) {
efree(actual);
}
@@ -1281,13 +1372,13 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
/* set up our manifest */
mydata = ecalloc(1, sizeof(phar_archive_data));
-
mydata->fname = expand_filepath(fname, NULL TSRMLS_CC);
fname_len = strlen(mydata->fname);
#ifdef PHP_WIN32
phar_unixify_path_separators(mydata->fname, fname_len);
#endif
p = strrchr(mydata->fname, '/');
+
if (p) {
mydata->ext = memchr(p, '.', (mydata->fname + fname_len) - p);
if (mydata->ext == p) {
@@ -1301,6 +1392,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
if (pphar) {
*pphar = mydata;
}
+
zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
zend_get_hash_value, destroy_phar_manifest_entry, 0);
zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
@@ -1316,6 +1408,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
mydata->is_brandnew = 1;
phar_request_initialize(TSRMLS_C);
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
+
if (is_data) {
alias = NULL;
alias_len = 0;
@@ -1330,16 +1423,21 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
if (error) {
spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias);
}
+
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
+
if (pphar) {
*pphar = NULL;
}
+
return FAILURE;
}
}
+
mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
mydata->alias_len = alias ? alias_len : fname_len;
}
+
if (alias_len && alias) {
if (FAILURE == zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL)) {
if (options & REPORT_ERRORS) {
@@ -1347,13 +1445,17 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias);
}
}
+
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
+
if (pphar) {
*pphar = NULL;
}
+
return FAILURE;
}
}
+
return SUCCESS;
}
/* }}}*/
@@ -1384,18 +1486,17 @@ int phar_open_from_filename(char *fname, int fname_len, char *alias, int alias_l
} else if (error && *error) {
return FAILURE;
}
-
#if PHP_MAJOR_VERSION < 6
if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
return FAILURE;
}
#endif
-
if (php_check_open_basedir(fname TSRMLS_CC)) {
return FAILURE;
}
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);
+
if (!fp) {
if (options & REPORT_ERRORS) {
if (error) {
@@ -1414,9 +1515,11 @@ int phar_open_from_filename(char *fname, int fname_len, char *alias, int alias_l
}
ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
+
if (actual) {
efree(actual);
}
+
return ret;
}
/* }}}*/
@@ -1429,15 +1532,20 @@ static inline char *phar_strnstr(const char *buf, int buf_len, const char *searc
if (buf_len < search_len) {
return NULL;
}
+
c = buf - 1;
+
do {
if (!(c = memchr(c + 1, search[0], buf_len - search_len - so_far))) {
return (char *) NULL;
}
+
so_far = c - buf;
+
if (so_far >= (buf_len - search_len)) {
return (char *) NULL;
}
+
if (!memcmp(c, search, search_len)) {
return (char *) c;
}
@@ -1466,6 +1574,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
if (error) {
*error = NULL;
}
+
if (-1 == php_stream_rewind(fp)) {
MAPPHAR_ALLOC_FAIL("cannot rewind phar \"%s\"")
}
@@ -1480,6 +1589,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
if ((got = php_stream_read(fp, buffer+tokenlen, readsize)) < (size_t) tokenlen) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)")
}
+
if (!test) {
test = '\1';
pos = buffer+tokenlen;
@@ -1494,23 +1604,26 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file, enable zlib extension in php.ini")
}
array_init(&filterparams);
-
/* this is defined in zlib's zconf.h */
#ifndef MAX_WBITS
#define MAX_WBITS 15
#endif
add_assoc_long(&filterparams, "window", MAX_WBITS + 32);
+
/* entire file is gzip-compressed, uncompress to temporary file */
if (!(temp = php_stream_fopen_tmpfile())) {
MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"")
}
+
php_stream_rewind(fp);
filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp) TSRMLS_CC);
+
if (!filter) {
err = 1;
add_assoc_long(&filterparams, "window", MAX_WBITS);
filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp) TSRMLS_CC);
zval_dtor(&filterparams);
+
if (!filter) {
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\", ext/zlib is buggy in PHP versions older than 5.2.6")
@@ -1518,7 +1631,9 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
} else {
zval_dtor(&filterparams);
}
+
php_stream_filter_append(&temp->writefilters, filter);
+
if (0 == php_stream_copy_to_stream(fp, temp, PHP_STREAM_COPY_ALL)) {
if (err) {
php_stream_close(temp);
@@ -1527,6 +1642,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file")
}
+
php_stream_filter_flush(filter, 1);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
php_stream_close(fp);
@@ -1544,21 +1660,27 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
if (!PHAR_G(has_bz2)) {
MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file, enable bz2 extension in php.ini")
}
+
/* entire file is bzip-compressed, uncompress to temporary file */
if (!(temp = php_stream_fopen_tmpfile())) {
MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of bzipped phar archive \"%s\"")
}
+
php_stream_rewind(fp);
filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
+
if (!filter) {
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\", filter creation failed")
}
+
php_stream_filter_append(&temp->writefilters, filter);
+
if (0 == php_stream_copy_to_stream(fp, temp, PHP_STREAM_COPY_ALL)) {
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file")
}
+
php_stream_filter_flush(filter, 1);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
php_stream_close(fp);
@@ -1570,10 +1692,12 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
test = '\0';
continue;
}
+
if (!memcmp(pos, zip_magic, 4)) {
php_stream_seek(fp, 0, SEEK_END);
return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error TSRMLS_CC);
}
+
if (got > 512) {
if (phar_is_tar(pos, fname)) {
php_stream_rewind(fp);
@@ -1581,6 +1705,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
}
}
}
+
if (got > 0 && (pos = phar_strnstr(buffer, got + sizeof(token), token, sizeof(token)-1)) != NULL) {
halt_offset += (pos - buffer); /* no -tokenlen+tokenlen here */
return phar_parse_pharfile(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, compression, error TSRMLS_CC);
@@ -1589,7 +1714,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
halt_offset += got;
memmove(buffer, buffer + tokenlen, got + 1);
}
-
+
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (__HALT_COMPILER(); not found)")
}
/* }}} */
@@ -1610,6 +1735,7 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
old = *a;
*a = '\0';
+
if ((realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
#ifdef PHP_WIN32
phar_unixify_path_separators(realpath, strlen(realpath));
@@ -1619,6 +1745,7 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
efree(realpath);
return SUCCESS;
}
+
if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_phars, realpath, strlen(realpath))) {
*a = old;
efree(realpath);
@@ -1626,14 +1753,18 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
}
efree(realpath);
}
+
if (SUCCESS == php_stream_stat_path((char *) fname, &ssb)) {
*a = old;
+
if (ssb.sb.st_mode & S_IFDIR) {
return FAILURE;
}
+
if (for_create == 1) {
return FAILURE;
}
+
return SUCCESS;
} else {
char *slash;
@@ -1642,12 +1773,15 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
*a = old;
return FAILURE;
}
+
slash = (char *) strrchr(fname, '/');
*a = old;
+
if (slash) {
old = *slash;
*slash = '\0';
}
+
if (SUCCESS != php_stream_stat_path((char *) fname, &ssb)) {
if (slash) {
*slash = old;
@@ -1661,29 +1795,37 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
a = strstr(realpath, fname) + ((ext - fname) + ext_len);
*a = '\0';
slash = strrchr(realpath, '/');
+
if (slash) {
*slash = '\0';
} else {
efree(realpath);
return FAILURE;
}
+
if (SUCCESS != php_stream_stat_path(realpath, &ssb)) {
efree(realpath);
return FAILURE;
}
+
efree(realpath);
+
if (ssb.sb.st_mode & S_IFDIR) {
return SUCCESS;
}
}
+
return FAILURE;
}
+
if (slash) {
*slash = old;
}
+
if (ssb.sb.st_mode & S_IFDIR) {
return SUCCESS;
}
+
return FAILURE;
}
}
@@ -1698,6 +1840,7 @@ static int phar_check_str(const char *fname, const char *ext_str, int ext_len, i
if (ext_len >= 50) {
return FAILURE;
}
+
if (executable == 1) {
/* copy "." as well */
memcpy(test, ext_str - 1, ext_len + 1);
@@ -1705,6 +1848,7 @@ static int phar_check_str(const char *fname, const char *ext_str, int ext_len, i
/* executable phars must contain ".phar" as a valid extension (phar://.pharmy/oops is invalid) */
/* (phar://hi/there/.phar/oops is also invalid) */
pos = strstr(test, ".phar");
+
if (pos && (*(pos - 1) != '/')
&& (pos += 5) && (*pos == '\0' || *pos == '/' || *pos == '.')) {
return phar_analyze_path(fname, ext_str, ext_len, for_create TSRMLS_CC);
@@ -1712,6 +1856,7 @@ static int phar_check_str(const char *fname, const char *ext_str, int ext_len, i
return FAILURE;
}
}
+
/* data phars need only contain a single non-"." to be valid */
if (!executable) {
pos = strstr(ext_str, ".phar");
@@ -1724,6 +1869,7 @@ static int phar_check_str(const char *fname, const char *ext_str, int ext_len, i
return phar_analyze_path(fname, ext_str, ext_len, for_create TSRMLS_CC);
}
}
+
return FAILURE;
}
/* }}} */
@@ -1750,15 +1896,18 @@ int phar_detect_phar_fname_ext(const char *filename, int filename_len, const cha
if (!filename_len || filename_len == 1) {
return FAILURE;
}
+
phar_request_initialize(TSRMLS_C);
/* first check for alias in first segment */
pos = memchr(filename, '/', filename_len);
+
if (pos && pos != filename) {
if (zend_hash_exists(&(PHAR_GLOBALS->phar_alias_map), (char *) filename, pos - filename)) {
*ext_str = pos;
*ext_len = -1;
return FAILURE;
}
+
if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_alias, (char *) filename, pos - filename)) {
*ext_str = pos;
*ext_len = -1;
@@ -1774,17 +1923,22 @@ int phar_detect_phar_fname_ext(const char *filename, int filename_len, const cha
*ext_str = filename + (filename_len - (*pphar)->ext_len);
woohoo:
*ext_len = (*pphar)->ext_len;
+
if (executable == 2) {
return SUCCESS;
}
+
if (executable == 1 && !(*pphar)->is_data) {
return SUCCESS;
}
+
if (!executable && (*pphar)->is_data) {
return SUCCESS;
}
+
return FAILURE;
}
+
if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_find(&cached_phars, (char *) filename, filename_len, (void **)&pphar)) {
*ext_str = filename + (filename_len - (*pphar)->ext_len);
goto woohoo;
@@ -1796,6 +1950,7 @@ woohoo:
ulong unused;
zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_fname_map));
+
while (FAILURE != zend_hash_has_more_elements(&(PHAR_GLOBALS->phar_fname_map))) {
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_fname_map), &key, &keylen, &unused, 0, NULL)) {
break;
@@ -1807,6 +1962,7 @@ woohoo:
zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
continue;
}
+
if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen
|| filename[keylen] == '/' || filename[keylen] == '\0')) {
if (FAILURE == zend_hash_get_current_data(&(PHAR_GLOBALS->phar_fname_map), (void **) &pphar)) {
@@ -1815,10 +1971,13 @@ woohoo:
*ext_str = filename + (keylen - (*pphar)->ext_len);
goto woohoo;
}
+
zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
}
+
if (PHAR_G(manifest_cached)) {
zend_hash_internal_pointer_reset(&cached_phars);
+
while (FAILURE != zend_hash_has_more_elements(&cached_phars)) {
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&cached_phars, &key, &keylen, &unused, 0, NULL)) {
break;
@@ -1830,6 +1989,7 @@ woohoo:
zend_hash_move_forward(&cached_phars);
continue;
}
+
if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen
|| filename[keylen] == '/' || filename[keylen] == '\0')) {
if (FAILURE == zend_hash_get_current_data(&cached_phars, (void **) &pphar)) {
@@ -1849,6 +2009,7 @@ next_extension:
if (!pos) {
return FAILURE;
}
+
while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) {
pos = memchr(pos + 1, '.', filename_len - (pos - filename) + 1);
if (!pos) {
@@ -1857,26 +2018,30 @@ next_extension:
}
slash = memchr(pos, '/', filename_len - (pos - filename));
+
if (!slash) {
/* this is a url like "phar://blah.phar" with no directory */
*ext_str = pos;
*ext_len = strlen(pos);
+
/* file extension must contain "phar" */
switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
- case SUCCESS :
+ case SUCCESS:
return SUCCESS;
- case FAILURE :
+ case FAILURE:
/* we are at the end of the string, so we fail */
return FAILURE;
}
}
+
/* we've found an extension that ends at a directory separator */
*ext_str = pos;
*ext_len = slash - pos;
+
switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
- case SUCCESS :
+ case SUCCESS:
return SUCCESS;
- case FAILURE :
+ case FAILURE:
/* look for more extensions */
pos = strchr(pos + 1, '.');
if (pos) {
@@ -1885,11 +2050,12 @@ next_extension:
}
goto next_extension;
}
+
return FAILURE;
}
/* }}} */
-static int php_check_dots(const char *element, int n) /* {{{ */
+static int php_check_dots(const char *element, int n) /* {{{ */
{
for(n--; n >= 0; --n) {
if (element[n] != '.') {
@@ -1906,7 +2072,7 @@ static int php_check_dots(const char *element, int n) /* {{{ */
#define IS_DIRECTORY_CURRENT(element, len) \
(len == 1 && element[0] == '.')
-#define IS_BACKSLASH(c) ((c) == '/')
+#define IS_BACKSLASH(c) ((c) == '/')
#ifdef COMPILE_DL_PHAR
/* stupid-ass non-extern declaration in tsrm_strtok.h breaks dumbass MS compiler */
@@ -1933,6 +2099,7 @@ char *tsrm_strtok_r(char *s, const char *delim, char **last) /* {{{ */
while (*s && in_character_class(*s, delim)) {
++s;
}
+
if (!*s) {
return NULL;
}
@@ -1942,12 +2109,14 @@ char *tsrm_strtok_r(char *s, const char *delim, char **last) /* {{{ */
while (*s && !in_character_class(*s, delim)) {
++s;
}
+
if (!*s) {
*last = s;
} else {
*s = '\0';
*last = s + 1;
}
+
return token;
}
/* }}} */
@@ -1971,22 +2140,29 @@ char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC) /* {{{
newpath[0] = '/';
newpath_len = 1;
}
+
ptr = path;
- if (*ptr == '/') ++ptr;
+
+ if (*ptr == '/') {
+ ++ptr;
+ }
+
tok = ptr;
+
do {
ptr = memchr(ptr, '/', path_length - (ptr - path));
} while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);
+
if (!ptr && (path_length - (tok - path))) {
switch (path_length - (tok - path)) {
- case 1 :
+ case 1:
if (*tok == '.') {
efree(path);
*new_len = 1;
return estrndup("/", 1);
}
break;
- case 2 :
+ case 2:
if (tok[0] == '.' && tok[1] == '.') {
efree(path);
*new_len = 1;
@@ -1995,6 +2171,7 @@ char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC) /* {{{
}
return path;
}
+
while (ptr) {
ptr_length = ptr - tok;
last_time:
@@ -2020,19 +2197,24 @@ last_time:
newpath_len += ptr_length;
}
+
if (ptr == path + path_length) {
break;
}
+
tok = ++ptr;
+
do {
ptr = memchr(ptr, '/', path_length - (ptr - path));
} while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);
+
if (!ptr && (path_length - (tok - path))) {
ptr_length = path_length - (tok - path);
ptr = path + path_length;
goto last_time;
}
}
+
efree(path);
*new_len = newpath_len;
return estrndup(newpath, newpath_len);
@@ -2081,17 +2263,21 @@ int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_le
*arch = filename;
#endif
}
+
if (free_filename) {
efree(filename);
}
+
return FAILURE;
}
+
ext_len = 0;
/* no extension detected - instead we are dealing with an alias */
}
*arch_len = ext_str - filename + ext_len;
*arch = estrndup(filename, *arch_len);
+
if (ext_str[ext_len]) {
*entry_len = filename_len - *arch_len;
*entry = estrndup(ext_str+ext_len, *entry_len);
@@ -2103,9 +2289,11 @@ int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_le
*entry_len = 1;
*entry = estrndup("/", 1);
}
+
if (free_filename) {
efree(filename);
}
+
return SUCCESS;
}
/* }}} */
@@ -2127,6 +2315,7 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error TSRMLS_
if (error) {
*error = NULL;
}
+
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
@@ -2142,6 +2331,7 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error TSRMLS_
}
MAKE_STD_ZVAL(halt_constant);
+
if (0 == zend_get_constant("__COMPILER_HALT_OFFSET__", 24, halt_constant TSRMLS_CC)) {
FREE_ZVAL(halt_constant);
if (error) {
@@ -2149,6 +2339,7 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error TSRMLS_
}
return FAILURE;
}
+
halt_offset = Z_LVAL(*halt_constant);
FREE_ZVAL(halt_constant);
@@ -2163,6 +2354,7 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error TSRMLS_
}
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, &actual);
+
if (!fp) {
if (error) {
spprintf(error, 0, "unable to open phar for reading \"%s\"", fname);
@@ -2179,9 +2371,11 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error TSRMLS_
}
ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, error TSRMLS_CC);
+
if (actual) {
efree(actual);
}
+
return ret;
}
/* }}} */
@@ -2199,6 +2393,7 @@ int phar_postprocess_file(php_stream_wrapper *wrapper, int options, phar_entry_d
if (error) {
*error = NULL;
}
+
if (entry->is_zip) {
/* verify local file header */
phar_zip_file_header local;
@@ -2214,23 +2409,30 @@ int phar_postprocess_file(php_stream_wrapper *wrapper, int options, phar_entry_d
spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", idata->phar->fname, entry->filename);
return FAILURE;
}
+
/* verify local header */
if (entry->filename_len != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) {
spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local head of file \"%s\" does not match central directory)", idata->phar->fname, entry->filename);
return FAILURE;
}
+
/* construct actual offset to file start - local extra_len can be different from central extra_len */
entry->offset = entry->offset_abs =
sizeof(local) + entry->header_offset + PHAR_ZIP_16(local.filename_len) + PHAR_ZIP_16(local.extra_len);
+
if (idata->zero && idata->zero != entry->offset_abs) {
idata->zero = entry->offset_abs;
}
}
- php_stream_seek(fp, idata->zero, SEEK_SET);
+
+ php_stream_seek(fp, idata->zero, SEEK_SET);
+
while (len--) {
CRC32(crc, php_stream_getc(fp));
}
+
php_stream_seek(fp, idata->zero, SEEK_SET);
+
if (~crc == crc32) {
entry->is_crc_checked = 1;
return SUCCESS;
@@ -2352,6 +2554,7 @@ static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t end,
zval_dtor(openssl);
return FAILURE;
}
+
zval_dtor(openssl);
efree(openssl);
@@ -2363,11 +2566,13 @@ static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t end,
++(zkey->refcount);
#else
Z_ADDREF_P(zdata);
+
if (is_sign) {
Z_SET_ISREF_P(zsig);
} else {
Z_ADDREF_P(zsig);
}
+
Z_ADDREF_P(zkey);
#endif
fci.retval_ptr_ptr = &retval_ptr;
@@ -2387,20 +2592,23 @@ static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t end,
--(zkey->refcount);
#else
Z_DELREF_P(zdata);
+
if (is_sign) {
Z_UNSET_ISREF_P(zsig);
} else {
Z_DELREF_P(zsig);
}
+
Z_DELREF_P(zkey);
#endif
zval_dtor(zdata);
efree(zdata);
zval_dtor(zkey);
efree(zkey);
+
switch (Z_TYPE_P(retval_ptr)) {
default:
- case IS_LONG :
+ case IS_LONG:
zval_dtor(zsig);
efree(zsig);
if (1 == Z_LVAL_P(retval_ptr)) {
@@ -2409,7 +2617,7 @@ static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t end,
}
efree(retval_ptr);
return FAILURE;
- case IS_BOOL :
+ case IS_BOOL:
efree(retval_ptr);
if (Z_BVAL_P(retval_ptr)) {
*signature = estrndup(Z_STRVAL_P(zsig), Z_STRLEN_P(zsig));
@@ -2546,7 +2754,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
}
len = pos - user_stub + 18;
if ((size_t)len != php_stream_write(newfile, user_stub, len)
- || 5 != php_stream_write(newfile, " ?>\r\n", 5)) {
+ || 5 != php_stream_write(newfile, " ?>\r\n", 5)) {
if (closeoldfile) {
php_stream_close(oldfile);
}
@@ -2615,8 +2823,8 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
new_manifest_count = 0;
offset = 0;
for (zend_hash_internal_pointer_reset(&phar->manifest);
- zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
- zend_hash_move_forward(&phar->manifest)) {
+ zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
+ zend_hash_move_forward(&phar->manifest)) {
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
@@ -2808,55 +3016,67 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
/* write the manifest header */
if (sizeof(manifest) != php_stream_write(newfile, manifest, sizeof(manifest))
|| (size_t)phar->alias_len != php_stream_write(newfile, phar->alias, phar->alias_len)) {
+
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
phar->alias_len = restore_alias_len;
+
if (error) {
spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname);
}
+
return EOF;
}
-
+
phar->alias_len = restore_alias_len;
-
+
phar_set_32(manifest, main_metadata_str.len);
if (4 != php_stream_write(newfile, manifest, 4) || (main_metadata_str.len
&& main_metadata_str.len != php_stream_write(newfile, main_metadata_str.c, main_metadata_str.len))) {
smart_str_free(&main_metadata_str);
+
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
phar->alias_len = restore_alias_len;
+
if (error) {
spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname);
}
+
return EOF;
- }
+ }
smart_str_free(&main_metadata_str);
-
+
/* re-calculate the manifest location to simplify later code */
manifest_ftell = php_stream_tell(newfile);
-
+
/* now write the manifest */
for (zend_hash_internal_pointer_reset(&phar->manifest);
- zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
- zend_hash_move_forward(&phar->manifest)) {
+ zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
+ zend_hash_move_forward(&phar->manifest)) {
+
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
+
if (entry->is_deleted || entry->is_mounted) {
/* remove this from the new phar if deleted, ignore if mounted */
continue;
}
+
if (entry->is_dir) {
/* add 1 for trailing slash */
phar_set_32(entry_buffer, entry->filename_len + 1);
} else {
phar_set_32(entry_buffer, entry->filename_len);
}
+
if (4 != php_stream_write(newfile, entry_buffer, 4)
|| entry->filename_len != php_stream_write(newfile, entry->filename, entry->filename_len)
|| (entry->is_dir && 1 != php_stream_write(newfile, "/", 1))) {
@@ -2873,6 +3093,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
}
return EOF;
}
+
/* set the manifest meta-data:
4: uncompressed filesize
4: creation timestamp
@@ -2889,30 +3110,37 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
phar_set_32(entry_buffer+12, entry->crc32);
phar_set_32(entry_buffer+16, entry->flags);
phar_set_32(entry_buffer+20, entry->metadata_str.len);
+
if (sizeof(entry_buffer) != php_stream_write(newfile, entry_buffer, sizeof(entry_buffer))
|| entry->metadata_str.len != php_stream_write(newfile, entry->metadata_str.c, entry->metadata_str.len)) {
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
+
if (error) {
spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
}
+
return EOF;
}
}
-
+
/* now copy the actual file data to the new phar */
offset = php_stream_tell(newfile);
for (zend_hash_internal_pointer_reset(&phar->manifest);
- zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
- zend_hash_move_forward(&phar->manifest)) {
+ zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
+ zend_hash_move_forward(&phar->manifest)) {
+
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
+
if (entry->is_deleted || entry->is_dir || entry->is_mounted) {
continue;
}
+
if (entry->cfp) {
file = entry->cfp;
php_stream_rewind(file);
@@ -2929,6 +3157,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
return EOF;
}
}
+
if (!file) {
if (closeoldfile) {
php_stream_close(oldfile);
@@ -2939,32 +3168,39 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
}
return EOF;
}
- /* this will have changed for all files that have either
- changed compression or been modified */
+
+ /* this will have changed for all files that have either changed compression or been modified */
entry->offset = entry->offset_abs = offset;
offset += entry->compressed_filesize;
wrote = php_stream_copy_to_stream(file, newfile, entry->compressed_filesize);
+
if (entry->compressed_filesize != wrote) {
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
+
if (error) {
spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
}
+
return EOF;
}
+
entry->is_modified = 0;
+
if (entry->cfp) {
php_stream_close(entry->cfp);
entry->cfp = NULL;
}
+
if (entry->fp_type == PHAR_MOD) {
- /* this fp is in use by a phar_entry_data returned by phar_get_entry_data, it will be closed
- when the phar_entry_data is phar_entry_delref'ed */
+ /* this fp is in use by a phar_entry_data returned by phar_get_entry_data, it will be closed when the phar_entry_data is phar_entry_delref'ed */
if (entry->fp_refcount == 0 && entry->fp != phar->fp && entry->fp != phar->ufp) {
php_stream_close(entry->fp);
}
+
entry->fp = NULL;
entry->fp_type = PHAR_FP;
} else if (entry->fp_type == PHAR_UFP) {
@@ -3034,12 +3270,14 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
if (phar->fp && free_fp) {
php_stream_close(phar->fp);
}
+
if (phar->ufp) {
if (free_ufp) {
php_stream_close(phar->ufp);
}
phar->ufp = NULL;
}
+
if (closeoldfile) {
php_stream_close(oldfile);
}
@@ -3062,6 +3300,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
}
return EOF;
}
+
if (phar->flags & PHAR_FILE_COMPRESSED_GZ) {
php_stream_filter *filter;
/* to properly compress, we have to tell zlib to add a zlib header */
@@ -3071,12 +3310,14 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
add_assoc_long(&filterparams, "window", MAX_WBITS+16);
filter = php_stream_filter_create("zlib.deflate", &filterparams, php_stream_is_persistent(phar->fp) TSRMLS_CC);
zval_dtor(&filterparams);
+
if (!filter) {
if (error) {
spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname);
}
return EOF;
}
+
php_stream_filter_append(&phar->fp->writefilters, filter);
php_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL);
php_stream_filter_flush(filter, 1);
@@ -3122,7 +3363,7 @@ ZEND_GET_MODULE(phar)
* Every user visible function must have an entry in phar_functions[].
*/
function_entry phar_functions[] = {
- {NULL, NULL, NULL} /* Must be the last line in phar_functions[] */
+ {NULL, NULL, NULL} /* Must be the last line in phar_functions[] */
};
/* }}}*/
@@ -3222,18 +3463,22 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type
}
}
}
+
zend_try {
failed = 0;
res = phar_orig_compile_file(file_handle, type TSRMLS_CC);
} zend_catch {
failed = 1;
} zend_end_try();
+
if (name) {
efree(name);
}
+
if (failed) {
zend_bailout();
}
+
return res;
}
/* }}} */
@@ -3253,6 +3498,7 @@ int phar_zend_open(const char *filename, zend_file_handle *handle TSRMLS_DC) /*
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
+
if (fname_len > 7 && !strncasecmp(fname, "phar://", 7)) {
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);
@@ -3263,11 +3509,13 @@ int phar_zend_open(const char *filename, zend_file_handle *handle TSRMLS_DC) /*
efree(entry);
}
}
+
/* retrieving an include within the current directory, so use this if possible */
if (!(entry = phar_find_in_include_path((char *) filename, strlen(filename), NULL TSRMLS_CC))) {
/* this file is not in the phar, use the original path */
goto skip_phar;
}
+
if (SUCCESS == phar_orig_zend_open(entry, handle TSRMLS_CC)) {
if (!handle->opened_path) {
handle->opened_path = entry;
@@ -3277,9 +3525,11 @@ int phar_zend_open(const char *filename, zend_file_handle *handle TSRMLS_DC) /*
}
return SUCCESS;
}
+
if (entry != filename) {
efree(entry);
}
+
return FAILURE;
}
skip_phar:
@@ -3404,6 +3654,7 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */
PHAR_GLOBALS->request_done = 0;
zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), 5, zend_get_hash_value, destroy_phar_data, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), 5, zend_get_hash_value, NULL, 0);
+
if (PHAR_G(manifest_cached)) {
phar_archive_data **pphar;
phar_entry_fp *stuff = (phar_entry_fp *) ecalloc(zend_hash_num_elements(&cached_phars), sizeof(phar_entry_fp));
@@ -3413,8 +3664,10 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */
zend_hash_move_forward(&cached_phars)) {
stuff[pphar[0]->phar_pos].manifest = (phar_entry_fp_info *) ecalloc( zend_hash_num_elements(&(pphar[0]->manifest)), sizeof(phar_entry_fp_info));
}
+
PHAR_GLOBALS->cached_fp = stuff;
}
+
PHAR_GLOBALS->phar_SERVER_mung_list = 0;
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
@@ -3429,6 +3682,7 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */
int i;
PHAR_GLOBALS->request_ends = 1;
+
if (PHAR_GLOBALS->request_init)
{
phar_release_functions(TSRMLS_C);
@@ -3437,6 +3691,7 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */
zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map));
PHAR_GLOBALS->phar_fname_map.arBuckets = NULL;
PHAR_GLOBALS->phar_SERVER_mung_list = 0;
+
if (PHAR_GLOBALS->cached_fp) {
for (i = 0; i < zend_hash_num_elements(&cached_phars); ++i) {
if (PHAR_GLOBALS->cached_fp[i].fp) {
@@ -3450,14 +3705,18 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */
efree(PHAR_GLOBALS->cached_fp);
PHAR_GLOBALS->cached_fp = 0;
}
+
PHAR_GLOBALS->request_init = 0;
+
if (PHAR_G(cwd)) {
efree(PHAR_G(cwd));
}
+
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
PHAR_G(cwd_init) = 0;
}
+
PHAR_GLOBALS->request_done = 1;
return SUCCESS;
}
@@ -3474,11 +3733,13 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */
php_info_print_table_row(2, "Phar-based phar archives", "enabled");
php_info_print_table_row(2, "Tar-based phar archives", "enabled");
php_info_print_table_row(2, "ZIP-based phar archives", "enabled");
+
if (PHAR_G(has_zlib)) {
php_info_print_table_row(2, "gzip compression", "enabled");
} else {
php_info_print_table_row(2, "gzip compression", "disabled (install ext/zlib)");
}
+
if (PHAR_G(has_bz2)) {
php_info_print_table_row(2, "bzip2 compression", "enabled");
} else {
@@ -3497,10 +3758,10 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */
php_info_print_box_start(0);
PUTS("Phar based on pear/PHP_Archive, original concept by Davey Shafik.");
- PUTS(!sapi_module.phpinfo_as_text?"
":"\n");
+ PUTS(!sapi_module.phpinfo_as_text?"
":"\n");
PUTS("Phar fully realized by Gregory Beaver and Marcus Boerger.");
- PUTS(!sapi_module.phpinfo_as_text?"
":"\n");
- PUTS("Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.");
+ PUTS(!sapi_module.phpinfo_as_text?"
":"\n");
+ PUTS("Portions of tar implementation Copyright (c) 2003-2008 Tim Kientzle.");
php_info_print_box_end();
DISPLAY_INI_ENTRIES();
diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h
index 52242c4231e..d97dee0adbf 100755
--- a/ext/phar/phar_internal.h
+++ b/ext/phar/phar_internal.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2006-2007 The PHP Group |
+ | Copyright (c) 2006-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -163,7 +163,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phar)
int has_bz2;
zend_bool readonly_orig;
zend_bool require_hash_orig;
- zend_bool intercepted;
+ zend_bool intercepted;
int request_init;
int require_hash;
int request_done;
@@ -493,8 +493,8 @@ union _phar_archive_object {
zend_object std;
spl_filesystem_object spl;
struct {
- zend_object std;
- phar_archive_data *archive;
+ zend_object std;
+ phar_archive_data *archive;
} arc;
};
#endif
@@ -505,8 +505,8 @@ union _phar_entry_object {
zend_object std;
spl_filesystem_object spl;
struct {
- zend_object std;
- phar_entry_info *entry;
+ zend_object std;
+ phar_entry_info *entry;
} ent;
};
#endif
@@ -520,11 +520,15 @@ extern char *(*phar_save_resolve_path)(const char *filename, int filename_len TS
#if PHP_VERSION_ID >= 60000
typedef zstr phar_zstr;
#define PHAR_STR(a, b) \
- spprintf(&b, 0, "%r", a.s);
+ spprintf(&b, 0, "%s", a.s);
+#define PHAR_ZSTR(a, b) \
+ b = ZSTR(a);
#else
typedef char *phar_zstr;
#define PHAR_STR(a, b) \
b = a;
+#define PHAR_ZSTR(a, b) \
+ b = a;
#endif
BEGIN_EXTERN_C()
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index add4495c493..fe8eff26614 100755
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2005-2007 The PHP Group |
+ | Copyright (c) 2005-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -65,42 +65,47 @@ static void phar_mung_server_vars(char *fname, char *entry, int entry_len, char
_SERVER = Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]);
/* PATH_INFO and PATH_TRANSLATED should always be munged */
- if (SUCCESS == zend_hash_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO"), (void **) &stuff)) {
- int code;
- zval *temp;
+ if (SUCCESS == zend_hash_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO"), (void **) &stuff)) {
+ int code;
+ zval *temp;
path_info = Z_STRVAL_PP(stuff);
code = Z_STRLEN_PP(stuff);
+
if (Z_STRLEN_PP(stuff) > entry_len && !memcmp(Z_STRVAL_PP(stuff), entry, entry_len)) {
ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + entry_len, request_uri_len, 1);
- MAKE_STD_ZVAL(temp);
+ MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
zend_hash_update(_SERVER, "PHAR_PATH_INFO", sizeof("PHAR_PATH_INFO"), (void *) &temp, sizeof(zval **), NULL);
}
}
- if (SUCCESS == zend_hash_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"), (void **) &stuff)) {
- int code;
- zval *temp;
- path_info = Z_STRVAL_PP(stuff);
- code = Z_STRLEN_PP(stuff);
+ if (SUCCESS == zend_hash_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"), (void **) &stuff)) {
+ int code;
+ zval *temp;
+
+ path_info = Z_STRVAL_PP(stuff);
+ code = Z_STRLEN_PP(stuff);
Z_STRLEN_PP(stuff) = spprintf(&(Z_STRVAL_PP(stuff)), 4096, "phar://%s%s", fname, entry);
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
- zend_hash_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED"), (void *) &temp, sizeof(zval **), NULL);
+ zend_hash_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED"), (void *) &temp, sizeof(zval **), NULL);
}
+
if (!PHAR_GLOBALS->phar_SERVER_mung_list) {
return;
}
+
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_REQUEST_URI) {
- if (SUCCESS == zend_hash_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &stuff)) {
+ if (SUCCESS == zend_hash_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &stuff)) {
int code;
zval *temp;
path_info = Z_STRVAL_PP(stuff);
code = Z_STRLEN_PP(stuff);
+
if (Z_STRLEN_PP(stuff) > basename_len && !memcmp(Z_STRVAL_PP(stuff), basename, basename_len)) {
ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + basename_len, Z_STRLEN_PP(stuff) - basename_len, 1);
@@ -110,13 +115,15 @@ static void phar_mung_server_vars(char *fname, char *entry, int entry_len, char
}
}
}
+
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_PHP_SELF) {
- if (SUCCESS == zend_hash_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF"), (void **) &stuff)) {
+ if (SUCCESS == zend_hash_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF"), (void **) &stuff)) {
int code;
zval *temp;
path_info = Z_STRVAL_PP(stuff);
code = Z_STRLEN_PP(stuff);
+
if (Z_STRLEN_PP(stuff) > basename_len && !memcmp(Z_STRVAL_PP(stuff), basename, basename_len)) {
ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + basename_len, Z_STRLEN_PP(stuff) - basename_len, 1);
@@ -128,32 +135,32 @@ static void phar_mung_server_vars(char *fname, char *entry, int entry_len, char
}
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_SCRIPT_NAME) {
- if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void **) &stuff)) {
- int code;
- zval *temp;
-
- path_info = Z_STRVAL_PP(stuff);
- code = Z_STRLEN_PP(stuff);
+ if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void **) &stuff)) {
+ int code;
+ zval *temp;
+
+ path_info = Z_STRVAL_PP(stuff);
+ code = Z_STRLEN_PP(stuff);
ZVAL_STRINGL(*stuff, entry, entry_len, 1);
-
+
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
- zend_hash_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME"), (void *) &temp, sizeof(zval **), NULL);
- }
+ zend_hash_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME"), (void *) &temp, sizeof(zval **), NULL);
+ }
}
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_SCRIPT_FILENAME) {
if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &stuff)) {
- int code;
- zval *temp;
+ int code;
+ zval *temp;
- path_info = Z_STRVAL_PP(stuff);
- code = Z_STRLEN_PP(stuff);
+ path_info = Z_STRVAL_PP(stuff);
+ code = Z_STRLEN_PP(stuff);
Z_STRLEN_PP(stuff) = spprintf(&(Z_STRVAL_PP(stuff)), 4096, "phar://%s%s", fname, entry);
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
- zend_hash_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME"), (void *) &temp, sizeof(zval **), NULL);
+ zend_hash_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME"), (void *) &temp, sizeof(zval **), NULL);
}
}
}
@@ -199,12 +206,14 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %d", info->uncompressed_filesize);
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
efree(ctr.line);
+
if (FAILURE == sapi_send_headers(TSRMLS_C)) {
zend_bailout();
}
/* prepare to output */
fp = phar_get_efp(info, 1 TSRMLS_CC);
+
if (!fp) {
char *error;
if (!phar_open_jit(phar, info, phar_get_pharfp(phar TSRMLS_CC), &error, 0 TSRMLS_CC)) {
@@ -218,6 +227,7 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
}
position = 0;
phar_seek_efp(info, 0, SEEK_SET, 0, 1 TSRMLS_CC);
+
do {
got = php_stream_read(fp, buf, MIN(8192, info->uncompressed_filesize - position));
if (got > 0) {
@@ -235,6 +245,7 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
phar_mung_server_vars(arch, entry, entry_len, basename, ru, ru_len TSRMLS_CC);
efree(basename);
}
+
if (entry[0] == '/') {
name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
} else {
@@ -249,6 +260,7 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
+
if (zend_hash_add(&EG(included_files), name, name_len+1, (void *)&dummy, sizeof(int), NULL) == SUCCESS) {
if ((cwd = zend_memrchr(entry, '/', entry_len))) {
PHAR_G(cwd_init) = 1;
@@ -264,11 +276,15 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
PHAR_G(cwd) = estrndup(entry, PHAR_G(cwd_len));
}
}
+
new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
+
if (!new_op_array) {
zend_hash_del(&EG(included_files), name, name_len+1);
}
+
zend_destroy_file_handle(&file_handle TSRMLS_CC);
+
} else {
efree(name);
new_op_array = NULL;
@@ -286,18 +302,23 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
} zend_end_try();
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
+
if (PHAR_G(cwd)) {
efree(PHAR_G(cwd));
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
}
+
PHAR_G(cwd_init) = 0;
efree(name);
+
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
+
zend_bailout();
}
+
return PHAR_MIME_PHP;
}
return -1;
@@ -355,6 +376,7 @@ static void phar_postprocess_ru_web(char *fname, int fname_len, char **entry, in
/* we already know we can retrieve the phar if we reach here */
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void **) &pphar);
+
if (!pphar && PHAR_G(manifest_cached)) {
zend_hash_find(&cached_phars, fname, fname_len, (void **) &pphar);
}
@@ -373,6 +395,7 @@ static void phar_postprocess_ru_web(char *fname, int fname_len, char **entry, in
*entry_len = e_len + 1;
return;
}
+
if (u) {
u1 = strrchr(e, '/');
u[0] = '/';
@@ -391,9 +414,11 @@ static void phar_postprocess_ru_web(char *fname, int fname_len, char **entry, in
return;
}
}
+
u[0] = '\0';
u_len = strlen(u + 1);
e_len -= u_len + 1;
+
if (e_len < 0) {
if (saveu) {
saveu[0] = '/';
@@ -431,6 +456,7 @@ PHP_METHOD(Phar, running)
RETURN_STRINGL(arch, arch_len, 0);
}
}
+
RETURN_STRINGL("", 0, 1);
}
/* }}} */
@@ -461,6 +487,7 @@ PHP_METHOD(Phar, mount)
if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
efree(entry);
entry = NULL;
+
if (path_len > 7 && !memcmp(path, "phar://", 7)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path);
efree(arch);
@@ -473,7 +500,9 @@ carry_on2:
goto carry_on;
}
}
+
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s is not a phar archive, cannot mount", arch);
+
if (arch) {
efree(arch);
}
@@ -485,17 +514,22 @@ carry_on:
if (path && path == entry) {
efree(entry);
}
+
if (arch) {
efree(arch);
}
+
return;
}
+
if (entry && path && path == entry) {
efree(entry);
}
+
if (arch) {
efree(arch);
}
+
return;
} else if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void **)&pphar)) {
goto carry_on;
@@ -503,12 +537,14 @@ carry_on:
if (SUCCESS == phar_copy_on_write(pphar TSRMLS_CC)) {
goto carry_on;
}
+
goto carry_on;
} else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
path = entry;
path_len = entry_len;
goto carry_on2;
}
+
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Mounting of %s to %s failed", path, actual);
}
/* }}} */
@@ -537,6 +573,7 @@ PHP_METHOD(Phar, webPhar)
phar_request_initialize(TSRMLS_C);
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
+
if (phar_open_executed_filename(alias, alias_len, &error TSRMLS_CC) != SUCCESS) {
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
@@ -549,11 +586,13 @@ PHP_METHOD(Phar, webPhar)
if (!(SG(request_info).request_method && SG(request_info).request_uri && (!strcmp(SG(request_info).request_method, "GET") || !strcmp(SG(request_info).request_method, "POST")))) {
return;
}
+
#ifdef PHP_WIN32
fname = estrndup(fname, fname_len);
phar_unixify_path_separators(fname, fname_len);
#endif
basename = zend_memrchr(fname, '/', fname_len);
+
if (!basename) {
basename = fname;
} else {
@@ -568,12 +607,13 @@ PHP_METHOD(Phar, webPhar)
zval **z_script_name, **z_path_info;
if (SUCCESS != zend_hash_find(ht, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void**)&z_script_name) ||
- IS_STRING != Z_TYPE_PP(z_script_name) ||
- !strstr(Z_STRVAL_PP(z_script_name), basename)) {
+ IS_STRING != Z_TYPE_PP(z_script_name) ||
+ !strstr(Z_STRVAL_PP(z_script_name), basename)) {
return;
}
+
if (SUCCESS == zend_hash_find(ht, "PATH_INFO", sizeof("PATH_INFO"), (void**)&z_path_info) &&
- IS_STRING == Z_TYPE_PP(z_path_info)) {
+ IS_STRING == Z_TYPE_PP(z_path_info)) {
entry_len = Z_STRLEN_PP(z_path_info);
entry = estrndup(Z_STRVAL_PP(z_path_info), entry_len);
path_info = emalloc(Z_STRLEN_PP(z_script_name) + entry_len + 1);
@@ -585,7 +625,9 @@ PHP_METHOD(Phar, webPhar)
entry = estrndup("", 0);
path_info = Z_STRVAL_PP(z_script_name);
}
+
pt = estrndup(Z_STRVAL_PP(z_script_name), Z_STRLEN_PP(z_script_name));
+
} else {
char *testit;
@@ -594,7 +636,9 @@ PHP_METHOD(Phar, webPhar)
efree(testit);
return;
}
+
path_info = sapi_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
+
if (path_info) {
entry = path_info;
entry_len = strlen(entry);
@@ -606,6 +650,7 @@ PHP_METHOD(Phar, webPhar)
entry = estrndup("", 0);
entry_len = 0;
}
+
pt = estrndup(testit, (pt - testit) + (fname_len - (basename - fname)));
}
not_cgi = 0;
@@ -616,8 +661,8 @@ PHP_METHOD(Phar, webPhar)
/* this can happen with rewrite rules - and we have no idea what to do then, so return */
return;
}
- entry_len = strlen(path_info);
+ entry_len = strlen(path_info);
entry_len -= (pt - path_info) + (fname_len - (basename - fname));
entry = estrndup(pt + (fname_len - (basename - fname)), entry_len);
@@ -640,9 +685,11 @@ PHP_METHOD(Phar, webPhar)
if (FAILURE == zend_fcall_info_init(rewrite, 0, &fci, &fcc, NULL, NULL TSRMLS_CC)) {
#endif
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: invalid rewrite callback");
+
if (free_pathinfo) {
efree(path_info);
}
+
return;
}
@@ -659,11 +706,14 @@ PHP_METHOD(Phar, webPhar)
if (!EG(exception)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: failed to call rewrite callback");
}
+
if (free_pathinfo) {
efree(path_info);
}
+
return;
}
+
if (!fci.retval_ptr_ptr || !retval_ptr) {
if (free_pathinfo) {
efree(path_info);
@@ -671,9 +721,16 @@ PHP_METHOD(Phar, webPhar)
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: rewrite callback must return a string or false");
return;
}
+
switch (Z_TYPE_P(retval_ptr)) {
- case IS_STRING :
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(retval_ptr TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
+ case IS_STRING:
efree(entry);
+
if (fci.retval_ptr_ptr != &retval_ptr) {
entry = estrndup(Z_STRVAL_PP(fci.retval_ptr_ptr), Z_STRLEN_PP(fci.retval_ptr_ptr));
entry_len = Z_STRLEN_PP(fci.retval_ptr_ptr);
@@ -681,19 +738,24 @@ PHP_METHOD(Phar, webPhar)
entry = Z_STRVAL_P(retval_ptr);
entry_len = Z_STRLEN_P(retval_ptr);
}
+
break;
- case IS_BOOL :
+ case IS_BOOL:
phar_do_403(entry, entry_len TSRMLS_CC);
+
if (free_pathinfo) {
efree(path_info);
}
+
zend_bailout();
return;
default:
efree(retval_ptr);
+
if (free_pathinfo) {
efree(path_info);
}
+
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: rewrite callback must return a string or false");
return;
}
@@ -702,6 +764,7 @@ PHP_METHOD(Phar, webPhar)
if (entry_len) {
phar_postprocess_ru_web(fname, fname_len, &entry, &entry_len, &ru, &ru_len TSRMLS_CC);
}
+
if (!entry_len || (entry_len == 1 && entry[0] == '/')) {
efree(entry);
/* direct request */
@@ -721,9 +784,11 @@ PHP_METHOD(Phar, webPhar)
if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL TSRMLS_CC) ||
(info = phar_get_entry_info(phar, entry, entry_len, NULL, 0 TSRMLS_CC)) == NULL) {
phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len TSRMLS_CC);
+
if (free_pathinfo) {
efree(path_info);
}
+
zend_bailout();
} else {
char *tmp, sa;
@@ -738,18 +803,23 @@ PHP_METHOD(Phar, webPhar)
sa = *tmp;
*tmp = '\0';
}
+
ctr.response_code = 0;
+
if (path_info[strlen(path_info)-1] == '/') {
ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry + 1);
} else {
ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry);
}
+
if (not_cgi) {
*tmp = sa;
}
+
if (free_pathinfo) {
efree(path_info);
}
+
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
sapi_send_headers(TSRMLS_C);
efree(ctr.line);
@@ -775,7 +845,7 @@ PHP_METHOD(Phar, webPhar)
if (SUCCESS == zend_hash_find(Z_ARRVAL_P(mimeoverride), ext, strlen(ext)+1, (void **) &val)) {
switch (Z_TYPE_PP(val)) {
- case IS_LONG :
+ case IS_LONG:
if (Z_LVAL_PP(val) == PHAR_MIME_PHP || Z_LVAL_PP(val) == PHAR_MIME_PHPS) {
mime_type = "";
code = Z_LVAL_PP(val);
@@ -787,11 +857,11 @@ PHP_METHOD(Phar, webPhar)
RETURN_FALSE;
}
break;
- case IS_STRING :
+ case IS_STRING:
mime_type = Z_STRVAL_PP(val);
code = PHAR_MIME_OTHER;
break;
- default :
+ default:
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed");
#ifdef PHP_WIN32
efree(fname);
@@ -818,6 +888,7 @@ PHP_METHOD(Phar, webPhar)
PHP_METHOD(Phar, mungServer)
{
zval *mungvalues;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &mungvalues) == FAILURE) {
return;
}
@@ -826,6 +897,7 @@ PHP_METHOD(Phar, mungServer)
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
return;
}
+
if (zend_hash_num_elements(Z_ARRVAL_P(mungvalues)) > 4) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
return;
@@ -840,13 +912,16 @@ PHP_METHOD(Phar, mungServer)
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "unable to retrieve array value in Phar::mungServer()");
return;
}
+
if (Z_TYPE_PP(data) != IS_STRING) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
return;
}
+
if (Z_STRLEN_PP(data) == sizeof("PHP_SELF")-1 && !strncmp(Z_STRVAL_PP(data), "PHP_SELF", sizeof("PHP_SELF")-1)) {
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_PHP_SELF;
}
+
if (Z_STRLEN_PP(data) == sizeof("REQUEST_URI")-1) {
if (!strncmp(Z_STRVAL_PP(data), "REQUEST_URI", sizeof("REQUEST_URI")-1)) {
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_REQUEST_URI;
@@ -855,6 +930,7 @@ PHP_METHOD(Phar, mungServer)
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_SCRIPT_NAME;
}
}
+
if (Z_STRLEN_PP(data) == sizeof("SCRIPT_FILENAME")-1 && !strncmp(Z_STRVAL_PP(data), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1)) {
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_SCRIPT_FILENAME;
}
@@ -909,6 +985,7 @@ PHP_METHOD(Phar, mapPhar)
char *alias = NULL, *error;
int alias_len = 0;
long dataoffset = 0;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) {
return;
}
@@ -916,6 +993,7 @@ PHP_METHOD(Phar, mapPhar)
phar_request_initialize(TSRMLS_C);
RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error TSRMLS_CC) == SUCCESS);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -936,6 +1014,7 @@ PHP_METHOD(Phar, loadPhar)
phar_request_initialize(TSRMLS_C);
RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error TSRMLS_CC) == SUCCESS);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -968,14 +1047,12 @@ PHP_METHOD(Phar, canCompress)
} else {
RETURN_FALSE;
}
-
case PHAR_ENT_COMPRESSED_BZ2:
if (PHAR_G(has_bz2)) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
-
default:
if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) {
RETURN_TRUE;
@@ -1019,9 +1096,11 @@ PHP_METHOD(Phar, isValidPharFilename)
static void phar_spl_foreign_dtor(spl_filesystem_object *object TSRMLS_DC) /* {{{ */
{
phar_archive_data *phar = (phar_archive_data *) object->oth;
+
if (!phar->is_persistent) {
phar_archive_delref(phar TSRMLS_CC);
}
+
object->oth = NULL;
}
/* }}} */
@@ -1040,8 +1119,8 @@ static void phar_spl_foreign_clone(spl_filesystem_object *src, spl_filesystem_ob
/* }}} */
static spl_other_handler phar_spl_foreign_handler = {
- phar_spl_foreign_dtor,
- phar_spl_foreign_clone
+ phar_spl_foreign_dtor,
+ phar_spl_foreign_clone
};
#endif /* HAVE_SPL */
@@ -1057,7 +1136,12 @@ PHP_METHOD(Phar, __construct)
#else
char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname;
int fname_len, alias_len = 0, arch_len, entry_len, is_data;
- long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS, format = 0;
+#if PHP_VERSION_ID < 50300
+ long flags = 0;
+#else
+ long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
+#endif
+ long format = 0;
phar_archive_object *phar_obj;
phar_archive_data *phar_data;
zval *zobj = getThis(), arg1, arg2;
@@ -1127,6 +1211,7 @@ PHP_METHOD(Phar, __construct)
phar_data->is_zip = 1;
phar_data->is_tar = 0;
}
+
if (fname == arch) {
efree(arch);
fname = save_fname;
@@ -1143,10 +1228,13 @@ PHP_METHOD(Phar, __construct)
efree(entry);
return;
}
+
is_data = phar_data->is_data;
+
if (!phar_data->is_persistent) {
++(phar_data->refcount);
}
+
phar_obj->arc.archive = phar_data;
phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
@@ -1159,22 +1247,21 @@ PHP_METHOD(Phar, __construct)
INIT_PZVAL(&arg1);
ZVAL_STRINGL(&arg1, fname, fname_len, 0);
-
INIT_PZVAL(&arg2);
ZVAL_LONG(&arg2, flags);
+
zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj),
&spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
if (!phar_data->is_persistent) {
phar_obj->arc.archive->is_data = is_data;
}
- phar_obj->spl.info_class = phar_ce_entry;
+ phar_obj->spl.info_class = phar_ce_entry;
efree(fname);
#endif /* HAVE_SPL */
}
/* }}} */
-/* }}} */
/* {{{ proto array Phar::getSupportedSignatures()
* Return array of supported signature types
@@ -1185,12 +1272,10 @@ PHP_METHOD(Phar, getSupportedSignatures)
add_next_index_stringl(return_value, "MD5", 3, 1);
add_next_index_stringl(return_value, "SHA-1", 5, 1);
-
#if HAVE_HASH_EXT
add_next_index_stringl(return_value, "SHA-256", 7, 1);
add_next_index_stringl(return_value, "SHA-512", 7, 1);
#endif
-
#if PHAR_HAVE_OPENSSL
add_next_index_stringl(return_value, "OpenSSL", 7, 1);
#else
@@ -1207,11 +1292,12 @@ PHP_METHOD(Phar, getSupportedSignatures)
PHP_METHOD(Phar, getSupportedCompression)
{
array_init(return_value);
-
phar_request_initialize(TSRMLS_C);
+
if (PHAR_G(has_zlib)) {
add_next_index_stringl(return_value, "GZ", 2, 1);
}
+
if (PHAR_G(has_bz2)) {
add_next_index_stringl(return_value, "BZIP2", 5, 1);
}
@@ -1264,11 +1350,14 @@ PHP_METHOD(Phar, unlinkArchive)
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" is in phar.cache_list, cannot unlinkArchive()", fname);
return;
}
+
if (phar->refcount) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname);
return;
}
+
fname = estrndup(phar->fname, phar->fname_len);
+
/* invalidate phar cache */
PHAR_G(last_phar) = NULL;
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
@@ -1319,23 +1408,33 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{
char *str = "[stream]";
iter->funcs->get_current_data(iter, &value TSRMLS_CC);
+
if (EG(exception)) {
return ZEND_HASH_APPLY_STOP;
}
+
if (!value) {
/* failure in get_current_data */
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned no value", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned no value", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
switch (Z_TYPE_PP(value)) {
- case IS_STRING :
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(*(value) TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
+ case IS_STRING:
break;
- case IS_RESOURCE :
+ case IS_RESOURCE:
php_stream_from_zval_no_verify(fp, value);
+
if (!fp) {
- zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %s returned an invalid stream handle", ce->name);
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %v returned an invalid stream handle", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
if (iter->funcs->get_current_key) {
key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC);
@@ -1343,31 +1442,42 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{
return ZEND_HASH_APPLY_STOP;
}
- PHAR_STR(key, str_key);
-
if (key_type == HASH_KEY_IS_LONG) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
+ if (key_type > 9) { /* IS_UNICODE == 10 */
+ spprintf(&str_key, 0, "%v", key);
+ } else {
+ PHAR_STR(key, str_key);
+ }
+
save = str_key;
- if (str_key[str_key_len - 1] == '\0') str_key_len--;
+
+ if (str_key[str_key_len - 1] == '\0') {
+ str_key_len--;
+ }
+
} else {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
close_fp = 0;
opened = (char *) estrndup(str, sizeof("[stream]") + 1);
goto after_open_fp;
- case IS_OBJECT :
+ case IS_OBJECT:
if (instanceof_function(Z_OBJCE_PP(value), spl_ce_SplFileInfo TSRMLS_CC)) {
char *test = NULL;
zval dummy;
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(*value TSRMLS_CC);
if (!base_len) {
- zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %s returns an SplFileInfo object, so base directory must be specified", ce->name);
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %v returns an SplFileInfo object, so base directory must be specified", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
switch (intern->type) {
case SPL_FS_DIR:
#if PHP_VERSION_ID >= 60000
@@ -1379,23 +1489,31 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{
#endif
fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
php_stat(fname, fname_len, FS_IS_DIR, &dummy TSRMLS_CC);
+
if (Z_BVAL(dummy)) {
/* ignore directories */
efree(fname);
return ZEND_HASH_APPLY_KEEP;
}
+
test = expand_filepath(fname, NULL TSRMLS_CC);
+
if (test) {
efree(fname);
fname = test;
fname_len = strlen(fname);
}
+
save = fname;
is_splfileinfo = 1;
goto phar_spl_fileinfo;
case SPL_FS_INFO:
case SPL_FS_FILE:
+#if PHP_VERSION_ID >= 60000
+ fname = expand_filepath(intern->file_name.s, NULL TSRMLS_CC);
+#else
fname = expand_filepath(intern->file_name, NULL TSRMLS_CC);
+#endif
fname_len = strlen(fname);
save = fname;
is_splfileinfo = 1;
@@ -1403,8 +1521,8 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{
}
}
/* fall-through */
- default :
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid value (must return a string)", ce->name);
+ default:
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid value (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
@@ -1416,8 +1534,10 @@ phar_spl_fileinfo:
temp = expand_filepath(base, NULL TSRMLS_CC);
base = temp;
base_len = strlen(base);
+
if (strstr(fname, base)) {
str_key_len = fname_len - base_len;
+
if (str_key_len <= 0) {
if (save) {
efree(save);
@@ -1425,17 +1545,22 @@ phar_spl_fileinfo:
}
return ZEND_HASH_APPLY_KEEP;
}
+
str_key = fname + base_len;
+
if (*str_key == '/' || *str_key == '\\') {
str_key++;
str_key_len--;
}
+
} else {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that is not in the base directory \"%s\"", ce->name, fname, base);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that is not in the base directory \"%s\"", ce->name, fname, base);
+
if (save) {
efree(save);
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
} else {
@@ -1446,89 +1571,115 @@ phar_spl_fileinfo:
return ZEND_HASH_APPLY_STOP;
}
- PHAR_STR(key, str_key);
-
if (key_type == HASH_KEY_IS_LONG) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
+ if (key_type > 9) { /* IS_UNICODE == 10 */
+ spprintf(&str_key, 0, "%v", key);
+ } else {
+ PHAR_STR(key, str_key);
+ }
+
save = str_key;
+
if (str_key[str_key_len - 1] == '\0') str_key_len--;
} else {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
}
#if PHP_MAJOR_VERSION < 6
if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that safe mode prevents opening", ce->name, fname);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that safe mode prevents opening", ce->name, fname);
+
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
#endif
if (php_check_open_basedir(fname TSRMLS_CC)) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that open_basedir prevents opening", ce->name, fname);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that open_basedir prevents opening", ce->name, fname);
+
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
/* try to open source file, then create internal phar file and copy contents */
fp = php_stream_open_wrapper(fname, "rb", STREAM_MUST_SEEK|0, &opened);
+
if (!fp) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a file that could not be opened \"%s\"", ce->name, fname);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a file that could not be opened \"%s\"", ce->name, fname);
+
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
-
after_open_fp:
if (str_key_len >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
/* silently skip any files that would be added to the magic .phar directory */
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
if (opened) {
efree(opened);
}
+
if (close_fp) {
php_stream_close(fp);
}
+
return ZEND_HASH_APPLY_KEEP;
}
+
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, 1 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) {
efree(save);
}
+
if (opened) {
efree(opened);
}
+
if (temp) {
efree(temp);
}
+
if (close_fp) {
php_stream_close(fp);
}
+
return ZEND_HASH_APPLY_STOP;
+
} else {
if (error) {
efree(error);
@@ -1537,6 +1688,7 @@ after_open_fp:
if (data->internal_file->fp_type == PHAR_MOD) {
php_stream_close(data->internal_file->fp);
}
+
data->internal_file->fp = NULL;
data->internal_file->fp_type = PHAR_UFP;
data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp);
@@ -1545,6 +1697,7 @@ after_open_fp:
data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
php_stream_tell(p_obj->fp) - data->internal_file->offset;
}
+
if (close_fp) {
php_stream_close(fp);
}
@@ -1554,6 +1707,7 @@ after_open_fp:
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
@@ -1602,7 +1756,11 @@ PHP_METHOD(Phar, buildFromDirectory)
INIT_PZVAL(&arg);
ZVAL_STRINGL(&arg, dir, dir_len, 0);
INIT_PZVAL(&arg2);
+#if PHP_VERSION_ID < 50300
+ ZVAL_LONG(&arg2, 0);
+#else
ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
+#endif
zend_call_method_with_2_params(&iter, spl_ce_RecursiveDirectoryIterator,
&spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2);
@@ -1662,15 +1820,19 @@ PHP_METHOD(Phar, buildFromDirectory)
if (SUCCESS == spl_iterator_apply((apply_reg ? regexiter : iteriter), (spl_iterator_apply_func_t) phar_build, (void *) &pass TSRMLS_CC)) {
zval_ptr_dtor(&iteriter);
+
if (apply_reg) {
zval_ptr_dtor(®exiter);
}
+
phar_obj->arc.archive->ufp = pass.fp;
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
} else {
zval_ptr_dtor(&iteriter);
php_stream_close(pass.fp);
@@ -1728,7 +1890,6 @@ PHP_METHOD(Phar, buildFromIterator)
} else {
php_stream_close(pass.fp);
}
-
}
/* }}} */
@@ -1738,7 +1899,7 @@ PHP_METHOD(Phar, buildFromIterator)
PHP_METHOD(Phar, count)
{
PHAR_ARCHIVE_OBJECT();
-
+
RETURN_LONG(zend_hash_num_elements(&phar_obj->arc.archive->manifest));
}
/* }}} */
@@ -1755,6 +1916,7 @@ PHP_METHOD(Phar, isFileFormat)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) {
RETURN_FALSE;
}
+
switch (type) {
case PHAR_FORMAT_TAR:
RETURN_BOOL(phar_obj->arc.archive->is_tar);
@@ -1785,23 +1947,28 @@ static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp TSRMLS
}
return FAILURE;
}
+
/* copy old contents in entirety */
phar_seek_efp(entry, 0, SEEK_SET, 0, 1 TSRMLS_CC);
offset = php_stream_tell(fp);
link = phar_get_link_source(entry TSRMLS_CC);
+
if (!link) {
link = entry;
}
+
if (link->uncompressed_filesize != php_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize)) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename);
return FAILURE;
}
+
if (entry->fp_type == PHAR_MOD) {
/* save for potential restore on error */
entry->cfp = entry->fp;
entry->fp = NULL;
}
+
/* set new location of file contents */
entry->fp_type = PHAR_FP;
entry->offset = offset;
@@ -1823,12 +1990,15 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
if (!ext) {
if (phar->is_zip) {
+
if (phar->is_data) {
ext = "zip";
} else {
ext = "phar.zip";
}
+
} else if (phar->is_tar) {
+
switch (phar->flags) {
case PHAR_FILE_COMPRESSED_GZ:
if (phar->is_data) {
@@ -1852,6 +2022,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
}
}
} else {
+
switch (phar->flags) {
case PHAR_FILE_COMPRESSED_GZ:
ext = "phar.gz";
@@ -1864,6 +2035,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
}
}
} else if (phar_path_check(&ext, &ext_len, &pcr_error) > pcr_is_ok) {
+
if (phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
} else {
@@ -1913,11 +2085,11 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
goto its_ok;
}
}
+
efree(oldpath);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to add newly converted phar \"%s\" to the list of phars, a phar with that name already exists", phar->fname);
return NULL;
}
-
its_ok:
if (!phar->is_data) {
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 1, 1, 1 TSRMLS_CC)) {
@@ -1925,6 +2097,7 @@ its_ok:
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar \"%s\" has invalid extension %s", phar->fname, ext);
return NULL;
}
+
if (phar->alias) {
if (phar->is_temporary_alias) {
phar->alias = NULL;
@@ -1936,12 +2109,15 @@ its_ok:
zend_hash_update(&(PHAR_GLOBALS->phar_alias_map), newpath, phar->fname_len, (void*)&phar, sizeof(phar_archive_data*), NULL);
}
}
+
} else {
+
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 0, 1, 1 TSRMLS_CC)) {
efree(oldpath);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
return NULL;
}
+
phar->alias = NULL;
phar->alias_len = 0;
}
@@ -1953,6 +2129,7 @@ its_ok:
}
phar_flush(phar, 0, 0, 1, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, error);
efree(error);
@@ -1969,16 +2146,17 @@ its_ok:
}
MAKE_STD_ZVAL(ret);
+
if (SUCCESS != object_init_ex(ret, ce)) {
zval_dtor(ret);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname);
return NULL;
}
+
INIT_PZVAL(&arg1);
ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len, 0);
zend_call_method_with_1_params(&ret, ce, &ce->constructor, "__construct", NULL, &arg1);
-
return ret;
}
/* }}} */
@@ -1996,16 +2174,16 @@ static zval *phar_convert_to_other(phar_archive_data *source, int convert, char
phar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
/* set whole-archive compression and type from parameter */
phar->flags = flags;
-
phar->is_data = source->is_data;
+
switch (convert) {
- case PHAR_FORMAT_TAR :
+ case PHAR_FORMAT_TAR:
phar->is_tar = 1;
break;
- case PHAR_FORMAT_ZIP :
+ case PHAR_FORMAT_ZIP:
phar->is_zip = 1;
break;
- default :
+ default:
phar->is_data = 0;
break;
}
@@ -2022,6 +2200,7 @@ static zval *phar_convert_to_other(phar_archive_data *source, int convert, char
phar->fname_len = source->fname_len;
phar->is_temporary_alias = source->is_temporary_alias;
phar->alias = source->alias;
+
/* first copy each file's uncompressed contents to a temporary file and set per-file flags */
for (zend_hash_internal_pointer_reset(&source->manifest); SUCCESS == zend_hash_has_more_elements(&source->manifest); zend_hash_move_forward(&source->manifest)) {
@@ -2033,16 +2212,21 @@ static zval *phar_convert_to_other(phar_archive_data *source, int convert, char
"Cannot convert phar archive \"%s\"", source->fname);
return NULL;
}
+
newentry = *entry;
+
if (newentry.link) {
newentry.link = estrdup(newentry.link);
goto no_copy;
}
+
if (newentry.tmp) {
newentry.tmp = estrdup(newentry.tmp);
goto no_copy;
}
+
newentry.metadata_str.c = 0;
+
if (FAILURE == phar_copy_file_contents(&newentry, phar->fp TSRMLS_CC)) {
zend_hash_destroy(&(phar->manifest));
php_stream_close(phar->fp);
@@ -2052,6 +2236,7 @@ static zval *phar_convert_to_other(phar_archive_data *source, int convert, char
}
no_copy:
newentry.filename = estrndup(newentry.filename, newentry.filename_len);
+
if (newentry.metadata) {
zval *t;
@@ -2068,11 +2253,14 @@ no_copy:
newentry.metadata_str.c = NULL;
newentry.metadata_str.len = 0;
}
+
newentry.is_zip = phar->is_zip;
newentry.is_tar = phar->is_tar;
+
if (newentry.is_tar) {
newentry.tar_type = (entry->is_dir ? TAR_DIR : TAR_FILE);
}
+
newentry.is_modified = 1;
newentry.phar = phar;
newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */
@@ -2096,7 +2284,7 @@ no_copy:
/* }}} */
/* {{{ proto object Phar::convertToExecutable([int format[, int compression [, string file_ext]]])
- * Convert a phar.tar or phar.zip archive to the phar file format. The
+ * Convert a phar.tar or phar.zip archive to the phar file format. The
* optional parameter allows the user to determine the new
* filename extension (default is phar).
*/
@@ -2155,25 +2343,28 @@ PHP_METHOD(Phar, convertToExecutable)
"Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_GZ;
break;
-
case PHAR_ENT_COMPRESSED_BZ2:
if (format == PHAR_FORMAT_ZIP) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_BZ2;
break;
default:
@@ -2186,6 +2377,7 @@ PHP_METHOD(Phar, convertToExecutable)
phar_obj->arc.archive->is_data = 0;
ret = phar_convert_to_other(phar_obj->arc.archive, format, ext, flags TSRMLS_CC);
phar_obj->arc.archive->is_data = is_data;
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
@@ -2253,25 +2445,28 @@ PHP_METHOD(Phar, convertToData)
"Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_GZ;
break;
-
case PHAR_ENT_COMPRESSED_BZ2:
if (format == PHAR_FORMAT_ZIP) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_BZ2;
break;
default:
@@ -2284,6 +2479,7 @@ PHP_METHOD(Phar, convertToData)
phar_obj->arc.archive->is_data = 1;
ret = phar_convert_to_other(phar_obj->arc.archive, format, ext, flags TSRMLS_CC);
phar_obj->arc.archive->is_data = is_data;
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
@@ -2299,13 +2495,15 @@ PHP_METHOD(Phar, convertToData)
PHP_METHOD(Phar, isCompressed)
{
PHAR_ARCHIVE_OBJECT();
-
+
if (phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSED_GZ) {
RETURN_LONG(PHAR_ENT_COMPRESSED_GZ);
}
+
if (phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSED_BZ2) {
RETURN_LONG(PHAR_ENT_COMPRESSED_BZ2);
}
+
RETURN_FALSE;
}
/* }}} */
@@ -2317,10 +2515,11 @@ PHP_METHOD(Phar, isWritable)
{
php_stream_statbuf ssb;
PHAR_ARCHIVE_OBJECT();
-
+
if (!phar_obj->arc.archive->is_writeable) {
RETURN_FALSE;
}
+
if (SUCCESS != php_stream_stat_path(phar_obj->arc.archive->fname, &ssb)) {
if (phar_obj->arc.archive->is_brandnew) {
/* assume it works if the file doesn't exist yet */
@@ -2328,6 +2527,7 @@ PHP_METHOD(Phar, isWritable)
}
RETURN_FALSE;
}
+
RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0);
}
/* }}} */
@@ -2374,7 +2574,7 @@ PHP_METHOD(Phar, delete)
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
-
+
RETURN_TRUE;
}
/* }}} */
@@ -2412,6 +2612,7 @@ PHP_METHOD(Phar, setAlias)
char *alias, *error, *oldalias;
phar_archive_data **fd_ptr;
int alias_len, oldalias_len, old_temp, readd = 0;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
@@ -2425,8 +2626,13 @@ PHP_METHOD(Phar, setAlias)
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
if (phar_obj->arc.archive->is_data) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "A Phar alias cannot be set in a plain %s archive", phar_obj->arc.archive->is_tar ? "tar" : "zip");
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar alias cannot be set in a plain tar archive");
+ } else {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar alias cannot be set in a plain zip archive");
+ }
RETURN_FALSE;
}
@@ -2458,15 +2664,17 @@ valid_alias:
oldalias = phar_obj->arc.archive->alias;
oldalias_len = phar_obj->arc.archive->alias_len;
old_temp = phar_obj->arc.archive->is_temporary_alias;
+
if (alias_len) {
phar_obj->arc.archive->alias = estrndup(alias, alias_len);
} else {
phar_obj->arc.archive->alias = NULL;
}
+
phar_obj->arc.archive->alias_len = alias_len;
phar_obj->arc.archive->is_temporary_alias = 0;
-
phar_flush(phar_obj->arc.archive, NULL, 0, 0, &error TSRMLS_CC);
+
if (error) {
phar_obj->arc.archive->alias = oldalias;
phar_obj->arc.archive->alias_len = oldalias_len;
@@ -2478,10 +2686,13 @@ valid_alias:
efree(error);
RETURN_FALSE;
}
+
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&(phar_obj->arc.archive), sizeof(phar_archive_data*), NULL);
+
if (oldalias) {
efree(oldalias);
}
+
RETURN_TRUE;
}
@@ -2495,7 +2706,7 @@ valid_alias:
PHP_METHOD(Phar, getVersion)
{
PHAR_ARCHIVE_OBJECT();
-
+
RETURN_STRING(phar_obj->arc.archive->version, 1);
}
/* }}} */
@@ -2506,7 +2717,7 @@ PHP_METHOD(Phar, getVersion)
PHP_METHOD(Phar, startBuffering)
{
PHAR_ARCHIVE_OBJECT();
-
+
phar_obj->arc.archive->donotflush = 1;
}
/* }}} */
@@ -2517,7 +2728,7 @@ PHP_METHOD(Phar, startBuffering)
PHP_METHOD(Phar, isBuffering)
{
PHAR_ARCHIVE_OBJECT();
-
+
RETURN_BOOL(!phar_obj->arc.archive->donotflush);
}
/* }}} */
@@ -2528,6 +2739,7 @@ PHP_METHOD(Phar, isBuffering)
PHP_METHOD(Phar, stopBuffering)
{
char *error;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
@@ -2537,8 +2749,8 @@ PHP_METHOD(Phar, stopBuffering)
}
phar_obj->arc.archive->donotflush = 0;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -2566,8 +2778,13 @@ PHP_METHOD(Phar, setStub)
}
if (phar_obj->arc.archive->is_data) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "A Phar stub cannot be set in a plain %s archive", phar_obj->arc.archive->is_tar ? "tar" : "zip");
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain tar archive");
+ } else {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain zip archive");
+ }
return;
}
@@ -2590,10 +2807,12 @@ PHP_METHOD(Phar, setStub)
}
} else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &stub, &stub_len) == SUCCESS) {
phar_flush(phar_obj->arc.archive, stub, stub_len, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
@@ -2614,7 +2833,7 @@ PHP_METHOD(Phar, setStub)
* files cannot be loaded via this kind of stub, no parameters are accepted
* when the Phar object is zip- or tar-based.
*/
- PHP_METHOD(Phar, setDefaultStub)
+PHP_METHOD(Phar, setDefaultStub)
{
char *index = NULL, *webindex = NULL, *error = NULL, *stub = NULL;
int index_len = 0, webindex_len = 0, created_stub = 0;
@@ -2622,8 +2841,13 @@ PHP_METHOD(Phar, setStub)
PHAR_ARCHIVE_OBJECT();
if (phar_obj->arc.archive->is_data) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "A Phar stub cannot be set in a plain %s archive", phar_obj->arc.archive->is_tar ? "tar" : "zip");
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain tar archive");
+ } else {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain zip archive");
+ }
return;
}
@@ -2643,7 +2867,6 @@ PHP_METHOD(Phar, setStub)
}
if (!phar_obj->arc.archive->is_tar && !phar_obj->arc.archive->is_zip) {
-
stub = phar_create_default_stub(index, webindex, &stub_len, &error TSRMLS_CC);
if (error) {
@@ -2654,6 +2877,7 @@ PHP_METHOD(Phar, setStub)
}
RETURN_FALSE;
}
+
created_stub = 1;
}
@@ -2684,6 +2908,7 @@ PHP_METHOD(Phar, setSignatureAlgorithm)
long algo;
char *error, *key = NULL;
int key_len = 0;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
@@ -2703,16 +2928,16 @@ PHP_METHOD(Phar, setSignatureAlgorithm)
}
switch (algo) {
- case PHAR_SIG_SHA256 :
- case PHAR_SIG_SHA512 :
+ case PHAR_SIG_SHA256:
+ case PHAR_SIG_SHA512:
#if !HAVE_HASH_EXT
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"SHA-256 and SHA-512 signatures are only supported if the hash extension is enabled");
return;
#endif
- case PHAR_SIG_MD5 :
- case PHAR_SIG_SHA1 :
- case PHAR_SIG_OPENSSL :
+ case PHAR_SIG_MD5:
+ case PHAR_SIG_SHA1:
+ case PHAR_SIG_OPENSSL:
phar_obj->arc.archive->sig_flags = algo;
phar_obj->arc.archive->is_modified = 1;
PHAR_G(openssl_privatekey) = key;
@@ -2724,7 +2949,7 @@ PHP_METHOD(Phar, setSignatureAlgorithm)
efree(error);
}
break;
- default :
+ default:
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Unknown signature algorithm specified");
}
@@ -2745,25 +2970,25 @@ PHP_METHOD(Phar, getSignature)
array_init(return_value);
add_assoc_stringl(return_value, "hash", phar_obj->arc.archive->signature, phar_obj->arc.archive->sig_len, 1);
switch(phar_obj->arc.archive->sig_flags) {
- case PHAR_SIG_MD5:
- add_assoc_stringl(return_value, "hash_type", "MD5", 3, 1);
- break;
- case PHAR_SIG_SHA1:
- add_assoc_stringl(return_value, "hash_type", "SHA-1", 5, 1);
- break;
- case PHAR_SIG_SHA256:
- add_assoc_stringl(return_value, "hash_type", "SHA-256", 7, 1);
- break;
- case PHAR_SIG_SHA512:
- add_assoc_stringl(return_value, "hash_type", "SHA-512", 7, 1);
- break;
- case PHAR_SIG_OPENSSL:
- add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7, 1);
- break;
- default:
- unknown_len = spprintf(&unknown, 0, "Unknown (%d)", phar_obj->arc.archive->sig_flags);
- add_assoc_stringl(return_value, "hash_type", unknown, unknown_len, 0);
- break;
+ case PHAR_SIG_MD5:
+ add_assoc_stringl(return_value, "hash_type", "MD5", 3, 1);
+ break;
+ case PHAR_SIG_SHA1:
+ add_assoc_stringl(return_value, "hash_type", "SHA-1", 5, 1);
+ break;
+ case PHAR_SIG_SHA256:
+ add_assoc_stringl(return_value, "hash_type", "SHA-256", 7, 1);
+ break;
+ case PHAR_SIG_SHA512:
+ add_assoc_stringl(return_value, "hash_type", "SHA-512", 7, 1);
+ break;
+ case PHAR_SIG_OPENSSL:
+ add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7, 1);
+ break;
+ default:
+ unknown_len = spprintf(&unknown, 0, "Unknown (%d)", phar_obj->arc.archive->sig_flags);
+ add_assoc_stringl(return_value, "hash_type", unknown, unknown_len, 0);
+ break;
}
} else {
RETURN_FALSE;
@@ -2790,6 +3015,7 @@ static int phar_set_compression(void *pDest, void *argument TSRMLS_DC) /* {{{ */
if (entry->is_deleted) {
return ZEND_HASH_APPLY_KEEP;
}
+
entry->old_flags = entry->flags;
entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
entry->flags |= compress;
@@ -2805,16 +3031,19 @@ static int phar_test_compression(void *pDest, void *argument TSRMLS_DC) /* {{{ *
if (entry->is_deleted) {
return ZEND_HASH_APPLY_KEEP;
}
+
if (!PHAR_G(has_bz2)) {
if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
*(int *) argument = 0;
}
}
+
if (!PHAR_G(has_zlib)) {
if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
*(int *) argument = 0;
}
}
+
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
@@ -2828,6 +3057,7 @@ static void pharobj_set_compression(HashTable *manifest, php_uint32 compress TSR
static int pharobj_cancompress(HashTable *manifest TSRMLS_DC) /* {{{ */
{
int test;
+
test = 1;
zend_hash_apply_with_argument(manifest, phar_test_compression, &test TSRMLS_CC);
return test;
@@ -2851,7 +3081,7 @@ PHP_METHOD(Phar, compress)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &method, &ext, &ext_len) == FAILURE) {
return;
}
-
+
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Cannot compress phar archive, phar is read-only");
@@ -2876,7 +3106,7 @@ PHP_METHOD(Phar, compress)
}
flags = PHAR_FILE_COMPRESSED_GZ;
break;
-
+
case PHAR_ENT_COMPRESSED_BZ2:
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
@@ -2896,6 +3126,7 @@ PHP_METHOD(Phar, compress)
} else {
ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_PHAR, ext, flags TSRMLS_CC);
}
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
@@ -2935,6 +3166,7 @@ PHP_METHOD(Phar, decompress)
} else {
ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_PHAR, ext, PHAR_FILE_COMPRESSED_NONE TSRMLS_CC);
}
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
@@ -2988,11 +3220,13 @@ PHP_METHOD(Phar, compressFiles)
"Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
return;
}
+
if (phar_obj->arc.archive->is_tar) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with Gzip compression, tar archives cannot compress individual files, use compress() to compress the whole archive");
return;
}
+
if (!pharobj_cancompress(&phar_obj->arc.archive->manifest TSRMLS_CC)) {
if (flags == PHAR_FILE_COMPRESSED_GZ) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
@@ -3003,11 +3237,11 @@ PHP_METHOD(Phar, compressFiles)
}
return;
}
+
pharobj_set_compression(&phar_obj->arc.archive->manifest, flags TSRMLS_CC);
-
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, error);
efree(error);
@@ -3028,11 +3262,13 @@ PHP_METHOD(Phar, decompressFiles)
"Phar is readonly, cannot change compression");
return;
}
+
if (!pharobj_cancompress(&phar_obj->arc.archive->manifest TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot decompress all files, some are compressed as bzip2 or gzip and cannot be decompressed");
return;
}
+
if (phar_obj->arc.archive->is_tar) {
RETURN_TRUE;
} else {
@@ -3040,12 +3276,13 @@ PHP_METHOD(Phar, decompressFiles)
}
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
/* }}} */
@@ -3059,6 +3296,7 @@ PHP_METHOD(Phar, copy)
const char *pcr_error;
int oldfile_len, newfile_len;
phar_entry_info *oldentry, newentry = {0}, *temp;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &oldfile, &oldfile_len, &newfile, &newfile_len) == FAILURE) {
@@ -3106,6 +3344,7 @@ PHP_METHOD(Phar, copy)
}
memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info));
+
if (newentry.metadata) {
zval *t;
@@ -3122,6 +3361,7 @@ PHP_METHOD(Phar, copy)
newentry.metadata_str.c = NULL;
newentry.metadata_str.len = 0;
}
+
newentry.filename = estrndup(newfile, newfile_len);
newentry.filename_len = newfile_len;
newentry.fp_refcount = 0;
@@ -3138,8 +3378,8 @@ PHP_METHOD(Phar, copy)
zend_hash_add(&oldentry->phar->manifest, newfile, newfile_len, (void*)&newentry, sizeof(phar_entry_info), NULL);
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -3157,6 +3397,7 @@ PHP_METHOD(Phar, offsetExists)
char *fname;
int fname_len;
phar_entry_info *entry;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
@@ -3205,12 +3446,12 @@ PHP_METHOD(Phar, offsetGet)
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use getStub", phar_obj->arc.archive->fname);
return;
}
-
+
if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use getAlias", phar_obj->arc.archive->fname);
return;
}
-
+
if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot directly get any files or directories in magic \".phar\" directory", phar_obj->arc.archive->fname);
return;
@@ -3220,13 +3461,13 @@ PHP_METHOD(Phar, offsetGet)
efree(entry->filename);
efree(entry);
}
+
fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
MAKE_STD_ZVAL(zfname);
ZVAL_STRINGL(zfname, fname, fname_len, 0);
spl_instantiate_arg_ex1(phar_obj->spl.info_class, &return_value, 0, zfname TSRMLS_CC);
zval_ptr_dtor(&zfname);
}
-
}
/* }}} */
@@ -3256,6 +3497,7 @@ static void phar_add_file(phar_archive_data *phar, char *filename, int filename_
if (error) {
efree(error);
}
+
if (!data->internal_file->is_dir) {
if (cont_str) {
contents_len = php_stream_write(data->fp, cont_str, cont_len);
@@ -3270,10 +3512,13 @@ static void phar_add_file(phar_archive_data *phar, char *filename, int filename_
}
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;
}
+
phar_entry_delref(data TSRMLS_CC);
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -3296,13 +3541,16 @@ static void phar_mkdir(phar_archive_data *phar, char *dirname, int dirname_len T
} else {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Directory %s does not exist and cannot be created", dirname);
}
+
return;
} else {
if (error) {
efree(error);
}
+
phar_entry_delref(data TSRMLS_CC);
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -3311,7 +3559,6 @@ static void phar_mkdir(phar_archive_data *phar, char *dirname, int dirname_len T
}
/* }}} */
-
/* {{{ proto int Phar::offsetSet(string entry, string value)
* set the contents of an internal file to those of an external file
*/
@@ -3326,7 +3573,7 @@ PHP_METHOD(Phar, offsetSet)
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
return;
}
-
+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sr", &fname, &fname_len, &zresource) == FAILURE
&& zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fname, &fname_len, &cont_str, &cont_len) == FAILURE) {
return;
@@ -3346,6 +3593,7 @@ PHP_METHOD(Phar, offsetSet)
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot set any files or directories in magic \".phar\" directory", phar_obj->arc.archive->fname);
return;
}
+
phar_add_file(phar_obj->arc.archive, fname, fname_len, cont_str, cont_len, zresource TSRMLS_CC);
}
/* }}} */
@@ -3375,14 +3623,17 @@ PHP_METHOD(Phar, offsetUnset)
/* entry is deleted, but has not been flushed to disk yet */
return;
}
+
entry->is_modified = 0;
entry->is_deleted = 1;
/* we need to "flush" the stream to save the newly deleted file on disk */
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
} else {
@@ -3398,6 +3649,7 @@ PHP_METHOD(Phar, addEmptyDir)
{
char *dirname;
int dirname_len;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &dirname, &dirname_len) == FAILURE) {
@@ -3408,6 +3660,7 @@ PHP_METHOD(Phar, addEmptyDir)
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot create a directory in magic \".phar\" directory");
return;
}
+
phar_mkdir(phar_obj->arc.archive, dirname, dirname_len TSRMLS_CC);
}
/* }}} */
@@ -3421,6 +3674,7 @@ PHP_METHOD(Phar, addFile)
int fname_len, localname_len = 0;
php_stream *resource;
zval *zresource;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &fname, &fname_len, &localname, &localname_len) == FAILURE) {
@@ -3443,6 +3697,7 @@ PHP_METHOD(Phar, addFile)
zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "phar error: unable to open file \"%s\" to add to phar archive", fname);
return;
}
+
if (localname) {
fname = localname;
fname_len = localname_len;
@@ -3463,6 +3718,7 @@ PHP_METHOD(Phar, addFromString)
{
char *localname, *cont_str;
int localname_len, cont_len;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &localname, &localname_len, &cont_str, &cont_len) == FAILURE) {
@@ -3483,6 +3739,7 @@ PHP_METHOD(Phar, getStub)
php_stream *fp;
php_stream_filter *filter = NULL;
phar_entry_info *stub;
+
PHAR_ARCHIVE_OBJECT();
if (phar_obj->arc.archive->is_tar || phar_obj->arc.archive->is_zip) {
@@ -3538,6 +3795,7 @@ PHP_METHOD(Phar, getStub)
php_stream_rewind(fp);
carry_on:
buf = safe_emalloc(len, 1, 1);
+
if (len != php_stream_read(fp, buf, len)) {
if (fp != phar_obj->arc.archive->fp) {
php_stream_close(fp);
@@ -3547,15 +3805,17 @@ carry_on:
efree(buf);
return;
}
+
if (filter) {
php_stream_filter_flush(filter, 1);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
}
+
if (fp != phar_obj->arc.archive->fp) {
php_stream_close(fp);
}
- buf[len] = '\0';
+ buf[len] = '\0';
RETURN_STRINGL(buf, len, 0);
}
/* }}}*/
@@ -3591,6 +3851,7 @@ PHP_METHOD(Phar, setMetadata)
{
char *error;
zval *metadata;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
@@ -3610,8 +3871,8 @@ PHP_METHOD(Phar, setMetadata)
MAKE_STD_ZVAL(phar_obj->arc.archive->metadata);
ZVAL_ZVAL(phar_obj->arc.archive->metadata, metadata, 1, 0);
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -3625,6 +3886,7 @@ PHP_METHOD(Phar, setMetadata)
PHP_METHOD(Phar, delMetadata)
{
char *error;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
@@ -3636,8 +3898,8 @@ PHP_METHOD(Phar, delMetadata)
zval_ptr_dtor(&phar_obj->arc.archive->metadata);
phar_obj->arc.archive->metadata = NULL;
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -3645,6 +3907,7 @@ PHP_METHOD(Phar, delMetadata)
} else {
RETURN_TRUE;
}
+
} else {
RETURN_TRUE;
}
@@ -3653,7 +3916,7 @@ PHP_METHOD(Phar, delMetadata)
#if (PHP_MAJOR_VERSION < 6)
#define OPENBASEDIR_CHECKPATH(filename) \
(PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)
-#else
+#else
#define OPENBASEDIR_CHECKPATH(filename) \
php_check_open_basedir(filename TSRMLS_CC)
#endif
@@ -3670,10 +3933,13 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
/* silently ignore mounted entries */
return SUCCESS;
}
+
if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
return SUCCESS;
}
+
len = spprintf(&fullpath, 0, "%s/%s", dest, entry->filename);
+
if (len >= MAXPATHLEN) {
char *tmp;
/* truncate for error message */
@@ -3688,6 +3954,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
efree(fullpath);
return FAILURE;
}
+
if (!len) {
spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
efree(fullpath);
@@ -3706,13 +3973,16 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
efree(fullpath);
return FAILURE;
}
+
/* perform dirname */
slash = zend_memrchr(entry->filename, '/', entry->filename_len);
+
if (slash) {
fullpath[dest_len + (slash - entry->filename) + 1] = '\0';
} else {
fullpath[dest_len] = '\0';
}
+
if (FAILURE == php_stream_stat_path(fullpath, &ssb)) {
if (entry->is_dir) {
if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
@@ -3728,6 +3998,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
}
}
}
+
if (slash) {
fullpath[dest_len + (slash - entry->filename) + 1] = '/';
} else {
@@ -3804,6 +4075,7 @@ PHP_METHOD(Phar, extractTo)
int nelems;
zval *zval_files = NULL;
zend_bool overwrite = 0;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z!b", &pathto, &pathto_len, &zval_files, &overwrite) == FAILURE) {
@@ -3811,11 +4083,13 @@ PHP_METHOD(Phar, extractTo)
}
fp = php_stream_open_wrapper(phar_obj->arc.archive->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);
+
if (!fp) {
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC,
"Invalid argument, %s cannot be found", phar_obj->arc.archive->fname);
return;
}
+
efree(actual);
php_stream_close(fp);
@@ -3824,6 +4098,7 @@ PHP_METHOD(Phar, extractTo)
"Invalid argument, extraction path must be non-zero length");
return;
}
+
if (pathto_len >= MAXPATHLEN) {
char *tmp = estrndup(pathto, 50);
/* truncate for error message */
@@ -3849,6 +4124,11 @@ PHP_METHOD(Phar, extractTo)
switch (Z_TYPE_P(zval_files)) {
case IS_NULL:
goto all_files;
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(zval_files TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
case IS_STRING:
filename = Z_STRVAL_P(zval_files);
filename_len = Z_STRLEN_P(zval_files);
@@ -3862,6 +4142,11 @@ PHP_METHOD(Phar, extractTo)
zval **zval_file;
if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
switch (Z_TYPE_PP(zval_file)) {
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(*(zval_file) TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
case IS_STRING:
break;
default:
@@ -3887,11 +4172,13 @@ PHP_METHOD(Phar, extractTo)
"Invalid argument, expected a filename (string) or array of filenames");
return;
}
+
if (FAILURE == zend_hash_find(&phar_obj->arc.archive->manifest, filename, filename_len, (void **)&entry)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
"Phar Error: attempted to extract non-existent file \"%s\" from phar \"%s\"", filename, phar_obj->arc.archive->fname);
return;
}
+
if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error TSRMLS_CC)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
"Extraction from phar \"%s\" failed: %s", phar_obj->arc.archive->fname, error);
@@ -3900,7 +4187,6 @@ PHP_METHOD(Phar, extractTo)
}
} else {
phar_archive_data *phar = phar_obj->arc.archive;
-
all_files:
/* Extract all files */
if (!zend_hash_num_elements(&(phar->manifest))) {
@@ -3911,9 +4197,11 @@ all_files:
zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
zend_hash_move_forward(&phar->manifest)) {
phar_entry_info *entry;
+
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
+
if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error TSRMLS_CC)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
"Extraction from phar \"%s\" failed: %s", phar->fname, error);
@@ -3934,15 +4222,15 @@ PHP_METHOD(PharFileInfo, __construct)
{
char *fname, *arch, *entry, *error;
int fname_len, arch_len, entry_len;
- phar_entry_object *entry_obj;
- phar_entry_info *entry_info;
+ phar_entry_object *entry_obj;
+ phar_entry_info *entry_info;
phar_archive_data *phar_data;
zval *zobj = getThis(), arg1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
return;
}
-
+
entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
if (entry_obj->ent.entry) {
@@ -3972,7 +4260,7 @@ PHP_METHOD(PharFileInfo, __construct)
if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, 1 TSRMLS_CC)) == NULL) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
- "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error?", ":"", error?error:"");
+ "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : "");
efree(arch);
efree(entry);
return;
@@ -4011,6 +4299,7 @@ PHP_METHOD(PharFileInfo, __destruct)
efree(entry_obj->ent.entry->filename);
entry_obj->ent.entry->filename = NULL;
}
+
efree(entry_obj->ent.entry);
entry_obj->ent.entry = NULL;
}
@@ -4067,6 +4356,7 @@ PHP_METHOD(PharFileInfo, getCRC32)
"Phar entry is a directory, does not have a CRC"); \
return;
}
+
if (entry_obj->ent.entry->is_crc_checked) {
RETURN_LONG(entry_obj->ent.entry->crc32);
} else {
@@ -4082,7 +4372,7 @@ PHP_METHOD(PharFileInfo, getCRC32)
PHP_METHOD(PharFileInfo, isCRCChecked)
{
PHAR_ENTRY_OBJECT();
-
+
RETURN_BOOL(entry_obj->ent.entry->is_crc_checked);
}
/* }}} */
@@ -4093,7 +4383,7 @@ PHP_METHOD(PharFileInfo, isCRCChecked)
PHP_METHOD(PharFileInfo, getPharFlags)
{
PHAR_ENTRY_OBJECT();
-
+
RETURN_LONG(entry_obj->ent.entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
}
/* }}} */
@@ -4112,32 +4402,38 @@ PHP_METHOD(PharFileInfo, chmod)
"Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", entry_obj->ent.entry->filename); \
return;
}
+
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
return;
}
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &perms) == FAILURE) {
return;
- }
- /* clear permissions */
+ }
+
+ /* clear permissions */
entry_obj->ent.entry->flags &= ~PHAR_ENT_PERM_MASK;
perms &= 0777;
entry_obj->ent.entry->flags |= perms;
entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
entry_obj->ent.entry->phar->is_modified = 1;
entry_obj->ent.entry->is_modified = 1;
+
/* hackish cache in php_stat needs to be cleared */
/* if this code fails to work, check main/streams/streams.c, _php_stream_stat_path */
if (BG(CurrentLStatFile)) {
efree(BG(CurrentLStatFile));
}
+
if (BG(CurrentStatFile)) {
efree(BG(CurrentStatFile));
}
+
BG(CurrentLStatFile) = NULL;
BG(CurrentStatFile) = NULL;
-
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -4151,7 +4447,7 @@ PHP_METHOD(PharFileInfo, chmod)
PHP_METHOD(PharFileInfo, hasMetadata)
{
PHAR_ENTRY_OBJECT();
-
+
RETURN_BOOL(entry_obj->ent.entry->metadata != NULL);
}
/* }}} */
@@ -4162,7 +4458,7 @@ PHP_METHOD(PharFileInfo, hasMetadata)
PHP_METHOD(PharFileInfo, getMetadata)
{
PHAR_ENTRY_OBJECT();
-
+
if (entry_obj->ent.entry->metadata) {
RETURN_ZVAL(entry_obj->ent.entry->metadata, 1, 0);
}
@@ -4176,17 +4472,20 @@ PHP_METHOD(PharFileInfo, setMetadata)
{
char *error;
zval *metadata;
+
PHAR_ENTRY_OBJECT();
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by phar.readonly INI setting");
return;
}
+
if (entry_obj->ent.entry->is_temp_dir) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
"Phar entry is a temporary directory (not an actual entry in the archive), cannot set metadata"); \
return;
}
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &metadata) == FAILURE) {
return;
}
@@ -4202,6 +4501,7 @@ PHP_METHOD(PharFileInfo, setMetadata)
entry_obj->ent.entry->is_modified = 1;
entry_obj->ent.entry->phar->is_modified = 1;
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -4215,17 +4515,20 @@ PHP_METHOD(PharFileInfo, setMetadata)
PHP_METHOD(PharFileInfo, delMetadata)
{
char *error;
+
PHAR_ENTRY_OBJECT();
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by phar.readonly INI setting");
return;
}
+
if (entry_obj->ent.entry->is_temp_dir) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
"Phar entry is a temporary directory (not an actual entry in the archive), cannot delete metadata"); \
return;
}
+
if (entry_obj->ent.entry->metadata) {
zval_ptr_dtor(&entry_obj->ent.entry->metadata);
entry_obj->ent.entry->metadata = NULL;
@@ -4233,6 +4536,7 @@ PHP_METHOD(PharFileInfo, delMetadata)
entry_obj->ent.entry->phar->is_modified = 1;
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
@@ -4240,6 +4544,7 @@ PHP_METHOD(PharFileInfo, delMetadata)
} else {
RETURN_TRUE;
}
+
} else {
RETURN_TRUE;
}
@@ -4254,6 +4559,7 @@ PHP_METHOD(PharFileInfo, getContent)
char *error;
php_stream *fp;
phar_entry_info *link;
+
PHAR_ENTRY_OBJECT();
if (entry_obj->ent.entry->is_dir) {
@@ -4261,24 +4567,30 @@ PHP_METHOD(PharFileInfo, getContent)
"Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
return;
}
+
link = phar_get_link_source(entry_obj->ent.entry TSRMLS_CC);
+
if (!link) {
link = entry_obj->ent.entry;
}
+
if (SUCCESS != phar_open_entry_fp(link, &error, 0 TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname, error);
efree(error);
return;
}
+
if (!(fp = phar_get_efp(link, 0 TSRMLS_CC))) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
return;
}
+
phar_seek_efp(link, 0, SEEK_SET, 0, 0 TSRMLS_CC);
Z_TYPE_P(return_value) = IS_STRING;
Z_STRLEN_P(return_value) = php_stream_copy_to_mem(fp, &(Z_STRVAL_P(return_value)), link->uncompressed_filesize, 0);
+
if (!Z_STRVAL_P(return_value)) {
Z_STRVAL_P(return_value) = estrndup("", 0);
}
@@ -4303,16 +4615,19 @@ PHP_METHOD(PharFileInfo, compress)
"Cannot compress with Gzip compression, not possible with tar-based phar archives");
return;
}
+
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"); \
return;
}
+
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar is readonly, cannot change compression");
return;
}
+
if (entry_obj->ent.entry->is_deleted) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress deleted file");
@@ -4325,12 +4640,14 @@ PHP_METHOD(PharFileInfo, compress)
RETURN_TRUE;
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0) {
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with gzip compression, file is already compressed with bzip2 compression and bz2 extension is not enabled, cannot decompress");
return;
}
+
/* decompress this file indirectly */
if (SUCCESS != phar_open_entry_fp(entry_obj->ent.entry, &error, 1 TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
@@ -4339,11 +4656,13 @@ PHP_METHOD(PharFileInfo, compress)
return;
}
}
+
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with gzip compression, zlib extension is not enabled");
return;
}
+
entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
entry_obj->ent.entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
entry_obj->ent.entry->flags |= PHAR_ENT_COMPRESSED_GZ;
@@ -4353,12 +4672,14 @@ PHP_METHOD(PharFileInfo, compress)
RETURN_TRUE;
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0) {
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with bzip2 compression, file is already compressed with gzip compression and zlib extension is not enabled, cannot decompress");
return;
}
+
/* decompress this file indirectly */
if (SUCCESS != phar_open_entry_fp(entry_obj->ent.entry, &error, 1 TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
@@ -4367,6 +4688,7 @@ PHP_METHOD(PharFileInfo, compress)
return;
}
}
+
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with bzip2 compression, bz2 extension is not enabled");
@@ -4383,12 +4705,13 @@ PHP_METHOD(PharFileInfo, compress)
entry_obj->ent.entry->phar->is_modified = 1;
entry_obj->ent.entry->is_modified = 1;
-
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
/* }}} */
@@ -4406,30 +4729,36 @@ PHP_METHOD(PharFileInfo, decompress)
"Phar entry is a directory, cannot set compression"); \
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) {
RETURN_TRUE;
return;
}
+
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar is readonly, cannot decompress");
return;
}
+
if (entry_obj->ent.entry->is_deleted) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress deleted file");
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0 && !PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot decompress Gzip-compressed file, zlib extension is not enabled");
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0 && !PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot decompress Bzip2-compressed file, bz2 extension is not enabled");
return;
}
+
if (!entry_obj->ent.entry->fp) {
if (FAILURE == phar_open_archive_fp(entry_obj->ent.entry->phar TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot decompress entry \"%s\", phar error: Cannot open phar archive \"%s\" for reading", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
@@ -4437,12 +4766,13 @@ PHP_METHOD(PharFileInfo, decompress)
}
entry_obj->ent.entry->fp_type = PHAR_FP;
}
+
entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
entry_obj->ent.entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
entry_obj->ent.entry->phar->is_modified = 1;
entry_obj->ent.entry->is_modified = 1;
-
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
diff --git a/ext/phar/phar_path_check.c b/ext/phar/phar_path_check.c
index c1a273281b5..480eed717b2 100755
--- a/ext/phar/phar_path_check.c
+++ b/ext/phar/phar_path_check.c
@@ -4,7 +4,7 @@
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2007 The PHP Group |
+ | Copyright (c) 2007-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/phar/phar_path_check.re b/ext/phar/phar_path_check.re
index 97a6b5d565f..9e89151fff1 100755
--- a/ext/phar/phar_path_check.re
+++ b/ext/phar/phar_path_check.re
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2007 The PHP Group |
+ | Copyright (c) 2007-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/phar/php_phar.h b/ext/phar/php_phar.h
index 89023972f61..f0a34a2e017 100644
--- a/ext/phar/php_phar.h
+++ b/ext/phar/php_phar.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2005 The PHP Group |
+ | Copyright (c) 2005-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -22,7 +22,7 @@
#ifndef PHP_PHAR_H
#define PHP_PHAR_H
-#define PHP_PHAR_VERSION "2.0.0b2-dev"
+#define PHP_PHAR_VERSION "2.0.0b2-dev"
#include "ext/standard/basic_functions.h"
extern zend_module_entry phar_module_entry;
@@ -34,7 +34,7 @@ extern zend_module_entry phar_module_entry;
#define PHP_PHAR_API
#endif
-#endif /* PHP_PHAR_H */
+#endif /* PHP_PHAR_H */
/*
diff --git a/ext/phar/shortarc.php b/ext/phar/shortarc.php
index 0f1679b992b..1bf3baa8aa1 100644
--- a/ext/phar/shortarc.php
+++ b/ext/phar/shortarc.php
@@ -3,293 +3,293 @@
$web = '000';
if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
- Phar::interceptFileFuncs();
- set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());
- Phar::webPhar(null, $web);
- include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
- return;
+ Phar::interceptFileFuncs();
+ set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());
+ Phar::webPhar(null, $web);
+ include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
+ return;
}
if (@(isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'POST'))) {
- Extract_Phar::go(true);
- $mimes = array(
- 'phps' => 2,
- 'c' => 'text/plain',
- 'cc' => 'text/plain',
- 'cpp' => 'text/plain',
- 'c++' => 'text/plain',
- 'dtd' => 'text/plain',
- 'h' => 'text/plain',
- 'log' => 'text/plain',
- 'rng' => 'text/plain',
- 'txt' => 'text/plain',
- 'xsd' => 'text/plain',
- 'php' => 1,
- 'inc' => 1,
- 'avi' => 'video/avi',
- 'bmp' => 'image/bmp',
- 'css' => 'text/css',
- 'gif' => 'image/gif',
- 'htm' => 'text/html',
- 'html' => 'text/html',
- 'htmls' => 'text/html',
- 'ico' => 'image/x-ico',
- 'jpe' => 'image/jpeg',
- 'jpg' => 'image/jpeg',
- 'jpeg' => 'image/jpeg',
- 'js' => 'application/x-javascript',
- 'midi' => 'audio/midi',
- 'mid' => 'audio/midi',
- 'mod' => 'audio/mod',
- 'mov' => 'movie/quicktime',
- 'mp3' => 'audio/mp3',
- 'mpg' => 'video/mpeg',
- 'mpeg' => 'video/mpeg',
- 'pdf' => 'application/pdf',
- 'png' => 'image/png',
- 'swf' => 'application/shockwave-flash',
- 'tif' => 'image/tiff',
- 'tiff' => 'image/tiff',
- 'wav' => 'audio/wav',
- 'xbm' => 'image/xbm',
- 'xml' => 'text/xml',
- );
+ Extract_Phar::go(true);
+ $mimes = array(
+ 'phps' => 2,
+ 'c' => 'text/plain',
+ 'cc' => 'text/plain',
+ 'cpp' => 'text/plain',
+ 'c++' => 'text/plain',
+ 'dtd' => 'text/plain',
+ 'h' => 'text/plain',
+ 'log' => 'text/plain',
+ 'rng' => 'text/plain',
+ 'txt' => 'text/plain',
+ 'xsd' => 'text/plain',
+ 'php' => 1,
+ 'inc' => 1,
+ 'avi' => 'video/avi',
+ 'bmp' => 'image/bmp',
+ 'css' => 'text/css',
+ 'gif' => 'image/gif',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'htmls' => 'text/html',
+ 'ico' => 'image/x-ico',
+ 'jpe' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'js' => 'application/x-javascript',
+ 'midi' => 'audio/midi',
+ 'mid' => 'audio/midi',
+ 'mod' => 'audio/mod',
+ 'mov' => 'movie/quicktime',
+ 'mp3' => 'audio/mp3',
+ 'mpg' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'pdf' => 'application/pdf',
+ 'png' => 'image/png',
+ 'swf' => 'application/shockwave-flash',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'wav' => 'audio/wav',
+ 'xbm' => 'image/xbm',
+ 'xml' => 'text/xml',
+ );
- header("Cache-Control: no-cache, must-revalidate");
- header("Pragma: no-cache");
+ header("Cache-Control: no-cache, must-revalidate");
+ header("Pragma: no-cache");
- $basename = basename(__FILE__);
- if (!strpos($_SERVER['REQUEST_URI'], $basename)) {
- chdir(Extract_Phar::$temp);
- include $web;
- return;
- }
- $pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename));
- if (!$pt || $pt == '/') {
- $pt = $web;
- header('HTTP/1.1 301 Moved Permanently');
- header('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt);
- exit;
- }
- $a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt);
- if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) {
- header('HTTP/1.0 404 Not Found');
- echo "\n