]> granicus.if.org Git - php/commitdiff
implement reading meta-data from phars. writing is not yet supported
authorGreg Beaver <cellog@php.net>
Sun, 21 Jan 2007 06:30:55 +0000 (06:30 +0000)
committerGreg Beaver <cellog@php.net>
Sun, 21 Jan 2007 06:30:55 +0000 (06:30 +0000)
12 files changed:
ext/phar/TODO
ext/phar/phar.c
ext/phar/tests/010.phpt
ext/phar/tests/011.phpt
ext/phar/tests/013.phpt
ext/phar/tests/014.phpt
ext/phar/tests/015.phpt
ext/phar/tests/015b.phpt
ext/phar/tests/016.phpt
ext/phar/tests/016b.phpt
ext/phar/tests/017.phpt
ext/phar/tests/phar_test.inc

index e1e7f6bb6cc511f4cf30ca489de9ae9ca3e9ab4a..517fee55dd9bdcfa417c687be05869689c392bb2 100644 (file)
@@ -4,8 +4,9 @@ Version 1.0.0
  X implement ini handler for phar.readonly and phar.require_hash that allows enabling it on
    PHP_INI_ALL if it is disabled in the system, but does not allow disabling it
    if it is enabled in the system [Greg]
- * implement metadata in manifest as [type32][len16][metadata...] where 0 type is
-   used to finish metadata for this file
+ X implement reading in metadata in manifest as [type32][len16][metadata...] where 0 type is
+   used to finish metadata for this file [Greg]
+ * implement writing out of metadata to new manifest
  * if SPL is disabled, disable the Phar class
  * implement in-phar locking, so that a file that is opened for reading can't have
    a handle opened for writing
index 6d8eabc2463a18af4738ad224e3760b07318ab42..9c991b312e0240c7abc866905bf8a00f4ac43606 100644 (file)
 
 #define PHAR_METADATA_FINISHED 0x00000000
 
-/* #define PHAR_METADATA_WHATEVER 0x000000001
-   We don't need anything yet, so put this here
-   in order to remember how it works */
+/* basic meta-data types */
+#define PHAR_METADATA_STRING   0x00000001
+#define PHAR_METADATA_INT      0x00000002
+#define PHAR_METADATA_BOOL     0x00000003
 
 /* flags byte for each file adheres to these bitmasks.
    All unused values are reserved */
@@ -191,6 +192,7 @@ typedef struct _phar_entry_info {
        php_uint32               crc32;
        php_uint32               flags;
        /* remainder */
+       zval                     *metadata;
        php_uint32               filename_len;
        char                     *filename;
        long                     offset_within_phar;
@@ -391,6 +393,10 @@ static void destroy_phar_manifest(void *pDest) /* {{{ */
        if (entry->temp_file) {
                php_stream_close(entry->temp_file);
        }
+       if (entry->metadata) {
+               zval_dtor(entry->metadata);
+               entry->metadata = 0;
+       }
        efree(entry->filename);
 }
 /* }}} */
@@ -591,15 +597,22 @@ PHP_METHOD(Phar, canWrite)
 
 #ifdef WORDS_BIGENDIAN
 # define PHAR_GET_32(buffer, var) \
-       var = ((unsigned char)buffer[3]) << 24 \
-               + ((unsigned char)buffer[2]) << 16 \
-               + ((unsigned char)buffer[1]) <<  8 \
-               + ((unsigned char)buffer[0]); \
-       buffer += 4
+       var = ((unsigned char)(buffer)[3]) << 24 \
+               + ((unsigned char)(buffer)[2]) << 16 \
+               + ((unsigned char)(buffer)[1]) <<  8 \
+               + ((unsigned char)(buffer)[0]); \
+       (buffer) += 4
+# define PHAR_GET_16(buffer, var) \
+       var = ((unsigned char)(buffer)[1]) <<  8 \
+               + ((unsigned char)(buffer)[0]); \
+       (buffer) += 2
 #else
 # define PHAR_GET_32(buffer, var) \
        var = *(php_uint32*)(buffer); \
        buffer += 4
+# define PHAR_GET_16(buffer, var) \
+       var = *(php_uint16*)(buffer); \
+       buffer += 2
 #endif
 
 /**
@@ -628,6 +641,50 @@ static int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_l
 }
 /* }}}*/
 
+/**
+ * Parse out metadata from the manifest for a single file
+ *
+ * Meta-data is in this format:
+ * [type32][len16][data...]
+ * 
+ * where type32 is a 32-bit type indicator, len16 is a 16-bit length indicator,
+ * and data is the actual meta-data.
+ */
+static int phar_parse_metadata(php_stream *fp, char **buffer, char *endbuffer, zval *metadata TSRMLS_DC) /* {{{ */
+{
+       zval *dataarray, *found;
+       php_uint32 datatype;
+       php_uint16 len;
+       char *data;
+       do {
+               /* for each meta-data, add an array index to the metadata array
+                  if the index already exists, convert to a sub-array */
+               PHAR_GET_32(*buffer, datatype);
+               PHAR_GET_16(*buffer, len);
+               data = (char *) emalloc(len);
+               if (len != php_stream_read(fp, data, (size_t) len) TSRMLS_CC) {
+                       return FAILURE;
+               }
+               if (SUCCESS == zend_hash_index_find(metadata->value.ht, datatype, (void**)&found)) {
+                       if (Z_TYPE_P(found) == IS_ARRAY) {
+                               add_next_index_stringl(dataarray, data, len, 0);
+                       } else {
+                               MAKE_STD_ZVAL(dataarray);
+                               array_init(dataarray);
+                               add_next_index_zval(dataarray, found);
+                               add_next_index_stringl(dataarray, data, len, 0); 
+                       }
+               } else {
+                       MAKE_STD_ZVAL(dataarray);
+                       add_index_stringl(metadata, datatype, data, len, 0);
+               }
+               
+       } while (*(php_uint32 *) *buffer && *buffer < endbuffer);
+       *buffer += 4;
+       return SUCCESS;
+}
+/* }}}*/
+
 /**
  * Does not check for a previously opened phar in the cache.
  *
@@ -912,6 +969,13 @@ static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alia
                PHAR_GET_32(buffer, entry.compressed_filesize);
                PHAR_GET_32(buffer, entry.crc32);
                PHAR_GET_32(buffer, entry.flags);
+               if (*(php_uint32 *) buffer) {
+                       MAKE_STD_ZVAL(entry.metadata);
+                       array_init(entry.metadata);
+                       phar_parse_metadata(fp, &buffer, endbuffer, entry.metadata TSRMLS_CC);
+               } else {
+                       buffer += 4;
+               }
                entry.offset_within_phar = offset;
                offset += entry.compressed_filesize;
                switch (entry.flags & PHAR_ENT_COMPRESSION_MASK) {
@@ -1518,7 +1582,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
                /* Unfortunately we cannot check the read position of fp after getting */
                /* uncompressed data because the new stream posiition is being changed */
                /* by the number of bytes read throughthe filter not by the raw number */
-               /* bytes being consumed on the stream. Therefor use a consumed filter. */ 
+               /* bytes being consumed on the stream. Therefore use a consumed filter. */ 
                consumed = php_stream_filter_create("consumed", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
                php_stream_filter_append(&fp->readfilters, consumed);
                php_stream_filter_append(&fp->readfilters, filter);
@@ -1781,7 +1845,7 @@ static int phar_flush(phar_entry_data *data TSRMLS_DC) /* {{{ */
        phar_entry_info *entry;
        int alias_len, fname_len, halt_offset, restore_alias_len, global_flags = 0;
        char *fname, *alias;
-       char manifest[18], entry_buffer[20];
+       char manifest[18], entry_buffer[24];
        off_t manifest_ftell;
        long offset;
        php_uint32 copy, loc, new_manifest_count;
@@ -1971,6 +2035,7 @@ static int phar_flush(phar_entry_data *data TSRMLS_DC) /* {{{ */
                        4: compressed filesize
                        4: crc32
                        4: flags
+                       4+: metadata TODO: copy the actual metadata, 0 for now
                */
                copy = time(NULL);
                phar_set_32(entry_buffer, entry->uncompressed_filesize);
@@ -1978,6 +2043,8 @@ static int phar_flush(phar_entry_data *data TSRMLS_DC) /* {{{ */
                phar_set_32(entry_buffer+8, entry->compressed_filesize);
                phar_set_32(entry_buffer+12, entry->crc32);
                phar_set_32(entry_buffer+16, entry->flags);
+               copy = 0;
+               phar_set_32(entry_buffer+20, 0);
                if (sizeof(entry_buffer) != php_stream_write(newfile, entry_buffer, sizeof(entry_buffer))) {
                        if (oldfile) {
                                php_stream_close(oldfile);
index 008bdc8feee4fd51231b4a8d2605c1214c6ae5ea..dd905edada9a13734b8c744a8c24e822bdc84818 100644 (file)
@@ -12,7 +12,7 @@ __HALT_COMPILER(); ?>";
 
 // this fails because the manifest length does not include the other 10 byte manifest data
 
-$manifest = pack('V', 1) . 'a' . pack('VVVVV', 0, time(), 0, crc32(''), 0x00000000);
+$manifest = pack('V', 1) . 'a' . pack('VVVVVV', 0, time(), 0, crc32(''), 0x00000000, 0);
 $file .= pack('VVnVV', strlen($manifest), 1, 0x0900, 0x00000000, 3) . 'hio' . $manifest;
 
 file_put_contents(dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php', $file);
index 1ff2a32f97b6171c851ec273d0d19acbf23f0930..009d51d4e7388b51aa887a3eb428c5b030b69212 100644 (file)
@@ -17,7 +17,7 @@ $files['a'] = 'a';
 $manifest = '';
 foreach($files as $name => $cont) {
        $len = strlen($cont);
-       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVV', $len, time(), $len+1, crc32($cont), 0x00000000);
+       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVVV', $len, time(), $len+1, crc32($cont), 0x00000000, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00000000, strlen($alias)) . $alias . $manifest;
index 3327e53db9a0d296fde2fe75ebee82088607720b..808d37462ae79d2fa2a3b59dff496b188104407f 100644 (file)
@@ -18,7 +18,7 @@ $files['a'] = 'a';
 $manifest = '';
 foreach($files as $name => $cont) {
        $len = strlen($cont)+1;
-       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVV', $len, time(), $len, crc32($cont), 0x00000000);
+       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVVV', $len, time(), $len, crc32($cont), 0x00000000, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00000000, strlen($alias)) . $alias . $manifest;
index ea27faaf7e1d657b96916d3ebcbe3c7261646180..2117eaaff9a94a0e7ab5e8559255412ec2bd56a1 100644 (file)
@@ -16,7 +16,7 @@ $files['a'] = 'a';
 $manifest = '';
 foreach($files as $name => $cont) {
        $len = strlen($cont);
-       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVV', $len, time(), $len, crc32($cont.'X'), 0x00000000);
+       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVVV', $len, time(), $len, crc32($cont.'X'), 0x00000000, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00000000, strlen($alias)) . $alias . $manifest;
index 240537bcf8ed8516d3a89589dfdac7f114ca5816..4d5477c557f57ae978223f6a4ccb7523921f2d1c 100644 (file)
@@ -16,7 +16,7 @@ $files['a'] = 'a';
 $manifest = '';
 foreach($files as $name => $cont) {
        $len = strlen($cont);
-       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVV', $len, time(), 3, crc32($cont), 0x00001000);
+       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVVV', $len, time(), 3, crc32($cont), 0x00001000, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00001000, strlen($alias)) . $alias . $manifest;
index 1cccdd613c70388739c260efe8f5e03d5e601c6f..1909da6a825aa9f9ece7438b64b690dd9d397785 100755 (executable)
@@ -15,7 +15,7 @@ $files = array();
 $files['a'] = array('Hello World', pack('H*', '425a6839314159265359d872012f00000157800010400000400080060490002000220686d420c988c769e8281f8bb9229c28486c39009780'));
 $manifest = '';
 foreach($files as $name => $cont) {
-       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVV', strlen($cont[0]), time(), strlen($cont[1]), crc32($cont[0]), 0x00002000);
+       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVVV', strlen($cont[0]), time(), strlen($cont[1]), crc32($cont[0]), 0x00002000, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00002000, strlen($alias)) . $alias . $manifest;
index e4d944104d4d9efba632a51ac74fec861bd0ba2b..929e21a1f31fa17569f4651a16b4a056e68e805e 100644 (file)
@@ -22,7 +22,7 @@ foreach($files as $name => $cont) {
        $ulen = strlen($cont[0]);
        $clen = strlen($cont[1]);
        $manifest .= pack('V', strlen($name)) . $name 
-                 . pack('VVVVV', $ulen, time(), $clen, crc32($cont[0]), $cont[2]);
+                 . pack('VVVVVV', $ulen, time(), $clen, crc32($cont[0]), $cont[2], 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00001000, strlen($alias)) . $alias . $manifest;
index a58c8bbfd6ad75bbb1f3b2101898ee1ef8b8bca9..ae5ec5fded0d282e5cbe83d0ef6a7de3516e8cac 100755 (executable)
@@ -17,7 +17,7 @@ $files['a'] = 'a';
 $manifest = '';
 foreach($files as $name => $cont) {
        $len = strlen($cont);
-       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVV', $len, time(), 1, crc32($cont), 0x00001000);
+       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVVV', $len, time(), 1, crc32($cont), 0x00001000, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00001000, strlen($alias)) . $alias . $manifest;
index 197649d451bbc53227ebf378c0cda45c15c68fb0..b3332bb6dc8e34062b01791a026a67c5b97b3e3b 100644 (file)
@@ -16,7 +16,7 @@ $files['a'] = 'abc';
 $manifest = '';
 foreach($files as $name => $cont) {
        $len = strlen($cont);
-       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVV', $len, time(), $len, crc32($cont), 0x00000001);
+       $manifest .= pack('V', strlen($name)) . $name . pack('VVVVVV', $len, time(), $len, crc32($cont), 0x00000001, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00000001, strlen($alias)) . $alias . $manifest;
index 6f85bfd418a88aa295c60896a26eb39bb6e5c1f7..9f887dceb52440376023c4363336171f3ff1730e 100755 (executable)
@@ -8,7 +8,7 @@ foreach($files as $name => $cont)
        $clen = $ulen;
        $time = isset($ftime) ? $ftime : @mktime(12, 0, 0, 3, 1, 2006);
        $manifest .= pack('V', strlen($name)) . $name;
-       $manifest .= pack('VVVVV', $ulen, $time, $clen, crc32($cont), 0x000001B6);
+       $manifest .= pack('VVVVVV', $ulen, $time, $clen, crc32($cont), 0x000001B6, 0);
 }
 $alias = 'hio';
 $manifest = pack('VnVV', count($files), 0x0900, 0x00000000, strlen($alias)) . $alias . $manifest;