From 3066cfb3ef780e5c765cf99728fdb9f1188abd0d Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Sun, 21 Jan 2007 15:25:50 +0000 Subject: [PATCH] - Disable most of class Phar and all of class PharFileInfo if SPL is not present --- ext/phar/TODO | 29 +- ext/phar/config.m4 | 2 +- ext/phar/config.w32 | 2 +- ext/phar/phar.c | 802 +--------------------- ext/phar/phar_internal.h | 260 +++++++ ext/phar/phar_object.c | 638 +++++++++++++++++ ext/phar/tests/create_new_and_modify.phpt | 1 + ext/phar/tests/create_new_phar_c.phpt | 1 + ext/phar/tests/phar_oo_001.phpt | 1 + ext/phar/tests/phar_oo_002.phpt | 1 + ext/phar/tests/phar_oo_003.phpt | 1 + ext/phar/tests/phar_oo_004.phpt | 1 + ext/phar/tests/phar_oo_005.phpt | 1 + ext/phar/tests/phar_oo_006.phpt | 1 + ext/phar/tests/phar_oo_007.phpt | 1 + ext/phar/tests/phar_oo_008.phpt | 1 + ext/phar/tests/phar_oo_010.phpt | 1 + ext/phar/tests/phar_oo_011.phpt | 1 + ext/phar/tests/phar_oo_011b.phpt | 1 + ext/phar/tests/phar_oo_012.phpt | 1 + ext/phar/tests/phar_oo_012_confirm.phpt | 1 + ext/phar/tests/phar_oo_012b.phpt | 1 + ext/phar/tests/refcount1.phpt | 1 + 23 files changed, 948 insertions(+), 802 deletions(-) create mode 100755 ext/phar/phar_internal.h create mode 100755 ext/phar/phar_object.c diff --git a/ext/phar/TODO b/ext/phar/TODO index 517fee55dd..d739111d50 100644 --- a/ext/phar/TODO +++ b/ext/phar/TODO @@ -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 diff --git a/ext/phar/config.m4 b/ext/phar/config.m4 index b1c9985c2e..8a35fa779d 100644 --- a/ext/phar/config.m4 +++ b/ext/phar/config.m4 @@ -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) diff --git a/ext/phar/config.w32 b/ext/phar/config.w32 index 694de2e7f4..3ad36b4d89 100644 --- a/ext/phar/config.w32 +++ b/ext/phar/config.w32 @@ -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); diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 7722e39e7f..87844ddcc8 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -19,101 +19,8 @@ /* $Id$ */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#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 -#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[] = "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 index 0000000000..cbe6b23e14 --- /dev/null +++ b/ext/phar/phar_internal.h @@ -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 | + | Marcus Boerger | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#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 +#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 index 0000000000..37f14bfa57 --- /dev/null +++ b/ext/phar/phar_object.c @@ -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 | + | Marcus Boerger | + +----------------------------------------------------------------------+ +*/ + +/* $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 + */ diff --git a/ext/phar/tests/create_new_and_modify.phpt b/ext/phar/tests/create_new_and_modify.phpt index 27a2fb60e5..fce85c40ab 100755 --- a/ext/phar/tests/create_new_and_modify.phpt +++ b/ext/phar/tests/create_new_and_modify.phpt @@ -2,6 +2,7 @@ Phar: create and mofiy phar --SKIPIF-- + --INI-- phar.readonly=0 phar.require_hash=1 diff --git a/ext/phar/tests/create_new_phar_c.phpt b/ext/phar/tests/create_new_phar_c.phpt index 09cdb27d62..ddf9bef2a2 100755 --- a/ext/phar/tests/create_new_phar_c.phpt +++ b/ext/phar/tests/create_new_phar_c.phpt @@ -2,6 +2,7 @@ Phar: create a completely new phar --SKIPIF-- + --INI-- phar.readonly=0 phar.require_hash=1 diff --git a/ext/phar/tests/phar_oo_001.phpt b/ext/phar/tests/phar_oo_001.phpt index ee006e83e2..ebd1c5b81e 100755 --- a/ext/phar/tests/phar_oo_001.phpt +++ b/ext/phar/tests/phar_oo_001.phpt @@ -2,6 +2,7 @@ Phar object: basics --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_002.phpt b/ext/phar/tests/phar_oo_002.phpt index ca798c958c..d2769b034b 100755 --- a/ext/phar/tests/phar_oo_002.phpt +++ b/ext/phar/tests/phar_oo_002.phpt @@ -2,6 +2,7 @@ Phar object: iterator & entries --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_003.phpt b/ext/phar/tests/phar_oo_003.phpt index c9b5098eff..67ac3cf99c 100755 --- a/ext/phar/tests/phar_oo_003.phpt +++ b/ext/phar/tests/phar_oo_003.phpt @@ -2,6 +2,7 @@ Phar object: entry & openFile() --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_004.phpt b/ext/phar/tests/phar_oo_004.phpt index 5d8768ca8b..55829c744b 100755 --- a/ext/phar/tests/phar_oo_004.phpt +++ b/ext/phar/tests/phar_oo_004.phpt @@ -2,6 +2,7 @@ Phar and DirectoryIteraotr --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_005.phpt b/ext/phar/tests/phar_oo_005.phpt index 6eb2ec1d5b..c3d0c29bb2 100755 --- a/ext/phar/tests/phar_oo_005.phpt +++ b/ext/phar/tests/phar_oo_005.phpt @@ -2,6 +2,7 @@ Phar and RecursiveDirectoryIterator --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_006.phpt b/ext/phar/tests/phar_oo_006.phpt index 6459bb9f6d..7ae5dd8727 100755 --- a/ext/phar/tests/phar_oo_006.phpt +++ b/ext/phar/tests/phar_oo_006.phpt @@ -2,6 +2,7 @@ Phar object: array access --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_007.phpt b/ext/phar/tests/phar_oo_007.phpt index 48f1b90864..05ff9baf0f 100755 --- a/ext/phar/tests/phar_oo_007.phpt +++ b/ext/phar/tests/phar_oo_007.phpt @@ -2,6 +2,7 @@ Phar object: access through SplFileObject --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_008.phpt b/ext/phar/tests/phar_oo_008.phpt index 6db2e8606b..6e847c92f8 100755 --- a/ext/phar/tests/phar_oo_008.phpt +++ b/ext/phar/tests/phar_oo_008.phpt @@ -2,6 +2,7 @@ Phar object: iterating via SplFileObject --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_010.phpt b/ext/phar/tests/phar_oo_010.phpt index 86c21017e2..1b6c8277a7 100755 --- a/ext/phar/tests/phar_oo_010.phpt +++ b/ext/phar/tests/phar_oo_010.phpt @@ -2,6 +2,7 @@ Phar object: ArrayAccess and isset --SKIPIF-- + --INI-- phar.require_hash=0 --FILE-- diff --git a/ext/phar/tests/phar_oo_011.phpt b/ext/phar/tests/phar_oo_011.phpt index ad9e9c4179..321530e9ee 100644 --- a/ext/phar/tests/phar_oo_011.phpt +++ b/ext/phar/tests/phar_oo_011.phpt @@ -2,6 +2,7 @@ Phar object: add file --SKIPIF-- + --INI-- phar.readonly=0 phar.require_hash=0 diff --git a/ext/phar/tests/phar_oo_011b.phpt b/ext/phar/tests/phar_oo_011b.phpt index 9ea22246cc..7380aa18da 100755 --- a/ext/phar/tests/phar_oo_011b.phpt +++ b/ext/phar/tests/phar_oo_011b.phpt @@ -2,6 +2,7 @@ Phar object: add file --SKIPIF-- + --INI-- phar.readonly=1 phar.require_hash=0 diff --git a/ext/phar/tests/phar_oo_012.phpt b/ext/phar/tests/phar_oo_012.phpt index a7b013529d..04e5e34692 100644 --- a/ext/phar/tests/phar_oo_012.phpt +++ b/ext/phar/tests/phar_oo_012.phpt @@ -2,6 +2,7 @@ Phar object: unset file --SKIPIF-- + --INI-- phar.readonly=0 phar.require_hash=0 diff --git a/ext/phar/tests/phar_oo_012_confirm.phpt b/ext/phar/tests/phar_oo_012_confirm.phpt index 2c194e8afd..8375ed9b08 100644 --- a/ext/phar/tests/phar_oo_012_confirm.phpt +++ b/ext/phar/tests/phar_oo_012_confirm.phpt @@ -2,6 +2,7 @@ Phar object: unset file (confirm disk file is changed) --SKIPIF-- + --INI-- phar.readonly=0 phar.require_hash=0 diff --git a/ext/phar/tests/phar_oo_012b.phpt b/ext/phar/tests/phar_oo_012b.phpt index 648d8ce198..ae344c1bd2 100755 --- a/ext/phar/tests/phar_oo_012b.phpt +++ b/ext/phar/tests/phar_oo_012b.phpt @@ -2,6 +2,7 @@ Phar object: unset file --SKIPIF-- + --INI-- phar.readonly=1 phar.require_hash=0 diff --git a/ext/phar/tests/refcount1.phpt b/ext/phar/tests/refcount1.phpt index a7aa6bef4e..b82a0bc06e 100644 --- a/ext/phar/tests/refcount1.phpt +++ b/ext/phar/tests/refcount1.phpt @@ -2,6 +2,7 @@ Phar: test that refcounting avoids problems with deleting a file --SKIPIF-- + --INI-- phar.readonly=0 phar.require_hash=0 -- 2.40.0