]> granicus.if.org Git - php/commitdiff
- Disable most of class Phar and all of class PharFileInfo if SPL is not present
authorMarcus Boerger <helly@php.net>
Sun, 21 Jan 2007 15:25:50 +0000 (15:25 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 21 Jan 2007 15:25:50 +0000 (15:25 +0000)
23 files changed:
ext/phar/TODO
ext/phar/config.m4
ext/phar/config.w32
ext/phar/phar.c
ext/phar/phar_internal.h [new file with mode: 0755]
ext/phar/phar_object.c [new file with mode: 0755]
ext/phar/tests/create_new_and_modify.phpt
ext/phar/tests/create_new_phar_c.phpt
ext/phar/tests/phar_oo_001.phpt
ext/phar/tests/phar_oo_002.phpt
ext/phar/tests/phar_oo_003.phpt
ext/phar/tests/phar_oo_004.phpt
ext/phar/tests/phar_oo_005.phpt
ext/phar/tests/phar_oo_006.phpt
ext/phar/tests/phar_oo_007.phpt
ext/phar/tests/phar_oo_008.phpt
ext/phar/tests/phar_oo_010.phpt
ext/phar/tests/phar_oo_011.phpt
ext/phar/tests/phar_oo_011b.phpt
ext/phar/tests/phar_oo_012.phpt
ext/phar/tests/phar_oo_012_confirm.phpt
ext/phar/tests/phar_oo_012b.phpt
ext/phar/tests/refcount1.phpt

index 517fee55dd9bdcfa417c687be05869689c392bb2..d739111d50fc9b15c061b6875f95dbda7f7f6438 100644 (file)
@@ -1,24 +1,29 @@
 Version 1.0.0
 
  X make permissions in the lowest bits of flags to simplify using them [Greg]
- 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]
- X implement reading in metadata in manifest as [type32][len16][metadata...] where 0 type is
+ 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]
+ 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
+ X if SPL is disabled, enable only static methods of class Phar and disable 
+   class PharFileInfo completley [Marcus]
+ * implement in-phar locking, so that a file that is opened for reading can't 
+   have a handle opened for writing
  * docs on file format/manifest description
  * docs on uses
- * support stream context for specifying compression of a file, as well as meta-data, and
-   copying of new prologue to the phar
- * add setUncompressed(), setCompressedGZ() and setCompressedBZ2() to PharFileInfo class
- * add uncompressAllFiles(), compressAllFilesGZ() and compressAllFilesBZ2() to Phar class
+ * support stream context for specifying compression of a file, as well as 
+   meta-data, and copying of new prologue to the phar
+ * add setUncompressed(), setCompressedGZ() and setCompressedBZ2() to 
+   PharFileInfo class
+ * add uncompressAllFiles(), compressAllFilesGZ() and compressAllFilesBZ2() 
+   to Phar class
  * add setMetaData($key, $contents) to PharFileInfo
  * add getMetaData($key = null) to PharFileInfo
- * always throw exceptions from the Phar object, and E_RECOVERABLE_ERROR from streams interface
+ * always throw exceptions from the Phar object, and E_RECOVERABLE_ERROR from 
+   streams interface
  
 Version 1.1.0
 
index b1c9985c2e03b6b8f68427d68879aa848ae981ef..8a35fa779ddd1d9d34d20dbfffa89bd5078c3ed9 100644 (file)
@@ -5,7 +5,7 @@ PHP_ARG_ENABLE(phar, for phar support/phar zlib support,
 [  --enable-phar           Enable phar support, use --with-zlib-dir if zlib detection fails])
 
 if test "$PHP_PHAR" != "no"; then
-  PHP_NEW_EXTENSION(phar, phar.c, $ext_shared)
+  PHP_NEW_EXTENSION(phar, phar.c phar_object.c, $ext_shared)
   PHP_ADD_EXTENSION_DEP(phar, zlib, true)
   PHP_ADD_EXTENSION_DEP(phar, bz2, true)
   PHP_ADD_EXTENSION_DEP(phar, spl, false)
index 694de2e7f4d5f4ec6d18be7200eb35721a1b33ea..3ad36b4d897e211aefecb68c8821621fdd683a2c 100644 (file)
@@ -4,7 +4,7 @@
 ARG_ENABLE("phar", "enable phar support", "no");
 
 if (PHP_PHAR != "no") {
-       EXTENSION("phar", "phar.c");
+       EXTENSION("phar", "phar.c phar_object.c");
        ADD_EXTENSION_DEP('phar', 'zlib', true);
        ADD_EXTENSION_DEP('phar', 'bz2', true);
        ADD_EXTENSION_DEP('phar', 'spl', false);
index 7722e39e7f1f9afd9c3c1b57e8f465b307b84625..87844ddcc82a662fa9d83060b0b2911fc16b0dcb 100644 (file)
 
 /* $Id$ */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <time.h>
-#include "php.h"
-#include "php_ini.h"
-#include "zend_constants.h"
-#include "zend_execute.h"
-#include "zend_exceptions.h"
-#include "zend_hash.h"
-#include "zend_interfaces.h"
-#include "zend_operators.h"
-#include "zend_qsort.h"
-#include "main/php_streams.h"
-#include "ext/standard/info.h"
-#include "ext/standard/url.h"
-#include "ext/standard/crc32.h"
-#include "ext/standard/md5.h"
-#include "ext/standard/sha1.h"
-#include "ext/spl/spl_array.h"
-#include "ext/spl/spl_directory.h"
-#include "ext/spl/spl_engine.h"
-#include "ext/spl/spl_exceptions.h"
-#include "php_phar.h"
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-#ifndef E_RECOVERABLE_ERROR
-#define E_RECOVERABLE_ERROR E_ERROR
-#endif
-
-#define PHAR_VERSION_STR          "0.9.0"
-/* x.y.z maps to 0xyz0 */
-#define PHAR_API_VERSION          0x0900
-#define PHAR_API_MIN_READ         0x0900
-#define PHAR_API_MAJORVERSION     0x0000
-#define PHAR_API_MAJORVER_MASK    0xF000
-#define PHAR_API_VER_MASK         0xFFF0
-
-#define PHAR_HDR_COMPRESSION_MASK 0x0000F000
-#define PHAR_HDR_COMPRESSED_NONE  0x00000000
-#define PHAR_HDR_COMPRESSED_GZ    0x00001000
-#define PHAR_HDR_COMPRESSED_BZ2   0x00002000
-#define PHAR_HDR_SIGNATURE        0x00010000
-
-#define PHAR_SIG_MD5              0x0001
-#define PHAR_SIG_SHA1             0x0002
-#define PHAR_SIG_PGP              0x0010
-
-#define PHAR_SIG_USE  PHAR_SIG_SHA1
-
-/* metadata type constants */
-
-#define PHAR_METADATA_FINISHED 0x00000000
-
-/* 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 */
-#define PHAR_ENT_COMPRESSION_MASK 0x0000F000
-#define PHAR_ENT_COMPRESSED_NONE  0x00000000
-#define PHAR_ENT_COMPRESSED_GZ    0x00001000
-#define PHAR_ENT_COMPRESSED_BZ2   0x00002000
-
-#define PHAR_ENT_PERM_MASK        0x000001FF
-#define PHAR_ENT_PERM_MASK_USR    0x000001C0
-#define PHAR_ENT_PERM_SHIFT_USR   6
-#define PHAR_ENT_PERM_MASK_GRP    0x00000038
-#define PHAR_ENT_PERM_SHIFT_GRP   3
-#define PHAR_ENT_PERM_MASK_OTH    0x00000007
-#define PHAR_ENT_PERM_DEF_FILE    0x000001B6
-#define PHAR_ENT_PERM_DEF_DIR     0x000001FF
-
-#ifdef ZTS
-#      include "TSRM.h"
-#      define PHAR_G(v) TSRMG(phar_globals_id, zend_phar_globals *, v)
-#      define PHAR_GLOBALS ((zend_phar_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(phar_globals_id)])
-#else
-#      define PHAR_G(v) (phar_globals.v)
-#      define PHAR_GLOBALS (&phar_globals)
-#endif
-
-ZEND_BEGIN_MODULE_GLOBALS(phar)
-       HashTable   phar_fname_map;
-       HashTable   phar_alias_map;
-       int         readonly;
-       int         require_hash;
-       zend_bool   readonly_orig;
-       zend_bool   require_hash_orig;
-ZEND_END_MODULE_GLOBALS(phar)
+#define PHAR_MAIN
+#include "phar_internal.h"
 
 ZEND_DECLARE_MODULE_GLOBALS(phar)
 
@@ -172,123 +79,11 @@ PHP_INI_BEGIN()
        STD_PHP_INI_BOOLEAN("phar.require_hash", "1", PHP_INI_ALL, phar_ini_modify_handler, require_hash, zend_phar_globals, phar_globals)
 PHP_INI_END()
 
-#ifndef php_uint16
-# if SIZEOF_SHORT == 2
-#  define php_uint16 unsigned short
-# else
-#  define php_uint16 uint16_t
-# endif
-#endif
-
-typedef union _phar_archive_object  phar_archive_object;
-typedef union _phar_entry_object    phar_entry_object;
-
-/* entry for one file in a phar file */
-typedef struct _phar_entry_info {
-       /* first bytes are exactly as in file */
-       php_uint32               uncompressed_filesize;
-       php_uint32               timestamp;
-       php_uint32               compressed_filesize;
-       php_uint32               crc32;
-       php_uint32               flags;
-       /* remainder */
-       zval                     *metadata;
-       php_uint32               filename_len;
-       char                     *filename;
-       long                     offset_within_phar;
-       php_stream               *fp;
-       php_stream               *temp_file;
-       int                      is_crc_checked:1;
-       int                      is_modified:1;
-       int                      is_deleted:1;
-} phar_entry_info;
-
-/* information about a phar file (the archive itself) */
-typedef struct _phar_archive_data {
-       char                     *fname;
-       int                      fname_len;
-       char                     *alias;
-       int                      alias_len;
-       char                     version[12];
-       size_t                   internal_file_start;
-       size_t                   halt_offset;
-       HashTable                manifest;
-       php_uint32               flags;
-       php_uint32               min_timestamp;
-       php_uint32               max_timestamp;
-       php_stream               *fp;
-       int                      refcount;
-       php_uint32               sig_flags;
-       int                      sig_len;
-       char                     *signature;
-       int                      is_explicit_alias:1;
-       int                      is_modified:1;
-       int                      is_writeable:1;
-} phar_archive_data;
-
-/* stream access data for one file entry in a phar file */
-typedef struct _phar_entry_data {
-       phar_archive_data        *phar;
-       php_stream               *fp;
-       phar_entry_info          *internal_file;
-} phar_entry_data;
-
-/* archive php object */
-union _phar_archive_object {
-       zend_object              std;
-       spl_filesystem_object    spl;
-       struct {
-           zend_object          std;
-           phar_archive_data    *archive;
-       } arc;
-};
-
-/* entry php object */
-union _phar_entry_object {
-       zend_object              std;
-       spl_filesystem_object    spl;
-       struct {
-           zend_object          std;
-           phar_entry_info      *entry;
-       } ent;
-};
-
-/* {{{ forward declarations */
-static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC);
-static int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC);
-
-static php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char *mode, int options TSRMLS_DC);
-
-static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
-static php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
-static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
-static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);
-
-/* file/stream handlers */
-static size_t phar_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
-static size_t phar_stream_read( php_stream *stream, char *buf, size_t count TSRMLS_DC);
-static int    phar_stream_close(php_stream *stream, int close_handle TSRMLS_DC);
-static int    phar_stream_flush(php_stream *stream TSRMLS_DC);
-static int    phar_stream_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC);
-static int    phar_stream_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
-
-/* directory handlers */
-static size_t phar_dir_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
-static size_t phar_dir_read( php_stream *stream, char *buf, size_t count TSRMLS_DC);
-static int    phar_dir_close(php_stream *stream, int close_handle TSRMLS_DC);
-static int    phar_dir_flush(php_stream *stream TSRMLS_DC);
-static int    phar_dir_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC);
-static int    phar_dir_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
-/* }}} */
-
-static zend_class_entry *phar_ce_archive;
-static zend_class_entry *phar_ce_entry;
-
 /**
  * When all uses of a phar have been concluded, this frees the manifest
  * and the phar slot
  */
-static void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC) /* {{{ */
+void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC) /* {{{ */
 {
        if (data->alias && data->alias != data->fname) {
                efree(data->alias);
@@ -347,38 +142,6 @@ static void destroy_phar_data(void *pDest) /* {{{ */
 }
 /* }}}*/
 
-/**
- * from spl_directory
- */
-static void phar_spl_foreign_dtor(spl_filesystem_object *object TSRMLS_DC) /* {{{ */
-{
-       phar_archive_data *phar_data = (phar_archive_data *) object->oth;
-
-       if (--phar_data->refcount < 0) {
-               phar_destroy_phar_data(phar_data TSRMLS_CC);
-       }
-}
-/* }}} */
-
-/**
- * from spl_directory
- */
-static void phar_spl_foreign_clone(spl_filesystem_object *src, spl_filesystem_object *dst TSRMLS_DC) /* {{{ */
-{
-       phar_archive_data *phar_data = (phar_archive_data *) dst->oth;
-
-       phar_data->refcount++;
-}
-/* }}} */
-
-/**
- * from spl_directory
- */
-static spl_other_handler phar_spl_foreign_handler = {
-       phar_spl_foreign_dtor,
-       phar_spl_foreign_clone
-};
-
 /**
  * destructor for the manifest hash, frees each file's entry
  */
@@ -438,7 +201,7 @@ static phar_archive_data * phar_get_archive(char *fname, int fname_len, char *al
 /**
  * retrieve information on a file contained within a phar, or null if it ain't there
  */
-static phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC) /* {{{ */
+phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC) /* {{{ */
 {
        phar_entry_info *entry;
 
@@ -493,7 +256,7 @@ static phar_entry_data *phar_get_entry_data(char *fname, int fname_len, char *pa
 /**
  * Create a new dummy file slot within a writeable phar for a newly created file
  */
-static phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len TSRMLS_DC) /* {{{ */
+phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len TSRMLS_DC) /* {{{ */
 {
        phar_archive_data *phar;
        phar_entry_info *entry, etemp;
@@ -553,34 +316,6 @@ static phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len
 }
 /* }}} */
 
-/* {{{ proto string apiVersion()
- * Returns the api version */
-PHP_METHOD(Phar, apiVersion)
-{
-       RETURN_STRINGL(PHAR_VERSION_STR, sizeof(PHAR_VERSION_STR)-1, 1);
-}
-/* }}}*/
-
-/* {{{ proto bool canCompress()
- * Returns whether phar extension supports compression using zlib/bzip2 */
-PHP_METHOD(Phar, canCompress)
-{
-#if HAVE_ZLIB || HAVE_BZ2
-       RETURN_TRUE;
-#else
-       RETURN_FALSE;
-#endif
-}
-/* }}} */
-
-/* {{{ proto bool canWrite()
- * Returns whether phar extension supports writing and creating phars */
-PHP_METHOD(Phar, canWrite)
-{
-       RETURN_BOOL(PHAR_G(readonly));
-}
-/* }}} */
-
 #define MAPPHAR_ALLOC_FAIL(msg) \
        php_stream_close(fp);\
        php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, msg, fname);\
@@ -696,7 +431,7 @@ static int phar_parse_metadata(php_stream *fp, char **buffer, char *endbuffer, z
  * This is used by phar_open_filename to process the manifest, but can be called
  * directly.
  */
-static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
+int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
 {
        char b32[4], *buffer, *endbuffer, *savebuf;
        phar_archive_data *mydata = NULL;
@@ -1109,7 +844,7 @@ static int phar_open_or_create_filename(char *fname, int fname_len, char *alias,
  * that the manifest is proper, then pass it to phar_open_file().  SUCCESS
  * or FAILURE is returned and pphar is set to a pointer to the phar's manifest
  */
-static int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
+int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
 {
        php_stream *fp;
        
@@ -1190,7 +925,7 @@ static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias,
  *
  * This is used by phar_open_url()
  */
-static int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC) /* {{{ */
+int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC) /* {{{ */
 {
        char *pos_p, *pos_z, *pos_b, *ext_str;
        int ext_len;
@@ -1295,7 +1030,7 @@ static php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char
  * Invoked when a user calls Phar::mapPhar() from within an executing .phar
  * to set up its manifest directly
  */
-static int phar_open_compiled_file(char *alias, int alias_len TSRMLS_DC) /* {{{ */
+int phar_open_compiled_file(char *alias, int alias_len TSRMLS_DC) /* {{{ */
 {
        char *fname;
        long halt_offset;
@@ -1336,32 +1071,6 @@ static int phar_open_compiled_file(char *alias, int alias_len TSRMLS_DC) /* {{{
 }
 /* }}} */
 
-/* {{{ proto mixed Phar::mapPhar([string alias])
- * Reads the currently executed file (a phar) and registers its manifest */
-PHP_METHOD(Phar, mapPhar)
-{
-       char * alias = NULL;
-       int alias_len = 0;
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &alias, &alias_len) == FAILURE) {
-               return;
-       }
-
-       RETURN_BOOL(phar_open_compiled_file(alias, alias_len TSRMLS_CC) == SUCCESS);
-} /* }}} */
-
-/* {{{ proto mixed Phar::loadPhar(string filename [, string alias])
- * Loads any phar archive with an alias */
-PHP_METHOD(Phar, loadPhar)
-{
-       char *fname, *alias = NULL;
-       int fname_len, alias_len = 0;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &fname, &fname_len, &alias, &alias_len) == FAILURE) {
-               return;
-       }
-       RETURN_BOOL(phar_open_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL TSRMLS_CC) == SUCCESS);
-} /* }}} */
-
 static php_stream_ops phar_ops = {
        phar_stream_write, /* write */
        phar_stream_read,  /* read */
@@ -1841,7 +1550,7 @@ static inline void phar_set_16(char *buffer, int var) /* {{{ */
 #endif
 } /* }}} */
 
-static int phar_flush(phar_entry_data *data TSRMLS_DC) /* {{{ */
+int phar_flush(phar_entry_data *data TSRMLS_DC) /* {{{ */
 {
        static const char newprologue[] = "<?php __HALT_COMPILER();";
        phar_entry_info *entry;
@@ -2696,410 +2405,6 @@ static php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path
 }
 /* }}} */
 
-/* {{{ proto void Phar::__construct(string fname [, int flags [, string alias]])
- * Construct a Phar archive object
- */
-PHP_METHOD(Phar, __construct)
-{
-       char *fname, *alias = NULL;
-       int fname_len, alias_len = 0;
-       long flags = 0;
-       phar_archive_object *phar_obj;
-       phar_archive_data   *phar_data;
-       zval *zobj = getThis(), arg1, arg2;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) {
-               return;
-       }
-
-       phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
-       if (phar_obj->arc.archive) {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice");
-               return;
-       }
-
-       if (phar_open_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, &phar_data TSRMLS_CC) == FAILURE) {
-               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
-                       "Cannot open phar file '%s' with alias '%s'", fname, alias);
-               return;
-       }
-
-       phar_data->refcount++;
-       phar_obj->arc.archive = phar_data;
-       phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
-
-       fname_len = spprintf(&fname, 0, "phar://%s", fname);
-
-       INIT_PZVAL(&arg1);
-       ZVAL_STRINGL(&arg1, fname, fname_len, 0);
-
-       if (ZEND_NUM_ARGS() > 1) {
-               INIT_PZVAL(&arg2);
-               ZVAL_LONG(&arg2, flags);
-               zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj), 
-                       &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
-       } else {
-               zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), 
-                       &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1);
-       }
-
-       phar_obj->spl.info_class = phar_ce_entry;
-
-       efree(fname);
-}
-/* }}} */
-
-#define PHAR_ARCHIVE_OBJECT() \
-       phar_archive_object *phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
-       if (!phar_obj->arc.archive) { \
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
-                       "Cannot call method on an uninitialzed Phar object"); \
-               return; \
-       }
-
-/* {{{ proto int Phar::count()
- * Returns the number of entries in the Phar archive
- */
-PHP_METHOD(Phar, count)
-{
-       PHAR_ARCHIVE_OBJECT();
-       
-       RETURN_LONG(zend_hash_num_elements(&phar_obj->arc.archive->manifest));
-}
-/* }}} */
-
-/* {{{ proto string Phar::getVersion()
- * Return version info of Phar archive
- */
-PHP_METHOD(Phar, getVersion)
-{
-       PHAR_ARCHIVE_OBJECT();
-       
-       RETURN_STRING(phar_obj->arc.archive->version, 1);
-}
-/* }}} */
-
-/* {{{ proto array|false Phar::getSignature()
- * Return signature or false
- */
-PHP_METHOD(Phar, getSignature)
-{
-       PHAR_ARCHIVE_OBJECT();
-
-       if (phar_obj->arc.archive->signature) {
-               array_init(return_value);
-               add_assoc_stringl(return_value, "hash", phar_obj->arc.archive->signature, phar_obj->arc.archive->sig_len, 1);
-               switch(phar_obj->arc.archive->sig_flags) {
-               case PHAR_SIG_MD5:
-                       add_assoc_stringl(return_value, "hash_type", "md5", 3, 1);
-                       break;
-               case PHAR_SIG_SHA1:
-                       add_assoc_stringl(return_value, "hash_type", "sha1", 4, 1);
-                       break;
-               }
-       } else {
-               RETURN_FALSE;
-       }
-}
-/* }}} */
-
-/* {{{ proto bool Phar::getModified()
- * Return whether phar was modified
- */
-PHP_METHOD(Phar, getModified)
-{
-       PHAR_ARCHIVE_OBJECT();
-
-       RETURN_BOOL(phar_obj->arc.archive->is_modified);
-}
-/* }}} */
-
-/* {{{ proto int Phar::offsetExists(string offset)
- * determines whether a file exists in the phar
- */
-PHP_METHOD(Phar, offsetExists)
-{
-       char *fname;
-       int fname_len;
-       phar_entry_info *entry;
-       PHAR_ARCHIVE_OBJECT();
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
-               return;
-       }
-
-       if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
-               if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
-                       if (entry->is_deleted) {
-                               /* entry is deleted, but has not been flushed to disk yet */
-                               RETURN_FALSE;
-                       }
-               }
-               RETURN_TRUE;
-       } else {
-               RETURN_FALSE;
-       }
-}
-/* }}} */
-
-/* {{{ proto int Phar::offsetGet(string offset)
- * get a PharFileInfo object for a specific file
- */
-PHP_METHOD(Phar, offsetGet)
-{
-       char *fname;
-       int fname_len;
-       zval *zfname;
-       PHAR_ARCHIVE_OBJECT();
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
-               return;
-       }
-       
-       if (!phar_get_entry_info(phar_obj->arc.archive, fname, fname_len TSRMLS_CC)) {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist", fname);
-       } else {
-               fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
-               MAKE_STD_ZVAL(zfname);
-               ZVAL_STRINGL(zfname, fname, fname_len, 0);
-               spl_instantiate_arg_ex1(phar_obj->spl.file_class, &return_value, 0, zfname TSRMLS_CC);
-               zval_ptr_dtor(&zfname);
-       }
-
-}
-/* }}} */
-
-/* {{{ proto int Phar::offsetSet(string offset, string value)
- * set the contents of an internal file to those of an external file
- */
-PHP_METHOD(Phar, offsetSet)
-{
-       char *fname;
-       int fname_len;
-       char *contents;
-       int contents_len;
-       phar_entry_data *data;
-       php_stream *fp;
-       PHAR_ARCHIVE_OBJECT();
-
-       if (PHAR_G(readonly)) {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
-               return;
-       }
-       
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fname, &fname_len, &contents, &contents_len) == FAILURE) {
-               return;
-       }
-
-       if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len TSRMLS_CC))) {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created", fname);
-       } else {
-               fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
-               fp = php_stream_open_wrapper(fname, "w+b", STREAM_MUST_SEEK|REPORT_ERRORS, NULL);
-               if (contents_len != php_stream_write(fp, contents, contents_len)) {
-                       zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname);
-               }
-               php_stream_close(fp);
-               efree(fname);
-               efree(data);
-       }
-}
-/* }}} */
-
-/* {{{ proto int Phar::offsetUnset()
- * remove a file from a phar
- */
-PHP_METHOD(Phar, offsetUnset)
-{
-       char *fname;
-       int fname_len;
-       phar_entry_info *entry;
-       phar_entry_data *data;
-       PHAR_ARCHIVE_OBJECT();
-
-       if (PHAR_G(readonly)) {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
-               return;
-       }
-       
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
-               return;
-       }
-
-       if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
-               if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
-                       if (entry->is_deleted) {
-                               /* entry is deleted, but has not been flushed to disk yet */
-                               return;
-                       }
-                       entry->is_modified = 0;
-                       entry->is_deleted = 1;
-                       /* we need to "flush" the stream to save the newly deleted file on disk */
-                       data = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
-                       data->phar = phar_obj->arc.archive;
-                       data->fp = 0;
-                       /* internal_file is unused in phar_flush, so we won't set it */
-                       phar_flush(data TSRMLS_CC);
-                       efree(data);
-                       RETURN_TRUE;
-               }
-       } else {
-               RETURN_FALSE;
-       }
-}
-/* }}} */
-
-/* {{{ proto void PharFileInfo::__construct(string entry)
- * Construct a Phar entry object
- */
-PHP_METHOD(PharFileInfo, __construct)
-{
-       char *fname, *arch, *entry;
-       int fname_len, arch_len, entry_len;
-       phar_entry_object  *entry_obj;
-       phar_entry_info    *entry_info;
-       phar_archive_data *phar_data;
-       zval *zobj = getThis(), arg1;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
-               return;
-       }
-       
-       entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
-       if (entry_obj->ent.entry) {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice");
-               return;
-       }
-
-       if (phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC) == FAILURE) {
-               efree(arch);
-               efree(entry);
-               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
-                       "Cannot access phar file entry '%s'", fname);
-               return;
-       }
-
-       if (phar_open_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data TSRMLS_CC) == FAILURE) {
-               efree(arch);
-               efree(entry);
-               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
-                       "Cannot open phar file '%s'", fname);
-               return;
-       }
-
-       if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len TSRMLS_CC)) == NULL) {
-               efree(arch);
-               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
-                       "Cannot access phar file entry '%s' in archive '%s'", entry, arch);
-               efree(entry);
-               return;
-       }
-
-       efree(arch);
-       efree(entry);
-
-       entry_obj->ent.entry = entry_info;
-
-       INIT_PZVAL(&arg1);
-       ZVAL_STRINGL(&arg1, fname, fname_len, 0);
-
-       zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), 
-               &spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1);
-}
-/* }}} */
-
-#define PHAR_ENTRY_OBJECT() \
-       phar_entry_object *entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
-       if (!entry_obj->ent.entry) { \
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
-                       "Cannot call method on an uninitialzed PharFileInfo object"); \
-               return; \
-       }
-
-/* {{{ proto int PharFileInfo::getCompressedSize()
- * Returns the compressed size
- */
-PHP_METHOD(PharFileInfo, getCompressedSize)
-{
-       PHAR_ENTRY_OBJECT();
-       
-       RETURN_LONG(entry_obj->ent.entry->compressed_filesize);
-}
-/* }}} */
-
-/* {{{ proto bool PharFileInfo::isCompressed()
- * Returns whether the entry is compressed
- */
-PHP_METHOD(PharFileInfo, isCompressed)
-{
-       PHAR_ENTRY_OBJECT();
-       
-       RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK);
-}
-/* }}} */
-
-/* {{{ proto bool PharFileInfo::isCompressedGZ()
- * Returns whether the entry is compressed using gz
- */
-PHP_METHOD(PharFileInfo, isCompressedGZ)
-{
-       PHAR_ENTRY_OBJECT();
-       
-       RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ);
-}
-/* }}} */
-
-/* {{{ proto bool PharFileInfo::isCompressedBZIP2()
- * Returns whether the entry is compressed using bzip2
- */
-PHP_METHOD(PharFileInfo, isCompressedBZIP2)
-{
-       PHAR_ENTRY_OBJECT();
-       
-       RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2);
-}
-/* }}} */
-
-/* {{{ proto int PharFileInfo::getCRC32()
- * Returns CRC32 code or throws an exception if not CRC checked
- */
-PHP_METHOD(PharFileInfo, getCRC32)
-{
-       PHAR_ENTRY_OBJECT();
-
-       if (entry_obj->ent.entry->is_crc_checked) {
-               RETURN_LONG(entry_obj->ent.entry->crc32);
-       } else {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
-                       "Phar entry was not CRC checked"); \
-       }
-}
-/* }}} */
-
-/* {{{ proto int PharFileInfo::isCRCChecked()
- * Returns whether file entry is CRC checked
- */
-PHP_METHOD(PharFileInfo, isCRCChecked)
-{
-       PHAR_ENTRY_OBJECT();
-       
-       RETURN_BOOL(entry_obj->ent.entry->is_crc_checked);
-}
-/* }}} */
-
-/* {{{ proto int PharFileInfo::getPharFlags()
- * Returns the Phar file entry flags
- */
-PHP_METHOD(PharFileInfo, getPharFlags)
-{
-       PHAR_ENTRY_OBJECT();
-       
-       RETURN_LONG(entry_obj->ent.entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
-}
-/* }}} */
-
 #ifdef COMPILE_DL_PHAR
 ZEND_GET_MODULE(phar)
 #endif
@@ -3109,75 +2414,8 @@ ZEND_GET_MODULE(phar)
  * Every user visible function must have an entry in phar_functions[].
  */
 function_entry phar_functions[] = {
-       {NULL, NULL, NULL}      /* Must be the last line in phar_functions[] */
-};
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1)
-       ZEND_ARG_INFO(0, fname)
-       ZEND_ARG_INFO(0, flags)
-       ZEND_ARG_INFO(0, alias)
-ZEND_END_ARG_INFO();
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mapPhar, 0, 0, 0)
-       ZEND_ARG_INFO(0, alias)
-ZEND_END_ARG_INFO();
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_loadPhar, 0, 0, 1)
-       ZEND_ARG_INFO(0, fname)
-       ZEND_ARG_INFO(0, alias)
-ZEND_END_ARG_INFO();
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetExists, 0, 0, 1)
-       ZEND_ARG_INFO(0, entry)
-ZEND_END_ARG_INFO();
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetSet, 0, 0, 2)
-       ZEND_ARG_INFO(0, entry)
-       ZEND_ARG_INFO(0, value)
-ZEND_END_ARG_INFO();
-
-zend_function_entry php_archive_methods[] = {
-       PHP_ME(Phar, __construct,   arginfo_phar___construct,  0)
-       PHP_ME(Phar, count,         NULL,                      0)
-       PHP_ME(Phar, getVersion,    NULL,                      0)
-       PHP_ME(Phar, getSignature,  NULL,                      0)
-       PHP_ME(Phar, getModified,   NULL,                      0)
-       PHP_ME(Phar, offsetGet,     arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
-       PHP_ME(Phar, offsetSet,     arginfo_phar_offsetSet,    ZEND_ACC_PUBLIC)
-       PHP_ME(Phar, offsetUnset,   arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
-       PHP_ME(Phar, offsetExists,  arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
-       /* static member functions */
-       PHP_ME(Phar, apiVersion,    NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
-       PHP_ME(Phar, canCompress,   NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
-       PHP_ME(Phar, canWrite,      NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
-       PHP_ME(Phar, mapPhar,       arginfo_phar_mapPhar,      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
-       PHP_ME(Phar, loadPhar,      arginfo_phar_loadPhar,     ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
-       {NULL, NULL, NULL}
-};
-
-static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_entry___construct, 0, 0, 1)
-       ZEND_ARG_INFO(0, fname)
-       ZEND_ARG_INFO(0, flags)
-ZEND_END_ARG_INFO();
-
-zend_function_entry php_entry_methods[] = {
-       PHP_ME(PharFileInfo, __construct,        arginfo_entry___construct,  0)
-       PHP_ME(PharFileInfo, getCompressedSize,  NULL,                       0)
-       PHP_ME(PharFileInfo, isCompressed,       NULL,                       0)
-       PHP_ME(PharFileInfo, isCompressedGZ,     NULL,                       0)
-       PHP_ME(PharFileInfo, isCompressedBZIP2,  NULL,                       0)
-       PHP_ME(PharFileInfo, getCRC32,           NULL,                       0)
-       PHP_ME(PharFileInfo, isCRCChecked,       NULL,                       0)
-       PHP_ME(PharFileInfo, getPharFlags,       NULL,                       0)
-       {NULL, NULL, NULL}
+       {NULL, NULL, NULL}      /* Must be the last line in phar_functions[] */
 };
-/* }}} */
 
 /* {{{ php_phar_init_globals
  */
@@ -3187,27 +2425,13 @@ static void php_phar_init_globals_module(zend_phar_globals *phar_globals)
        phar_globals->readonly = 1;
 }
 /* }}} */
-#define REGISTER_PHAR_CLASS_CONST_LONG(class_name, const_name, value) \
-       zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
 
 PHP_MINIT_FUNCTION(phar) /* {{{ */
 {
-       zend_class_entry ce;
-
        ZEND_INIT_MODULE_GLOBALS(phar, php_phar_init_globals_module, NULL);
        REGISTER_INI_ENTRIES();
 
-       INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
-       phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator, NULL  TSRMLS_CC);
-
-       zend_class_implements(phar_ce_archive TSRMLS_CC, 2, spl_ce_Countable, zend_ce_arrayaccess);
-
-       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "COMPRESSED", PHAR_ENT_COMPRESSION_MASK)
-       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ)
-       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2)
-
-       INIT_CLASS_ENTRY(ce, "PharFileInfo", php_entry_methods);
-       phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo, NULL  TSRMLS_CC);
+       phar_object_init(TSRMLS_C);
 
        return php_register_url_stream_wrapper("phar", &php_stream_phar_wrapper TSRMLS_CC);
 }
@@ -3269,7 +2493,9 @@ static zend_module_dep phar_deps[] = {
 #if HAVE_BZ2
        ZEND_MOD_REQUIRED("bz2")
 #endif
+#if HAVE_SPL
        ZEND_MOD_REQUIRED("spl")
+#endif
        {NULL, NULL, NULL}
 };
 
diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h
new file mode 100755 (executable)
index 0000000..cbe6b23
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+  +----------------------------------------------------------------------+
+  | phar php single-file executable PHP extension                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2005-2006 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt.                                 |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Authors: Gregory Beaver <cellog@php.net>                             |
+  |          Marcus Boerger <helly@php.net>                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+#include "php.h"
+#include "php_ini.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_exceptions.h"
+#include "zend_hash.h"
+#include "zend_interfaces.h"
+#include "zend_operators.h"
+#include "zend_qsort.h"
+#include "main/php_streams.h"
+#include "ext/standard/info.h"
+#include "ext/standard/url.h"
+#include "ext/standard/crc32.h"
+#include "ext/standard/md5.h"
+#include "ext/standard/sha1.h"
+#if HAVE_SPL
+#include "ext/spl/spl_array.h"
+#include "ext/spl/spl_directory.h"
+#include "ext/spl/spl_engine.h"
+#include "ext/spl/spl_exceptions.h"
+#endif
+#include "php_phar.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifndef E_RECOVERABLE_ERROR
+#define E_RECOVERABLE_ERROR E_ERROR
+#endif
+
+#define PHAR_VERSION_STR          "0.9.0"
+/* x.y.z maps to 0xyz0 */
+#define PHAR_API_VERSION          0x0900
+#define PHAR_API_MIN_READ         0x0900
+#define PHAR_API_MAJORVERSION     0x0000
+#define PHAR_API_MAJORVER_MASK    0xF000
+#define PHAR_API_VER_MASK         0xFFF0
+
+#define PHAR_HDR_COMPRESSION_MASK 0x0000F000
+#define PHAR_HDR_COMPRESSED_NONE  0x00000000
+#define PHAR_HDR_COMPRESSED_GZ    0x00001000
+#define PHAR_HDR_COMPRESSED_BZ2   0x00002000
+#define PHAR_HDR_SIGNATURE        0x00010000
+
+#define PHAR_SIG_MD5              0x0001
+#define PHAR_SIG_SHA1             0x0002
+#define PHAR_SIG_PGP              0x0010
+
+#define PHAR_SIG_USE  PHAR_SIG_SHA1
+
+/* metadata type constants */
+
+#define PHAR_METADATA_FINISHED 0x00000000
+
+/* 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 */
+#define PHAR_ENT_COMPRESSION_MASK 0x0000F000
+#define PHAR_ENT_COMPRESSED_NONE  0x00000000
+#define PHAR_ENT_COMPRESSED_GZ    0x00001000
+#define PHAR_ENT_COMPRESSED_BZ2   0x00002000
+
+#define PHAR_ENT_PERM_MASK        0x000001FF
+#define PHAR_ENT_PERM_MASK_USR    0x000001C0
+#define PHAR_ENT_PERM_SHIFT_USR   6
+#define PHAR_ENT_PERM_MASK_GRP    0x00000038
+#define PHAR_ENT_PERM_SHIFT_GRP   3
+#define PHAR_ENT_PERM_MASK_OTH    0x00000007
+#define PHAR_ENT_PERM_DEF_FILE    0x000001B6
+#define PHAR_ENT_PERM_DEF_DIR     0x000001FF
+
+ZEND_BEGIN_MODULE_GLOBALS(phar)
+       HashTable   phar_fname_map;
+       HashTable   phar_alias_map;
+       int         readonly;
+       int         require_hash;
+       zend_bool   readonly_orig;
+       zend_bool   require_hash_orig;
+ZEND_END_MODULE_GLOBALS(phar)
+
+ZEND_EXTERN_MODULE_GLOBALS(phar)
+
+#ifdef ZTS
+#      include "TSRM.h"
+#      define PHAR_G(v) TSRMG(phar_globals_id, zend_phar_globals *, v)
+#      define PHAR_GLOBALS ((zend_phar_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(phar_globals_id)])
+#else
+#      define PHAR_G(v) (phar_globals.v)
+#      define PHAR_GLOBALS (&phar_globals)
+#endif
+
+#ifndef php_uint16
+# if SIZEOF_SHORT == 2
+#  define php_uint16 unsigned short
+# else
+#  define php_uint16 uint16_t
+# endif
+#endif
+
+#if HAVE_SPL
+typedef union _phar_archive_object  phar_archive_object;
+typedef union _phar_entry_object    phar_entry_object;
+#endif
+
+/* entry for one file in a phar file */
+typedef struct _phar_entry_info {
+       /* first bytes are exactly as in file */
+       php_uint32               uncompressed_filesize;
+       php_uint32               timestamp;
+       php_uint32               compressed_filesize;
+       php_uint32               crc32;
+       php_uint32               flags;
+       /* remainder */
+       zval                     *metadata;
+       php_uint32               filename_len;
+       char                     *filename;
+       long                     offset_within_phar;
+       php_stream               *fp;
+       php_stream               *temp_file;
+       int                      is_crc_checked:1;
+       int                      is_modified:1;
+       int                      is_deleted:1;
+} phar_entry_info;
+
+/* information about a phar file (the archive itself) */
+typedef struct _phar_archive_data {
+       char                     *fname;
+       int                      fname_len;
+       char                     *alias;
+       int                      alias_len;
+       char                     version[12];
+       size_t                   internal_file_start;
+       size_t                   halt_offset;
+       HashTable                manifest;
+       php_uint32               flags;
+       php_uint32               min_timestamp;
+       php_uint32               max_timestamp;
+       php_stream               *fp;
+       int                      refcount;
+       php_uint32               sig_flags;
+       int                      sig_len;
+       char                     *signature;
+       int                      is_explicit_alias:1;
+       int                      is_modified:1;
+       int                      is_writeable:1;
+} phar_archive_data;
+
+/* stream access data for one file entry in a phar file */
+typedef struct _phar_entry_data {
+       phar_archive_data        *phar;
+       php_stream               *fp;
+       phar_entry_info          *internal_file;
+} phar_entry_data;
+
+#if HAVE_SPL
+/* archive php object */
+union _phar_archive_object {
+       zend_object              std;
+       spl_filesystem_object    spl;
+       struct {
+           zend_object          std;
+           phar_archive_data    *archive;
+       } arc;
+};
+#endif
+
+#if HAVE_SPL
+/* entry php object */
+union _phar_entry_object {
+       zend_object              std;
+       spl_filesystem_object    spl;
+       struct {
+           zend_object          std;
+           phar_entry_info      *entry;
+       } ent;
+};
+#endif
+
+BEGIN_EXTERN_C()
+
+void phar_object_init(TSRMLS_D);
+
+int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC);
+int phar_open_compiled_file(char *alias, int alias_len 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 TSRMLS_DC);
+
+static php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char *mode, int options TSRMLS_DC);
+
+static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
+static php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
+static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
+static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);
+
+/* file/stream handlers */
+static size_t phar_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
+static size_t phar_stream_read( php_stream *stream, char *buf, size_t count TSRMLS_DC);
+static int    phar_stream_close(php_stream *stream, int close_handle TSRMLS_DC);
+static int    phar_stream_flush(php_stream *stream TSRMLS_DC);
+static int    phar_stream_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC);
+static int    phar_stream_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
+
+/* directory handlers */
+static size_t phar_dir_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
+static size_t phar_dir_read( php_stream *stream, char *buf, size_t count TSRMLS_DC);
+static int    phar_dir_close(php_stream *stream, int close_handle TSRMLS_DC);
+static int    phar_dir_flush(php_stream *stream TSRMLS_DC);
+static int    phar_dir_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC);
+static int    phar_dir_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
+
+#endif
+
+void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC);
+phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC);
+phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len TSRMLS_DC);
+int phar_flush(phar_entry_data *data TSRMLS_DC);
+int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);
+
+END_EXTERN_C()
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
new file mode 100755 (executable)
index 0000000..37f14bf
--- /dev/null
@@ -0,0 +1,638 @@
+/*
+  +----------------------------------------------------------------------+
+  | phar php single-file executable PHP extension                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2005-2006 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt.                                 |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Authors: Gregory Beaver <cellog@php.net>                             |
+  |          Marcus Boerger <helly@php.net>                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "phar_internal.h"
+
+static zend_class_entry *phar_ce_archive;
+
+#if HAVE_SPL
+static zend_class_entry *phar_ce_entry;
+#endif
+
+/* {{{ proto mixed Phar::mapPhar([string alias])
+ * Reads the currently executed file (a phar) and registers its manifest */
+PHP_METHOD(Phar, mapPhar)
+{
+       char * alias = NULL;
+       int alias_len = 0;
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &alias, &alias_len) == FAILURE) {
+               return;
+       }
+
+       RETURN_BOOL(phar_open_compiled_file(alias, alias_len TSRMLS_CC) == SUCCESS);
+} /* }}} */
+
+/* {{{ proto mixed Phar::loadPhar(string filename [, string alias])
+ * Loads any phar archive with an alias */
+PHP_METHOD(Phar, loadPhar)
+{
+       char *fname, *alias = NULL;
+       int fname_len, alias_len = 0;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &fname, &fname_len, &alias, &alias_len) == FAILURE) {
+               return;
+       }
+       RETURN_BOOL(phar_open_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL TSRMLS_CC) == SUCCESS);
+} /* }}} */
+
+/* {{{ proto string apiVersion()
+ * Returns the api version */
+PHP_METHOD(Phar, apiVersion)
+{
+       RETURN_STRINGL(PHAR_VERSION_STR, sizeof(PHAR_VERSION_STR)-1, 1);
+}
+/* }}}*/
+
+/* {{{ proto bool canCompress()
+ * Returns whether phar extension supports compression using zlib/bzip2 */
+PHP_METHOD(Phar, canCompress)
+{
+#if HAVE_ZLIB || HAVE_BZ2
+       RETURN_TRUE;
+#else
+       RETURN_FALSE;
+#endif
+}
+/* }}} */
+
+/* {{{ proto bool canWrite()
+ * Returns whether phar extension supports writing and creating phars */
+PHP_METHOD(Phar, canWrite)
+{
+       RETURN_BOOL(PHAR_G(readonly));
+}
+/* }}} */
+
+#if HAVE_SPL
+/**
+ * from spl_directory
+ */
+static void phar_spl_foreign_dtor(spl_filesystem_object *object TSRMLS_DC) /* {{{ */
+{
+       phar_archive_data *phar_data = (phar_archive_data *) object->oth;
+
+       if (--phar_data->refcount < 0) {
+               phar_destroy_phar_data(phar_data TSRMLS_CC);
+       }
+}
+/* }}} */
+
+/**
+ * from spl_directory
+ */
+static void phar_spl_foreign_clone(spl_filesystem_object *src, spl_filesystem_object *dst TSRMLS_DC) /* {{{ */
+{
+       phar_archive_data *phar_data = (phar_archive_data *) dst->oth;
+
+       phar_data->refcount++;
+}
+/* }}} */
+
+static spl_other_handler phar_spl_foreign_handler = {
+       phar_spl_foreign_dtor,
+       phar_spl_foreign_clone
+};
+#endif /* HAVE_SPL */
+
+/* {{{ proto void Phar::__construct(string fname [, int flags [, string alias]])
+ * Construct a Phar archive object
+ */
+PHP_METHOD(Phar, __construct)
+{
+#if !HAVE_SPL
+       zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Cannot instantiate Phar object without SPL extension");
+#else
+       char *fname, *alias = NULL;
+       int fname_len, alias_len = 0;
+       long flags = 0;
+       phar_archive_object *phar_obj;
+       phar_archive_data   *phar_data;
+       zval *zobj = getThis(), arg1, arg2;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) {
+               return;
+       }
+
+       phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       if (phar_obj->arc.archive) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice");
+               return;
+       }
+
+       if (phar_open_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, &phar_data TSRMLS_CC) == FAILURE) {
+               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+                       "Cannot open phar file '%s' with alias '%s'", fname, alias);
+               return;
+       }
+
+       phar_data->refcount++;
+       phar_obj->arc.archive = phar_data;
+       phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
+
+       fname_len = spprintf(&fname, 0, "phar://%s", fname);
+
+       INIT_PZVAL(&arg1);
+       ZVAL_STRINGL(&arg1, fname, fname_len, 0);
+
+       if (ZEND_NUM_ARGS() > 1) {
+               INIT_PZVAL(&arg2);
+               ZVAL_LONG(&arg2, flags);
+               zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj), 
+                       &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
+       } else {
+               zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), 
+                       &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1);
+       }
+
+       phar_obj->spl.info_class = phar_ce_entry;
+
+       efree(fname);
+#endif /* HAVE_SPL */
+}
+/* }}} */
+
+#if HAVE_SPL
+
+#define PHAR_ARCHIVE_OBJECT() \
+       phar_archive_object *phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
+       if (!phar_obj->arc.archive) { \
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Cannot call method on an uninitialzed Phar object"); \
+               return; \
+       }
+
+/* {{{ proto int Phar::count()
+ * Returns the number of entries in the Phar archive
+ */
+PHP_METHOD(Phar, count)
+{
+       PHAR_ARCHIVE_OBJECT();
+       
+       RETURN_LONG(zend_hash_num_elements(&phar_obj->arc.archive->manifest));
+}
+/* }}} */
+
+/* {{{ proto string Phar::getVersion()
+ * Return version info of Phar archive
+ */
+PHP_METHOD(Phar, getVersion)
+{
+       PHAR_ARCHIVE_OBJECT();
+       
+       RETURN_STRING(phar_obj->arc.archive->version, 1);
+}
+/* }}} */
+
+/* {{{ proto array|false Phar::getSignature()
+ * Return signature or false
+ */
+PHP_METHOD(Phar, getSignature)
+{
+       PHAR_ARCHIVE_OBJECT();
+
+       if (phar_obj->arc.archive->signature) {
+               array_init(return_value);
+               add_assoc_stringl(return_value, "hash", phar_obj->arc.archive->signature, phar_obj->arc.archive->sig_len, 1);
+               switch(phar_obj->arc.archive->sig_flags) {
+               case PHAR_SIG_MD5:
+                       add_assoc_stringl(return_value, "hash_type", "md5", 3, 1);
+                       break;
+               case PHAR_SIG_SHA1:
+                       add_assoc_stringl(return_value, "hash_type", "sha1", 4, 1);
+                       break;
+               }
+       } else {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ proto bool Phar::getModified()
+ * Return whether phar was modified
+ */
+PHP_METHOD(Phar, getModified)
+{
+       PHAR_ARCHIVE_OBJECT();
+
+       RETURN_BOOL(phar_obj->arc.archive->is_modified);
+}
+/* }}} */
+
+/* {{{ proto int Phar::offsetExists(string offset)
+ * determines whether a file exists in the phar
+ */
+PHP_METHOD(Phar, offsetExists)
+{
+       char *fname;
+       int fname_len;
+       phar_entry_info *entry;
+       PHAR_ARCHIVE_OBJECT();
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
+               return;
+       }
+
+       if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
+               if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
+                       if (entry->is_deleted) {
+                               /* entry is deleted, but has not been flushed to disk yet */
+                               RETURN_FALSE;
+                       }
+               }
+               RETURN_TRUE;
+       } else {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ proto int Phar::offsetGet(string offset)
+ * get a PharFileInfo object for a specific file
+ */
+PHP_METHOD(Phar, offsetGet)
+{
+       char *fname;
+       int fname_len;
+       zval *zfname;
+       PHAR_ARCHIVE_OBJECT();
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
+               return;
+       }
+       
+       if (!phar_get_entry_info(phar_obj->arc.archive, fname, fname_len TSRMLS_CC)) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist", fname);
+       } else {
+               fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
+               MAKE_STD_ZVAL(zfname);
+               ZVAL_STRINGL(zfname, fname, fname_len, 0);
+               spl_instantiate_arg_ex1(phar_obj->spl.file_class, &return_value, 0, zfname TSRMLS_CC);
+               zval_ptr_dtor(&zfname);
+       }
+
+}
+/* }}} */
+
+/* {{{ proto int Phar::offsetSet(string offset, string value)
+ * set the contents of an internal file to those of an external file
+ */
+PHP_METHOD(Phar, offsetSet)
+{
+       char *fname;
+       int fname_len;
+       char *contents;
+       int contents_len;
+       phar_entry_data *data;
+       php_stream *fp;
+       PHAR_ARCHIVE_OBJECT();
+
+       if (PHAR_G(readonly)) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
+               return;
+       }
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fname, &fname_len, &contents, &contents_len) == FAILURE) {
+               return;
+       }
+
+       if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len TSRMLS_CC))) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created", fname);
+       } else {
+               fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
+               fp = php_stream_open_wrapper(fname, "w+b", STREAM_MUST_SEEK|REPORT_ERRORS, NULL);
+               if (contents_len != php_stream_write(fp, contents, contents_len)) {
+                       zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname);
+               }
+               php_stream_close(fp);
+               efree(fname);
+               efree(data);
+       }
+}
+/* }}} */
+
+/* {{{ proto int Phar::offsetUnset()
+ * remove a file from a phar
+ */
+PHP_METHOD(Phar, offsetUnset)
+{
+       char *fname;
+       int fname_len;
+       phar_entry_info *entry;
+       phar_entry_data *data;
+       PHAR_ARCHIVE_OBJECT();
+
+       if (PHAR_G(readonly)) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
+               return;
+       }
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
+               return;
+       }
+
+       if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
+               if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
+                       if (entry->is_deleted) {
+                               /* entry is deleted, but has not been flushed to disk yet */
+                               return;
+                       }
+                       entry->is_modified = 0;
+                       entry->is_deleted = 1;
+                       /* we need to "flush" the stream to save the newly deleted file on disk */
+                       data = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
+                       data->phar = phar_obj->arc.archive;
+                       data->fp = 0;
+                       /* internal_file is unused in phar_flush, so we won't set it */
+                       phar_flush(data TSRMLS_CC);
+                       efree(data);
+                       RETURN_TRUE;
+               }
+       } else {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ proto void PharFileInfo::__construct(string entry)
+ * Construct a Phar entry object
+ */
+PHP_METHOD(PharFileInfo, __construct)
+{
+       char *fname, *arch, *entry;
+       int fname_len, arch_len, entry_len;
+       phar_entry_object  *entry_obj;
+       phar_entry_info    *entry_info;
+       phar_archive_data *phar_data;
+       zval *zobj = getThis(), arg1;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
+               return;
+       }
+       
+       entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       if (entry_obj->ent.entry) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice");
+               return;
+       }
+
+       if (phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC) == FAILURE) {
+               efree(arch);
+               efree(entry);
+               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+                       "Cannot access phar file entry '%s'", fname);
+               return;
+       }
+
+       if (phar_open_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data TSRMLS_CC) == FAILURE) {
+               efree(arch);
+               efree(entry);
+               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+                       "Cannot open phar file '%s'", fname);
+               return;
+       }
+
+       if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len TSRMLS_CC)) == NULL) {
+               efree(arch);
+               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+                       "Cannot access phar file entry '%s' in archive '%s'", entry, arch);
+               efree(entry);
+               return;
+       }
+
+       efree(arch);
+       efree(entry);
+
+       entry_obj->ent.entry = entry_info;
+
+       INIT_PZVAL(&arg1);
+       ZVAL_STRINGL(&arg1, fname, fname_len, 0);
+
+       zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), 
+               &spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1);
+}
+/* }}} */
+
+#define PHAR_ENTRY_OBJECT() \
+       phar_entry_object *entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
+       if (!entry_obj->ent.entry) { \
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Cannot call method on an uninitialzed PharFileInfo object"); \
+               return; \
+       }
+
+/* {{{ proto int PharFileInfo::getCompressedSize()
+ * Returns the compressed size
+ */
+PHP_METHOD(PharFileInfo, getCompressedSize)
+{
+       PHAR_ENTRY_OBJECT();
+       
+       RETURN_LONG(entry_obj->ent.entry->compressed_filesize);
+}
+/* }}} */
+
+/* {{{ proto bool PharFileInfo::isCompressed()
+ * Returns whether the entry is compressed
+ */
+PHP_METHOD(PharFileInfo, isCompressed)
+{
+       PHAR_ENTRY_OBJECT();
+       
+       RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK);
+}
+/* }}} */
+
+/* {{{ proto bool PharFileInfo::isCompressedGZ()
+ * Returns whether the entry is compressed using gz
+ */
+PHP_METHOD(PharFileInfo, isCompressedGZ)
+{
+       PHAR_ENTRY_OBJECT();
+       
+       RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ);
+}
+/* }}} */
+
+/* {{{ proto bool PharFileInfo::isCompressedBZIP2()
+ * Returns whether the entry is compressed using bzip2
+ */
+PHP_METHOD(PharFileInfo, isCompressedBZIP2)
+{
+       PHAR_ENTRY_OBJECT();
+       
+       RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2);
+}
+/* }}} */
+
+/* {{{ proto int PharFileInfo::getCRC32()
+ * Returns CRC32 code or throws an exception if not CRC checked
+ */
+PHP_METHOD(PharFileInfo, getCRC32)
+{
+       PHAR_ENTRY_OBJECT();
+
+       if (entry_obj->ent.entry->is_crc_checked) {
+               RETURN_LONG(entry_obj->ent.entry->crc32);
+       } else {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
+                       "Phar entry was not CRC checked"); \
+       }
+}
+/* }}} */
+
+/* {{{ proto int PharFileInfo::isCRCChecked()
+ * Returns whether file entry is CRC checked
+ */
+PHP_METHOD(PharFileInfo, isCRCChecked)
+{
+       PHAR_ENTRY_OBJECT();
+       
+       RETURN_BOOL(entry_obj->ent.entry->is_crc_checked);
+}
+/* }}} */
+
+/* {{{ proto int PharFileInfo::getPharFlags()
+ * Returns the Phar file entry flags
+ */
+PHP_METHOD(PharFileInfo, getPharFlags)
+{
+       PHAR_ENTRY_OBJECT();
+       
+       RETURN_LONG(entry_obj->ent.entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
+}
+/* }}} */
+
+#endif /* HAVE_SPL */
+
+/* {{{ phar methods */
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1)
+       ZEND_ARG_INFO(0, fname)
+       ZEND_ARG_INFO(0, flags)
+       ZEND_ARG_INFO(0, alias)
+ZEND_END_ARG_INFO();
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mapPhar, 0, 0, 0)
+       ZEND_ARG_INFO(0, alias)
+ZEND_END_ARG_INFO();
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_loadPhar, 0, 0, 1)
+       ZEND_ARG_INFO(0, fname)
+       ZEND_ARG_INFO(0, alias)
+ZEND_END_ARG_INFO();
+
+#if HAVE_SPL
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetExists, 0, 0, 1)
+       ZEND_ARG_INFO(0, entry)
+ZEND_END_ARG_INFO();
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetSet, 0, 0, 2)
+       ZEND_ARG_INFO(0, entry)
+       ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO();
+#endif
+
+zend_function_entry php_archive_methods[] = {
+#if !HAVE_SPL
+       PHP_ME(Phar, __construct,   arginfo_phar___construct,  ZEND_ACC_PRIVATE)
+#else
+       PHP_ME(Phar, __construct,   arginfo_phar___construct,  0)
+       PHP_ME(Phar, count,         NULL,                      0)
+       PHP_ME(Phar, getVersion,    NULL,                      0)
+       PHP_ME(Phar, getSignature,  NULL,                      0)
+       PHP_ME(Phar, getModified,   NULL,                      0)
+       PHP_ME(Phar, offsetGet,     arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
+       PHP_ME(Phar, offsetSet,     arginfo_phar_offsetSet,    ZEND_ACC_PUBLIC)
+       PHP_ME(Phar, offsetUnset,   arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
+       PHP_ME(Phar, offsetExists,  arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
+#endif
+       /* static member functions */
+       PHP_ME(Phar, apiVersion,    NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
+       PHP_ME(Phar, canCompress,   NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
+       PHP_ME(Phar, canWrite,      NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
+       PHP_ME(Phar, mapPhar,       arginfo_phar_mapPhar,      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
+       PHP_ME(Phar, loadPhar,      arginfo_phar_loadPhar,     ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
+       {NULL, NULL, NULL}
+};
+
+#if HAVE_SPL
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_entry___construct, 0, 0, 1)
+       ZEND_ARG_INFO(0, fname)
+       ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO();
+
+zend_function_entry php_entry_methods[] = {
+       PHP_ME(PharFileInfo, __construct,        arginfo_entry___construct,  0)
+       PHP_ME(PharFileInfo, getCompressedSize,  NULL,                       0)
+       PHP_ME(PharFileInfo, isCompressed,       NULL,                       0)
+       PHP_ME(PharFileInfo, isCompressedGZ,     NULL,                       0)
+       PHP_ME(PharFileInfo, isCompressedBZIP2,  NULL,                       0)
+       PHP_ME(PharFileInfo, getCRC32,           NULL,                       0)
+       PHP_ME(PharFileInfo, isCRCChecked,       NULL,                       0)
+       PHP_ME(PharFileInfo, getPharFlags,       NULL,                       0)
+       {NULL, NULL, NULL}
+};
+#endif
+/* }}} */
+
+#define REGISTER_PHAR_CLASS_CONST_LONG(class_name, const_name, value) \
+       zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
+
+void phar_object_init(TSRMLS_D) /* {{{ */
+{
+       zend_class_entry ce;
+
+#if HAVE_SPL
+       INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
+       phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator, NULL  TSRMLS_CC);
+
+       zend_class_implements(phar_ce_archive TSRMLS_CC, 2, spl_ce_Countable, zend_ce_arrayaccess);
+
+       INIT_CLASS_ENTRY(ce, "PharFileInfo", php_entry_methods);
+       phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo, NULL  TSRMLS_CC);
+#else
+       INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
+       phar_ce_archive = zend_register_internal_class(&ce TSRMLS_CC);
+       phar_ce_archive->ce_flags |= ZEND_ACC_FINAL_CLASS;
+#endif
+
+       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "COMPRESSED", PHAR_ENT_COMPRESSION_MASK)
+       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ)
+       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2)
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
index 27a2fb60e52498ff1bc334183e0f77be56a10bbc..fce85c40ab3ae0583e84e8ab6615501de5f1c557 100755 (executable)
@@ -2,6 +2,7 @@
 Phar: create and mofiy phar
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=0
 phar.require_hash=1
index 09cdb27d621194d8c9b846960eed2e003249d42a..ddf9bef2a2dd13f3c05463f4341d3d4d5c8d2e21 100755 (executable)
@@ -2,6 +2,7 @@
 Phar: create a completely new phar
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=0
 phar.require_hash=1
index ee006e83e27b3bc378d1a621952d6cd4471f4a00..ebd1c5b81e399a26bfb8a714a5cf90ca0e89c33e 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: basics
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index ca798c958c607fcb6fab7900dd933804f789b5f8..d2769b034b0e02fce2b6649c97ba2d8a4e985ec1 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: iterator & entries
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index c9b5098effbb78bb725545cf030fb479013db9b9..67ac3cf99c0eb193782b91c9d625236a79a3ff41 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: entry & openFile()
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index 5d8768ca8bb63455ca93bf05617f1ae5d2e58dba..55829c744b437f71a693aef89499b498fc222d94 100755 (executable)
@@ -2,6 +2,7 @@
 Phar and DirectoryIteraotr
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index 6eb2ec1d5bf858842f1f9d9ad1ba13c996bc610e..c3d0c29bb27c1f106badda1deb780882749182b3 100755 (executable)
@@ -2,6 +2,7 @@
 Phar and RecursiveDirectoryIterator
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index 6459bb9f6dd5397e17d627acfd1373356a985967..7ae5dd8727aa8c41bc258394e3846d2c8abdd389 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: array access
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index 48f1b90864bb09105cc97d41c3a97e4e414d26f3..05ff9baf0f4af5316db02f17c69b16718d0a232a 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: access through SplFileObject
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index 6db2e8606b902dcfeaddb556f48d41f41c6f0c7b..6e847c92f82a518c5839d170e32dfcc14114eb07 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: iterating via SplFileObject
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index 86c21017e2c86515dd276db14e14689f94aef90d..1b6c8277a77d98828999498a56b3377edb3a7880 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: ArrayAccess and isset
 --SKIPIF--
 <?php if (!extension_loaded('phar')) die('skip'); ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.require_hash=0
 --FILE--
index ad9e9c4179c3db641d6c2e173682f1d3e119d049..321530e9eede1a65dbec50d787258d7539306204 100644 (file)
@@ -2,6 +2,7 @@
 Phar object: add file
 --SKIPIF--
 <?php if (!extension_loaded('phar')) die('skip'); ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=0
 phar.require_hash=0
index 9ea22246cc49dd3d9f5d24f594d745e44e5a49b1..7380aa18da0311ae49ad001dafa53ca334f1ecec 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: add file
 --SKIPIF--
 <?php if (!extension_loaded('phar')) die('skip'); ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=1
 phar.require_hash=0
index a7b013529d0915bb0b62848f96d0b36e9d133c13..04e5e34692e5b5472fc10dda64a6a2728c5916c3 100644 (file)
@@ -2,6 +2,7 @@
 Phar object: unset file
 --SKIPIF--
 <?php if (!extension_loaded('phar')) die('skip'); ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=0
 phar.require_hash=0
index 2c194e8afd16353c32c21c709ea198c1c04bcd07..8375ed9b08e8abf86e921b899ee4fa538c38e3ae 100644 (file)
@@ -2,6 +2,7 @@
 Phar object: unset file (confirm disk file is changed)
 --SKIPIF--
 <?php if (!extension_loaded('phar')) die('skip'); ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=0
 phar.require_hash=0
index 648d8ce1986d5a1cafe548762ca2749133288896..ae344c1bd2684a5f96aac22345480daf593b8203 100755 (executable)
@@ -2,6 +2,7 @@
 Phar object: unset file
 --SKIPIF--
 <?php if (!extension_loaded('phar')) die('skip'); ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=1
 phar.require_hash=0
index a7aa6bef4ed3092af5f7f979659b44705094a848..b82a0bc06edb001689d23130d48c9dc54a2a25e2 100644 (file)
@@ -2,6 +2,7 @@
 Phar: test that refcounting avoids problems with deleting a file
 --SKIPIF--
 <?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
 --INI--
 phar.readonly=0
 phar.require_hash=0