From f4e4ad0cd16d83ae3cb3ac3191432cd67b0b165d Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Mon, 28 Jan 2008 20:18:15 +0000 Subject: [PATCH] fix PharFileInfo->setAlias (was wildly broken) fix directory creation in zip archives update zip tests to use phar to create the zip, and then copy to a new file --- ext/phar/phar_object.c | 16 +++---- ext/phar/tests/zip/033a.phpt | 3 +- ext/phar/tests/zip/delete_in_phar_b.phpt | 3 +- .../tests/zip/open_for_write_existing_b.phpt | 3 +- .../tests/zip/open_for_write_existing_c.phpt | 3 +- .../tests/zip/open_for_write_newfile_b.phpt | 3 +- .../tests/zip/open_for_write_newfile_c.phpt | 3 +- ext/phar/tests/zip/tarmaker.php.inc | 42 +++++++++++-------- ext/phar/util.c | 7 +++- ext/phar/zip.c | 41 +++++++++++++----- 10 files changed, 82 insertions(+), 42 deletions(-) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 5c48ea4869..d8c514e792 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1818,28 +1818,28 @@ PHP_METHOD(Phar, setAlias) if (alias_len == phar_obj->arc.archive->alias_len && memcmp(phar_obj->arc.archive->alias, alias, alias_len) == 0) { RETURN_TRUE; } - if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void**)&fd_ptr)) { + if (alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void**)&fd_ptr)) { spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", alias, (*fd_ptr)->fname); zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); efree(error); RETURN_FALSE; } - if (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), alias, alias_len); + 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); fd = *fd_ptr; - if (alias && alias_len) { - zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&fd, sizeof(phar_archive_data*), NULL); - } } - efree(phar_obj->arc.archive->alias); + if (phar_obj->arc.archive->alias) { + efree(phar_obj->arc.archive->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 = 0; + phar_obj->arc.archive->is_explicit_alias = 1; + phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); diff --git a/ext/phar/tests/zip/033a.phpt b/ext/phar/tests/zip/033a.phpt index 65d67e6f08..71e154f480 100644 --- a/ext/phar/tests/zip/033a.phpt +++ b/ext/phar/tests/zip/033a.phpt @@ -3,7 +3,7 @@ Phar::chmod zip-based --SKIPIF-- --INI-- -phar.readonly=1 +phar.readonly=0 phar.require_hash=0 --FILE-- addFile('a.php', '') $a->addFile('.phar/alias.txt', 'hio'); $a->mkDir('test'); $a->close(); +ini_set('phar.readonly', 1); try { $a = new Phar($fname); diff --git a/ext/phar/tests/zip/delete_in_phar_b.phpt b/ext/phar/tests/zip/delete_in_phar_b.phpt index 0a7336fee9..cb01890444 100644 --- a/ext/phar/tests/zip/delete_in_phar_b.phpt +++ b/ext/phar/tests/zip/delete_in_phar_b.phpt @@ -3,7 +3,7 @@ Phar: delete a file within a zip-based .phar --SKIPIF-- --INI-- -phar.readonly=1 +phar.readonly=0 phar.require_hash=0 --FILE-- addFile('b.php', ''); $a->addFile('b/c.php', ''); $a->addFile('.phar/stub.php', ''); $a->close(); +ini_set('phar.readonly', 1); include $pname . '/a.php'; include $pname . '/b.php'; diff --git a/ext/phar/tests/zip/open_for_write_existing_b.phpt b/ext/phar/tests/zip/open_for_write_existing_b.phpt index ef0eedb334..7468ef330d 100755 --- a/ext/phar/tests/zip/open_for_write_existing_b.phpt +++ b/ext/phar/tests/zip/open_for_write_existing_b.phpt @@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (existing file) zip-based --SKIPIF-- --INI-- -phar.readonly=1 +phar.readonly=0 phar.require_hash=0 --FILE-- $file) { $a->addFile($n, $file); } $a->close(); +ini_set('phar.readonly', 1); function err_handler($errno, $errstr, $errfile, $errline) { echo "Catchable fatal error: $errstr in $errfile on line $errline\n"; diff --git a/ext/phar/tests/zip/open_for_write_existing_c.phpt b/ext/phar/tests/zip/open_for_write_existing_c.phpt index a859aada7d..8586b8694f 100755 --- a/ext/phar/tests/zip/open_for_write_existing_c.phpt +++ b/ext/phar/tests/zip/open_for_write_existing_c.phpt @@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (existing file) tar-based --SKIPIF-- --INI-- -phar.readonly=1 +phar.readonly=0 phar.require_hash=0 --FILE-- $file) { $a->addFile($n, $file); } $a->close(); +ini_set('phar.readonly', 1); $fp = fopen($pname . '/b/c.php', 'wb'); fwrite($fp, 'extra'); diff --git a/ext/phar/tests/zip/open_for_write_newfile_b.phpt b/ext/phar/tests/zip/open_for_write_newfile_b.phpt index 247706dd7e..05ea2d6bfb 100755 --- a/ext/phar/tests/zip/open_for_write_newfile_b.phpt +++ b/ext/phar/tests/zip/open_for_write_newfile_b.phpt @@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (new file) zip-based --SKIPIF-- --INI-- -phar.readonly=1 +phar.readonly=0 phar.require_hash=0 --FILE-- $file) { $a->addFile($n, $file); } $a->close(); +ini_set('phar.readonly', 1); function err_handler($errno, $errstr, $errfile, $errline) { echo "Catchable fatal error: $errstr in $errfile on line $errline\n"; diff --git a/ext/phar/tests/zip/open_for_write_newfile_c.phpt b/ext/phar/tests/zip/open_for_write_newfile_c.phpt index 8833f9f009..499dfc5774 100755 --- a/ext/phar/tests/zip/open_for_write_newfile_c.phpt +++ b/ext/phar/tests/zip/open_for_write_newfile_c.phpt @@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (new file) zip-based --SKIPIF-- --INI-- -phar.readonly=1 +phar.readonly=0 phar.require_hash=0 --FILE-- $file) { $a->addFile($n, $file); } $a->close(); +ini_set('phar.readonly', 1); $fp = fopen($pname . '/b/new.php', 'wb'); fwrite($fp, 'extra'); diff --git a/ext/phar/tests/zip/tarmaker.php.inc b/ext/phar/tests/zip/tarmaker.php.inc index ad05ae64c3..da2add772b 100644 --- a/ext/phar/tests/zip/tarmaker.php.inc +++ b/ext/phar/tests/zip/tarmaker.php.inc @@ -9,17 +9,19 @@ class tarmaker */ protected $archive; /** - * @var ZIPArchive + * @var Phar */ protected $zip; protected $path; + /** + * this is the location we'll create the phar, then we'll copy() it to $path + * @var string + */ + protected $tmppath; function __construct($path) { - if (!class_exists('ZIPArchive')) { - throw new Exception( - 'Zip extension is not available'); - } $this->path = $path; + $this->tmppath = dirname($path) . "/.tmp.thingy.phar"; } /** @@ -29,11 +31,12 @@ class tarmaker */ function addFile($path, $fileOrStream) { - if (is_resource($fileOrStream)) { - $this->zip->addFromString($path, stream_get_contents($fileOrStream)); - } else { - $this->zip->addFromString($path, $fileOrStream); + if ($path == '.phar/stub.php') { + $this->zip->setStub($fileOrStream); + } elseif ($path == '.phar/alias.txt') { + $this->zip->setAlias($fileOrStream); } + $this->zip[$path] = $fileOrStream; } /** @@ -41,12 +44,8 @@ class tarmaker */ function init() { - $this->zip = new ZipArchive; - if (true !== $this->zip->open($this->path, ZIPARCHIVE::CREATE)) { - throw new Exception( - 'Cannot open ZIP archive ' . $this->path - ); - } + $this->zip = new Phar($this->tmppath); + $this->zip->convertToZip(); } /** @@ -57,7 +56,8 @@ class tarmaker */ function mkdir($dir) { - $this->zip->addEmptyDir($dir); + if ($dir[strlen($dir)-1] != '/') $dir .= '/'; + $this->zip[$dir] = ''; } /** @@ -65,6 +65,14 @@ class tarmaker */ function close() { - $this->zip->close(); + $this->zip->stopBuffering(); + copy($this->tmppath, $this->path); + $this->zip->setAlias('not.to.be.used'); // for preventing alias conflict + $this->zip->stopBuffering(); + } + + function __destruct() + { + unlink($this->tmppath); } } \ No newline at end of file diff --git a/ext/phar/util.c b/ext/phar/util.c index 4205ae23ab..41ad528109 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -245,7 +245,12 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char etemp.is_tar = phar->is_tar; etemp.tar_type = TAR_FILE; } - zend_hash_add(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info), (void **) &entry); + if (FAILURE == zend_hash_add(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info), (void **) &entry)) { + if (error) { + spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", etemp.filename, phar->fname); + } + return NULL; + } if (!entry) { php_stream_close(etemp.fp); diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 367702f9e0..dc70aa1ee4 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -448,7 +448,7 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */ phar_zip_u2d_time(entry->timestamp, &local.timestamp, &local.datestamp); central.timestamp = local.timestamp; central.datestamp = local.datestamp; - central.filename_len = local.filename_len = entry->filename_len; + central.filename_len = local.filename_len = entry->filename_len + (entry->is_dir ? 1 : 0); central.offset = php_stream_tell(p->filefp); /* do extra field for perms later */ if (entry->is_modified) { @@ -549,7 +549,7 @@ continue_dir: central.comment_len = entry->metadata_str.len; } entry->header_offset = php_stream_tell(p->filefp); - offset = entry->header_offset + sizeof(local) + entry->filename_len + sizeof(perms); + offset = entry->header_offset + sizeof(local) + entry->filename_len + (entry->is_dir ? 1 : 0) + sizeof(perms); if (sizeof(local) != php_stream_write(p->filefp, (char *)&local, sizeof(local))) { spprintf(p->error, 0, "unable to write local file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); return ZEND_HASH_APPLY_STOP; @@ -558,13 +558,32 @@ continue_dir: spprintf(p->error, 0, "unable to write central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); return ZEND_HASH_APPLY_STOP; } - if (entry->filename_len != php_stream_write(p->filefp, entry->filename, entry->filename_len)) { - spprintf(p->error, 0, "unable to write filename to local directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); - return ZEND_HASH_APPLY_STOP; - } - if (entry->filename_len != php_stream_write(p->centralfp, entry->filename, entry->filename_len)) { - spprintf(p->error, 0, "unable to write filename to central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); - return ZEND_HASH_APPLY_STOP; + if (entry->is_dir) { + if (entry->filename_len != php_stream_write(p->filefp, entry->filename, entry->filename_len)) { + spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + return ZEND_HASH_APPLY_STOP; + } + if (1 != php_stream_write(p->filefp, "/", 1)) { + spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + return ZEND_HASH_APPLY_STOP; + } + if (entry->filename_len != php_stream_write(p->centralfp, entry->filename, entry->filename_len)) { + spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + return ZEND_HASH_APPLY_STOP; + } + if (1 != php_stream_write(p->centralfp, "/", 1)) { + spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + return ZEND_HASH_APPLY_STOP; + } + } else { + if (entry->filename_len != php_stream_write(p->filefp, entry->filename, entry->filename_len)) { + spprintf(p->error, 0, "unable to write filename to local directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + return ZEND_HASH_APPLY_STOP; + } + if (entry->filename_len != php_stream_write(p->centralfp, entry->filename, entry->filename_len)) { + spprintf(p->error, 0, "unable to write filename to central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + return ZEND_HASH_APPLY_STOP; + } } if (sizeof(perms) != php_stream_write(p->filefp, (char *)&perms, sizeof(perms))) { spprintf(p->error, 0, "unable to write local extra permissions file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); @@ -660,7 +679,9 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, char **er } /* register alias */ if (phar->alias_len) { - phar_get_archive(&phar, phar->fname, phar->fname_len, phar->alias, phar->alias_len, NULL TSRMLS_CC); + if (FAILURE == phar_get_archive(&phar, phar->fname, phar->fname_len, phar->alias, phar->alias_len, error TSRMLS_CC)) { + return EOF; + } } /* set stub */ -- 2.40.0