]> granicus.if.org Git - php/commitdiff
fix PharFileInfo->setAlias (was wildly broken)
authorGreg Beaver <cellog@php.net>
Mon, 28 Jan 2008 20:18:15 +0000 (20:18 +0000)
committerGreg Beaver <cellog@php.net>
Mon, 28 Jan 2008 20:18:15 +0000 (20:18 +0000)
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
ext/phar/tests/zip/033a.phpt
ext/phar/tests/zip/delete_in_phar_b.phpt
ext/phar/tests/zip/open_for_write_existing_b.phpt
ext/phar/tests/zip/open_for_write_existing_c.phpt
ext/phar/tests/zip/open_for_write_newfile_b.phpt
ext/phar/tests/zip/open_for_write_newfile_c.phpt
ext/phar/tests/zip/tarmaker.php.inc
ext/phar/util.c
ext/phar/zip.c

index 5c48ea4869cb8b6f15ef4f99af2cb6fdf8e21203..d8c514e79246d554fedf2af879455a9f180bc2df 100755 (executable)
@@ -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);
index 65d67e6f082be59e6fb7b8428916886e47015a25..71e154f480fe85cee5f9c1b934b37d9a1c8d6c42 100644 (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);
index 0a7336fee9e66411ed7f5aa753e6f026d3e4d50e..cb01890444bba7111efee3bc6905321075b89fc2 100644 (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';
index ef0eedb33487aa0b6874f4855a8b579f5994568b..7468ef330d7ea5b24e2f2c5aef95d70fe1a24b72 100755 (executable)
@@ -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";
index a859aada7d620ff104d4900d2e3d854d2b1598e4..8586b8694f70dbcca74173680e1c6e0956d526c3 100755 (executable)
@@ -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');
index 247706dd7eb8e6549ecf20074ee8cf51caeb55fe..05ea2d6bfbd4a065b064e3a60c3964bb8ddab054 100755 (executable)
@@ -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";
index 8833f9f009260a3948aa01cdd8c270358bc22c7d..499dfc57749ef1c61b9ef900a80d1f871eff8741 100755 (executable)
@@ -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');
index ad05ae64c39584c1580c92795b534e62c81a73cb..da2add772b1f2a6edd6c09759997ec2dc5fcc18a 100644 (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);
     }
 }
\ No newline at end of file
index 4205ae23ab66e9bf6949036b7e7cdf990b6ac779..41ad5281097598a6c0e21df952366f5dda5a0e8b 100644 (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);
index 367702f9e0c638cfd66c949261688dfb8fd1db9e..dc70aa1ee428959356fc51052ddbcb35c462b474 100644 (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 */