From 78e8eb39007d51e8dec43e89140dfa54a18d25ba Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Mon, 11 Feb 2008 06:46:44 +0000 Subject: [PATCH] major refactoring of internal handling of aliases. 1) rename is_explicit_alias to is_temporary_alias for clarity and flip the value 2) fix setAlias so that it sets a permanent to-be-saved alias, and restores the old one on error 3) fix Phar constructor to work with sub-directories in RecursiveDirectoryIterator --- ext/phar/phar.c | 15 ++++++------ ext/phar/phar_internal.h | 3 ++- ext/phar/phar_object.c | 52 +++++++++++++++++++++++++++++++++------- ext/phar/tar.c | 22 +++++++++++++---- ext/phar/zip.c | 10 ++++---- 5 files changed, 76 insertions(+), 26 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 65f476b5f6..90f1a0ca84 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -498,7 +498,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int php_uint32 manifest_len, manifest_count, manifest_flags, manifest_index, tmp_len, sig_flags; php_uint16 manifest_ver; long offset; - int register_alias, sig_len; + int register_alias, sig_len, temp_alias = 0; char *signature = NULL; if (pphar) { @@ -808,8 +808,9 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int alias = NULL; alias_len = 0; register_alias = 0; - } else { + } else if (alias_len) { register_alias = 1; + temp_alias = 1; } /* we have 5 32-bit items plus 1 byte at least */ @@ -929,10 +930,10 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int 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 (register_alias) { - mydata->is_explicit_alias = 1; + mydata->is_temporary_alias = temp_alias; zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL); } else { - mydata->is_explicit_alias = 0; + mydata->is_temporary_alias = 1; } efree(savebuf); @@ -1069,7 +1070,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len); mydata->alias_len = alias ? alias_len : fname_len; snprintf(mydata->version, sizeof(mydata->version), "%s", PHAR_API_VERSION_STR); - mydata->is_explicit_alias = alias ? 1 : 0; + mydata->is_temporary_alias = alias ? 0 : 1; mydata->internal_file_start = -1; mydata->fp = fp; mydata->is_writeable = 1; @@ -1201,7 +1202,7 @@ static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias, array_init(&filterparams); /* ext/zlib zval_dtors a separated zval, so we have to make sure it doesn't destroy ours */ #if PHP_VERSION_ID < 50300 - filterparams->refcount = 26; + filterparams.refcount = 26; #else Z_SET_REFCOUNT(filterparams, 26); #endif @@ -2082,7 +2083,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error * ?: phar metadata */ restore_alias_len = phar->alias_len; - if (!phar->is_explicit_alias) { + if (phar->is_temporary_alias) { phar->alias_len = 0; } diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 3e28299ec8..57a5ec1de6 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -265,7 +265,8 @@ struct _phar_archive_data { int sig_len; char *signature; zval *metadata; - int is_explicit_alias:1; + /* if 1, then this alias was manually specified by the user and is not a permanent alias */ + int is_temporary_alias:1; int is_modified:1; int is_writeable:1; int is_brandnew:1; diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 9e92f1f0cc..4a768390fd 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1046,8 +1046,8 @@ PHP_METHOD(Phar, __construct) #if !HAVE_SPL zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Cannot instantiate Phar object without SPL extension"); #else - char *fname, *alias = NULL, *error; - int fname_len, alias_len = 0; + char *fname, *alias = NULL, *error, *arch, *entry = NULL, *save_fname; + int fname_len, alias_len = 0, arch_len, entry_len; long flags = 0; phar_archive_object *phar_obj; phar_archive_data *phar_data; @@ -1064,23 +1064,45 @@ PHP_METHOD(Phar, __construct) return; } + if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len)) { + /* use arch for fname instead of fname */ + /* this allows support for RecursiveDirectoryIterator of subdirectories */ + save_fname = fname; + fname = arch; + fname_len = arch_len; + } if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, &phar_data, &error TSRMLS_CC) == FAILURE) { + if (fname == arch) { + efree(arch); + fname = save_fname; + } if (error) { + efree(entry); zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Cannot open phar file '%s' with alias '%s': %s", fname, alias, error); efree(error); } else { + efree(entry); zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Cannot open phar file '%s' with alias '%s'", fname, alias); } return; } + if (fname == arch) { + efree(arch); + fname = save_fname; + } phar_data->refcount++; phar_obj->arc.archive = phar_data; phar_obj->spl.oth_handler = &phar_spl_foreign_handler; - fname_len = spprintf(&fname, 0, "phar://%s", phar_data->fname); + if (entry) { + fname_len = spprintf(&fname, 0, "phar://%s%s", phar_data->fname, entry); + efree(entry); + } else { + fname_len = spprintf(&fname, 0, "phar://%s", phar_data->fname); + } INIT_PZVAL(&arg1); ZVAL_STRINGL(&arg1, fname, fname_len, 0); @@ -1976,9 +1998,9 @@ PHP_METHOD(Phar, getAlias) */ PHP_METHOD(Phar, setAlias) { - char *alias, *error; + char *alias, *error, *oldalias; phar_archive_data **fd_ptr; - int alias_len; + int alias_len, oldalias_len, old_temp, readd = 0; PHAR_ARCHIVE_OBJECT(); if (PHAR_G(readonly)) { @@ -1999,23 +2021,35 @@ PHP_METHOD(Phar, setAlias) } if (phar_obj->arc.archive->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), phar_obj->arc.archive->alias, phar_obj->arc.archive->alias_len, (void**)&fd_ptr)) { zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), phar_obj->arc.archive->alias, phar_obj->arc.archive->alias_len); + readd = 1; } - if (phar_obj->arc.archive->alias) { - efree(phar_obj->arc.archive->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_explicit_alias = 1; + phar_obj->arc.archive->is_temporary_alias = 0; phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); if (error) { + phar_obj->arc.archive->alias = oldalias; + phar_obj->arc.archive->alias_len = oldalias_len; + phar_obj->arc.archive->is_temporary_alias = old_temp; zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); + if (readd) { + zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), oldalias, oldalias_len, (void*)&(phar_obj->arc.archive), sizeof(phar_archive_data*), NULL); + } efree(error); + return; + } + 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; } diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 30d962615f..78f4d1b8e3 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -312,12 +312,12 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i } myphar = *actual; if (actual_alias) { - myphar->is_explicit_alias = 1; + myphar->is_temporary_alias = 0; zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL); } else { myphar->alias = estrndup(myphar->fname, fname_len); myphar->alias_len = fname_len; - myphar->is_explicit_alias = 0; + myphar->is_temporary_alias = 1; } if (pphar) { *pphar = myphar; @@ -448,14 +448,26 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, char **er entry.phar = phar; entry.fp_type = PHAR_MOD; /* set alias */ - if (phar->is_explicit_alias) { + if (!phar->is_temporary_alias && phar->alias_len) { entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1); entry.filename_len = sizeof(".phar/alias.txt")-1; entry.fp = php_stream_fopen_tmpfile(); entry.crc32 = phar_tar_checksum(phar->alias, phar->alias_len); - php_stream_write(entry.fp, phar->alias, phar->alias_len); + if (phar->alias_len != (int)php_stream_write(entry.fp, phar->alias, phar->alias_len)) { + if (error) { + spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname); + } + return EOF; + } entry.uncompressed_filesize = phar->alias_len; - zend_hash_update(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL); + if (SUCCESS != zend_hash_update(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) { + if (error) { + spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname); + } + return EOF; + } + } else { + zend_hash_del(&phar->manifest, ".phar/alias.txt", sizeof(".phar/alias.txt")-1); } /* set stub */ diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 5fc548ebf2..2626a34cd9 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -350,7 +350,7 @@ foundit: } } - mydata->is_explicit_alias = 1; + mydata->is_temporary_alias = 0; mydata->alias_len = zipentry.uncompsize; zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), mydata->alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL); /* return to central directory parsing */ @@ -659,11 +659,11 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, char **er entry.fp_type = PHAR_MOD; /* set alias */ - if (phar->is_explicit_alias) { + if (!phar->is_temporary_alias && phar->alias_len) { entry.fp = php_stream_fopen_tmpfile(); if (phar->alias_len != (int)php_stream_write(entry.fp, phar->alias, phar->alias_len)) { if (error) { - spprintf(error, 0, "unable to set alias in new zip-based phar \"%s\"", phar->fname); + spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname); } return EOF; } @@ -673,10 +673,12 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, char **er entry.is_modified = 1; if (SUCCESS != zend_hash_update(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) { if (error) { - spprintf(error, 0, "unable to set alias in new zip-based phar \"%s\"", phar->fname); + spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname); } return EOF; } + } else { + zend_hash_del(&phar->manifest, ".phar/alias.txt", sizeof(".phar/alias.txt")-1); } /* register alias */ if (phar->alias_len) { -- 2.50.1