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
This commit is contained in:
Greg Beaver 2008-01-28 20:18:15 +00:00
parent 18c8e6501b
commit f4e4ad0cd1
10 changed files with 82 additions and 42 deletions

View File

@ -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);

View File

@ -3,7 +3,7 @@ Phar::chmod zip-based
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=1
phar.readonly=0
phar.require_hash=0
--FILE--
<?php
@ -17,6 +17,7 @@ $a->addFile('a.php', '<?php echo "This is a\n"; include "'.$pname.'/b.php"; ?>')
$a->addFile('.phar/alias.txt', 'hio');
$a->mkDir('test');
$a->close();
ini_set('phar.readonly', 1);
try {
$a = new Phar($fname);

View File

@ -3,7 +3,7 @@ Phar: delete a file within a zip-based .phar
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=1
phar.readonly=0
phar.require_hash=0
--FILE--
<?php
@ -18,6 +18,7 @@ $a->addFile('b.php', '<?php echo "This is b\n"; ?>');
$a->addFile('b/c.php', '<?php echo "This is b/c\n"; ?>');
$a->addFile('.phar/stub.php', '<?php __HALT_COMPILER(); ?>');
$a->close();
ini_set('phar.readonly', 1);
include $pname . '/a.php';
include $pname . '/b.php';

View File

@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (existing file) zip-based
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=1
phar.readonly=0
phar.require_hash=0
--FILE--
<?php
@ -22,6 +22,7 @@ foreach ($files as $n => $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";

View File

@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (existing file) tar-based
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=1
phar.readonly=0
phar.require_hash=0
--FILE--
<?php
@ -22,6 +22,7 @@ foreach ($files as $n => $file) {
$a->addFile($n, $file);
}
$a->close();
ini_set('phar.readonly', 1);
$fp = fopen($pname . '/b/c.php', 'wb');
fwrite($fp, 'extra');

View File

@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (new file) zip-based
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=1
phar.readonly=0
phar.require_hash=0
--FILE--
<?php
@ -22,6 +22,7 @@ foreach ($files as $n => $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";

View File

@ -3,7 +3,7 @@ Phar: fopen a .phar for writing (new file) zip-based
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=1
phar.readonly=0
phar.require_hash=0
--FILE--
<?php
@ -22,6 +22,7 @@ foreach ($files as $n => $file) {
$a->addFile($n, $file);
}
$a->close();
ini_set('phar.readonly', 1);
$fp = fopen($pname . '/b/new.php', 'wb');
fwrite($fp, 'extra');

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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 */