From: Steph Fox Date: Sun, 24 Feb 2008 22:29:06 +0000 (+0000) Subject: A bunch of stuff to do with filename conversion. Hopefully it won't sink the ship. X-Git-Tag: RELEASE_2_0_0a1~343 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8513db73bbf2f9b43aa690805a15f13219b96763;p=php A bunch of stuff to do with filename conversion. Hopefully it won't sink the ship. --- diff --git a/ext/phar/TODO b/ext/phar/TODO index 7130121857..32053f2656 100644 --- a/ext/phar/TODO +++ b/ext/phar/TODO @@ -78,15 +78,14 @@ Version 2.0.0 storing sqlite databases, cache, or template files in a location external to the phar. Copy of the files would need to be performed in an installation step, phar would not attempt to do this for performance and security reasons. - * make convertToZip/convertToTar rename files and return the new filename. Also, convertToPhar() with full - file compression should rename to append .gz or .bz + X make convertToZip/convertToTar rename files [Steph] + X make convertTo*() with full file compression rename to append .gz or .bz2 [Steph] * don't automatically add a stub to .zip or .tar files - * don't allow a stub to be added to a .zip/.tar that does not have ".phar" in the filename somewhere + * don't allow a stub to be added to a .zip/.tar that does not have ".phar" in the filename * allow read/write on .tar/.zip files that do not contain a stub or alias file * prevent manual addition of stub via $a['.phar/stub.php'] = 'fname, error); zend_hash_del(&phar->manifest, entry.filename, entry.filename_len); @@ -576,7 +576,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_ /* now for the easy part */ entry->is_deleted = 1; entry->is_modified = 1; - phar_flush(phar, 0, 0, &error TSRMLS_CC); + 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); diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 1707259be5..d4c746e5d0 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -343,7 +343,7 @@ void phar_entry_remove(phar_entry_data *idata, char **error TSRMLS_DC) /* {{{ */ phar_entry_delref(idata TSRMLS_CC); } if (!phar->donotflush) { - phar_flush(phar, 0, 0, error TSRMLS_CC); + phar_flush(phar, 0, 0, 0, error TSRMLS_CC); } } /* }}} */ @@ -1749,7 +1749,7 @@ char *phar_create_default_stub(const char *index_php, const char *web_index, siz * user_stub contains either a string, or a resource pointer, if len is a negative length. * user_stub and len should be both 0 if the default or existing stub should be used */ -int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error TSRMLS_DC) /* {{{ */ +int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, char **error TSRMLS_DC) /* {{{ */ { /* static const char newstub[] = "\r\n"; */ char *newstub; @@ -1777,11 +1777,12 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error } if (phar->is_zip) { - return phar_zip_flush(phar, user_stub, len, error TSRMLS_CC); + return phar_zip_flush(phar, user_stub, len, convert, error TSRMLS_CC); } if (phar->is_tar) { - return phar_tar_flush(phar, user_stub, len, error TSRMLS_CC); + return phar_tar_flush(phar, user_stub, len, convert, error TSRMLS_CC); } + if (phar->fp && !phar->is_brandnew) { oldfile = phar->fp; closeoldfile = 0; @@ -1868,8 +1869,8 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error efree(user_stub); } } else { - if (phar->halt_offset && oldfile && !phar->is_brandnew) { - if (phar->halt_offset != php_stream_copy_to_stream(oldfile, newfile, phar->halt_offset)) { + if (!user_stub && phar->halt_offset && oldfile && !phar->is_brandnew) { + if (phar->halt_offset != php_stream_copy_to_stream(oldfile, newfile, phar->halt_offset)) { if (closeoldfile) { php_stream_close(oldfile); } @@ -1880,7 +1881,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error return EOF; } } else { - /* this is a brand new phar */ + /* this is either a brand new phar or a default stub overwrite */ newstub = phar_create_default_stub(NULL, NULL, &(phar->halt_offset), NULL TSRMLS_CC); if (phar->halt_offset != php_stream_write(newfile, newstub, phar->halt_offset)) { efree(newstub); diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 7d18be8a0b..ae01d5b350 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -392,14 +392,13 @@ int phar_open_archive_fp(phar_archive_data *phar TSRMLS_DC); /* tar functions in tar.c */ int phar_is_tar(char *buf); int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC); -int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC); int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC); -int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, char **error TSRMLS_DC); +int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defaultstub, char **error TSRMLS_DC); /* zip functions in zip.c */ int phar_open_zipfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar, char **error TSRMLS_DC); int phar_open_or_create_zip(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC); -int phar_zip_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC); +int phar_zip_flush(phar_archive_data *archive, char *user_stub, long len, int defaultstub, char **error TSRMLS_DC); #ifdef PHAR_MAIN static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC); @@ -413,7 +412,7 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int pa phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error TSRMLS_DC); phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC); int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC); -int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC); +int phar_flush(phar_archive_data *archive, char *user_stub, long len, int convert, char **error TSRMLS_DC); int phar_detect_phar_fname_ext(const char *filename, int check_length, char **ext_str, int *ext_len); int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 1b40ce5bc4..4f49241b07 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1452,7 +1452,7 @@ PHP_METHOD(Phar, buildFromIterator) pass.ret = return_value; if (SUCCESS == spl_iterator_apply(obj, (spl_iterator_apply_func_t) phar_build, (void *) &pass TSRMLS_CC)) { - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -1560,13 +1560,10 @@ static int phar_restore_apply(void *data TSRMLS_DC) /* {{{ */ } /* }}} */ -static void phar_convert_to_other(phar_archive_data *source, int convert, php_uint32 flags TSRMLS_DC) /* {{{ */ +static void phar_convert_to_other(phar_archive_data *source, int convert, char *ext, php_uint32 flags TSRMLS_DC) /* {{{ */ { phar_archive_data phar = {0}; char *error; - zval *userz; - long tmp; - php_stream *fp; phar_entry_info *entry, newentry; /* set whole-archive compression from parameter */ @@ -1596,17 +1593,6 @@ static void phar_convert_to_other(phar_archive_data *source, int convert, php_ui zend_hash_apply(&source->manifest, phar_restore_apply TSRMLS_CC); return; } - if (!convert) { - /* converting to Phar */ - if (entry->filename_len == sizeof(".phar/stub.php")-1 && !strncmp(entry->filename, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { - /* do not copy stub file */ - continue; - } - if (entry->filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry->filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) { - /* do not copy alias file */ - continue; - } - } if (entry->fp_refcount > 0) { zend_hash_destroy(&(phar.manifest)); php_stream_close(phar.fp); @@ -1651,41 +1637,7 @@ static void phar_convert_to_other(phar_archive_data *source, int convert, php_ui zend_hash_add(&(phar.manifest), newentry.filename, newentry.filename_len, (void*)&newentry, sizeof(phar_entry_info), NULL); } - /* next copy the stub and flush */ - - if (source->is_tar || source->is_zip) { - if (FAILURE == (zend_hash_find(&source->manifest, ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&entry))) { - /* use default stub - the existing one in the manifest will be used if present */ - phar_flush(&phar, NULL, 0, &error TSRMLS_CC); - goto finalize; - } - fp = php_stream_open_wrapper(source->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL); - php_stream_seek(fp, entry->offset, SEEK_SET); - /* use this unused value to set the stub size */ - source->internal_file_start = entry->uncompressed_filesize; - } else { - fp = php_stream_open_wrapper(source->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL); - } - /* copy the other phar's stub */ - ALLOC_ZVAL(userz); - php_stream_to_zval(fp, userz); - tmp = source->internal_file_start; - source->internal_file_start = 0; - phar_flush(&phar, (char *) &userz, -tmp, &error TSRMLS_CC); - php_stream_close(fp); - efree(userz); - - if (error) { - zend_hash_destroy(&(phar.manifest)); - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, - "Cannot convert phar archive \"%s\": %s", source->fname, error); - efree(error); - php_stream_close(phar.fp); - return; - } - -finalize: - /* third, update the old phar's manifest */ + /* update the original manifest */ for (zend_hash_internal_pointer_reset(&(phar.manifest)); SUCCESS == zend_hash_has_more_elements(&(phar.manifest)); zend_hash_move_forward(&(phar.manifest))) { phar_entry_info *entry, *mine; if (FAILURE == zend_hash_get_current_data(&(phar.manifest), (void **) &entry)) { @@ -1696,32 +1648,6 @@ finalize: return; } if (FAILURE == zend_hash_find(&source->manifest, entry->filename, entry->filename_len, (void **) &mine)) { - if (phar.is_tar || phar.is_zip) { - if (entry->filename_len == sizeof(".phar/stub.php")-1 && !strncmp(entry->filename, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { - /* a little hack to prevent destruction of data */ - dtor_func_t save; - - entry->phar = source; - save = phar.manifest.pDestructor; - phar.manifest.pDestructor = NULL; - zend_hash_add(&source->manifest, ".phar/stub.php", sizeof(".phar/stub.php")-1, (void*)entry, sizeof(phar_entry_info), NULL); - zend_hash_del(&(phar.manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1); - phar.manifest.pDestructor = save; - continue; - } - if (entry->filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry->filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) { - /* a little hack to prevent destruction of data */ - dtor_func_t save; - - entry->phar = source; - save = phar.manifest.pDestructor; - phar.manifest.pDestructor = NULL; - zend_hash_add(&source->manifest, ".phar/alias.txt", sizeof(".phar/alias.txt")-1, (void*)entry, sizeof(phar_entry_info), NULL); - zend_hash_del(&(phar.manifest), ".phar/alias.txt", sizeof(".phar/alias.txt")-1); - phar.manifest.pDestructor = save; - continue; - } - } zend_hash_destroy(&(phar.manifest)); php_stream_close(phar.fp); /* we can't throw an exception or bad crap will happen */ @@ -1748,10 +1674,10 @@ finalize: phar.manifest.pDestructor = NULL; zend_hash_destroy(&(phar.manifest)); source->is_zip = phar.is_zip; + source->is_tar = phar.is_tar; if (phar.is_zip || phar.is_tar) { source->internal_file_start = source->halt_offset = 0; } - source->is_tar = phar.is_tar; if (source->signature) { efree(source->signature); } @@ -1760,21 +1686,34 @@ finalize: } else { source->signature = 0; } + if (source->alias) { + efree(source->alias); + } + source->alias = NULL; + source->alias_len = 0; + source->is_temporary_alias = 0; + source->flags = phar.flags; + + phar_rename_archive(source, ext TSRMLS_CC); + phar_flush(source, 0, 0, convert, &error TSRMLS_CC); } /* }}} */ -/* {{{ proto bool Phar::convertToTar([int compression]) - * Convert the phar archive to the tar file format. The optional parameter can be one of Phar::GZ - * or Phar::BZ2 to specify whole-file compression +/* {{{ proto bool Phar::convertToTar([int compression, [string extension]]) + * Convert the phar archive to the tar file format. The first parameter can + * be one of Phar::GZ or Phar::BZ2 to specify whole-file compression. The + * second parameter allows the user to determine the new filename extension + * (default is phar.tar). Both parameters are optional. */ PHP_METHOD(Phar, convertToTar) { - char *error; + char *error, *ext = NULL; php_uint32 flags; long method = 0; + int ext_len = 0; PHAR_ARCHIVE_OBJECT(); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &method) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &method, &ext, &ext_len) == FAILURE) { return; } @@ -1814,26 +1753,13 @@ PHP_METHOD(Phar, convertToTar) return; } - if (!zend_hash_num_elements(&phar_obj->arc.archive->manifest)) { - /* nothing need be done specially, this has no files in it */ - phar_obj->arc.archive->is_tar = 1; - phar_obj->arc.archive->is_modified = 1; - RETURN_TRUE; - } - if (phar_obj->arc.archive->donotflush) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot convert phar archive to tar format, call stopBuffering() first"); return; } - phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); - if (error) { - zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); - efree(error); - return; - } - phar_convert_to_other(phar_obj->arc.archive, 1, flags TSRMLS_CC); + phar_convert_to_other(phar_obj->arc.archive, 1, ext, flags TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -1843,8 +1769,13 @@ PHP_METHOD(Phar, convertToTar) */ PHP_METHOD(Phar, convertToZip) { - char *error; + char *error, *ext = NULL; + int ext_len = 0; PHAR_ARCHIVE_OBJECT(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ext) == FAILURE) { + return; + } if (phar_obj->arc.archive->is_zip) { RETURN_TRUE; @@ -1861,29 +1792,26 @@ PHP_METHOD(Phar, convertToZip) return; } - phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); - if (error) { - zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); - efree(error); - return; - } - phar_convert_to_other(phar_obj->arc.archive, 2, 0 TSRMLS_CC); + phar_convert_to_other(phar_obj->arc.archive, 2, ext, 0 TSRMLS_CC); RETURN_TRUE; } /* }}} */ -/* {{{ proto bool Phar::convertToPhar([int compression]) - * Convert the phar archive to the phar file format. The optional parameter can be one of Phar::GZ - * or Phar::BZ2 to specify whole-file compression +/* {{{ proto bool Phar::convertToPhar([int compression, [bool rename]]) + * Convert the phar archive to the tar file format. The first parameter can + * be one of Phar::GZ or Phar::BZ2 to specify whole-file compression. The + * second parameter determines whether the filename should be changed to + * reflect the new type (on by default). Both parameters are optional. */ PHP_METHOD(Phar, convertToPhar) { - char *error; + char *error, *ext = NULL; php_uint32 flags; long method = 0; + int ext_len = 0; PHAR_ARCHIVE_OBJECT(); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &method) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &method, &ext, &ext_len) == FAILURE) { return; } @@ -1929,28 +1857,7 @@ PHP_METHOD(Phar, convertToPhar) return; } - if (!zend_hash_num_elements(&phar_obj->arc.archive->manifest)) { - /* nothing need be done specially, this has no files in it */ - phar_obj->arc.archive->is_tar = 0; - phar_obj->arc.archive->is_zip = 0; - phar_obj->arc.archive->is_modified = 1; - RETURN_TRUE; - } - - if (phar_obj->arc.archive->donotflush) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, - "Cannot convert phar archive to zip format, call stopBuffering() first"); - return; - } - - phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); - if (error) { - zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); - efree(error); - return; - } - - phar_convert_to_other(phar_obj->arc.archive, 0, flags TSRMLS_CC); + phar_convert_to_other(phar_obj->arc.archive, 0, ext, flags TSRMLS_CC); RETURN_TRUE; } /* }}} */ @@ -2009,7 +1916,7 @@ PHP_METHOD(Phar, delete) RETURN_FALSE; } - phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); + phar_flush(phar_obj->arc.archive, NULL, 0, 0, &error TSRMLS_CC); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); efree(error); @@ -2074,7 +1981,7 @@ PHP_METHOD(Phar, setAlias) phar_obj->arc.archive->alias_len = alias_len; phar_obj->arc.archive->is_temporary_alias = 0; - phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); + 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; @@ -2146,7 +2053,7 @@ PHP_METHOD(Phar, stopBuffering) phar_obj->arc.archive->donotflush = 0; - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -2179,7 +2086,7 @@ PHP_METHOD(Phar, setStub) } else { len = -1; } - phar_flush(phar_obj->arc.archive, (char *) &zstub, len, &error TSRMLS_CC); + phar_flush(phar_obj->arc.archive, (char *) &zstub, len, 0, &error TSRMLS_CC); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); efree(error); @@ -2190,7 +2097,7 @@ PHP_METHOD(Phar, setStub) "Cannot change stub, unable to read from input stream"); } } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &stub, &stub_len) == SUCCESS) { - phar_flush(phar_obj->arc.archive, stub, stub_len, &error TSRMLS_CC); + 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); @@ -2210,8 +2117,7 @@ PHP_METHOD(Phar, setStub) */ PHP_METHOD(Phar, setDefaultStub) { - char *index = NULL, *webindex = NULL, *error = NULL; - char *stub = "dummy"; + char *index = NULL, *webindex = NULL, *error = NULL, *stub = NULL; int index_len = 0, webindex_len = 0, created_stub = 0; size_t stub_len = 0; PHAR_ARCHIVE_OBJECT(); @@ -2232,6 +2138,7 @@ 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) { @@ -2245,7 +2152,8 @@ PHP_METHOD(Phar, setStub) created_stub = 1; } - phar_flush(phar_obj->arc.archive, stub, stub_len, &error TSRMLS_CC); + phar_flush(phar_obj->arc.archive, stub, stub_len, 1, &error TSRMLS_CC); + if (created_stub) { efree(stub); } @@ -2306,7 +2214,7 @@ PHP_METHOD(Phar, setSignatureAlgorithm) phar_obj->arc.archive->sig_flags = algo; phar_obj->arc.archive->is_modified = 1; - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -2443,7 +2351,7 @@ PHP_METHOD(Phar, compressAllFilesGZ) } phar_obj->arc.archive->is_modified = 1; - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -2482,7 +2390,7 @@ PHP_METHOD(Phar, compressAllFilesBZIP2) } phar_obj->arc.archive->is_modified = 1; - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -2515,7 +2423,7 @@ PHP_METHOD(Phar, uncompressAllFiles) } phar_obj->arc.archive->is_modified = 1; - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -2604,7 +2512,7 @@ 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, &error TSRMLS_CC); + 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); @@ -2721,7 +2629,7 @@ PHP_METHOD(Phar, offsetSet) data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len; } phar_entry_delref(data TSRMLS_CC); - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -2758,7 +2666,7 @@ PHP_METHOD(Phar, offsetUnset) 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, &error TSRMLS_CC); + 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); @@ -2912,7 +2820,7 @@ PHP_METHOD(Phar, setMetadata) MAKE_STD_ZVAL(phar_obj->arc.archive->metadata); ZVAL_ZVAL(phar_obj->arc.archive->metadata, metadata, 1, 0); - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -2936,7 +2844,7 @@ PHP_METHOD(Phar, delMetadata) zval_ptr_dtor(&phar_obj->arc.archive->metadata); phar_obj->arc.archive->metadata = NULL; - phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + 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); @@ -3168,7 +3076,7 @@ PHP_METHOD(PharFileInfo, chmod) BG(CurrentLStatFile) = NULL; BG(CurrentStatFile) = NULL; - phar_flush(entry_obj->ent.entry->phar, 0, 0, &error TSRMLS_CC); + 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); @@ -3235,7 +3143,7 @@ PHP_METHOD(PharFileInfo, setMetadata) MAKE_STD_ZVAL(entry_obj->ent.entry->metadata); ZVAL_ZVAL(entry_obj->ent.entry->metadata, metadata, 1, 0); - phar_flush(entry_obj->ent.entry->phar, 0, 0, &error TSRMLS_CC); + 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); @@ -3262,7 +3170,7 @@ PHP_METHOD(PharFileInfo, delMetadata) zval_ptr_dtor(&entry_obj->ent.entry->metadata); entry_obj->ent.entry->metadata = NULL; - phar_flush(entry_obj->ent.entry->phar, 0, 0, &error TSRMLS_CC); + 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); @@ -3319,7 +3227,7 @@ PHP_METHOD(PharFileInfo, setCompressedGZ) entry_obj->ent.entry->phar->is_modified = 1; entry_obj->ent.entry->is_modified = 1; - phar_flush(entry_obj->ent.entry->phar, 0, 0, &error TSRMLS_CC); + 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); @@ -3375,7 +3283,7 @@ PHP_METHOD(PharFileInfo, setCompressedBZIP2) entry_obj->ent.entry->phar->is_modified = 1; entry_obj->ent.entry->is_modified = 1; - phar_flush(entry_obj->ent.entry->phar, 0, 0, &error TSRMLS_CC); + 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); @@ -3432,7 +3340,7 @@ PHP_METHOD(PharFileInfo, setUncompressed) entry_obj->ent.entry->phar->is_modified = 1; entry_obj->ent.entry->is_modified = 1; - phar_flush(entry_obj->ent.entry->phar, 0, 0, &error TSRMLS_CC); + 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/stream.c b/ext/phar/stream.c index ac6aacef90..deeb968e6e 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -393,7 +393,7 @@ static int phar_stream_flush(php_stream *stream TSRMLS_DC) /* {{{ */ char *error; int ret; if (stream->mode[0] == 'w' || (stream->mode[0] == 'r' && stream->mode[1] == '+')) { - ret = phar_flush(((phar_entry_data *)stream->abstract)->phar, 0, 0, &error TSRMLS_CC); + ret = phar_flush(((phar_entry_data *)stream->abstract)->phar, 0, 0, 0, &error TSRMLS_CC); if (error) { php_stream_wrapper_log_error(stream->wrapper, REPORT_ERRORS TSRMLS_CC, error); efree(error); @@ -803,7 +803,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char } entry->is_modified = 1; entry->filename_len = strlen(entry->filename); - phar_flush(phar, 0, 0, &error TSRMLS_CC); + phar_flush(phar, 0, 0, 0, &error TSRMLS_CC); if (error) { php_url_free(resource_from); php_url_free(resource_to); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 10cd0655d8..52ab15cc3e 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -442,7 +442,7 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC) return ZEND_HASH_APPLY_KEEP; } -int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, char **error TSRMLS_DC) /* {{{ */ +int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defaultstub, char **error TSRMLS_DC) /* {{{ */ { phar_entry_info entry = {0}; static const char newstub[] = "is_temporary_alias && phar->alias_len) { entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1); @@ -485,7 +484,7 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, char **er } /* set stub */ - if (user_stub && len) { + if (user_stub && !defaultstub) { char *pos; if (len < 0) { /* resource passed in */ @@ -543,8 +542,9 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, char **er efree(user_stub); } } else { - /* Either this is a brand new phar (add the stub), or setDefaultStub() is the caller (overwrite the stub) */ + /* Either this is a brand new phar (add the stub), or the default stub is required (overwrite the stub) */ entry.fp = php_stream_fopen_tmpfile(); + if (sizeof(newstub)-1 != php_stream_write(entry.fp, newstub, sizeof(newstub)-1)) { php_stream_close(entry.fp); if (error) { @@ -552,11 +552,12 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, char **er } return EOF; } + entry.uncompressed_filesize = entry.compressed_filesize = sizeof(newstub) - 1; entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1); entry.filename_len = sizeof(".phar/stub.php")-1; - if (!user_stub) { + if (!defaultstub) { if (!zend_hash_exists(&phar->manifest, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { if (SUCCESS != zend_hash_add(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) { php_stream_close(entry.fp); diff --git a/ext/phar/util.c b/ext/phar/util.c index 92227ffe79..50c3371f46 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -72,6 +72,74 @@ int phar_seek_efp(phar_entry_info *entry, off_t offset, int whence, off_t positi return php_stream_seek(fp, temp, SEEK_SET); } +void phar_rename_archive(phar_archive_data *phar, char *ext TSRMLS_DC) { + + char *oldname = NULL, *oldpath = NULL; + char *basename = NULL, *basepath = NULL; + char *newname = NULL, *newpath = NULL; + + if (!ext) { + if (phar->is_zip) { + ext = "phar.zip"; + } else if (phar->is_tar) { + switch (phar->flags) { + case PHAR_FILE_COMPRESSED_GZ: + ext = "phar.tar.gz"; + break; + case PHAR_FILE_COMPRESSED_BZ2: + ext = "phar.tar.bz2"; + break; + default: + ext = "phar.tar"; + } + } else { + switch (phar->flags) { + case PHAR_FILE_COMPRESSED_GZ: + ext = "phar.gz"; + break; + case PHAR_FILE_COMPRESSED_BZ2: + ext = "phar.bz2"; + break; + default: + ext = "phar"; + } + } + } + + if (ext[0] == '.') { + ext++; + } + + oldpath = estrndup(phar->fname, phar->fname_len); + oldname = strrchr(phar->fname, '/'); + oldname++; + + basename = estrndup(oldname, strlen(oldname)); + spprintf(&newname, 0, "%s.%s", strtok(basename, "."), ext); + efree(basename); + + basepath = estrndup(oldpath, strlen(oldpath) - strlen(oldname)); + spprintf(&newpath, 0, "%s%s", basepath, newname); + efree(basepath); + efree(newname); + + if (!phar->is_zip && !phar->is_tar) { + phar->alias = estrndup(newpath, strlen(newpath)); + phar->alias_len = strlen(newpath); + zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), newpath, strlen(newpath), (void*)&phar, sizeof(phar_archive_data*), NULL); + } + + zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), newpath, strlen(newpath), (void*)&phar, sizeof(phar_archive_data*), NULL); + + efree(phar->fname); + + phar->fname = newpath; + phar->fname_len = strlen(newpath); + + unlink(oldpath); + efree(oldpath); +} + /* mount an absolute path or uri to a path internal to the phar archive */ int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len TSRMLS_DC) { diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 7ae5a86261..166fd2ae7c 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -641,7 +641,7 @@ continue_dir: } /* }}} */ -int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, char **error TSRMLS_DC) /* {{{ */ +int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defaultstub, char **error TSRMLS_DC) /* {{{ */ { char *pos; smart_str main_metadata_str = {0}; @@ -691,7 +691,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, char **er } /* set stub */ - if (user_stub && len) { + if (user_stub && !defaultstub) { if (len < 0) { /* resource passed in */ if (!(php_stream_from_zval_no_verify(stubfile, (zval **)user_stub))) { @@ -756,8 +756,9 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, char **er efree(user_stub); } } else { - /* Either this is a brand new phar (add the stub), or setDefaultStub() is the caller (overwrite the stub) */ + /* Either this is a brand new phar (add the stub), or the default stub is required (overwrite the stub) */ entry.fp = php_stream_fopen_tmpfile(); + if (sizeof(newstub)-1 != php_stream_write(entry.fp, newstub, sizeof(newstub)-1)) { php_stream_close(entry.fp); if (error) { @@ -765,11 +766,12 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, char **er } return EOF; } + entry.uncompressed_filesize = entry.compressed_filesize = sizeof(newstub) - 1; entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1); entry.filename_len = sizeof(".phar/stub.php")-1; - if (!user_stub) { + if (!defaultstub) { if (!zend_hash_exists(&phar->manifest, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { if (SUCCESS != zend_hash_add(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) { php_stream_close(entry.fp);