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
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) {
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 */
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);
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;
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
* ?: phar metadata
*/
restore_alias_len = phar->alias_len;
- if (!phar->is_explicit_alias) {
+ if (phar->is_temporary_alias) {
phar->alias_len = 0;
}
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;
#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;
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);
*/
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)) {
}
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;
}
}
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;
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 */
}
}
- 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 */
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;
}
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) {