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
[ --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)
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);
/* $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)
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);
}
/* }}}*/
-/**
- * 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
*/
/**
* 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;
/**
* 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;
}
/* }}} */
-/* {{{ 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);\
* 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;
* 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;
*
* 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;
* 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;
}
/* }}} */
-/* {{{ 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 */
#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;
}
/* }}} */
-/* {{{ 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
* 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
*/
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);
}
#if HAVE_BZ2
ZEND_MOD_REQUIRED("bz2")
#endif
+#if HAVE_SPL
ZEND_MOD_REQUIRED("spl")
+#endif
{NULL, NULL, NULL}
};
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | 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
+ */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | 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
+ */
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
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
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--
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--
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--
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--
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--
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--
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--
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--
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--
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
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
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
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
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
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