diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/phar/TODO | 5 | ||||
-rw-r--r-- | ext/phar/package.xml | 2 | ||||
-rw-r--r-- | ext/phar/phar.c | 133 | ||||
-rwxr-xr-x | ext/phar/phar_internal.h | 4 | ||||
-rwxr-xr-x | ext/phar/phar_object.c | 22 | ||||
-rwxr-xr-x | ext/phar/tests/extracted.inc | 1 | ||||
-rwxr-xr-x | ext/phar/tests/extracted_001.phpt | 35 |
7 files changed, 190 insertions, 12 deletions
diff --git a/ext/phar/TODO b/ext/phar/TODO index 6bf549a6b3..3dced205c3 100644 --- a/ext/phar/TODO +++ b/ext/phar/TODO @@ -32,9 +32,14 @@ Version 1.0.0 Version 1.1.0 + X Ability connect a phar file 'phar://whatever' to a directory. That way all + access to that phat archive are directed to the extracted directory. This + allows to have the installed files and the archieve keep the same includes. + [Marcus] * ability to have Phar object return file class as offsetGet() result * [optional] Phar->rollback() to abort a write transaction * implement GPG signing + * add SHA-2 support * ability to match files containing a metadata key opendir('phar://a.phar/?mime-type=image/jpeg') or foreach ($p->match('mime-type', 'image/jpeg') as $file) * Phar::copy($from, $to); diff --git a/ext/phar/package.xml b/ext/phar/package.xml index 18b4661792..f6e6a1ee73 100644 --- a/ext/phar/package.xml +++ b/ext/phar/package.xml @@ -98,6 +98,8 @@ if the ini variable phar.require_hash is set to true. <file name="delete_in_phar.phpt" role="test"/> <file name="delete_in_phar_b.phpt" role="test"/> <file name="delete_in_phar_confirm.phpt" role="test"/> + <file name="extracted.inc" role="test"/> + <file name="extracted_001.phpt" role="test"/> <file name="ini_set.phpt" role="test"/> <file name="ini_set_off.phpt" role="test"/> <file name="metadata_read.phpt" role="test"/> diff --git a/ext/phar/phar.c b/ext/phar/phar.c index de5802147b..2f40a6df4b 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -21,6 +21,7 @@ #define PHAR_MAIN #include "phar_internal.h" +#include "SAPI.h" ZEND_DECLARE_MODULE_GLOBALS(phar) @@ -69,9 +70,98 @@ ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */ } /* }}}*/ +static void phar_split_extract_list(TSRMLS_D) +{ + char *tmp = estrdup(PHAR_GLOBALS->extract_list); + char *key; + char *lasts; + char *q; + int keylen; + + zend_hash_clean(&(PHAR_GLOBALS->phar_plain_map)); + + for (key = php_strtok_r(tmp, ",", &lasts); + key; + key = php_strtok_r(NULL, ",", &lasts)) + { + char *val = strchr(key, '='); + + if (val) { + *val++ = '\0'; + for (q = key; *q; q++) { + *q = tolower(*q); + } + keylen = q - key + 1; + zend_hash_add(&(PHAR_GLOBALS->phar_plain_map), key, keylen, val, strlen(val)+1, NULL); + } + } + efree(tmp); +} +/* }}} */ + +ZEND_INI_MH(phar_ini_extract_list) /* {{{ */ +{ + PHAR_G(extract_list) = new_value; + + if (stage == ZEND_INI_STAGE_RUNTIME) { + phar_split_extract_list(TSRMLS_C); + } + + return SUCCESS; +} +/* }}} */ + +ZEND_INI_DISP(phar_ini_extract_list_disp) /*void name(zend_ini_entry *ini_entry, int type) {{{ */ +{ + char *value; + + if (type==ZEND_INI_DISPLAY_ORIG && ini_entry->modified) { + value = ini_entry->orig_value; + } else if (ini_entry->value) { + value = ini_entry->value; + } else { + value = NULL; + } + + if (value) { + char *tmp = strdup(value); + char *key; + char *lasts; + char *q; + + if (!sapi_module.phpinfo_as_text) { + php_printf("<ul>"); + } + for (key = php_strtok_r(tmp, ",", &lasts); + key; + key = php_strtok_r(NULL, ",", &lasts)) + { + char *val = strchr(key, '='); + + if (val) { + *val++ = '\0'; + for (q = key; *q; q++) { + *q = tolower(*q); + } + if (sapi_module.phpinfo_as_text) { + php_printf("%s => %s", key, val); + } else { + php_printf("<li>%s => %s</li>", key, val); + } + } + } + if (!sapi_module.phpinfo_as_text) { + php_printf("</ul>"); + } + free(tmp); + } +} +/* }}} */ + 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.require_hash", "1", PHP_INI_ALL, phar_ini_modify_handler, require_hash, 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_EX("phar.extract_list", "", PHP_INI_ALL, phar_ini_extract_list, extract_list, zend_phar_globals, phar_globals, phar_ini_extract_list_disp) PHP_INI_END() /** @@ -774,7 +864,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int return FAILURE; } - sig_len = phar_hex_str(digest, sizeof(digest), &signature); + sig_len = phar_hex_str((const char*)digest, sizeof(digest), &signature); break; } case PHAR_SIG_MD5: { @@ -809,7 +899,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int return FAILURE; } - sig_len = phar_hex_str(digest, sizeof(digest), &signature); + sig_len = phar_hex_str((const char*)digest, sizeof(digest), &signature); break; } default: @@ -1446,6 +1536,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat char *buffer; char *error; char *filter_name; + char *plain_map; char tmpbuf[8]; HashTable *pharcontext; php_url *resource = NULL; @@ -1453,6 +1544,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat php_stream_filter *filter/*, *consumed */; php_uint32 offset, read, total, toread; zval **pzoption, *metadata; + uint host_len; resource = php_url_parse(path); @@ -1473,10 +1565,21 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat return NULL; } + host_len = strlen(resource->host); + if (zend_hash_find(&(PHAR_GLOBALS->phar_plain_map), resource->host, host_len+1, (void **)&plain_map) == SUCCESS) { + spprintf(&internal_file, 0, "%s%s", plain_map, resource->path); + fp = php_stream_open_wrapper_ex(internal_file, mode, options, opened_path, context); + if (!fp) { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: file \"%s\" extracted from \"%s\" could not be opened", internal_file, resource->host); + } + efree(internal_file); + return fp; + } + /* strip leading "/" */ internal_file = estrdup(resource->path + 1); if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) { - if (NULL == (idata = phar_get_or_create_entry_data(resource->host, strlen(resource->host), internal_file, strlen(internal_file), mode, &error TSRMLS_CC))) { + if (NULL == (idata = phar_get_or_create_entry_data(resource->host, host_len, internal_file, strlen(internal_file), mode, &error TSRMLS_CC))) { if (error) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error); efree(error); @@ -1518,7 +1621,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat } return fpf; } else { - if ((FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) || !idata) { + if ((FAILURE == phar_get_entry_data(&idata, resource->host, host_len, internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) || !idata) { if (error) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error); efree(error); @@ -2353,7 +2456,7 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err PHP_SHA1Final(digest, &context); php_stream_write(newfile, (char *) digest, sizeof(digest)); sig_flags |= PHAR_SIG_SHA1; - archive->sig_len = phar_hex_str(digest, sizeof(digest), &archive->signature); + archive->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &archive->signature); break; } case PHAR_SIG_MD5: { @@ -2367,7 +2470,7 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err PHP_MD5Final(digest, &context); php_stream_write(newfile, (char *) digest, sizeof(digest)); sig_flags |= PHAR_SIG_MD5; - archive->sig_len = phar_hex_str(digest, sizeof(digest), &archive->signature); + archive->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &archive->signature); break; } } @@ -3128,6 +3231,8 @@ PHP_RINIT_FUNCTION(phar) /* {{{ */ PHAR_GLOBALS->request_done = 0; zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data, 0); zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 0); + zend_hash_init(&(PHAR_GLOBALS->phar_plain_map), sizeof(const char *), zend_get_hash_value, NULL, 0); + phar_split_extract_list(TSRMLS_C); return SUCCESS; } /* }}} */ @@ -3135,8 +3240,9 @@ PHP_RINIT_FUNCTION(phar) /* {{{ */ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */ { zend_hash_destroy(&(PHAR_GLOBALS->phar_alias_map)); - PHAR_GLOBALS->phar_fname_map. pDestructor = destroy_phar_data_only; + PHAR_GLOBALS->phar_fname_map.pDestructor = destroy_phar_data_only; zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map)); + zend_hash_destroy(&(PHAR_GLOBALS->phar_plain_map)); PHAR_GLOBALS->request_done = 1; return SUCCESS; } @@ -3161,9 +3267,14 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */ #else "disabled"); #endif - php_info_print_table_row(1, "Phar based on pear/PHP_Archive, original concept by Davey Shafik"); - php_info_print_table_row(1, "Phar fully realized by Gregory Beaver and Marcus Boerger"); php_info_print_table_end(); + + php_info_print_box_start(0); + PUTS("Phar based on pear/PHP_Archive, original concept by Davey Shafik."); + PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n"); + PUTS("Phar fully realized by Gregory Beaver and Marcus Boerger."); + php_info_print_box_end(); + DISPLAY_INI_ENTRIES(); } /* }}} */ diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 06a45fbf10..c27137775f 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -98,10 +98,12 @@ ZEND_BEGIN_MODULE_GLOBALS(phar) HashTable phar_fname_map; HashTable phar_alias_map; + HashTable phar_plain_map; + char* extract_list; int readonly; - int require_hash; zend_bool readonly_orig; zend_bool require_hash_orig; + int require_hash; int request_done; ZEND_END_MODULE_GLOBALS(phar) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 6dead35e4e..707c22b198 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -28,6 +28,27 @@ static zend_class_entry *phar_ce_PharException; static zend_class_entry *phar_ce_entry; #endif +static int phar_get_extract_list(void *pDest, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ +{ + zval *return_value = va_arg(args, zval*); + + add_assoc_string_ex(return_value, hash_key->arKey, hash_key->nKeyLength, (char*)pDest, 1); + + return ZEND_HASH_APPLY_KEEP; +} +/* }}} */ + +/* {{ proto array Phar::getExtractList() + * Return array of extract list + */ +PHP_METHOD(Phar, getExtractList) +{ + array_init(return_value); + + zend_hash_apply_with_arguments(&PHAR_G(phar_plain_map), phar_get_extract_list, 1, return_value); +} +/* }}} */ + /* {{{ proto mixed Phar::mapPhar([string alias]) * Reads the currently executed file (a phar) and registers its manifest */ PHP_METHOD(Phar, mapPhar) @@ -1177,6 +1198,7 @@ zend_function_entry php_archive_methods[] = { PHP_ME(Phar, canWrite, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) + PHP_ME(Phar, getExtractList, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) {NULL, NULL, NULL} }; diff --git a/ext/phar/tests/extracted.inc b/ext/phar/tests/extracted.inc new file mode 100755 index 0000000000..a6e52246a3 --- /dev/null +++ b/ext/phar/tests/extracted.inc @@ -0,0 +1 @@ +<?php var_dump(__FILE__); ?> diff --git a/ext/phar/tests/extracted_001.phpt b/ext/phar/tests/extracted_001.phpt new file mode 100755 index 0000000000..8f1254d3d1 --- /dev/null +++ b/ext/phar/tests/extracted_001.phpt @@ -0,0 +1,35 @@ +--TEST-- +Phar: extracted +--SKIPIF-- +<?php if (!extension_loaded("phar")) print "skip"; ?> +--INI-- +phar.readonly=0 +phar.require_hash=0 +phar.extract_list="phar_test.phar=test" +--FILE-- +<?php +var_dump(Phar::getExtractList()); +ini_set('phar.extract_list', 'phar_test.phar='.dirname(__FILE__)); +var_dump(Phar::getExtractList()); + +$pname = 'phar://phar_test.phar'; + +var_dump(file_get_contents($pname . '/extracted.inc')); + +include $pname . '/extracted.inc'; + +?> +===DONE=== +--EXPECTF-- +array(1) { + ["phar_test.phar"]=> + string(4) "test" +} +array(1) { + ["phar_test.phar"]=> + string(%d) "%s" +} +string(29) "<?php var_dump(__FILE__); ?> +" +string(%d) "%sextracted.inc" +===DONE=== |