2005-12-05 04:35:38 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-12-05 06:50:54 +08:00
| phar php single - file executable PHP extension |
2005-12-05 04:35:38 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2008-12-31 19:12:40 +08:00
| Copyright ( c ) 2005 - 2009 The PHP Group |
2005-12-05 04:35:38 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-12-05 06:50:54 +08:00
| This source file is subject to version 3.01 of the PHP license , |
2005-12-05 04:35:38 +08:00
| that is bundled with this package in the file LICENSE , and is |
| available through the world - wide - web at the following url : |
2005-12-05 06:50:54 +08:00
| http : //www.php.net/license/3_01.txt. |
2005-12-05 04:35:38 +08:00
| 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 . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-04 21:18:31 +08:00
| Authors : Gregory Beaver < cellog @ php . net > |
| Marcus Boerger < helly @ php . net > |
2005-12-05 04:35:38 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
2008-01-09 04:31:54 +08:00
# define PHAR_MAIN 1
2007-01-21 23:25:50 +08:00
# include "phar_internal.h"
2007-03-26 03:03:38 +08:00
# include "SAPI.h"
2008-01-11 15:30:03 +08:00
# include "func_interceptors.h"
2006-01-10 14:46:17 +08:00
2008-08-01 21:45:06 +08:00
static void destroy_phar_data ( void * pDest ) ;
2005-12-05 04:35:38 +08:00
ZEND_DECLARE_MODULE_GLOBALS ( phar )
2008-04-14 12:47:34 +08:00
# if PHP_VERSION_ID >= 50300
char * ( * phar_save_resolve_path ) ( const char * filename , int filename_len TSRMLS_DC ) ;
# endif
2005-12-05 04:35:38 +08:00
2008-04-10 11:12:08 +08:00
/**
* set ' s phar - > is_writeable based on the current INI value
*/
static int phar_set_writeable_bit ( void * pDest , void * argument TSRMLS_DC ) /* { { { */
{
zend_bool keep = * ( zend_bool * ) argument ;
phar_archive_data * phar = * ( phar_archive_data * * ) pDest ;
if ( ! phar - > is_data ) {
phar - > is_writeable = ! keep ;
}
2008-08-01 21:45:06 +08:00
2008-04-10 11:12:08 +08:00
return ZEND_HASH_APPLY_KEEP ;
}
/* }}} */
2008-08-01 21:45:06 +08:00
/* if the original value is 0 (disabled), then allow setting/unsetting at will. Otherwise only allow 1 (enabled), and error on disabling */
2007-01-24 07:31:14 +08:00
ZEND_INI_MH ( phar_ini_modify_handler ) /* {{{ */
2007-01-21 06:40:47 +08:00
{
2007-02-07 06:41:39 +08:00
zend_bool old , ini ;
2007-01-21 06:40:47 +08:00
2007-02-07 06:41:39 +08:00
if ( entry - > name_length = = 14 ) {
old = PHAR_G ( readonly_orig ) ;
} else {
old = PHAR_G ( require_hash_orig ) ;
2008-08-01 21:45:06 +08:00
}
2007-01-21 06:40:47 +08:00
2007-02-07 06:41:39 +08:00
if ( new_value_length = = 2 & & ! strcasecmp ( " on " , new_value ) ) {
ini = ( zend_bool ) 1 ;
2007-01-21 06:40:47 +08:00
}
2007-02-07 06:41:39 +08:00
else if ( new_value_length = = 3 & & ! strcasecmp ( " yes " , new_value ) ) {
ini = ( zend_bool ) 1 ;
2007-01-21 06:40:47 +08:00
}
2007-02-07 06:41:39 +08:00
else if ( new_value_length = = 4 & & ! strcasecmp ( " true " , new_value ) ) {
ini = ( zend_bool ) 1 ;
2007-01-21 06:40:47 +08:00
}
else {
2007-02-07 06:41:39 +08:00
ini = ( zend_bool ) atoi ( new_value ) ;
2007-01-21 06:40:47 +08:00
}
2007-02-07 06:41:39 +08:00
/* do not allow unsetting in runtime */
if ( stage = = ZEND_INI_STAGE_STARTUP ) {
if ( entry - > name_length = = 14 ) {
2008-08-01 21:45:06 +08:00
PHAR_G ( readonly_orig ) = ini ;
2007-02-07 06:41:39 +08:00
} else {
PHAR_G ( require_hash_orig ) = ini ;
2008-08-01 21:45:06 +08:00
}
2007-02-07 06:41:39 +08:00
} else if ( old & & ! ini ) {
return FAILURE ;
2007-01-21 06:40:47 +08:00
}
2007-02-07 06:41:39 +08:00
if ( entry - > name_length = = 14 ) {
2008-04-10 11:12:08 +08:00
PHAR_G ( readonly ) = ini ;
if ( PHAR_GLOBALS - > request_init & & PHAR_GLOBALS - > phar_fname_map . arBuckets ) {
zend_hash_apply_with_argument ( & ( PHAR_GLOBALS - > phar_fname_map ) , phar_set_writeable_bit , ( void * ) & ini TSRMLS_CC ) ;
}
2007-02-07 06:41:39 +08:00
} else {
PHAR_G ( require_hash ) = ini ;
2008-08-01 21:45:06 +08:00
}
2007-01-21 06:40:47 +08:00
return SUCCESS ;
}
2007-01-24 07:31:14 +08:00
/* }}}*/
2007-01-21 06:40:47 +08:00
2008-08-01 21:45:06 +08:00
/* this global stores the global cached pre-parsed manifests */
HashTable cached_phars ;
HashTable cached_alias ;
static void phar_split_cache_list ( TSRMLS_D ) /* { { { */
{
char * tmp ;
char * key , * lasts , * end ;
char ds [ 2 ] ;
phar_archive_data * phar ;
uint i = 0 ;
if ( ! PHAR_GLOBALS - > cache_list | | ! ( PHAR_GLOBALS - > cache_list [ 0 ] ) ) {
return ;
}
ds [ 0 ] = DEFAULT_DIR_SEPARATOR ;
ds [ 1 ] = ' \0 ' ;
tmp = estrdup ( PHAR_GLOBALS - > cache_list ) ;
/* fake request startup */
PHAR_GLOBALS - > request_init = 1 ;
if ( zend_hash_init ( & EG ( regular_list ) , 0 , NULL , NULL , 0 ) = = SUCCESS ) {
EG ( regular_list ) . nNextFreeElement = 1 ; /* we don't want resource id 0 */
}
PHAR_G ( has_bz2 ) = zend_hash_exists ( & module_registry , " bz2 " , sizeof ( " bz2 " ) ) ;
PHAR_G ( has_zlib ) = zend_hash_exists ( & module_registry , " zlib " , sizeof ( " zlib " ) ) ;
/* these two are dummies and will be destroyed later */
zend_hash_init ( & cached_phars , sizeof ( phar_archive_data * ) , zend_get_hash_value , destroy_phar_data , 1 ) ;
zend_hash_init ( & cached_alias , sizeof ( phar_archive_data * ) , zend_get_hash_value , NULL , 1 ) ;
/* these two are real and will be copied over cached_phars/cached_alias later */
zend_hash_init ( & ( PHAR_GLOBALS - > phar_fname_map ) , sizeof ( phar_archive_data * ) , zend_get_hash_value , destroy_phar_data , 1 ) ;
zend_hash_init ( & ( PHAR_GLOBALS - > phar_alias_map ) , sizeof ( phar_archive_data * ) , zend_get_hash_value , NULL , 1 ) ;
PHAR_GLOBALS - > manifest_cached = 1 ;
PHAR_GLOBALS - > persist = 1 ;
for ( key = php_strtok_r ( tmp , ds , & lasts ) ;
key ;
key = php_strtok_r ( NULL , ds , & lasts ) ) {
end = strchr ( key , DEFAULT_DIR_SEPARATOR ) ;
if ( end ) {
if ( SUCCESS = = phar_open_from_filename ( key , end - key , NULL , 0 , 0 , & phar , NULL TSRMLS_CC ) ) {
finish_up :
phar - > phar_pos = i + + ;
php_stream_close ( phar - > fp ) ;
phar - > fp = NULL ;
} else {
finish_error :
PHAR_GLOBALS - > persist = 0 ;
PHAR_GLOBALS - > manifest_cached = 0 ;
efree ( tmp ) ;
zend_hash_destroy ( & ( PHAR_G ( phar_fname_map ) ) ) ;
PHAR_GLOBALS - > phar_fname_map . arBuckets = 0 ;
zend_hash_destroy ( & ( PHAR_G ( phar_alias_map ) ) ) ;
PHAR_GLOBALS - > phar_alias_map . arBuckets = 0 ;
zend_hash_destroy ( & cached_phars ) ;
zend_hash_destroy ( & cached_alias ) ;
zend_hash_graceful_reverse_destroy ( & EG ( regular_list ) ) ;
memset ( & EG ( regular_list ) , 0 , sizeof ( HashTable ) ) ;
/* free cached manifests */
PHAR_GLOBALS - > request_init = 0 ;
return ;
}
} else {
if ( SUCCESS = = phar_open_from_filename ( key , strlen ( key ) , NULL , 0 , 0 , & phar , NULL TSRMLS_CC ) ) {
goto finish_up ;
} else {
goto finish_error ;
}
}
}
PHAR_GLOBALS - > persist = 0 ;
PHAR_GLOBALS - > request_init = 0 ;
/* destroy dummy values from before */
zend_hash_destroy ( & cached_phars ) ;
zend_hash_destroy ( & cached_alias ) ;
cached_phars = PHAR_GLOBALS - > phar_fname_map ;
cached_alias = PHAR_GLOBALS - > phar_alias_map ;
PHAR_GLOBALS - > phar_fname_map . arBuckets = 0 ;
PHAR_GLOBALS - > phar_alias_map . arBuckets = 0 ;
zend_hash_graceful_reverse_destroy ( & EG ( regular_list ) ) ;
memset ( & EG ( regular_list ) , 0 , sizeof ( HashTable ) ) ;
efree ( tmp ) ;
}
/* }}} */
ZEND_INI_MH ( phar_ini_cache_list ) /* {{{ */
{
PHAR_G ( cache_list ) = new_value ;
if ( stage = = ZEND_INI_STAGE_STARTUP ) {
phar_split_cache_list ( TSRMLS_C ) ;
}
return SUCCESS ;
}
/* }}} */
2007-01-08 00:01:35 +08:00
PHP_INI_BEGIN ( )
2008-08-01 21:45:06 +08:00
STD_PHP_INI_BOOLEAN ( " phar.readonly " , " 1 " , PHP_INI_ALL , phar_ini_modify_handler , readonly , zend_phar_globals , phar_globals )
2007-03-26 03:03:38 +08:00
STD_PHP_INI_BOOLEAN ( " phar.require_hash " , " 1 " , PHP_INI_ALL , phar_ini_modify_handler , require_hash , zend_phar_globals , phar_globals )
2008-08-01 21:45:06 +08:00
STD_PHP_INI_ENTRY ( " phar.cache_list " , " " , PHP_INI_SYSTEM , phar_ini_cache_list , cache_list , zend_phar_globals , phar_globals )
2007-01-08 00:01:35 +08:00
PHP_INI_END ( )
2007-01-02 08:04:30 +08:00
/**
* When all uses of a phar have been concluded , this frees the manifest
* and the phar slot
*/
2008-05-24 21:59:56 +08:00
void phar_destroy_phar_data ( phar_archive_data * phar TSRMLS_DC ) /* { { { */
2005-12-05 04:35:38 +08:00
{
2008-01-28 16:52:08 +08:00
if ( phar - > alias & & phar - > alias ! = phar - > fname ) {
2008-08-01 21:45:06 +08:00
pefree ( phar - > alias , phar - > is_persistent ) ;
2008-01-28 16:52:08 +08:00
phar - > alias = NULL ;
2008-01-04 09:45:37 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( phar - > fname ) {
2008-08-01 21:45:06 +08:00
pefree ( phar - > fname , phar - > is_persistent ) ;
2008-01-28 16:52:08 +08:00
phar - > fname = NULL ;
2006-01-12 05:19:46 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( phar - > signature ) {
2008-08-01 21:45:06 +08:00
pefree ( phar - > signature , phar - > is_persistent ) ;
phar - > signature = NULL ;
2007-02-03 12:04:18 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( phar - > manifest . arBuckets ) {
zend_hash_destroy ( & phar - > manifest ) ;
phar - > manifest . arBuckets = NULL ;
2007-01-09 08:27:13 +08:00
}
2008-08-01 21:45:06 +08:00
2008-02-18 12:45:42 +08:00
if ( phar - > mounted_dirs . arBuckets ) {
zend_hash_destroy ( & phar - > mounted_dirs ) ;
phar - > mounted_dirs . arBuckets = NULL ;
}
2008-08-01 21:45:06 +08:00
if ( phar - > virtual_dirs . arBuckets ) {
zend_hash_destroy ( & phar - > virtual_dirs ) ;
phar - > virtual_dirs . arBuckets = NULL ;
}
2008-01-28 16:52:08 +08:00
if ( phar - > metadata ) {
2008-08-01 21:45:06 +08:00
if ( phar - > is_persistent ) {
if ( phar - > metadata_len ) {
/* for zip comments that are strings */
free ( phar - > metadata ) ;
} else {
zval_internal_ptr_dtor ( & phar - > metadata ) ;
}
} else {
zval_ptr_dtor ( & phar - > metadata ) ;
}
phar - > metadata_len = 0 ;
2008-01-28 16:52:08 +08:00
phar - > metadata = 0 ;
2007-01-03 23:43:07 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( phar - > fp ) {
php_stream_close ( phar - > fp ) ;
phar - > fp = 0 ;
2007-01-29 11:59:55 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( phar - > ufp ) {
php_stream_close ( phar - > ufp ) ;
2008-08-01 21:45:06 +08:00
phar - > ufp = 0 ;
2006-01-10 14:46:17 +08:00
}
2008-08-01 21:45:06 +08:00
pefree ( phar , phar - > is_persistent ) ;
2005-12-05 04:35:38 +08:00
}
2006-01-04 23:50:45 +08:00
/* }}}*/
2005-12-05 04:35:38 +08:00
2007-01-27 03:58:22 +08:00
/**
* Delete refcount and destruct if needed . On destruct return 1 else 0.
*/
int phar_archive_delref ( phar_archive_data * phar TSRMLS_DC ) /* { { { */
{
2008-08-01 21:45:06 +08:00
if ( phar - > is_persistent ) {
return 0 ;
}
2007-01-27 03:58:22 +08:00
if ( - - phar - > refcount < 0 ) {
2007-01-27 23:31:24 +08:00
if ( PHAR_GLOBALS - > request_done
| | zend_hash_del ( & ( PHAR_GLOBALS - > phar_fname_map ) , phar - > fname , phar - > fname_len ) ! = SUCCESS ) {
2007-01-27 03:58:22 +08:00
phar_destroy_phar_data ( phar TSRMLS_CC ) ;
}
return 1 ;
2008-02-12 01:13:18 +08:00
} else if ( ! phar - > refcount ) {
2008-08-01 21:45:06 +08:00
/* invalidate phar cache */
PHAR_G ( last_phar ) = NULL ;
PHAR_G ( last_phar_name ) = PHAR_G ( last_alias ) = NULL ;
2008-02-12 13:28:06 +08:00
if ( phar - > fp & & ! ( phar - > flags & PHAR_FILE_COMPRESSION_MASK ) ) {
2008-02-12 01:13:18 +08:00
/* close open file handle - allows removal or rename of
2008-02-12 13:28:06 +08:00
the file on windows , which has greedy locking
only close if the archive was not already compressed . If it
was compressed , then the fp does not refer to the original file */
2008-02-12 01:13:18 +08:00
php_stream_close ( phar - > fp ) ;
phar - > fp = NULL ;
}
2008-08-01 21:45:06 +08:00
2008-05-07 05:14:53 +08:00
if ( ! zend_hash_num_elements ( & phar - > manifest ) ) {
/* this is a new phar that has perhaps had an alias/metadata set, but has never
been flushed */
if ( zend_hash_del ( & ( PHAR_GLOBALS - > phar_fname_map ) , phar - > fname , phar - > fname_len ) ! = SUCCESS ) {
phar_destroy_phar_data ( phar TSRMLS_CC ) ;
}
return 1 ;
}
2007-01-27 03:58:22 +08:00
}
return 0 ;
}
/* }}}*/
2007-01-10 08:38:17 +08:00
/**
* Destroy phar ' s in shutdown , here we don ' t care about aliases
*/
static void destroy_phar_data_only ( void * pDest ) /* { { { */
{
phar_archive_data * phar_data = * ( phar_archive_data * * ) pDest ;
TSRMLS_FETCH ( ) ;
2007-02-03 12:04:18 +08:00
if ( EG ( exception ) | | - - phar_data - > refcount < 0 ) {
2007-01-10 08:38:17 +08:00
phar_destroy_phar_data ( phar_data TSRMLS_CC ) ;
}
}
/* }}}*/
/**
* Delete aliases to phar ' s that got kicked out of the global table
*/
2007-01-09 10:27:12 +08:00
static int phar_unalias_apply ( void * pDest , void * argument TSRMLS_DC ) /* { { { */
{
return * ( void * * ) pDest = = argument ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_KEEP ;
}
/* }}} */
2008-05-12 08:16:59 +08:00
/**
* Delete aliases to phar ' s that got kicked out of the global table
*/
static int phar_tmpclose_apply ( void * pDest TSRMLS_DC ) /* { { { */
{
phar_entry_info * entry = ( phar_entry_info * ) pDest ;
if ( entry - > fp_type ! = PHAR_TMP ) {
return ZEND_HASH_APPLY_KEEP ;
}
2008-08-01 21:45:06 +08:00
2008-05-12 08:16:59 +08:00
if ( entry - > fp & & ! entry - > fp_refcount ) {
php_stream_close ( entry - > fp ) ;
entry - > fp = NULL ;
}
2008-08-01 21:45:06 +08:00
2008-05-12 08:16:59 +08:00
return ZEND_HASH_APPLY_KEEP ;
}
/* }}} */
2007-01-02 08:04:30 +08:00
/**
* Filename map destructor
*/
2006-03-08 08:56:31 +08:00
static void destroy_phar_data ( void * pDest ) /* { { { */
{
2006-03-09 04:07:25 +08:00
phar_archive_data * phar_data = * ( phar_archive_data * * ) pDest ;
2007-01-09 10:27:12 +08:00
TSRMLS_FETCH ( ) ;
2007-01-09 03:30:52 +08:00
2007-03-28 05:28:22 +08:00
if ( PHAR_GLOBALS - > request_ends ) {
2008-05-12 08:16:59 +08:00
/* first, iterate over the manifest and close all PHAR_TMP entry fp handles,
this prevents unnecessary unfreed stream resources */
zend_hash_apply ( & ( phar_data - > manifest ) , phar_tmpclose_apply TSRMLS_CC ) ;
2007-10-19 03:47:24 +08:00
destroy_phar_data_only ( pDest ) ;
return ;
2007-03-28 05:28:22 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-09 10:27:12 +08:00
zend_hash_apply_with_argument ( & ( PHAR_GLOBALS - > phar_alias_map ) , phar_unalias_apply , phar_data TSRMLS_CC ) ;
2008-08-01 21:45:06 +08:00
2007-01-09 10:27:12 +08:00
if ( - - phar_data - > refcount < 0 ) {
2006-03-09 04:07:25 +08:00
phar_destroy_phar_data ( phar_data TSRMLS_CC ) ;
}
2006-03-08 08:56:31 +08:00
}
/* }}}*/
2007-01-02 08:04:30 +08:00
/**
* destructor for the manifest hash , frees each file ' s entry
*/
2008-01-09 11:47:22 +08:00
void destroy_phar_manifest_entry ( void * pDest ) /* { { { */
2005-12-05 04:35:38 +08:00
{
2006-02-28 09:36:30 +08:00
phar_entry_info * entry = ( phar_entry_info * ) pDest ;
2007-01-10 08:07:45 +08:00
TSRMLS_FETCH ( ) ;
2006-01-04 23:27:18 +08:00
2007-01-27 23:31:24 +08:00
if ( entry - > cfp ) {
php_stream_close ( entry - > cfp ) ;
entry - > cfp = 0 ;
}
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
if ( entry - > fp ) {
2008-01-28 16:52:08 +08:00
php_stream_close ( entry - > fp ) ;
2007-01-26 22:52:10 +08:00
entry - > fp = 0 ;
2007-01-03 05:21:18 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-21 14:30:55 +08:00
if ( entry - > metadata ) {
2008-08-01 21:45:06 +08:00
if ( entry - > is_persistent ) {
if ( entry - > metadata_len ) {
/* for zip comments that are strings */
free ( entry - > metadata ) ;
} else {
zval_internal_ptr_dtor ( & entry - > metadata ) ;
}
} else {
zval_ptr_dtor ( & entry - > metadata ) ;
}
entry - > metadata_len = 0 ;
2007-01-21 14:30:55 +08:00
entry - > metadata = 0 ;
}
2008-08-01 21:45:06 +08:00
2007-05-15 03:14:00 +08:00
if ( entry - > metadata_str . c ) {
smart_str_free ( & entry - > metadata_str ) ;
entry - > metadata_str . c = 0 ;
}
2008-08-01 21:45:06 +08:00
pefree ( entry - > filename , entry - > is_persistent ) ;
2008-01-04 02:13:27 +08:00
if ( entry - > link ) {
2008-08-01 21:45:06 +08:00
pefree ( entry - > link , entry - > is_persistent ) ;
2008-01-04 02:13:27 +08:00
entry - > link = 0 ;
2008-01-03 12:45:00 +08:00
}
2008-08-01 21:45:06 +08:00
2008-04-21 14:17:51 +08:00
if ( entry - > tmp ) {
2008-08-01 21:45:06 +08:00
pefree ( entry - > tmp , entry - > is_persistent ) ;
2008-04-21 14:17:51 +08:00
entry - > tmp = 0 ;
}
2005-12-05 04:35:38 +08:00
}
2006-01-04 23:50:45 +08:00
/* }}} */
2005-12-05 04:35:38 +08:00
2007-01-27 23:31:24 +08:00
int phar_entry_delref ( phar_entry_data * idata TSRMLS_DC ) /* { { { */
{
int ret = 0 ;
2008-08-01 21:45:06 +08:00
if ( idata - > internal_file & & ! idata - > internal_file - > is_persistent ) {
2008-01-04 02:13:27 +08:00
if ( - - idata - > internal_file - > fp_refcount < 0 ) {
2007-08-17 12:47:50 +08:00
idata - > internal_file - > fp_refcount = 0 ;
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( idata - > fp & & idata - > fp ! = idata - > phar - > fp & & idata - > fp ! = idata - > phar - > ufp & & idata - > fp ! = idata - > internal_file - > fp ) {
2007-08-17 12:47:50 +08:00
php_stream_close ( idata - > fp ) ;
}
2008-09-27 00:30:10 +08:00
/* if phar_get_or_create_entry_data returns a sub-directory, we have to free it */
if ( idata - > internal_file - > is_temp_dir ) {
destroy_phar_manifest_entry ( ( void * ) idata - > internal_file ) ;
efree ( idata - > internal_file ) ;
}
2007-01-27 23:31:24 +08:00
}
2008-08-01 21:45:06 +08:00
2007-08-17 12:47:50 +08:00
phar_archive_delref ( idata - > phar TSRMLS_CC ) ;
2007-01-27 23:31:24 +08:00
efree ( idata ) ;
return ret ;
}
2007-02-07 05:04:22 +08:00
/* }}} */
2007-01-27 23:31:24 +08:00
2007-01-26 22:52:10 +08:00
/**
2007-06-01 11:48:17 +08:00
* Removes an entry , either by actually removing it or by marking it .
2007-01-26 22:52:10 +08:00
*/
2007-01-29 14:02:19 +08:00
void phar_entry_remove ( phar_entry_data * idata , char * * error TSRMLS_DC ) /* { { { */
2007-01-26 22:52:10 +08:00
{
2007-08-17 12:47:50 +08:00
phar_archive_data * phar ;
phar = idata - > phar ;
2008-08-01 21:45:06 +08:00
2007-01-27 23:31:24 +08:00
if ( idata - > internal_file - > fp_refcount < 2 ) {
2008-01-28 16:52:08 +08:00
if ( idata - > fp & & idata - > fp ! = idata - > phar - > fp & & idata - > fp ! = idata - > phar - > ufp & & idata - > fp ! = idata - > internal_file - > fp ) {
2007-01-27 23:31:24 +08:00
php_stream_close ( idata - > fp ) ;
2007-01-26 22:52:10 +08:00
}
2007-01-28 01:27:48 +08:00
zend_hash_del ( & idata - > phar - > manifest , idata - > internal_file - > filename , idata - > internal_file - > filename_len ) ;
2007-01-28 06:23:52 +08:00
idata - > phar - > refcount - - ;
2007-01-26 22:52:10 +08:00
efree ( idata ) ;
2007-01-27 23:31:24 +08:00
} else {
idata - > internal_file - > is_deleted = 1 ;
phar_entry_delref ( idata TSRMLS_CC ) ;
2007-01-26 22:52:10 +08:00
}
2008-08-01 21:45:06 +08:00
2007-08-17 12:47:50 +08:00
if ( ! phar - > donotflush ) {
2008-02-25 06:29:06 +08:00
phar_flush ( phar , 0 , 0 , 0 , error TSRMLS_CC ) ;
2007-08-17 12:47:50 +08:00
}
2005-12-05 04:35:38 +08:00
}
2006-01-04 23:50:45 +08:00
/* }}} */
2005-12-05 04:35:38 +08:00
2006-01-04 10:26:15 +08:00
# define MAPPHAR_ALLOC_FAIL(msg) \
2008-05-07 05:14:53 +08:00
if ( fp ) { \
php_stream_close ( fp ) ; \
} \
2007-01-29 14:02:19 +08:00
if ( error ) { \
spprintf ( error , 0 , msg , fname ) ; \
} \
2006-01-04 10:26:15 +08:00
return FAILURE ;
# define MAPPHAR_FAIL(msg) \
efree ( savebuf ) ; \
2007-01-09 08:27:13 +08:00
if ( mydata ) { \
2007-02-03 12:04:18 +08:00
phar_destroy_phar_data ( mydata TSRMLS_CC ) ; \
2007-01-09 08:27:13 +08:00
} \
if ( signature ) { \
2008-08-01 21:45:06 +08:00
pefree ( signature , PHAR_G ( persist ) ) ; \
2007-01-09 08:27:13 +08:00
} \
2006-01-04 10:26:15 +08:00
MAPPHAR_ALLOC_FAIL ( msg )
2006-01-05 08:39:31 +08:00
# ifdef WORDS_BIGENDIAN
2006-01-10 14:46:17 +08:00
# define PHAR_GET_32(buffer, var) \
2007-02-07 05:43:46 +08:00
var = ( ( ( ( unsigned char * ) ( buffer ) ) [ 3 ] ) < < 24 ) \
| ( ( ( ( unsigned char * ) ( buffer ) ) [ 2 ] ) < < 16 ) \
| ( ( ( ( unsigned char * ) ( buffer ) ) [ 1 ] ) < < 8 ) \
| ( ( ( unsigned char * ) ( buffer ) ) [ 0 ] ) ; \
2007-01-21 14:30:55 +08:00
( buffer ) + = 4
# define PHAR_GET_16(buffer, var) \
2007-02-07 05:43:46 +08:00
var = ( ( ( ( unsigned char * ) ( buffer ) ) [ 1 ] ) < < 8 ) \
| ( ( ( unsigned char * ) ( buffer ) ) [ 0 ] ) ; \
2007-01-21 14:30:55 +08:00
( buffer ) + = 2
2008-04-16 03:16:47 +08:00
# define PHAR_ZIP_32(buffer) ((((unsigned char*)(buffer))[3]) << 24) \
| ( ( ( ( unsigned char * ) ( buffer ) ) [ 2 ] ) < < 16 ) \
| ( ( ( ( unsigned char * ) ( buffer ) ) [ 1 ] ) < < 8 ) \
| ( ( ( unsigned char * ) ( buffer ) ) [ 0 ] )
# define PHAR_ZIP_16(buffer) ((((unsigned char*)(buffer))[1]) << 8) \
| ( ( ( unsigned char * ) ( buffer ) ) [ 0 ] )
2006-01-05 08:39:31 +08:00
# else
2006-01-10 14:46:17 +08:00
# define PHAR_GET_32(buffer, var) \
2006-01-06 06:24:41 +08:00
var = * ( php_uint32 * ) ( buffer ) ; \
2006-01-05 08:39:31 +08:00
buffer + = 4
2007-01-21 14:30:55 +08:00
# define PHAR_GET_16(buffer, var) \
var = * ( php_uint16 * ) ( buffer ) ; \
buffer + = 2
2008-04-16 03:16:47 +08:00
# define PHAR_ZIP_32(buffer) buffer
# define PHAR_ZIP_16(buffer) buffer
2006-01-05 08:39:31 +08:00
# endif
2007-01-02 08:04:30 +08:00
/**
2007-01-11 09:04:47 +08:00
* Open an already loaded phar
*/
2008-05-31 06:39:33 +08:00
int phar_open_parsed_phar ( char * fname , int fname_len , char * alias , int alias_len , int is_data , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2007-01-11 09:04:47 +08:00
{
phar_archive_data * phar ;
2007-12-15 02:42:57 +08:00
# ifdef PHP_WIN32
char * unixfname ;
# endif
2007-01-11 09:04:47 +08:00
2007-01-29 15:59:19 +08:00
if ( error ) {
* error = NULL ;
}
2007-12-15 02:42:57 +08:00
# ifdef PHP_WIN32
unixfname = estrndup ( fname , fname_len ) ;
phar_unixify_path_separators ( unixfname , fname_len ) ;
2008-08-01 21:45:06 +08:00
2007-12-15 02:42:57 +08:00
if ( SUCCESS = = phar_get_archive ( & phar , unixfname , fname_len , alias , alias_len , error TSRMLS_CC )
& & ( ( alias & & fname_len = = phar - > fname_len
& & ! strncmp ( unixfname , phar - > fname , fname_len ) ) | | ! alias )
) {
2008-03-03 16:41:15 +08:00
phar_entry_info * stub ;
2007-12-15 02:42:57 +08:00
efree ( unixfname ) ;
# else
2007-01-29 14:02:19 +08:00
if ( SUCCESS = = phar_get_archive ( & phar , fname , fname_len , alias , alias_len , error TSRMLS_CC )
2007-11-20 13:34:35 +08:00
& & ( ( alias & & fname_len = = phar - > fname_len
& & ! strncmp ( fname , phar - > fname , fname_len ) ) | | ! alias )
2007-01-26 22:52:10 +08:00
) {
2008-03-03 16:41:15 +08:00
phar_entry_info * stub ;
2007-12-15 02:42:57 +08:00
# endif
2007-11-20 13:34:35 +08:00
/* logic above is as follows:
If an explicit alias was requested , ensure the filename passed in
matches the phar ' s filename .
If no alias was passed in , then it can match either and be valid
*/
2008-03-03 16:41:15 +08:00
if ( ! is_data ) {
/* prevent any ".phar" without a stub getting through */
2008-05-08 08:49:37 +08:00
if ( ! phar - > halt_offset & & ! phar - > is_brandnew & & ( phar - > is_tar | | phar - > is_zip ) ) {
2008-03-23 14:59:59 +08:00
if ( PHAR_G ( readonly ) & & FAILURE = = zend_hash_find ( & ( phar - > manifest ) , " .phar/stub.php " , sizeof ( " .phar/stub.php " ) - 1 , ( void * * ) & stub ) ) {
2008-05-08 01:24:22 +08:00
if ( error ) {
spprintf ( error , 0 , " '%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive " , fname ) ;
}
2008-03-03 16:41:15 +08:00
return FAILURE ;
}
}
}
2008-08-01 21:45:06 +08:00
2007-01-11 09:04:47 +08:00
if ( pphar ) {
* pphar = phar ;
}
2008-08-01 21:45:06 +08:00
2007-01-11 09:04:47 +08:00
return SUCCESS ;
} else {
2007-12-15 02:42:57 +08:00
# ifdef PHP_WIN32
efree ( unixfname ) ;
# endif
2007-01-11 09:04:47 +08:00
if ( pphar ) {
* pphar = NULL ;
}
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
if ( phar & & error & & ! ( options & REPORT_ERRORS ) ) {
efree ( error ) ;
2007-01-11 09:04:47 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-11 09:04:47 +08:00
return FAILURE ;
}
}
/* }}}*/
2007-01-21 14:30:55 +08:00
/**
* Parse out metadata from the manifest for a single file
*
* Meta - data is in this format :
2007-01-22 04:12:50 +08:00
* [ len32 ] [ data . . . ]
2007-01-21 14:30:55 +08:00
*
2007-01-22 04:12:50 +08:00
* data is the serialized zval
2007-01-21 14:30:55 +08:00
*/
2008-04-16 12:01:33 +08:00
int phar_parse_metadata ( char * * buffer , zval * * metadata , int zip_metadata_len TSRMLS_DC ) /* { { { */
2007-01-21 14:30:55 +08:00
{
2007-01-22 04:12:50 +08:00
const unsigned char * p ;
php_uint32 buf_len ;
php_unserialize_data_t var_hash ;
2008-04-16 12:01:33 +08:00
if ( ! zip_metadata_len ) {
2008-01-01 06:42:40 +08:00
PHAR_GET_32 ( * buffer , buf_len ) ;
} else {
2008-04-16 12:01:33 +08:00
buf_len = zip_metadata_len ;
2008-01-01 06:42:40 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-22 04:12:50 +08:00
if ( buf_len ) {
2008-08-01 21:45:06 +08:00
ALLOC_ZVAL ( * metadata ) ;
INIT_ZVAL ( * * metadata ) ;
2007-01-22 04:12:50 +08:00
p = ( const unsigned char * ) * buffer ;
PHP_VAR_UNSERIALIZE_INIT ( var_hash ) ;
2008-08-01 21:45:06 +08:00
if ( ! php_var_unserialize ( metadata , & p , p + buf_len , & var_hash TSRMLS_CC ) ) {
2007-01-22 04:12:50 +08:00
PHP_VAR_UNSERIALIZE_DESTROY ( var_hash ) ;
zval_ptr_dtor ( metadata ) ;
* metadata = NULL ;
2007-01-21 14:30:55 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2007-01-22 04:12:50 +08:00
PHP_VAR_UNSERIALIZE_DESTROY ( var_hash ) ;
2008-08-01 21:45:06 +08:00
if ( PHAR_G ( persist ) ) {
/* lazy init metadata */
zval_ptr_dtor ( metadata ) ;
* metadata = ( zval * ) pemalloc ( buf_len , 1 ) ;
memcpy ( * metadata , * buffer , buf_len ) ;
2008-10-13 03:40:30 +08:00
* buffer + = buf_len ;
2008-08-01 21:45:06 +08:00
return SUCCESS ;
}
2007-02-07 07:19:10 +08:00
} else {
* metadata = NULL ;
2007-01-22 04:12:50 +08:00
}
2008-08-01 21:45:06 +08:00
2008-04-16 12:15:08 +08:00
if ( ! zip_metadata_len ) {
* buffer + = buf_len ;
}
2008-08-01 21:45:06 +08:00
2007-01-21 14:30:55 +08:00
return SUCCESS ;
}
/* }}}*/
2007-01-11 09:04:47 +08:00
/**
* Does not check for a previously opened phar in the cache .
*
2008-08-01 21:45:06 +08:00
* Parse a new one and add it to the cache , returning either SUCCESS or
2007-01-11 09:04:47 +08:00
* FAILURE , and setting pphar to the pointer to the manifest entry
2007-01-02 08:04:30 +08:00
*
2008-05-31 06:39:33 +08:00
* This is used by phar_open_from_filename to process the manifest , but can be called
2007-01-02 08:04:30 +08:00
* directly .
*/
2008-08-01 21:45:06 +08:00
static int phar_parse_pharfile ( php_stream * fp , char * fname , int fname_len , char * alias , int alias_len , long halt_offset , phar_archive_data * * pphar , php_uint32 compression , char * * error TSRMLS_DC ) /* { { { */
2005-12-05 04:35:38 +08:00
{
2006-01-10 14:46:17 +08:00
char b32 [ 4 ] , * buffer , * endbuffer , * savebuf ;
2007-01-09 08:27:13 +08:00
phar_archive_data * mydata = NULL ;
2006-02-28 09:36:30 +08:00
phar_entry_info entry ;
2007-01-14 00:17:04 +08:00
php_uint32 manifest_len , manifest_count , manifest_flags , manifest_index , tmp_len , sig_flags ;
php_uint16 manifest_ver ;
2006-01-10 14:46:17 +08:00
long offset ;
2008-02-11 14:46:44 +08:00
int register_alias , sig_len , temp_alias = 0 ;
2007-01-09 08:27:13 +08:00
char * signature = NULL ;
2005-12-05 04:35:38 +08:00
2007-01-04 13:32:45 +08:00
if ( pphar ) {
2006-02-28 09:36:30 +08:00
* pphar = NULL ;
}
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
* error = NULL ;
}
2006-02-28 09:36:30 +08:00
2005-12-08 15:38:44 +08:00
/* check for ?>\n and increment accordingly */
2005-12-08 15:08:49 +08:00
if ( - 1 = = php_stream_seek ( fp , halt_offset , SEEK_SET ) ) {
2005-12-08 15:34:16 +08:00
MAPPHAR_ALLOC_FAIL ( " cannot seek to __HALT_COMPILER(); location in phar \" %s \" " )
2005-12-08 14:46:02 +08:00
}
2006-01-10 14:46:17 +08:00
buffer = b32 ;
2008-08-01 21:45:06 +08:00
2005-12-07 14:39:03 +08:00
if ( 3 ! = php_stream_read ( fp , buffer , 3 ) ) {
2007-06-01 11:48:17 +08:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest at stub end) " )
2005-12-05 04:35:38 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-29 05:26:54 +08:00
if ( ( * buffer = = ' ' | | * buffer = = ' \n ' ) & & * ( buffer + 1 ) = = ' ? ' & & * ( buffer + 2 ) = = ' > ' ) {
2005-12-05 04:35:38 +08:00
int nextchar ;
2005-12-07 09:18:54 +08:00
halt_offset + = 3 ;
2005-12-07 14:39:03 +08:00
if ( EOF = = ( nextchar = php_stream_getc ( fp ) ) ) {
2007-06-01 11:48:17 +08:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest at stub end) " )
2005-12-07 14:39:03 +08:00
}
2008-08-01 21:45:06 +08:00
2005-12-05 04:35:38 +08:00
if ( ( char ) nextchar = = ' \r ' ) {
2007-05-28 00:54:37 +08:00
/* if we have an \r we require an \n as well */
if ( EOF = = ( nextchar = php_stream_getc ( fp ) ) | | ( char ) nextchar ! = ' \n ' ) {
2007-06-01 11:48:17 +08:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest at stub end) " )
2005-12-07 14:39:03 +08:00
}
2008-03-23 06:11:49 +08:00
+ + halt_offset ;
2005-12-05 04:35:38 +08:00
}
2008-08-01 21:45:06 +08:00
2005-12-05 04:35:38 +08:00
if ( ( char ) nextchar = = ' \n ' ) {
2008-03-23 06:11:49 +08:00
+ + halt_offset ;
2005-12-05 04:35:38 +08:00
}
}
2008-08-01 21:45:06 +08:00
2005-12-08 15:38:44 +08:00
/* make sure we are at the right location to read the manifest */
2005-12-08 15:08:49 +08:00
if ( - 1 = = php_stream_seek ( fp , halt_offset , SEEK_SET ) ) {
2006-01-10 14:46:17 +08:00
MAPPHAR_ALLOC_FAIL ( " cannot seek to __HALT_COMPILER(); location in phar \" %s \" " )
2005-12-08 15:08:49 +08:00
}
2005-12-05 04:35:38 +08:00
2005-12-08 15:38:44 +08:00
/* read in manifest */
2006-01-10 14:46:17 +08:00
buffer = b32 ;
2008-08-01 21:45:06 +08:00
2005-12-07 14:39:03 +08:00
if ( 4 ! = php_stream_read ( fp , buffer , 4 ) ) {
2007-05-27 23:47:52 +08:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest at manifest length) " )
2005-12-07 14:39:03 +08:00
}
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
PHAR_GET_32 ( buffer , manifest_len ) ;
2008-08-01 21:45:06 +08:00
2008-02-08 13:56:26 +08:00
if ( manifest_len > 1048576 * 100 ) {
/* prevent serious memory issues by limiting manifest to at most 100 MB in length */
MAPPHAR_ALLOC_FAIL ( " manifest cannot be larger than 100 MB in phar \" %s \" " )
2005-12-07 14:39:03 +08:00
}
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
buffer = ( char * ) emalloc ( manifest_len ) ;
2005-12-05 04:35:38 +08:00
savebuf = buffer ;
endbuffer = buffer + manifest_len ;
2008-08-01 21:45:06 +08:00
2007-05-27 23:47:52 +08:00
if ( manifest_len < 10 | | manifest_len ! = php_stream_read ( fp , buffer , manifest_len ) ) {
2006-01-11 08:50:07 +08:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest header) " )
}
2006-01-10 14:46:17 +08:00
2005-12-08 15:38:44 +08:00
/* extract the number of entries */
2006-01-10 14:46:17 +08:00
PHAR_GET_32 ( buffer , manifest_count ) ;
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
if ( manifest_count = = 0 ) {
MAPPHAR_FAIL ( " in phar \" %s \" , manifest claims to have zero entries. Phars must have at least 1 entry " ) ;
2006-01-05 08:39:31 +08:00
}
2006-01-10 14:46:17 +08:00
2007-01-14 00:17:04 +08:00
/* extract API version, lowest nibble currently unused */
2008-08-01 21:45:06 +08:00
manifest_ver = ( ( ( unsigned char ) buffer [ 0 ] ) < < 8 )
+ ( ( unsigned char ) buffer [ 1 ] ) ;
2006-01-10 14:46:17 +08:00
buffer + = 2 ;
2008-08-01 21:45:06 +08:00
2007-01-14 00:44:54 +08:00
if ( ( manifest_ver & PHAR_API_VER_MASK ) < PHAR_API_MIN_READ ) {
2006-01-10 14:46:17 +08:00
efree ( savebuf ) ;
2007-01-11 09:04:47 +08:00
php_stream_close ( fp ) ;
2007-01-29 14:02:19 +08:00
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" is API version %1.u.%1.u.%1.u, and cannot be processed " , fname , manifest_ver > > 12 , ( manifest_ver > > 8 ) & 0xF , ( manifest_ver > > 4 ) & 0x0F ) ;
}
2006-01-10 14:46:17 +08:00
return FAILURE ;
}
2007-01-09 07:03:41 +08:00
2007-01-14 00:17:04 +08:00
PHAR_GET_32 ( buffer , manifest_flags ) ;
2008-01-09 15:09:04 +08:00
manifest_flags & = ~ PHAR_HDR_COMPRESSION_MASK ;
manifest_flags & = ~ PHAR_FILE_COMPRESSION_MASK ;
/* remember whether this entire phar was compressed with gz/bzip2 */
manifest_flags | = compression ;
2007-01-14 00:17:04 +08:00
2007-01-20 13:28:48 +08:00
/* The lowest nibble contains the phar wide flags. The compression flags can */
2006-01-13 05:16:29 +08:00
/* be ignored on reading because it is being generated anyways. */
2007-01-14 00:17:04 +08:00
if ( manifest_flags & PHAR_HDR_SIGNATURE ) {
2007-01-09 07:03:41 +08:00
char sig_buf [ 8 ] , * sig_ptr = sig_buf ;
off_t read_len ;
2008-08-01 21:45:06 +08:00
size_t end_of_phar ;
2007-01-09 07:03:41 +08:00
if ( - 1 = = php_stream_seek ( fp , - 8 , SEEK_END )
| | ( read_len = php_stream_tell ( fp ) ) < 20
2008-08-01 21:45:06 +08:00
| | 8 ! = php_stream_read ( fp , sig_buf , 8 )
2007-01-09 07:03:41 +08:00
| | memcmp ( sig_buf + 4 , " GBMB " , 4 ) ) {
efree ( savebuf ) ;
2007-01-11 09:04:47 +08:00
php_stream_close ( fp ) ;
2007-01-29 14:02:19 +08:00
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
2007-01-09 07:03:41 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2007-01-09 07:03:41 +08:00
PHAR_GET_32 ( sig_ptr , sig_flags ) ;
2008-08-01 21:45:06 +08:00
2007-01-09 07:03:41 +08:00
switch ( sig_flags ) {
2008-08-01 21:45:06 +08:00
case PHAR_SIG_OPENSSL : {
php_uint32 signature_len ;
char * sig ;
off_t whence ;
/* we store the signature followed by the signature length */
if ( - 1 = = php_stream_seek ( fp , - 12 , SEEK_CUR )
| | 4 ! = php_stream_read ( fp , sig_buf , 4 ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" openssl signature length could not be read " , fname ) ;
}
return FAILURE ;
2007-03-26 05:43:49 +08:00
}
2008-08-01 21:45:06 +08:00
sig_ptr = sig_buf ;
PHAR_GET_32 ( sig_ptr , signature_len ) ;
sig = ( char * ) emalloc ( signature_len ) ;
whence = signature_len + 4 ;
whence = - whence ;
if ( - 1 = = php_stream_seek ( fp , whence , SEEK_CUR )
| | ! ( end_of_phar = php_stream_tell ( fp ) )
| | signature_len ! = php_stream_read ( fp , sig , signature_len ) ) {
efree ( savebuf ) ;
efree ( sig ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" openssl signature could not be read " , fname ) ;
}
return FAILURE ;
2007-03-26 05:43:49 +08:00
}
2008-08-01 21:45:06 +08:00
if ( FAILURE = = phar_verify_signature ( fp , end_of_phar , PHAR_SIG_OPENSSL , sig , signature_len , fname , & signature , & sig_len , error TSRMLS_CC ) ) {
efree ( savebuf ) ;
efree ( sig ) ;
php_stream_close ( fp ) ;
if ( error ) {
char * save = * error ;
spprintf ( error , 0 , " phar \" %s \" openssl signature could not be verified: %s " , fname , * error ) ;
efree ( save ) ;
}
return FAILURE ;
}
efree ( sig ) ;
}
2007-03-26 05:43:49 +08:00
break ;
2008-10-09 08:51:27 +08:00
# if PHAR_HASH_OK
2008-08-01 21:45:06 +08:00
case PHAR_SIG_SHA512 : {
unsigned char digest [ 64 ] ;
2007-03-26 05:43:49 +08:00
2008-08-01 21:45:06 +08:00
php_stream_seek ( fp , - ( 8 + 64 ) , SEEK_END ) ;
read_len = php_stream_tell ( fp ) ;
if ( php_stream_read ( fp , ( char * ) digest , sizeof ( digest ) ) ! = sizeof ( digest ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
return FAILURE ;
2007-03-26 05:43:49 +08:00
}
2008-08-01 21:45:06 +08:00
if ( FAILURE = = phar_verify_signature ( fp , read_len , PHAR_SIG_SHA512 , ( char * ) digest , 64 , fname , & signature , & sig_len , error TSRMLS_CC ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
char * save = * error ;
spprintf ( error , 0 , " phar \" %s \" SHA512 signature could not be verified: %s " , fname , * error ) ;
efree ( save ) ;
}
return FAILURE ;
2007-03-26 05:43:49 +08:00
}
2008-08-01 21:45:06 +08:00
break ;
2007-03-26 05:43:49 +08:00
}
2008-08-01 21:45:06 +08:00
case PHAR_SIG_SHA256 : {
unsigned char digest [ 32 ] ;
2007-03-26 05:43:49 +08:00
2008-08-01 21:45:06 +08:00
php_stream_seek ( fp , - ( 8 + 32 ) , SEEK_END ) ;
read_len = php_stream_tell ( fp ) ;
if ( php_stream_read ( fp , ( char * ) digest , sizeof ( digest ) ) ! = sizeof ( digest ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
return FAILURE ;
2007-01-09 07:03:41 +08:00
}
2008-08-01 21:45:06 +08:00
if ( FAILURE = = phar_verify_signature ( fp , read_len , PHAR_SIG_SHA256 , ( char * ) digest , 32 , fname , & signature , & sig_len , error TSRMLS_CC ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
char * save = * error ;
spprintf ( error , 0 , " phar \" %s \" SHA256 signature could not be verified: %s " , fname , * error ) ;
efree ( save ) ;
}
return FAILURE ;
}
break ;
}
# else
case PHAR_SIG_SHA512 :
case PHAR_SIG_SHA256 :
2007-01-09 07:03:41 +08:00
efree ( savebuf ) ;
2007-01-11 09:04:47 +08:00
php_stream_close ( fp ) ;
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-08-01 21:45:06 +08:00
spprintf ( error , 0 , " phar \" %s \" has a unsupported signature " , fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-09 07:03:41 +08:00
return FAILURE ;
2008-08-01 21:45:06 +08:00
# endif
case PHAR_SIG_SHA1 : {
unsigned char digest [ 20 ] ;
2006-01-10 14:46:17 +08:00
2008-08-01 21:45:06 +08:00
php_stream_seek ( fp , - ( 8 + 20 ) , SEEK_END ) ;
read_len = php_stream_tell ( fp ) ;
2007-01-09 07:03:41 +08:00
2008-08-01 21:45:06 +08:00
if ( php_stream_read ( fp , ( char * ) digest , sizeof ( digest ) ) ! = sizeof ( digest ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
return FAILURE ;
2007-01-09 07:03:41 +08:00
}
2008-08-01 21:45:06 +08:00
if ( FAILURE = = phar_verify_signature ( fp , read_len , PHAR_SIG_SHA1 , ( char * ) digest , 20 , fname , & signature , & sig_len , error TSRMLS_CC ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
char * save = * error ;
spprintf ( error , 0 , " phar \" %s \" SHA1 signature could not be verified: %s " , fname , * error ) ;
efree ( save ) ;
}
return FAILURE ;
}
break ;
2007-01-09 07:03:41 +08:00
}
2008-08-01 21:45:06 +08:00
case PHAR_SIG_MD5 : {
unsigned char digest [ 16 ] ;
php_stream_seek ( fp , - ( 8 + 16 ) , SEEK_END ) ;
read_len = php_stream_tell ( fp ) ;
if ( php_stream_read ( fp , ( char * ) digest , sizeof ( digest ) ) ! = sizeof ( digest ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
return FAILURE ;
}
2007-01-09 07:03:41 +08:00
2008-08-01 21:45:06 +08:00
if ( FAILURE = = phar_verify_signature ( fp , read_len , PHAR_SIG_MD5 , ( char * ) digest , 16 , fname , & signature , & sig_len , error TSRMLS_CC ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
char * save = * error ;
spprintf ( error , 0 , " phar \" %s \" MD5 signature could not be verified: %s " , fname , * error ) ;
efree ( save ) ;
}
return FAILURE ;
}
break ;
}
default :
2007-01-09 07:03:41 +08:00
efree ( savebuf ) ;
2007-01-11 09:04:47 +08:00
php_stream_close ( fp ) ;
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-08-01 21:45:06 +08:00
spprintf ( error , 0 , " phar \" %s \" has a broken or unsupported signature " , fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-09 07:03:41 +08:00
return FAILURE ;
}
} else if ( PHAR_G ( require_hash ) ) {
efree ( savebuf ) ;
2007-01-11 09:04:47 +08:00
php_stream_close ( fp ) ;
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" does not have a signature " , fname ) ;
}
2007-01-09 07:03:41 +08:00
return FAILURE ;
2007-01-09 08:27:13 +08:00
} else {
sig_flags = 0 ;
sig_len = 0 ;
2007-01-09 07:03:41 +08:00
}
2006-01-10 14:46:17 +08:00
/* extract alias */
PHAR_GET_32 ( buffer , tmp_len ) ;
2008-08-01 21:45:06 +08:00
2006-01-11 08:50:07 +08:00
if ( buffer + tmp_len > endbuffer ) {
2006-01-10 14:46:17 +08:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (buffer overrun) " ) ;
}
2008-08-01 21:45:06 +08:00
2006-01-11 08:50:07 +08:00
if ( manifest_len < 10 + tmp_len ) {
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest header) " )
}
2008-08-01 21:45:06 +08:00
2006-01-11 08:50:07 +08:00
/* tmp_len = 0 says alias length is 0, which means the alias is not stored in the phar */
2006-01-10 14:46:17 +08:00
if ( tmp_len ) {
/* if the alias is stored we enforce it (implicit overrides explicit) */
2007-02-06 04:34:23 +08:00
if ( alias & & alias_len & & ( alias_len ! = ( int ) tmp_len | | strncmp ( alias , buffer , tmp_len ) ) )
2006-01-10 14:46:17 +08:00
{
buffer [ tmp_len ] = ' \0 ' ;
2007-01-11 09:04:47 +08:00
php_stream_close ( fp ) ;
2008-08-01 21:45:06 +08:00
2007-01-09 08:27:13 +08:00
if ( signature ) {
efree ( signature ) ;
}
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
spprintf ( error , 0 , " cannot load phar \" %s \" with implicit alias \" %s \" under different alias \" %s \" " , fname , buffer , alias ) ;
}
2008-08-01 21:45:06 +08:00
2008-05-07 05:14:53 +08:00
efree ( savebuf ) ;
2006-01-10 14:46:17 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
alias_len = tmp_len ;
alias = buffer ;
buffer + = tmp_len ;
2006-01-12 05:19:46 +08:00
register_alias = 1 ;
2006-01-10 14:46:17 +08:00
} else if ( ! alias_len | | ! alias ) {
/* if we neither have an explicit nor an implicit alias, we use the filename */
2006-01-12 05:19:46 +08:00
alias = NULL ;
alias_len = 0 ;
register_alias = 0 ;
2008-02-11 14:46:44 +08:00
} else if ( alias_len ) {
2006-01-12 05:19:46 +08:00
register_alias = 1 ;
2008-02-11 14:46:44 +08:00
temp_alias = 1 ;
2006-01-10 14:46:17 +08:00
}
2008-05-15 05:27:31 +08:00
2006-01-11 08:50:07 +08:00
/* we have 5 32-bit items plus 1 byte at least */
if ( manifest_count > ( ( manifest_len - 10 - tmp_len ) / ( 5 * 4 + 1 ) ) ) {
/* prevent serious memory issues */
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (too many manifest entries for size of manifest) " )
}
2008-08-01 21:45:06 +08:00
mydata = pecalloc ( 1 , sizeof ( phar_archive_data ) , PHAR_G ( persist ) ) ;
mydata - > is_persistent = PHAR_G ( persist ) ;
2007-02-07 07:19:10 +08:00
2007-03-22 01:14:46 +08:00
/* check whether we have meta data, zero check works regardless of byte order */
2008-08-01 21:45:06 +08:00
if ( mydata - > is_persistent ) {
PHAR_GET_32 ( buffer , mydata - > metadata_len ) ;
if ( phar_parse_metadata ( & buffer , & mydata - > metadata , mydata - > metadata_len TSRMLS_CC ) = = FAILURE ) {
MAPPHAR_FAIL ( " unable to read phar metadata in .phar file \" %s \" " ) ;
}
} else {
if ( phar_parse_metadata ( & buffer , & mydata - > metadata , 0 TSRMLS_CC ) = = FAILURE ) {
MAPPHAR_FAIL ( " unable to read phar metadata in .phar file \" %s \" " ) ;
}
2007-01-29 11:59:55 +08:00
}
2008-01-01 06:42:40 +08:00
2007-01-29 11:59:55 +08:00
/* set up our manifest */
2008-08-01 21:45:06 +08:00
zend_hash_init ( & mydata - > manifest , manifest_count ,
zend_get_hash_value , destroy_phar_manifest_entry , ( zend_bool ) mydata - > is_persistent ) ;
zend_hash_init ( & mydata - > mounted_dirs , 5 ,
zend_get_hash_value , NULL , ( zend_bool ) mydata - > is_persistent ) ;
zend_hash_init ( & mydata - > virtual_dirs , manifest_count * 2 ,
zend_get_hash_value , NULL , ( zend_bool ) mydata - > is_persistent ) ;
mydata - > fname = pestrndup ( fname , fname_len , mydata - > is_persistent ) ;
# ifdef PHP_WIN32
phar_unixify_path_separators ( mydata - > fname , fname_len ) ;
# endif
mydata - > fname_len = fname_len ;
2008-01-28 16:52:08 +08:00
offset = halt_offset + manifest_len + 4 ;
memset ( & entry , 0 , sizeof ( phar_entry_info ) ) ;
entry . phar = mydata ;
entry . fp_type = PHAR_FP ;
2008-08-01 21:45:06 +08:00
entry . is_persistent = mydata - > is_persistent ;
2008-01-28 16:52:08 +08:00
2008-03-23 06:11:49 +08:00
for ( manifest_index = 0 ; manifest_index < manifest_count ; + + manifest_index ) {
2006-01-05 08:39:31 +08:00
if ( buffer + 4 > endbuffer ) {
2006-01-11 08:50:07 +08:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest entry) " )
2005-12-07 14:39:03 +08:00
}
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
PHAR_GET_32 ( buffer , entry . filename_len ) ;
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
if ( entry . filename_len = = 0 ) {
MAPPHAR_FAIL ( " zero-length filename encountered in phar \" %s \" " ) ;
}
2008-08-01 21:45:06 +08:00
if ( entry . is_persistent ) {
entry . manifest_pos = manifest_index ;
}
2007-01-14 00:17:04 +08:00
if ( buffer + entry . filename_len + 20 > endbuffer ) {
2006-01-11 08:50:07 +08:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest entry) " ) ;
2006-01-05 08:39:31 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-20 02:30:30 +08:00
if ( ( manifest_ver & PHAR_API_VER_MASK ) > = PHAR_API_MIN_DIR & & buffer [ entry . filename_len - 1 ] = = ' / ' ) {
2008-01-09 06:14:16 +08:00
entry . is_dir = 1 ;
} else {
entry . is_dir = 0 ;
}
2008-08-01 21:45:06 +08:00
phar_add_virtual_dirs ( mydata , buffer , entry . filename_len TSRMLS_CC ) ;
entry . filename = pestrndup ( buffer , entry . filename_len , entry . is_persistent ) ;
2008-01-28 16:52:08 +08:00
buffer + = entry . filename_len ;
2006-01-10 14:46:17 +08:00
PHAR_GET_32 ( buffer , entry . uncompressed_filesize ) ;
PHAR_GET_32 ( buffer , entry . timestamp ) ;
2008-08-01 21:45:06 +08:00
2008-01-28 22:39:17 +08:00
if ( offset = = halt_offset + ( int ) manifest_len + 4 ) {
2006-03-09 04:07:25 +08:00
mydata - > min_timestamp = entry . timestamp ;
mydata - > max_timestamp = entry . timestamp ;
2006-03-03 06:44:39 +08:00
} else {
2006-03-09 04:07:25 +08:00
if ( mydata - > min_timestamp > entry . timestamp ) {
mydata - > min_timestamp = entry . timestamp ;
} else if ( mydata - > max_timestamp < entry . timestamp ) {
mydata - > max_timestamp = entry . timestamp ;
2006-03-03 06:44:39 +08:00
}
}
2008-08-01 21:45:06 +08:00
2006-01-10 14:46:17 +08:00
PHAR_GET_32 ( buffer , entry . compressed_filesize ) ;
PHAR_GET_32 ( buffer , entry . crc32 ) ;
2007-01-14 00:17:04 +08:00
PHAR_GET_32 ( buffer , entry . flags ) ;
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( entry . is_dir ) {
entry . filename_len - - ;
entry . flags | = PHAR_ENT_PERM_DEF_DIR ;
}
2008-08-01 21:45:06 +08:00
if ( entry . is_persistent ) {
2008-10-26 13:49:24 +08:00
PHAR_GET_32 ( buffer , entry . metadata_len ) ;
if ( ! entry . metadata_len ) buffer - = 4 ;
if ( phar_parse_metadata ( & buffer , & entry . metadata , entry . metadata_len TSRMLS_CC ) = = FAILURE ) {
2008-08-01 21:45:06 +08:00
pefree ( entry . filename , entry . is_persistent ) ;
MAPPHAR_FAIL ( " unable to read file metadata in .phar file \" %s \" " ) ;
}
} else {
if ( phar_parse_metadata ( & buffer , & entry . metadata , 0 TSRMLS_CC ) = = FAILURE ) {
pefree ( entry . filename , entry . is_persistent ) ;
MAPPHAR_FAIL ( " unable to read file metadata in .phar file \" %s \" " ) ;
}
2007-01-21 14:30:55 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
entry . offset = entry . offset_abs = offset ;
2006-01-10 14:46:17 +08:00
offset + = entry . compressed_filesize ;
2008-08-01 21:45:06 +08:00
2006-01-13 05:16:29 +08:00
switch ( entry . flags & PHAR_ENT_COMPRESSION_MASK ) {
2008-08-01 21:45:06 +08:00
case PHAR_ENT_COMPRESSED_GZ :
if ( ! PHAR_G ( has_zlib ) ) {
if ( entry . metadata ) {
if ( entry . is_persistent ) {
free ( entry . metadata ) ;
} else {
zval_ptr_dtor ( & entry . metadata ) ;
}
}
pefree ( entry . filename , entry . is_persistent ) ;
MAPPHAR_FAIL ( " zlib extension is required for gz compressed .phar file \" %s \" " ) ;
2007-11-25 13:04:40 +08:00
}
2008-08-01 21:45:06 +08:00
break ;
case PHAR_ENT_COMPRESSED_BZ2 :
if ( ! PHAR_G ( has_bz2 ) ) {
if ( entry . metadata ) {
if ( entry . is_persistent ) {
free ( entry . metadata ) ;
} else {
zval_ptr_dtor ( & entry . metadata ) ;
}
}
pefree ( entry . filename , entry . is_persistent ) ;
MAPPHAR_FAIL ( " bz2 extension is required for bzip2 compressed .phar file \" %s \" " ) ;
2007-11-25 13:04:40 +08:00
}
2008-08-01 21:45:06 +08:00
break ;
default :
if ( entry . uncompressed_filesize ! = entry . compressed_filesize ) {
if ( entry . metadata ) {
if ( entry . is_persistent ) {
free ( entry . metadata ) ;
} else {
zval_ptr_dtor ( & entry . metadata ) ;
}
}
pefree ( entry . filename , entry . is_persistent ) ;
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (compressed and uncompressed size does not match for uncompressed entry) " ) ;
2007-02-03 12:04:18 +08:00
}
2008-08-01 21:45:06 +08:00
break ;
2006-01-06 06:24:41 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-14 00:17:04 +08:00
manifest_flags | = ( entry . flags & PHAR_ENT_COMPRESSION_MASK ) ;
2007-08-30 10:30:16 +08:00
/* if signature matched, no need to check CRC32 for each file */
entry . is_crc_checked = ( manifest_flags & PHAR_HDR_SIGNATURE ? 1 : 0 ) ;
2008-08-01 21:45:06 +08:00
phar_set_inode ( & entry TSRMLS_CC ) ;
2006-03-09 04:07:25 +08:00
zend_hash_add ( & mydata - > manifest , entry . filename , entry . filename_len , ( void * ) & entry , sizeof ( phar_entry_info ) , NULL ) ;
}
2007-01-14 00:17:04 +08:00
snprintf ( mydata - > version , sizeof ( mydata - > version ) , " %u.%u.%u " , manifest_ver > > 12 , ( manifest_ver > > 8 ) & 0xF , ( manifest_ver > > 4 ) & 0xF ) ;
2006-03-09 04:07:25 +08:00
mydata - > internal_file_start = halt_offset + manifest_len + 4 ;
2007-01-03 02:15:17 +08:00
mydata - > halt_offset = halt_offset ;
2007-01-14 00:17:04 +08:00
mydata - > flags = manifest_flags ;
2008-05-08 01:24:22 +08:00
endbuffer = strrchr ( mydata - > fname , ' / ' ) ;
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
if ( endbuffer ) {
mydata - > ext = memchr ( endbuffer , ' . ' , ( mydata - > fname + fname_len ) - endbuffer ) ;
if ( mydata - > ext = = endbuffer ) {
mydata - > ext = memchr ( endbuffer + 1 , ' . ' , ( mydata - > fname + fname_len ) - endbuffer - 1 ) ;
}
if ( mydata - > ext ) {
mydata - > ext_len = ( mydata - > fname + mydata - > fname_len ) - mydata - > ext ;
}
}
2008-08-01 21:45:06 +08:00
mydata - > alias = alias ?
pestrndup ( alias , alias_len , mydata - > is_persistent ) :
pestrndup ( mydata - > fname , fname_len , mydata - > is_persistent ) ;
2007-01-04 13:32:45 +08:00
mydata - > alias_len = alias ? alias_len : fname_len ;
2007-01-09 08:27:13 +08:00
mydata - > sig_flags = sig_flags ;
2008-08-01 21:45:06 +08:00
mydata - > fp = fp ;
2007-01-09 08:27:13 +08:00
mydata - > sig_len = sig_len ;
mydata - > signature = signature ;
2007-05-17 07:16:51 +08:00
phar_request_initialize ( TSRMLS_C ) ;
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
if ( register_alias ) {
2008-05-07 05:14:53 +08:00
phar_archive_data * * fd_ptr ;
2008-02-11 14:46:44 +08:00
mydata - > is_temporary_alias = temp_alias ;
2008-08-01 21:45:06 +08:00
2008-05-07 05:14:53 +08:00
if ( ! phar_validate_alias ( mydata - > alias , mydata - > alias_len ) ) {
signature = NULL ;
fp = NULL ;
MAPPHAR_FAIL ( " Cannot open archive \" %s \" , invalid alias " ) ;
}
2008-08-01 21:45:06 +08:00
2008-05-07 05:14:53 +08:00
if ( SUCCESS = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * * ) & fd_ptr ) ) {
2008-05-08 11:10:18 +08:00
if ( SUCCESS ! = phar_free_alias ( * fd_ptr , alias , alias_len TSRMLS_CC ) ) {
2008-05-07 05:14:53 +08:00
signature = NULL ;
fp = NULL ;
MAPPHAR_FAIL ( " Cannot open archive \" %s \" , alias is already in use by existing archive " ) ;
}
}
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
zend_hash_add ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ;
2007-01-05 12:45:52 +08:00
} else {
2008-02-11 14:46:44 +08:00
mydata - > is_temporary_alias = 1 ;
2006-01-12 05:19:46 +08:00
}
2008-08-01 21:45:06 +08:00
2008-05-07 05:14:53 +08:00
zend_hash_add ( & ( PHAR_GLOBALS - > phar_fname_map ) , mydata - > fname , fname_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ;
2005-12-05 04:35:38 +08:00
efree ( savebuf ) ;
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
if ( pphar ) {
2006-03-09 04:07:25 +08:00
* pphar = mydata ;
2006-02-28 09:36:30 +08:00
}
2006-01-04 10:26:15 +08:00
return SUCCESS ;
}
/* }}} */
2008-01-01 06:42:40 +08:00
/**
* Create or open a phar for writing
*/
2008-04-18 12:13:13 +08:00
int phar_open_or_create_filename ( char * fname , int fname_len , char * alias , int alias_len , int is_data , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2008-01-01 06:42:40 +08:00
{
2008-04-18 12:13:13 +08:00
const char * ext_str , * z ;
2008-05-13 04:42:07 +08:00
char * my_error ;
2008-04-18 12:13:13 +08:00
int ext_len ;
2008-05-08 08:49:37 +08:00
phar_archive_data * * test , * unused = NULL ;
2008-01-01 06:42:40 +08:00
2008-05-08 08:49:37 +08:00
test = & unused ;
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
* error = NULL ;
}
2007-01-14 08:32:38 +08:00
2008-04-18 12:13:13 +08:00
/* first try to open an existing file */
2008-08-01 21:45:06 +08:00
if ( phar_detect_phar_fname_ext ( fname , fname_len , & ext_str , & ext_len , ! is_data , 0 , 1 TSRMLS_CC ) = = SUCCESS ) {
2008-04-18 12:13:13 +08:00
goto check_file ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
/* next try to create a new file */
2008-08-01 21:45:06 +08:00
if ( FAILURE = = phar_detect_phar_fname_ext ( fname , fname_len , & ext_str , & ext_len , ! is_data , 1 , 1 TSRMLS_CC ) ) {
2008-04-18 12:13:13 +08:00
if ( error ) {
spprintf ( error , 0 , " Cannot create phar '%s', file extension (or combination) not recognised " , fname ) ;
2008-02-28 05:34:26 +08:00
}
2008-04-18 12:13:13 +08:00
return FAILURE ;
}
check_file :
2008-05-31 06:39:33 +08:00
if ( phar_open_parsed_phar ( fname , fname_len , alias , alias_len , is_data , options , test , & my_error TSRMLS_CC ) = = SUCCESS ) {
2008-05-08 08:49:37 +08:00
if ( pphar ) {
* pphar = * test ;
}
2008-08-01 21:45:06 +08:00
2008-05-08 08:49:37 +08:00
if ( ( * test ) - > is_data & & ! ( * test ) - > is_tar & & ! ( * test ) - > is_zip ) {
2008-04-18 12:13:13 +08:00
if ( error ) {
spprintf ( error , 0 , " Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives " , fname ) ;
2008-02-28 05:34:26 +08:00
}
2008-05-08 08:49:37 +08:00
return FAILURE ;
2008-04-18 12:13:13 +08:00
}
2008-08-01 21:45:06 +08:00
2008-05-08 08:49:37 +08:00
if ( PHAR_G ( readonly ) & & ! ( * test ) - > is_data & & ( ( * test ) - > is_tar | | ( * test ) - > is_zip ) ) {
2008-04-18 12:13:13 +08:00
phar_entry_info * stub ;
2008-05-08 08:49:37 +08:00
if ( FAILURE = = zend_hash_find ( & ( ( * test ) - > manifest ) , " .phar/stub.php " , sizeof ( " .phar/stub.php " ) - 1 , ( void * * ) & stub ) ) {
2008-04-18 12:13:13 +08:00
spprintf ( error , 0 , " '%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive " , fname ) ;
2008-02-28 05:34:26 +08:00
return FAILURE ;
}
}
2008-08-01 21:45:06 +08:00
2008-05-08 08:49:37 +08:00
if ( ! PHAR_G ( readonly ) | | ( * test ) - > is_data ) {
( * test ) - > is_writeable = 1 ;
2007-01-28 18:32:45 +08:00
}
2007-01-11 09:04:47 +08:00
return SUCCESS ;
2008-05-13 04:42:07 +08:00
} else if ( my_error ) {
if ( error ) {
* error = my_error ;
} else {
efree ( my_error ) ;
}
return FAILURE ;
2007-01-03 02:15:17 +08:00
}
2007-01-03 03:59:38 +08:00
2008-04-18 12:13:13 +08:00
if ( ext_len > 3 & & ( z = memchr ( ext_str , ' z ' , ext_len ) ) & & ( ( ext_str + ext_len ) - z > = 2 ) & & ! memcmp ( z + 1 , " ip " , 2 ) ) {
2008-05-24 22:18:31 +08:00
/* assume zip-based phar */
2008-02-28 05:34:26 +08:00
return phar_open_or_create_zip ( fname , fname_len , alias , alias_len , is_data , options , pphar , error TSRMLS_CC ) ;
2008-01-01 06:42:40 +08:00
}
2008-02-28 05:34:26 +08:00
2008-04-18 12:13:13 +08:00
if ( ext_len > 3 & & ( z = memchr ( ext_str , ' t ' , ext_len ) ) & & ( ( ext_str + ext_len ) - z > = 2 ) & & ! memcmp ( z + 1 , " ar " , 2 ) ) {
2008-05-24 22:18:31 +08:00
/* assume tar-based phar */
2008-02-28 05:34:26 +08:00
return phar_open_or_create_tar ( fname , fname_len , alias , alias_len , is_data , options , pphar , error TSRMLS_CC ) ;
}
2008-03-03 16:41:15 +08:00
return phar_create_or_parse_filename ( fname , fname_len , alias , alias_len , is_data , options , pphar , error TSRMLS_CC ) ;
2008-01-01 06:42:40 +08:00
}
2008-08-01 21:45:06 +08:00
/* }}} */
2008-01-01 06:42:40 +08:00
2008-03-03 16:41:15 +08:00
int phar_create_or_parse_filename ( char * fname , int fname_len , char * alias , int alias_len , int is_data , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2008-01-01 06:42:40 +08:00
{
phar_archive_data * mydata ;
php_stream * fp ;
2008-05-08 01:24:22 +08:00
char * actual = NULL , * p ;
2008-01-01 06:42:40 +08:00
if ( ! pphar ) {
pphar = & mydata ;
}
2007-01-03 03:59:38 +08:00
# if PHP_MAJOR_VERSION < 6
if ( PG ( safe_mode ) & & ( ! php_checkuid ( fname , NULL , CHECKUID_ALLOW_ONLY_FILE ) ) ) {
return FAILURE ;
}
# endif
if ( php_check_open_basedir ( fname TSRMLS_CC ) ) {
return FAILURE ;
}
2008-01-06 06:46:54 +08:00
/* first open readonly so it won't be created if not present */
2008-01-28 16:52:08 +08:00
fp = php_stream_open_wrapper ( fname , " rb " , IGNORE_URL | STREAM_MUST_SEEK | 0 , & actual ) ;
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( actual ) {
fname = actual ;
fname_len = strlen ( actual ) ;
}
2007-01-03 03:59:38 +08:00
2008-01-06 06:46:54 +08:00
if ( fp ) {
2008-05-31 06:39:33 +08:00
if ( phar_open_from_fp ( fp , fname , fname_len , alias , alias_len , options , pphar , error TSRMLS_CC ) = = SUCCESS ) {
2008-05-08 08:49:37 +08:00
if ( ( * pphar ) - > is_data | | ! PHAR_G ( readonly ) ) {
2008-01-06 06:46:54 +08:00
( * pphar ) - > is_writeable = 1 ;
}
2008-01-28 16:52:08 +08:00
if ( actual ) {
efree ( actual ) ;
}
2008-01-06 06:46:54 +08:00
return SUCCESS ;
} else {
/* file exists, but is either corrupt or not a phar archive */
2008-01-28 16:52:08 +08:00
if ( actual ) {
efree ( actual ) ;
}
2008-01-06 06:46:54 +08:00
return FAILURE ;
2007-01-28 18:32:45 +08:00
}
2008-01-28 16:52:08 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( actual ) {
efree ( actual ) ;
2007-01-08 00:01:35 +08:00
}
2008-03-03 16:41:15 +08:00
if ( PHAR_G ( readonly ) & & ! is_data ) {
2007-01-08 00:01:35 +08:00
if ( options & REPORT_ERRORS ) {
2007-01-29 15:59:19 +08:00
if ( error ) {
2007-01-29 14:02:19 +08:00
spprintf ( error , 0 , " creating archive \" %s \" disabled by INI setting " , fname ) ;
}
2007-01-08 00:01:35 +08:00
}
return FAILURE ;
2007-01-03 03:59:38 +08:00
}
2007-01-10 02:54:37 +08:00
2007-01-03 02:15:17 +08:00
/* set up our manifest */
2008-08-01 21:45:06 +08:00
mydata = ecalloc ( 1 , sizeof ( phar_archive_data ) ) ;
2008-02-11 14:53:56 +08:00
mydata - > fname = expand_filepath ( fname , NULL TSRMLS_CC ) ;
2008-02-11 15:33:20 +08:00
fname_len = strlen ( mydata - > fname ) ;
2007-11-15 13:21:11 +08:00
# ifdef PHP_WIN32
2008-02-11 15:33:20 +08:00
phar_unixify_path_separators ( mydata - > fname , fname_len ) ;
2007-11-15 13:21:11 +08:00
# endif
2008-05-08 01:24:22 +08:00
p = strrchr ( mydata - > fname , ' / ' ) ;
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
if ( p ) {
mydata - > ext = memchr ( p , ' . ' , ( mydata - > fname + fname_len ) - p ) ;
if ( mydata - > ext = = p ) {
mydata - > ext = memchr ( p + 1 , ' . ' , ( mydata - > fname + fname_len ) - p - 1 ) ;
}
if ( mydata - > ext ) {
mydata - > ext_len = ( mydata - > fname + fname_len ) - mydata - > ext ;
}
}
2008-01-08 15:08:46 +08:00
if ( pphar ) {
* pphar = mydata ;
}
2008-08-01 21:45:06 +08:00
2008-01-08 15:08:46 +08:00
zend_hash_init ( & mydata - > manifest , sizeof ( phar_entry_info ) ,
2008-01-09 11:47:22 +08:00
zend_get_hash_value , destroy_phar_manifest_entry , 0 ) ;
2008-02-25 12:23:36 +08:00
zend_hash_init ( & mydata - > mounted_dirs , sizeof ( char * ) ,
zend_get_hash_value , NULL , 0 ) ;
2008-08-01 21:45:06 +08:00
zend_hash_init ( & mydata - > virtual_dirs , sizeof ( char * ) ,
zend_get_hash_value , NULL , ( zend_bool ) mydata - > is_persistent ) ;
2007-01-03 02:15:17 +08:00
mydata - > fname_len = fname_len ;
2008-03-23 01:09:24 +08:00
snprintf ( mydata - > version , sizeof ( mydata - > version ) , " %s " , PHP_PHAR_API_VERSION ) ;
2008-02-11 14:46:44 +08:00
mydata - > is_temporary_alias = alias ? 0 : 1 ;
2007-01-03 02:15:17 +08:00
mydata - > internal_file_start = - 1 ;
2008-02-11 14:53:56 +08:00
mydata - > fp = NULL ;
2007-01-14 08:32:38 +08:00
mydata - > is_writeable = 1 ;
2007-01-29 05:26:54 +08:00
mydata - > is_brandnew = 1 ;
2008-05-13 04:42:07 +08:00
phar_request_initialize ( TSRMLS_C ) ;
zend_hash_add ( & ( PHAR_GLOBALS - > phar_fname_map ) , mydata - > fname , fname_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ;
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
if ( is_data ) {
2007-01-03 02:15:17 +08:00
alias = NULL ;
alias_len = 0 ;
2008-05-24 22:18:31 +08:00
mydata - > is_data = 1 ;
/* assume tar format, PharData can specify other */
mydata - > is_tar = 1 ;
2007-01-03 02:15:17 +08:00
} else {
2008-05-13 04:42:07 +08:00
phar_archive_data * * fd_ptr ;
if ( alias & & SUCCESS = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * * ) & fd_ptr ) ) {
if ( SUCCESS ! = phar_free_alias ( * fd_ptr , alias , alias_len TSRMLS_CC ) ) {
if ( error ) {
spprintf ( error , 4096 , " phar error: phar \" %s \" cannot set alias \" %s \" , already in use by another phar archive " , mydata - > fname , alias ) ;
}
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
zend_hash_del ( & ( PHAR_GLOBALS - > phar_fname_map ) , mydata - > fname , fname_len ) ;
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
if ( pphar ) {
* pphar = NULL ;
}
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
return FAILURE ;
}
}
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
mydata - > alias = alias ? estrndup ( alias , alias_len ) : estrndup ( mydata - > fname , fname_len ) ;
mydata - > alias_len = alias ? alias_len : fname_len ;
2007-01-03 02:15:17 +08:00
}
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
if ( alias_len & & alias ) {
2008-04-16 11:42:29 +08:00
if ( FAILURE = = zend_hash_add ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ) {
if ( options & REPORT_ERRORS ) {
if ( error ) {
spprintf ( error , 0 , " archive \" %s \" cannot be associated with alias \" %s \" , already in use " , fname , alias ) ;
}
}
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
zend_hash_del ( & ( PHAR_GLOBALS - > phar_fname_map ) , mydata - > fname , fname_len ) ;
2008-08-01 21:45:06 +08:00
2008-05-13 04:42:07 +08:00
if ( pphar ) {
* pphar = NULL ;
}
2008-08-01 21:45:06 +08:00
2008-04-16 11:42:29 +08:00
return FAILURE ;
}
2007-01-03 02:15:17 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-03 02:15:17 +08:00
return SUCCESS ;
}
2007-01-24 07:31:14 +08:00
/* }}}*/
2007-01-03 02:15:17 +08:00
2007-01-02 08:04:30 +08:00
/**
2007-01-11 09:04:47 +08:00
* Return an already opened filename .
*
* Or scan a phar file for the required __HALT_COMPILER ( ) ; ? > token and verify
2008-05-31 06:39:33 +08:00
* that the manifest is proper , then pass it to phar_parse_pharfile ( ) . SUCCESS
2007-01-02 08:04:30 +08:00
* or FAILURE is returned and pphar is set to a pointer to the phar ' s manifest
*/
2008-05-31 06:39:33 +08:00
int phar_open_from_filename ( char * fname , int fname_len , char * alias , int alias_len , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2006-01-04 10:26:15 +08:00
{
php_stream * fp ;
2008-01-28 16:52:08 +08:00
char * actual ;
2008-03-03 16:41:15 +08:00
int ret , is_data = 0 ;
2007-01-29 14:02:19 +08:00
if ( error ) {
* error = NULL ;
}
2008-03-03 16:41:15 +08:00
if ( ! strstr ( fname , " .phar " ) ) {
is_data = 1 ;
}
2008-05-31 06:39:33 +08:00
if ( phar_open_parsed_phar ( fname , fname_len , alias , alias_len , is_data , options , pphar , error TSRMLS_CC ) = = SUCCESS ) {
2007-01-11 09:04:47 +08:00
return SUCCESS ;
2008-01-06 13:16:20 +08:00
} else if ( error & & * error ) {
2007-01-29 14:02:19 +08:00
return FAILURE ;
2006-02-28 09:36:30 +08:00
}
2006-03-09 04:31:23 +08:00
# if PHP_MAJOR_VERSION < 6
2006-01-05 19:32:05 +08:00
if ( PG ( safe_mode ) & & ( ! php_checkuid ( fname , NULL , CHECKUID_ALLOW_ONLY_FILE ) ) ) {
return FAILURE ;
}
2006-03-09 04:31:23 +08:00
# endif
2006-01-05 19:32:05 +08:00
if ( php_check_open_basedir ( fname TSRMLS_CC ) ) {
return FAILURE ;
}
2008-01-28 16:52:08 +08:00
fp = php_stream_open_wrapper ( fname , " rb " , IGNORE_URL | STREAM_MUST_SEEK , & actual ) ;
2008-08-01 21:45:06 +08:00
2006-01-04 10:26:15 +08:00
if ( ! fp ) {
2007-01-08 00:01:35 +08:00
if ( options & REPORT_ERRORS ) {
2007-01-29 14:02:19 +08:00
if ( error ) {
spprintf ( error , 0 , " unable to open phar for reading \" %s \" " , fname ) ;
}
2007-01-08 00:01:35 +08:00
}
2008-01-28 16:52:08 +08:00
if ( actual ) {
efree ( actual ) ;
}
2006-01-04 10:26:15 +08:00
return FAILURE ;
}
2008-01-28 16:52:08 +08:00
if ( actual ) {
fname = actual ;
fname_len = strlen ( actual ) ;
}
2008-05-31 06:39:33 +08:00
ret = phar_open_from_fp ( fp , fname , fname_len , alias , alias_len , options , pphar , error TSRMLS_CC ) ;
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( actual ) {
efree ( actual ) ;
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
return ret ;
2007-01-11 09:04:47 +08:00
}
/* }}}*/
2008-08-01 21:45:06 +08:00
static inline char * phar_strnstr ( const char * buf , int buf_len , const char * search , int search_len ) /* { { { */
2008-04-27 15:20:02 +08:00
{
const char * c ;
int so_far = 0 ;
2008-08-01 21:45:06 +08:00
if ( buf_len < search_len ) {
return NULL ;
}
2008-04-27 15:20:02 +08:00
c = buf - 1 ;
2008-08-01 21:45:06 +08:00
2008-04-27 15:20:02 +08:00
do {
if ( ! ( c = memchr ( c + 1 , search [ 0 ] , buf_len - search_len - so_far ) ) ) {
return ( char * ) NULL ;
}
2008-08-01 21:45:06 +08:00
2008-04-27 15:20:02 +08:00
so_far = c - buf ;
2008-08-01 21:45:06 +08:00
2008-04-27 15:20:02 +08:00
if ( so_far > = ( buf_len - search_len ) ) {
return ( char * ) NULL ;
}
2008-08-01 21:45:06 +08:00
2008-04-27 15:20:02 +08:00
if ( ! memcmp ( c , search , search_len ) ) {
return ( char * ) c ;
}
} while ( 1 ) ;
}
2008-08-01 21:45:06 +08:00
/* }}} */
2008-04-27 15:20:02 +08:00
2007-01-11 09:04:47 +08:00
/**
* Scan an open fp for the required __HALT_COMPILER ( ) ; ? > token and verify
2008-05-31 06:39:33 +08:00
* that the manifest is proper , then pass it to phar_parse_pharfile ( ) . SUCCESS
2007-01-11 09:04:47 +08:00
* or FAILURE is returned and pphar is set to a pointer to the phar ' s manifest
*/
2008-05-31 06:39:33 +08:00
static int phar_open_from_fp ( php_stream * fp , char * fname , int fname_len , char * alias , int alias_len , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2007-01-11 09:04:47 +08:00
{
const char token [ ] = " __HALT_COMPILER(); " ;
2008-01-01 06:42:40 +08:00
const char zip_magic [ ] = " PK \x03 \x04 " ;
2008-01-09 15:09:04 +08:00
const char gz_magic [ ] = " \x1f \x8b \x08 " ;
const char bz_magic [ ] = " BZh " ;
2008-01-01 06:42:40 +08:00
char * pos , buffer [ 1024 + sizeof ( token ) ] , test = ' \0 ' ;
2007-01-11 09:04:47 +08:00
const long readsize = sizeof ( buffer ) - sizeof ( token ) ;
const long tokenlen = sizeof ( token ) - 1 ;
long halt_offset ;
2007-02-07 06:12:21 +08:00
size_t got ;
2008-01-09 15:09:04 +08:00
php_uint32 compression = PHAR_FILE_COMPRESSED_NONE ;
2006-01-04 10:26:15 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
* error = NULL ;
}
2008-08-01 21:45:06 +08:00
2007-01-11 09:04:47 +08:00
if ( - 1 = = php_stream_rewind ( fp ) ) {
2006-01-05 08:39:31 +08:00
MAPPHAR_ALLOC_FAIL ( " cannot rewind phar \" %s \" " )
2006-01-04 10:26:15 +08:00
}
buffer [ sizeof ( buffer ) - 1 ] = ' \0 ' ;
memset ( buffer , 32 , sizeof ( token ) ) ;
halt_offset = 0 ;
2008-01-09 15:09:04 +08:00
/* Maybe it's better to compile the file instead of just searching, */
/* but we only want the offset. So we want a .re scanner to find it. */
2006-01-04 10:26:15 +08:00
while ( ! php_stream_eof ( fp ) ) {
2007-12-14 13:39:20 +08:00
if ( ( got = php_stream_read ( fp , buffer + tokenlen , readsize ) ) < ( size_t ) tokenlen ) {
2007-05-27 23:47:52 +08:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated entry) " )
2006-01-04 10:26:15 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-01 06:42:40 +08:00
if ( ! test ) {
test = ' \1 ' ;
pos = buffer + tokenlen ;
2008-01-09 15:09:04 +08:00
if ( ! memcmp ( pos , gz_magic , 3 ) ) {
char err = 0 ;
php_stream_filter * filter ;
php_stream * temp ;
/* to properly decompress, we have to tell zlib to look for a zlib or gzip header */
zval filterparams ;
2008-05-18 04:07:38 +08:00
if ( ! PHAR_G ( has_zlib ) ) {
2008-01-11 05:21:38 +08:00
MAPPHAR_ALLOC_FAIL ( " unable to decompress gzipped phar archive \" %s \" to temporary file, enable zlib extension in php.ini " )
}
2008-01-09 15:09:04 +08:00
array_init ( & filterparams ) ;
2008-01-13 00:15:17 +08:00
/* this is defined in zlib's zconf.h */
# ifndef MAX_WBITS
# define MAX_WBITS 15
# endif
2008-01-09 15:09:04 +08:00
add_assoc_long ( & filterparams , " window " , MAX_WBITS + 32 ) ;
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
/* entire file is gzip-compressed, uncompress to temporary file */
if ( ! ( temp = php_stream_fopen_tmpfile ( ) ) ) {
MAPPHAR_ALLOC_FAIL ( " unable to create temporary file for decompression of gzipped phar archive \" %s \" " )
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
php_stream_rewind ( fp ) ;
filter = php_stream_filter_create ( " zlib.inflate " , & filterparams , php_stream_is_persistent ( fp ) TSRMLS_CC ) ;
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
if ( ! filter ) {
err = 1 ;
add_assoc_long ( & filterparams , " window " , MAX_WBITS ) ;
filter = php_stream_filter_create ( " zlib.inflate " , & filterparams , php_stream_is_persistent ( fp ) TSRMLS_CC ) ;
2008-02-08 13:41:59 +08:00
zval_dtor ( & filterparams ) ;
2008-08-01 21:45:06 +08:00
2008-01-11 05:21:38 +08:00
if ( ! filter ) {
php_stream_close ( temp ) ;
MAPPHAR_ALLOC_FAIL ( " unable to decompress gzipped phar archive \" %s \" , ext/zlib is buggy in PHP versions older than 5.2.6 " )
}
2008-02-08 13:41:59 +08:00
} else {
zval_dtor ( & filterparams ) ;
2008-01-09 15:09:04 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
php_stream_filter_append ( & temp - > writefilters , filter ) ;
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
if ( 0 = = php_stream_copy_to_stream ( fp , temp , PHP_STREAM_COPY_ALL ) ) {
if ( err ) {
2008-01-11 05:21:38 +08:00
php_stream_close ( temp ) ;
2008-01-09 15:09:04 +08:00
MAPPHAR_ALLOC_FAIL ( " unable to decompress gzipped phar archive \" %s \" , ext/zlib is buggy in PHP versions older than 5.2.6 " )
}
php_stream_close ( temp ) ;
MAPPHAR_ALLOC_FAIL ( " unable to decompress gzipped phar archive \" %s \" to temporary file " )
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
php_stream_filter_flush ( filter , 1 ) ;
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
php_stream_close ( fp ) ;
fp = temp ;
php_stream_rewind ( fp ) ;
compression = PHAR_FILE_COMPRESSED_GZ ;
/* now, start over */
test = ' \0 ' ;
continue ;
} else if ( ! memcmp ( pos , bz_magic , 3 ) ) {
php_stream_filter * filter ;
php_stream * temp ;
2008-05-18 04:07:38 +08:00
if ( ! PHAR_G ( has_bz2 ) ) {
2008-01-17 11:48:29 +08:00
MAPPHAR_ALLOC_FAIL ( " unable to decompress bzipped phar archive \" %s \" to temporary file, enable bz2 extension in php.ini " )
2008-01-11 05:21:38 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
/* entire file is bzip-compressed, uncompress to temporary file */
if ( ! ( temp = php_stream_fopen_tmpfile ( ) ) ) {
MAPPHAR_ALLOC_FAIL ( " unable to create temporary file for decompression of bzipped phar archive \" %s \" " )
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
php_stream_rewind ( fp ) ;
filter = php_stream_filter_create ( " bzip2.decompress " , NULL , php_stream_is_persistent ( fp ) TSRMLS_CC ) ;
2008-08-01 21:45:06 +08:00
2008-01-11 05:21:38 +08:00
if ( ! filter ) {
php_stream_close ( temp ) ;
MAPPHAR_ALLOC_FAIL ( " unable to decompress bzipped phar archive \" %s \" , filter creation failed " )
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
php_stream_filter_append ( & temp - > writefilters , filter ) ;
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
if ( 0 = = php_stream_copy_to_stream ( fp , temp , PHP_STREAM_COPY_ALL ) ) {
php_stream_close ( temp ) ;
2008-01-11 05:21:38 +08:00
MAPPHAR_ALLOC_FAIL ( " unable to decompress bzipped phar archive \" %s \" to temporary file " )
2008-01-09 15:09:04 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
php_stream_filter_flush ( filter , 1 ) ;
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
php_stream_close ( fp ) ;
fp = temp ;
php_stream_rewind ( fp ) ;
compression = PHAR_FILE_COMPRESSED_BZ2 ;
/* now, start over */
test = ' \0 ' ;
continue ;
}
2008-08-01 21:45:06 +08:00
2008-01-01 06:42:40 +08:00
if ( ! memcmp ( pos , zip_magic , 4 ) ) {
2008-01-28 16:52:08 +08:00
php_stream_seek ( fp , 0 , SEEK_END ) ;
2008-05-31 06:39:33 +08:00
return phar_parse_zipfile ( fp , fname , fname_len , alias , alias_len , pphar , error TSRMLS_CC ) ;
2008-01-01 06:42:40 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-03 12:45:00 +08:00
if ( got > 512 ) {
2008-04-21 01:28:54 +08:00
if ( phar_is_tar ( pos , fname ) ) {
2008-01-09 15:09:04 +08:00
php_stream_rewind ( fp ) ;
2008-09-14 06:31:18 +08:00
return phar_parse_tarfile ( fp , fname , fname_len , alias , alias_len , pphar , compression , error TSRMLS_CC ) ;
2008-01-03 12:45:00 +08:00
}
}
2008-01-01 06:42:40 +08:00
}
2008-08-01 21:45:06 +08:00
if ( got > 0 & & ( pos = phar_strnstr ( buffer , got + sizeof ( token ) , token , sizeof ( token ) - 1 ) ) ! = NULL ) {
2006-01-05 08:39:31 +08:00
halt_offset + = ( pos - buffer ) ; /* no -tokenlen+tokenlen here */
2008-05-31 06:39:33 +08:00
return phar_parse_pharfile ( fp , fname , fname_len , alias , alias_len , halt_offset , pphar , compression , error TSRMLS_CC ) ;
2006-01-04 10:26:15 +08:00
}
2007-02-07 06:12:21 +08:00
halt_offset + = got ;
memmove ( buffer , buffer + tokenlen , got + 1 ) ;
2006-01-04 10:26:15 +08:00
}
2008-08-01 21:45:06 +08:00
2006-01-04 10:26:15 +08:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (__HALT_COMPILER(); not found) " )
}
/* }}} */
2008-04-18 12:13:13 +08:00
/*
* given the location of the file extension and the start of the file path ,
* determine the end of the portion of the path ( i . e . / path / to / file . ext / blah
* grabs " /path/to/file.ext " as does the straight / path / to / file . ext ) ,
* stat it to determine if it exists .
* if so , check to see if it is a directory and fail if so
* if not , check to see if its dirname ( ) exists ( i . e . " /path/to " ) and is a directory
* succeed if we are creating the file , otherwise fail .
*/
2008-08-01 21:45:06 +08:00
static int phar_analyze_path ( const char * fname , const char * ext , int ext_len , int for_create TSRMLS_DC ) /* { { { */
2008-04-18 12:13:13 +08:00
{
php_stream_statbuf ssb ;
char * realpath , old , * a = ( char * ) ( ext + ext_len ) ;
old = * a ;
* a = ' \0 ' ;
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( ( realpath = expand_filepath ( fname , NULL TSRMLS_CC ) ) ) {
2008-04-20 08:24:01 +08:00
# ifdef PHP_WIN32
phar_unixify_path_separators ( realpath , strlen ( realpath ) ) ;
# endif
2008-04-18 12:13:13 +08:00
if ( zend_hash_exists ( & ( PHAR_GLOBALS - > phar_fname_map ) , realpath , strlen ( realpath ) ) ) {
* a = old ;
efree ( realpath ) ;
return SUCCESS ;
}
2008-08-01 21:45:06 +08:00
if ( PHAR_G ( manifest_cached ) & & zend_hash_exists ( & cached_phars , realpath , strlen ( realpath ) ) ) {
* a = old ;
efree ( realpath ) ;
return SUCCESS ;
}
2008-04-18 12:13:13 +08:00
efree ( realpath ) ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( SUCCESS = = php_stream_stat_path ( ( char * ) fname , & ssb ) ) {
* a = old ;
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( ssb . sb . st_mode & S_IFDIR ) {
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( for_create = = 1 ) {
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
return SUCCESS ;
} else {
char * slash ;
if ( ! for_create ) {
* a = old ;
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
slash = ( char * ) strrchr ( fname , ' / ' ) ;
* a = old ;
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( slash ) {
old = * slash ;
* slash = ' \0 ' ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( SUCCESS ! = php_stream_stat_path ( ( char * ) fname , & ssb ) ) {
if ( slash ) {
* slash = old ;
} else {
if ( ! ( realpath = expand_filepath ( fname , NULL TSRMLS_CC ) ) ) {
return FAILURE ;
}
2008-04-20 12:19:13 +08:00
# ifdef PHP_WIN32
phar_unixify_path_separators ( realpath , strlen ( realpath ) ) ;
# endif
2008-04-18 12:13:13 +08:00
a = strstr ( realpath , fname ) + ( ( ext - fname ) + ext_len ) ;
* a = ' \0 ' ;
slash = strrchr ( realpath , ' / ' ) ;
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( slash ) {
* slash = ' \0 ' ;
} else {
efree ( realpath ) ;
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( SUCCESS ! = php_stream_stat_path ( realpath , & ssb ) ) {
efree ( realpath ) ;
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
efree ( realpath ) ;
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( ssb . sb . st_mode & S_IFDIR ) {
return SUCCESS ;
}
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( slash ) {
* slash = old ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( ssb . sb . st_mode & S_IFDIR ) {
return SUCCESS ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
return FAILURE ;
}
}
2008-08-01 21:45:06 +08:00
/* }}} */
2008-04-18 12:13:13 +08:00
/* check for ".phar" in extension */
2008-08-01 21:45:06 +08:00
static int phar_check_str ( const char * fname , const char * ext_str , int ext_len , int executable , int for_create TSRMLS_DC ) /* { { { */
2007-05-16 04:21:19 +08:00
{
2008-04-18 12:13:13 +08:00
char test [ 51 ] ;
2008-03-22 08:15:45 +08:00
const char * pos ;
2008-04-18 12:13:13 +08:00
if ( ext_len > = 50 ) {
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
if ( executable = = 1 ) {
/* copy "." as well */
memcpy ( test , ext_str - 1 , ext_len + 1 ) ;
test [ ext_len + 1 ] = ' \0 ' ;
/* executable phars must contain ".phar" as a valid extension (phar://.pharmy/oops is invalid) */
/* (phar://hi/there/.phar/oops is also invalid) */
2008-04-24 02:11:20 +08:00
pos = strstr ( test , " .phar " ) ;
2008-08-01 21:45:06 +08:00
2008-04-24 02:11:20 +08:00
if ( pos & & ( * ( pos - 1 ) ! = ' / ' )
2008-04-18 12:13:13 +08:00
& & ( pos + = 5 ) & & ( * pos = = ' \0 ' | | * pos = = ' / ' | | * pos = = ' . ' ) ) {
return phar_analyze_path ( fname , ext_str , ext_len , for_create TSRMLS_CC ) ;
} else {
return FAILURE ;
}
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
/* data phars need only contain a single non-"." to be valid */
2008-04-24 02:22:09 +08:00
if ( ! executable ) {
pos = strstr ( ext_str , " .phar " ) ;
if ( ! ( pos & & ( * ( pos - 1 ) ! = ' / ' )
& & ( pos + = 5 ) & & ( * pos = = ' \0 ' | | * pos = = ' / ' | | * pos = = ' . ' ) ) & & * ( ext_str + 1 ) ! = ' . ' & & * ( ext_str + 1 ) ! = ' / ' & & * ( ext_str + 1 ) ! = ' \0 ' ) {
return phar_analyze_path ( fname , ext_str , ext_len , for_create TSRMLS_CC ) ;
}
} else {
if ( * ( ext_str + 1 ) ! = ' . ' & & * ( ext_str + 1 ) ! = ' / ' & & * ( ext_str + 1 ) ! = ' \0 ' ) {
return phar_analyze_path ( fname , ext_str , ext_len , for_create TSRMLS_CC ) ;
}
2008-04-18 12:13:13 +08:00
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
/* }}} */
2008-04-18 12:13:13 +08:00
/*
* if executable is 1 , only returns SUCCESS if the extension is one of the tar / zip . phar extensions
* if executable is 0 , it returns SUCCESS only if the filename does * not * contain " .phar " anywhere , and treats
* the first extension as the filename extension
*
* if an extension is found , it sets ext_str to the location of the file extension in filename ,
* and ext_len to the length of the extension .
* for urls like " phar://alias/oops " it instead sets ext_len to - 1 and returns FAILURE , which tells
* the calling function to use " alias " as the phar alias
*
* the last parameter should be set to tell the thing to assume that filename is the full path , and only to check the
* extension rules , not to iterate .
*/
2008-08-01 21:45:06 +08:00
int phar_detect_phar_fname_ext ( const char * filename , int filename_len , const char * * ext_str , int * ext_len , int executable , int for_create , int is_complete TSRMLS_DC ) /* { { { */
2008-04-18 12:13:13 +08:00
{
const char * pos , * slash ;
2008-03-22 08:15:45 +08:00
* ext_str = NULL ;
2008-04-18 12:13:13 +08:00
if ( ! filename_len | | filename_len = = 1 ) {
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
phar_request_initialize ( TSRMLS_C ) ;
2008-05-07 13:38:31 +08:00
/* first check for alias in first segment */
2008-08-01 21:45:06 +08:00
pos = memchr ( filename , ' / ' , filename_len ) ;
2008-05-08 08:49:37 +08:00
if ( pos & & pos ! = filename ) {
2008-04-20 01:24:41 +08:00
if ( zend_hash_exists ( & ( PHAR_GLOBALS - > phar_alias_map ) , ( char * ) filename , pos - filename ) ) {
2008-04-18 12:13:13 +08:00
* ext_str = pos ;
2007-11-22 13:47:28 +08:00
* ext_len = - 1 ;
2008-04-18 12:13:13 +08:00
return FAILURE ;
2007-11-22 13:47:28 +08:00
}
2008-08-01 21:45:06 +08:00
if ( PHAR_G ( manifest_cached ) & & zend_hash_exists ( & cached_alias , ( char * ) filename , pos - filename ) ) {
* ext_str = pos ;
* ext_len = - 1 ;
return FAILURE ;
}
2007-05-16 04:21:19 +08:00
}
2008-04-18 12:13:13 +08:00
2008-08-01 21:45:06 +08:00
if ( zend_hash_num_elements ( & ( PHAR_GLOBALS - > phar_fname_map ) ) | | PHAR_G ( manifest_cached ) ) {
2008-05-08 01:24:22 +08:00
phar_archive_data * * pphar ;
if ( is_complete ) {
2008-05-08 11:10:18 +08:00
if ( SUCCESS = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_fname_map ) , ( char * ) filename , filename_len , ( void * * ) & pphar ) ) {
2008-05-08 01:24:22 +08:00
* ext_str = filename + ( filename_len - ( * pphar ) - > ext_len ) ;
woohoo :
* ext_len = ( * pphar ) - > ext_len ;
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
if ( executable = = 2 ) {
return SUCCESS ;
}
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
if ( executable = = 1 & & ! ( * pphar ) - > is_data ) {
return SUCCESS ;
}
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
if ( ! executable & & ( * pphar ) - > is_data ) {
return SUCCESS ;
}
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
if ( PHAR_G ( manifest_cached ) & & SUCCESS = = zend_hash_find ( & cached_phars , ( char * ) filename , filename_len , ( void * * ) & pphar ) ) {
* ext_str = filename + ( filename_len - ( * pphar ) - > ext_len ) ;
goto woohoo ;
}
2008-05-08 01:24:22 +08:00
} else {
2008-05-15 05:27:31 +08:00
phar_zstr key ;
char * str_key ;
2008-05-08 01:24:22 +08:00
uint keylen ;
ulong unused ;
zend_hash_internal_pointer_reset ( & ( PHAR_GLOBALS - > phar_fname_map ) ) ;
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
while ( FAILURE ! = zend_hash_has_more_elements ( & ( PHAR_GLOBALS - > phar_fname_map ) ) ) {
if ( HASH_KEY_NON_EXISTANT = = zend_hash_get_current_key_ex ( & ( PHAR_GLOBALS - > phar_fname_map ) , & key , & keylen , & unused , 0 , NULL ) ) {
break ;
}
2008-05-15 05:27:31 +08:00
PHAR_STR ( key , str_key ) ;
2008-05-08 11:10:18 +08:00
if ( keylen > ( uint ) filename_len ) {
2008-05-08 01:24:22 +08:00
zend_hash_move_forward ( & ( PHAR_GLOBALS - > phar_fname_map ) ) ;
continue ;
}
2008-08-01 21:45:06 +08:00
2008-05-15 05:27:31 +08:00
if ( ! memcmp ( filename , str_key , keylen ) & & ( ( uint ) filename_len = = keylen
2008-05-08 01:24:22 +08:00
| | filename [ keylen ] = = ' / ' | | filename [ keylen ] = = ' \0 ' ) ) {
if ( FAILURE = = zend_hash_get_current_data ( & ( PHAR_GLOBALS - > phar_fname_map ) , ( void * * ) & pphar ) ) {
break ;
}
* ext_str = filename + ( keylen - ( * pphar ) - > ext_len ) ;
goto woohoo ;
}
2008-08-01 21:45:06 +08:00
2008-05-08 01:24:22 +08:00
zend_hash_move_forward ( & ( PHAR_GLOBALS - > phar_fname_map ) ) ;
}
2008-08-01 21:45:06 +08:00
if ( PHAR_G ( manifest_cached ) ) {
zend_hash_internal_pointer_reset ( & cached_phars ) ;
while ( FAILURE ! = zend_hash_has_more_elements ( & cached_phars ) ) {
if ( HASH_KEY_NON_EXISTANT = = zend_hash_get_current_key_ex ( & cached_phars , & key , & keylen , & unused , 0 , NULL ) ) {
break ;
}
PHAR_STR ( key , str_key ) ;
if ( keylen > ( uint ) filename_len ) {
zend_hash_move_forward ( & cached_phars ) ;
continue ;
}
if ( ! memcmp ( filename , str_key , keylen ) & & ( ( uint ) filename_len = = keylen
| | filename [ keylen ] = = ' / ' | | filename [ keylen ] = = ' \0 ' ) ) {
if ( FAILURE = = zend_hash_get_current_data ( & cached_phars , ( void * * ) & pphar ) ) {
break ;
}
* ext_str = filename + ( keylen - ( * pphar ) - > ext_len ) ;
goto woohoo ;
}
zend_hash_move_forward ( & cached_phars ) ;
}
}
2008-05-08 01:24:22 +08:00
}
}
2008-08-01 21:45:06 +08:00
pos = memchr ( filename + 1 , ' . ' , filename_len ) ;
2008-04-18 12:13:13 +08:00
next_extension :
if ( ! pos ) {
2007-05-16 04:21:19 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2008-04-24 02:22:09 +08:00
while ( pos ! = filename & & ( * ( pos - 1 ) = = ' / ' | | * ( pos - 1 ) = = ' \0 ' ) ) {
2008-08-01 21:45:06 +08:00
pos = memchr ( pos + 1 , ' . ' , filename_len - ( pos - filename ) + 1 ) ;
2008-04-24 02:11:20 +08:00
if ( ! pos ) {
return FAILURE ;
}
}
2008-04-18 12:13:13 +08:00
2008-08-01 21:45:06 +08:00
slash = memchr ( pos , ' / ' , filename_len - ( pos - filename ) ) ;
2008-04-18 12:13:13 +08:00
if ( ! slash ) {
/* this is a url like "phar://blah.phar" with no directory */
* ext_str = pos ;
* ext_len = strlen ( pos ) ;
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
/* file extension must contain "phar" */
switch ( phar_check_str ( filename , * ext_str , * ext_len , executable , for_create TSRMLS_CC ) ) {
2008-08-01 21:45:06 +08:00
case SUCCESS :
2008-04-18 12:13:13 +08:00
return SUCCESS ;
2008-08-01 21:45:06 +08:00
case FAILURE :
2008-04-18 12:13:13 +08:00
/* we are at the end of the string, so we fail */
return FAILURE ;
}
2007-05-16 04:21:19 +08:00
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
/* we've found an extension that ends at a directory separator */
* ext_str = pos ;
* ext_len = slash - pos ;
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
switch ( phar_check_str ( filename , * ext_str , * ext_len , executable , for_create TSRMLS_CC ) ) {
2008-08-01 21:45:06 +08:00
case SUCCESS :
2008-04-18 12:13:13 +08:00
return SUCCESS ;
2008-08-01 21:45:06 +08:00
case FAILURE :
2008-04-18 12:13:13 +08:00
/* look for more extensions */
pos = strchr ( pos + 1 , ' . ' ) ;
if ( pos ) {
* ext_str = NULL ;
* ext_len = 0 ;
}
goto next_extension ;
}
2008-08-01 21:45:06 +08:00
2008-04-18 12:13:13 +08:00
return FAILURE ;
2007-05-16 04:21:19 +08:00
}
/* }}} */
2008-08-01 21:45:06 +08:00
static int php_check_dots ( const char * element , int n ) /* { { { */
2007-12-21 07:12:40 +08:00
{
2007-12-22 15:46:53 +08:00
for ( n - - ; n > = 0 ; - - n ) {
if ( element [ n ] ! = ' . ' ) {
return 1 ;
}
}
return 0 ;
2007-12-21 07:12:40 +08:00
}
2008-08-01 21:45:06 +08:00
/* }}} */
2007-12-21 07:12:40 +08:00
# define IS_DIRECTORY_UP(element, len) \
( len > = 2 & & ! php_check_dots ( element , len ) )
# define IS_DIRECTORY_CURRENT(element, len) \
( len = = 1 & & element [ 0 ] = = ' . ' )
2008-08-01 21:45:06 +08:00
# define IS_BACKSLASH(c) ((c) == ' / ')
2007-12-21 07:12:40 +08:00
2008-01-14 10:47:55 +08:00
# ifdef COMPILE_DL_PHAR
2007-12-25 05:40:54 +08:00
/* stupid-ass non-extern declaration in tsrm_strtok.h breaks dumbass MS compiler */
2008-08-01 21:45:06 +08:00
static inline int in_character_class ( char ch , const char * delim ) /* { { { */
2007-12-25 05:40:54 +08:00
{
while ( * delim ) {
if ( * delim = = ch ) {
return 1 ;
}
2008-03-23 06:11:49 +08:00
+ + delim ;
2007-12-25 05:40:54 +08:00
}
return 0 ;
}
2008-08-01 21:45:06 +08:00
/* }}} */
2007-12-25 05:40:54 +08:00
2008-08-01 21:45:06 +08:00
char * tsrm_strtok_r ( char * s , const char * delim , char * * last ) /* { { { */
2007-12-25 05:40:54 +08:00
{
char * token ;
if ( s = = NULL ) {
s = * last ;
}
while ( * s & & in_character_class ( * s , delim ) ) {
2008-03-23 06:11:49 +08:00
+ + s ;
2007-12-25 05:40:54 +08:00
}
2008-08-01 21:45:06 +08:00
2007-12-25 05:40:54 +08:00
if ( ! * s ) {
return NULL ;
}
token = s ;
while ( * s & & ! in_character_class ( * s , delim ) ) {
2008-03-23 06:11:49 +08:00
+ + s ;
2007-12-25 05:40:54 +08:00
}
2008-08-01 21:45:06 +08:00
2007-12-25 05:40:54 +08:00
if ( ! * s ) {
* last = s ;
} else {
* s = ' \0 ' ;
* last = s + 1 ;
}
2008-08-01 21:45:06 +08:00
2007-12-25 05:40:54 +08:00
return token ;
}
2008-08-01 21:45:06 +08:00
/* }}} */
2007-12-25 05:40:54 +08:00
# endif
2007-12-21 07:12:40 +08:00
/**
* Remove . . and . references within a phar filename
*/
2008-01-11 15:30:03 +08:00
char * phar_fix_filepath ( char * path , int * new_len , int use_cwd TSRMLS_DC ) /* { { { */
2007-12-21 07:12:40 +08:00
{
2008-08-01 21:45:06 +08:00
char newpath [ MAXPATHLEN ] ;
int newpath_len ;
char * ptr ;
2007-12-21 07:12:40 +08:00
char * tok ;
2008-08-01 21:45:06 +08:00
int ptr_length , path_length = * new_len ;
2007-12-21 07:12:40 +08:00
2008-02-13 23:00:31 +08:00
if ( PHAR_G ( cwd_len ) & & use_cwd & & path_length > 2 & & path [ 0 ] = = ' . ' & & path [ 1 ] = = ' / ' ) {
2008-08-01 21:45:06 +08:00
newpath_len = PHAR_G ( cwd_len ) ;
memcpy ( newpath , PHAR_G ( cwd ) , newpath_len ) ;
2008-01-10 23:13:00 +08:00
} else {
2008-08-01 21:45:06 +08:00
newpath [ 0 ] = ' / ' ;
newpath_len = 1 ;
2008-01-10 23:13:00 +08:00
}
2007-12-21 07:12:40 +08:00
2008-08-01 21:45:06 +08:00
ptr = path ;
if ( * ptr = = ' / ' ) {
+ + ptr ;
}
tok = ptr ;
2007-12-21 07:12:40 +08:00
2008-08-01 21:45:06 +08:00
do {
ptr = memchr ( ptr , ' / ' , path_length - ( ptr - path ) ) ;
} while ( ptr & & ptr - tok = = 0 & & * ptr = = ' / ' & & + + ptr & & + + tok ) ;
if ( ! ptr & & ( path_length - ( tok - path ) ) ) {
switch ( path_length - ( tok - path ) ) {
case 1 :
if ( * tok = = ' . ' ) {
efree ( path ) ;
* new_len = 1 ;
return estrndup ( " / " , 1 ) ;
}
break ;
case 2 :
if ( tok [ 0 ] = = ' . ' & & tok [ 1 ] = = ' . ' ) {
efree ( path ) ;
* new_len = 1 ;
return estrndup ( " / " , 1 ) ;
}
}
return path ;
}
2007-12-21 07:12:40 +08:00
2008-08-01 21:45:06 +08:00
while ( ptr ) {
ptr_length = ptr - tok ;
last_time :
if ( IS_DIRECTORY_UP ( tok , ptr_length ) ) {
# define PREVIOUS newpath[newpath_len - 1]
2007-12-21 07:12:40 +08:00
2008-08-01 21:45:06 +08:00
while ( newpath_len > 1 & & ! IS_BACKSLASH ( PREVIOUS ) ) {
newpath_len - - ;
2007-12-21 07:12:40 +08:00
}
2008-08-01 21:45:06 +08:00
if ( newpath [ 0 ] ! = ' / ' ) {
newpath [ newpath_len ] = ' \0 ' ;
} else if ( newpath_len > 1 ) {
- - newpath_len ;
2007-12-21 07:12:40 +08:00
}
2008-08-01 21:45:06 +08:00
} else if ( ! IS_DIRECTORY_CURRENT ( tok , ptr_length ) ) {
if ( newpath_len > 1 ) {
newpath [ newpath_len + + ] = ' / ' ;
memcpy ( newpath + newpath_len , tok , ptr_length + 1 ) ;
2007-12-21 07:12:40 +08:00
} else {
2008-08-01 21:45:06 +08:00
memcpy ( newpath + newpath_len , tok , ptr_length + 1 ) ;
2007-12-21 07:12:40 +08:00
}
2008-08-01 21:45:06 +08:00
newpath_len + = ptr_length ;
2007-12-21 07:12:40 +08:00
}
2008-08-01 21:45:06 +08:00
if ( ptr = = path + path_length ) {
break ;
}
2007-12-21 07:12:40 +08:00
2008-08-01 21:45:06 +08:00
tok = + + ptr ;
2008-02-01 19:25:11 +08:00
2008-08-01 21:45:06 +08:00
do {
ptr = memchr ( ptr , ' / ' , path_length - ( ptr - path ) ) ;
} while ( ptr & & ptr - tok = = 0 & & * ptr = = ' / ' & & + + ptr & & + + tok ) ;
if ( ! ptr & & ( path_length - ( tok - path ) ) ) {
ptr_length = path_length - ( tok - path ) ;
ptr = path + path_length ;
goto last_time ;
}
2007-12-21 07:12:40 +08:00
}
2008-08-01 21:45:06 +08:00
efree ( path ) ;
* new_len = newpath_len ;
return estrndup ( newpath , newpath_len ) ;
2007-12-21 07:12:40 +08:00
}
/* }}} */
2007-01-02 08:04:30 +08:00
/**
* Process a phar stream name , ensuring we can handle any of :
*
* - whatever . phar
* - whatever . phar . gz
* - whatever . phar . bz2
2007-05-16 04:21:19 +08:00
* - whatever . phar . php
*
* Optionally the name might start with ' phar : //'
2007-01-02 08:04:30 +08:00
*
2008-05-31 06:39:33 +08:00
* This is used by phar_parse_url ( )
2007-01-02 08:04:30 +08:00
*/
2008-04-18 12:13:13 +08:00
int phar_split_fname ( char * filename , int filename_len , char * * arch , int * arch_len , char * * entry , int * entry_len , int executable , int for_create TSRMLS_DC ) /* { { { */
2006-01-04 10:26:15 +08:00
{
2008-03-22 08:11:43 +08:00
const char * ext_str ;
2008-04-21 14:17:51 +08:00
# ifdef PHP_WIN32
2008-04-20 12:10:51 +08:00
char * save ;
2008-04-21 14:17:51 +08:00
# endif
2008-04-20 01:57:24 +08:00
int ext_len , free_filename = 0 ;
2006-01-04 10:26:15 +08:00
if ( ! strncasecmp ( filename , " phar:// " , 7 ) ) {
filename + = 7 ;
2006-02-28 09:36:30 +08:00
filename_len - = 7 ;
}
2007-11-20 13:34:35 +08:00
ext_len = 0 ;
2008-04-20 01:57:24 +08:00
# ifdef PHP_WIN32
free_filename = 1 ;
2008-04-20 12:10:51 +08:00
save = filename ;
2008-04-20 01:57:24 +08:00
filename = estrndup ( filename , filename_len ) ;
phar_unixify_path_separators ( filename , filename_len ) ;
# endif
2008-08-01 21:45:06 +08:00
if ( phar_detect_phar_fname_ext ( filename , filename_len , & ext_str , & ext_len , executable , for_create , 0 TSRMLS_CC ) = = FAILURE ) {
2007-11-20 13:34:35 +08:00
if ( ext_len ! = - 1 ) {
2007-11-22 13:47:28 +08:00
if ( ! ext_str ) {
/* no / detected, restore arch for error message */
2008-04-21 14:17:51 +08:00
# ifdef PHP_WIN32
2008-04-20 12:10:51 +08:00
* arch = save ;
2008-04-21 14:17:51 +08:00
# else
* arch = filename ;
# endif
2007-11-22 13:47:28 +08:00
}
2008-08-01 21:45:06 +08:00
2008-04-20 01:57:24 +08:00
if ( free_filename ) {
efree ( filename ) ;
}
2008-08-01 21:45:06 +08:00
2007-11-20 13:34:35 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2007-11-20 13:34:35 +08:00
ext_len = 0 ;
/* no extension detected - instead we are dealing with an alias */
2006-02-28 09:36:30 +08:00
}
2007-05-16 04:21:19 +08:00
2006-02-28 09:36:30 +08:00
* arch_len = ext_str - filename + ext_len ;
* arch = estrndup ( filename , * arch_len ) ;
2008-08-01 21:45:06 +08:00
2006-02-28 09:36:30 +08:00
if ( ext_str [ ext_len ] ) {
* entry_len = filename_len - * arch_len ;
* entry = estrndup ( ext_str + ext_len , * entry_len ) ;
2007-11-20 07:10:05 +08:00
# ifdef PHP_WIN32
phar_unixify_path_separators ( * entry , * entry_len ) ;
# endif
2008-01-11 05:21:38 +08:00
* entry = phar_fix_filepath ( * entry , entry_len , 0 TSRMLS_CC ) ;
2006-02-28 09:36:30 +08:00
} else {
* entry_len = 1 ;
* entry = estrndup ( " / " , 1 ) ;
}
2008-08-01 21:45:06 +08:00
2008-04-20 01:57:24 +08:00
if ( free_filename ) {
efree ( filename ) ;
}
2008-08-01 21:45:06 +08:00
2006-02-28 09:36:30 +08:00
return SUCCESS ;
}
/* }}} */
2005-12-05 04:35:38 +08:00
2007-01-02 08:04:30 +08:00
/**
* Invoked when a user calls Phar : : mapPhar ( ) from within an executing . phar
* to set up its manifest directly
*/
2008-05-31 06:39:33 +08:00
int phar_open_executed_filename ( char * alias , int alias_len , char * * error TSRMLS_DC ) /* { { { */
2006-01-04 10:26:15 +08:00
{
char * fname ;
zval * halt_constant ;
php_stream * fp ;
2008-05-08 08:49:37 +08:00
int fname_len ;
2008-05-29 05:50:41 +08:00
char * actual = NULL ;
int ret ;
2006-01-04 10:26:15 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
* error = NULL ;
}
2008-08-01 21:45:06 +08:00
2006-01-04 10:26:15 +08:00
fname = zend_get_executed_filename ( TSRMLS_C ) ;
2007-01-11 09:04:47 +08:00
fname_len = strlen ( fname ) ;
2008-05-31 06:39:33 +08:00
if ( phar_open_parsed_phar ( fname , fname_len , alias , alias_len , 0 , REPORT_ERRORS , NULL , 0 TSRMLS_CC ) = = SUCCESS ) {
2007-01-11 09:04:47 +08:00
return SUCCESS ;
}
2006-01-04 10:26:15 +08:00
if ( ! strcmp ( fname , " [no active file] " ) ) {
2007-01-29 14:02:19 +08:00
if ( error ) {
spprintf ( error , 0 , " cannot initialize a phar outside of PHP execution " ) ;
}
2006-01-04 10:26:15 +08:00
return FAILURE ;
}
MAKE_STD_ZVAL ( halt_constant ) ;
2008-08-01 21:45:06 +08:00
2006-01-04 10:26:15 +08:00
if ( 0 = = zend_get_constant ( " __COMPILER_HALT_OFFSET__ " , 24 , halt_constant TSRMLS_CC ) ) {
2006-01-07 04:43:19 +08:00
FREE_ZVAL ( halt_constant ) ;
2007-01-29 14:02:19 +08:00
if ( error ) {
spprintf ( error , 0 , " __HALT_COMPILER(); must be declared in a phar " ) ;
}
2006-01-04 10:26:15 +08:00
return FAILURE ;
}
2008-08-01 21:45:06 +08:00
2007-01-11 09:04:47 +08:00
FREE_ZVAL ( halt_constant ) ;
2006-01-04 10:26:15 +08:00
2008-05-29 05:50:41 +08:00
# if PHP_MAJOR_VERSION < 6
if ( PG ( safe_mode ) & & ( ! php_checkuid ( fname , NULL , CHECKUID_ALLOW_ONLY_FILE ) ) ) {
2008-08-01 21:45:06 +08:00
return FAILURE ;
}
2008-05-29 05:50:41 +08:00
# endif
if ( php_check_open_basedir ( fname TSRMLS_CC ) ) {
return FAILURE ;
2008-08-01 21:45:06 +08:00
}
2008-05-29 05:50:41 +08:00
fp = php_stream_open_wrapper ( fname , " rb " , IGNORE_URL | STREAM_MUST_SEEK | REPORT_ERRORS , & actual ) ;
2008-08-01 21:45:06 +08:00
2006-01-04 10:26:15 +08:00
if ( ! fp ) {
2008-08-01 21:45:06 +08:00
if ( error ) {
2007-01-29 14:02:19 +08:00
spprintf ( error , 0 , " unable to open phar for reading \" %s \" " , fname ) ;
2008-08-01 21:45:06 +08:00
}
2008-05-29 05:50:41 +08:00
if ( actual ) {
2008-08-01 21:45:06 +08:00
efree ( actual ) ;
}
2006-01-04 10:26:15 +08:00
return FAILURE ;
2008-08-01 21:45:06 +08:00
}
2006-01-04 10:26:15 +08:00
2008-05-29 05:50:41 +08:00
if ( actual ) {
2008-08-01 21:45:06 +08:00
fname = actual ;
2008-05-29 05:50:41 +08:00
fname_len = strlen ( actual ) ;
2008-08-01 21:45:06 +08:00
}
2008-05-29 05:50:41 +08:00
2008-05-31 06:39:33 +08:00
ret = phar_open_from_fp ( fp , fname , fname_len , alias , alias_len , REPORT_ERRORS , NULL , error TSRMLS_CC ) ;
2008-08-01 21:45:06 +08:00
if ( actual ) {
2008-05-29 05:50:41 +08:00
efree ( actual ) ;
2008-08-01 21:45:06 +08:00
}
return ret ;
2006-01-04 10:26:15 +08:00
}
/* }}} */
2007-01-02 08:04:30 +08:00
/**
* Validate the CRC32 of a file opened from within the phar
*/
2008-09-01 04:54:28 +08:00
int phar_postprocess_file ( phar_entry_data * idata , php_uint32 crc32 , char * * error , int process_zip TSRMLS_DC ) /* { { { */
2005-12-05 04:35:38 +08:00
{
2007-01-08 03:05:12 +08:00
php_uint32 crc = ~ 0 ;
2006-01-06 06:24:41 +08:00
int len = idata - > internal_file - > uncompressed_filesize ;
2007-01-10 07:57:03 +08:00
php_stream * fp = idata - > fp ;
2008-01-28 16:52:08 +08:00
phar_entry_info * entry = idata - > internal_file ;
2007-08-17 12:47:50 +08:00
if ( error ) {
* error = NULL ;
}
2008-08-01 21:45:06 +08:00
2008-09-01 04:54:28 +08:00
if ( entry - > is_zip & & process_zip > 0 ) {
2008-01-28 16:52:08 +08:00
/* verify local file header */
phar_zip_file_header local ;
2008-01-01 06:42:40 +08:00
2008-01-28 16:52:08 +08:00
if ( SUCCESS ! = phar_open_archive_fp ( idata - > phar TSRMLS_CC ) ) {
spprintf ( error , 0 , " phar error: unable to open zip-based phar archive \" %s \" to verify local file header for file \" %s \" " , idata - > phar - > fname , entry - > filename ) ;
return FAILURE ;
2008-01-01 06:42:40 +08:00
}
2008-08-01 21:45:06 +08:00
php_stream_seek ( phar_get_entrypfp ( idata - > internal_file TSRMLS_CC ) , entry - > header_offset , SEEK_SET ) ;
2008-01-01 06:42:40 +08:00
2008-08-01 21:45:06 +08:00
if ( sizeof ( local ) ! = php_stream_read ( phar_get_entrypfp ( idata - > internal_file TSRMLS_CC ) , ( char * ) & local , sizeof ( local ) ) ) {
2007-08-17 12:47:50 +08:00
2008-01-28 16:52:08 +08:00
spprintf ( error , 0 , " phar error: internal corruption of zip-based phar \" %s \" (cannot read local file header for file \" %s \" ) " , idata - > phar - > fname , entry - > filename ) ;
return FAILURE ;
2007-08-17 12:47:50 +08:00
}
2008-08-01 21:45:06 +08:00
2008-05-30 01:34:58 +08:00
/* verify local header */
2008-04-16 03:16:47 +08:00
if ( entry - > filename_len ! = PHAR_ZIP_16 ( local . filename_len ) | | entry - > crc32 ! = PHAR_ZIP_32 ( local . crc32 ) | | entry - > uncompressed_filesize ! = PHAR_ZIP_32 ( local . uncompsize ) | | entry - > compressed_filesize ! = PHAR_ZIP_32 ( local . compsize ) ) {
2008-01-28 16:52:08 +08:00
spprintf ( error , 0 , " phar error: internal corruption of zip-based phar \" %s \" (local head of file \" %s \" does not match central directory) " , idata - > phar - > fname , entry - > filename ) ;
return FAILURE ;
2007-12-12 03:21:01 +08:00
}
2008-08-01 21:45:06 +08:00
2008-05-30 01:34:58 +08:00
/* construct actual offset to file start - local extra_len can be different from central extra_len */
entry - > offset = entry - > offset_abs =
sizeof ( local ) + entry - > header_offset + PHAR_ZIP_16 ( local . filename_len ) + PHAR_ZIP_16 ( local . extra_len ) ;
2008-08-01 21:45:06 +08:00
2008-05-31 06:49:46 +08:00
if ( idata - > zero & & idata - > zero ! = entry - > offset_abs ) {
2008-05-30 01:34:58 +08:00
idata - > zero = entry - > offset_abs ;
2007-08-17 12:47:50 +08:00
}
}
2008-08-01 21:45:06 +08:00
2008-09-01 04:54:28 +08:00
if ( process_zip = = 1 ) {
return SUCCESS ;
}
2008-08-01 21:45:06 +08:00
php_stream_seek ( fp , idata - > zero , SEEK_SET ) ;
2008-01-28 16:52:08 +08:00
while ( len - - ) {
CRC32 ( crc , php_stream_getc ( fp ) ) ;
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
php_stream_seek ( fp , idata - > zero , SEEK_SET ) ;
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( ~ crc = = crc32 ) {
entry - > is_crc_checked = 1 ;
return SUCCESS ;
} else {
2008-09-01 04:54:28 +08:00
spprintf ( error , 0 , " phar error: internal corruption of phar \" %s \" (crc32 mismatch on file \" %s \" ) " , idata - > phar - > fname , entry - > filename ) ;
2008-01-28 16:52:08 +08:00
return FAILURE ;
}
2007-08-17 12:47:50 +08:00
}
2008-01-28 16:52:08 +08:00
/* }}} */
2007-08-17 12:47:50 +08:00
2007-01-03 04:25:04 +08:00
static inline void phar_set_32 ( char * buffer , int var ) /* { { { */
{
# ifdef WORDS_BIGENDIAN
2007-01-03 06:57:47 +08:00
* ( ( buffer ) + 3 ) = ( unsigned char ) ( ( ( var ) > > 24 ) & 0xFF ) ;
* ( ( buffer ) + 2 ) = ( unsigned char ) ( ( ( var ) > > 16 ) & 0xFF ) ;
* ( ( buffer ) + 1 ) = ( unsigned char ) ( ( ( var ) > > 8 ) & 0xFF ) ;
2007-01-03 04:25:04 +08:00
* ( ( buffer ) + 0 ) = ( unsigned char ) ( ( var ) & 0xFF ) ;
# else
2007-01-03 05:01:44 +08:00
* ( php_uint32 * ) ( buffer ) = ( php_uint32 ) ( var ) ;
2007-01-03 04:25:04 +08:00
# endif
} /* }}} */
2007-01-28 07:02:42 +08:00
static int phar_flush_clean_deleted_apply ( void * data TSRMLS_DC ) /* { { { */
{
phar_entry_info * entry = ( phar_entry_info * ) data ;
if ( entry - > fp_refcount < = 0 & & entry - > is_deleted ) {
return ZEND_HASH_APPLY_REMOVE ;
} else {
return ZEND_HASH_APPLY_KEEP ;
}
}
/* }}} */
2008-01-19 12:26:22 +08:00
# include "stub.h"
2008-01-20 08:49:45 +08:00
2008-08-01 21:45:06 +08:00
char * phar_create_default_stub ( const char * index_php , const char * web_index , size_t * len , char * * error TSRMLS_DC ) /* { { { */
2008-01-20 08:49:45 +08:00
{
2008-01-19 12:26:22 +08:00
char * stub = NULL ;
2008-02-19 05:45:02 +08:00
int index_len , web_len ;
2008-01-19 12:26:22 +08:00
size_t dummy ;
if ( ! len ) {
len = & dummy ;
}
if ( error ) {
* error = NULL ;
}
2008-02-19 05:45:02 +08:00
2008-02-21 08:24:38 +08:00
if ( ! index_php ) {
2008-02-19 05:45:02 +08:00
index_php = " index.php " ;
}
if ( ! web_index ) {
web_index = " index.php " ;
}
index_len = strlen ( index_php ) ;
web_len = strlen ( web_index ) ;
if ( index_len > 400 ) {
/* ridiculous size not allowed for index.php startup filename */
2008-01-19 12:26:22 +08:00
if ( error ) {
2008-02-19 05:45:02 +08:00
spprintf ( error , 0 , " Illegal filename passed in for stub creation, was %d characters long, and only 400 or less is allowed " , index_len ) ;
2008-01-19 12:26:22 +08:00
return NULL ;
}
}
2008-02-19 05:45:02 +08:00
if ( web_len > 400 ) {
/* ridiculous size not allowed for index.php startup filename */
2008-01-20 08:49:45 +08:00
if ( error ) {
spprintf ( error , 0 , " Illegal web filename passed in for stub creation, was %d characters long, and only 400 or less is allowed " , web_len ) ;
return NULL ;
}
}
2008-02-19 05:45:02 +08:00
phar_get_stub ( index_php , web_index , len , & stub , index_len + 1 , web_len + 1 TSRMLS_CC ) ;
2008-01-19 12:26:22 +08:00
return stub ;
}
2008-08-01 21:45:06 +08:00
/* }}} */
2007-01-22 07:22:57 +08:00
/**
* Save phar contents to disk
*
* user_stub contains either a string , or a resource pointer , if len is a negative length .
* user_stub and len should be both 0 if the default or existing stub should be used
*/
2008-02-25 06:29:06 +08:00
int phar_flush ( phar_archive_data * phar , char * user_stub , long len , int convert , char * * error TSRMLS_DC ) /* { { { */
2007-01-08 03:45:31 +08:00
{
2008-01-18 13:42:16 +08:00
/* static const char newstub[] = "<?php __HALT_COMPILER(); ?>\r\n"; */
2008-01-19 12:26:22 +08:00
char * newstub ;
2007-08-17 12:47:50 +08:00
phar_entry_info * entry , * newentry ;
2007-02-06 04:34:23 +08:00
int halt_offset , restore_alias_len , global_flags = 0 , closeoldfile ;
2008-01-28 16:52:08 +08:00
char * pos , has_dirs = 0 ;
2007-01-21 14:30:55 +08:00
char manifest [ 18 ] , entry_buffer [ 24 ] ;
2007-01-10 07:57:03 +08:00
off_t manifest_ftell ;
2007-01-04 13:32:45 +08:00
long offset ;
2007-05-27 23:47:52 +08:00
size_t wrote ;
2007-01-27 23:31:24 +08:00
php_uint32 manifest_len , mytime , loc , new_manifest_count ;
2007-10-04 11:33:21 +08:00
php_uint32 newcrc32 ;
2007-01-27 23:31:24 +08:00
php_stream * file , * oldfile , * newfile , * stubfile ;
2007-01-03 02:15:17 +08:00
php_stream_filter * filter ;
2007-01-22 04:12:50 +08:00
php_serialize_data_t metadata_hash ;
2007-05-15 03:36:09 +08:00
smart_str main_metadata_str = { 0 } ;
2008-04-27 15:04:56 +08:00
int free_user_stub , free_fp = 1 , free_ufp = 1 ;
2007-01-03 02:15:17 +08:00
2008-08-01 21:45:06 +08:00
if ( phar - > is_persistent ) {
if ( error ) {
spprintf ( error , 0 , " internal error: attempt to flush cached zip-based phar \" %s \" " , phar - > fname ) ;
}
return EOF ;
2007-02-07 01:09:37 +08:00
}
2008-08-01 21:45:06 +08:00
if ( error ) {
* error = NULL ;
2007-01-08 00:01:35 +08:00
}
2007-01-10 06:30:56 +08:00
2008-04-29 20:26:58 +08:00
if ( ! zend_hash_num_elements ( & phar - > manifest ) & & ! user_stub ) {
2008-04-29 20:06:54 +08:00
return EOF ;
}
2008-10-13 03:40:30 +08:00
zend_hash_clean ( & phar - > virtual_dirs ) ;
2008-01-09 15:09:04 +08:00
if ( phar - > is_zip ) {
2008-02-25 06:29:06 +08:00
return phar_zip_flush ( phar , user_stub , len , convert , error TSRMLS_CC ) ;
2008-01-01 06:42:40 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
if ( phar - > is_tar ) {
2008-02-25 06:29:06 +08:00
return phar_tar_flush ( phar , user_stub , len , convert , error TSRMLS_CC ) ;
2008-01-03 12:45:00 +08:00
}
2008-02-25 06:29:06 +08:00
2008-08-01 21:45:06 +08:00
if ( PHAR_G ( readonly ) ) {
return EOF ;
}
2008-01-09 15:09:04 +08:00
if ( phar - > fp & & ! phar - > is_brandnew ) {
oldfile = phar - > fp ;
2007-01-29 05:26:54 +08:00
closeoldfile = 0 ;
php_stream_rewind ( oldfile ) ;
2007-01-29 03:56:09 +08:00
} else {
2008-01-09 15:09:04 +08:00
oldfile = php_stream_open_wrapper ( phar - > fname , " rb " , 0 , NULL ) ;
2007-01-29 05:26:54 +08:00
closeoldfile = oldfile ! = NULL ;
2007-01-26 22:52:10 +08:00
}
2007-01-03 02:15:17 +08:00
newfile = php_stream_fopen_tmpfile ( ) ;
2007-02-06 06:11:27 +08:00
if ( ! newfile ) {
if ( error ) {
spprintf ( error , 0 , " unable to create temporary file " ) ;
}
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
return EOF ;
}
2007-01-03 02:15:17 +08:00
2007-01-27 23:31:24 +08:00
if ( user_stub ) {
2007-01-22 07:22:57 +08:00
if ( len < 0 ) {
/* resource passed in */
if ( ! ( php_stream_from_zval_no_verify ( stubfile , ( zval * * ) user_stub ) ) ) {
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-22 07:22:57 +08:00
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to access resource to copy stub to new phar \" %s \" " , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-22 07:22:57 +08:00
return EOF ;
}
if ( len = = - 1 ) {
len = PHP_STREAM_COPY_ALL ;
} else {
len = - len ;
}
2007-05-28 00:54:37 +08:00
user_stub = 0 ;
if ( ! ( len = php_stream_copy_to_mem ( stubfile , & user_stub , len , 0 ) ) | | ! user_stub ) {
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-22 07:22:57 +08:00
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to read resource to copy stub to new phar \" %s \" " , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-22 07:22:57 +08:00
return EOF ;
}
2007-05-28 00:54:37 +08:00
free_user_stub = 1 ;
2007-01-22 07:22:57 +08:00
} else {
2007-05-28 00:54:37 +08:00
free_user_stub = 0 ;
}
if ( ( pos = strstr ( user_stub , " __HALT_COMPILER(); " ) ) = = NULL )
{
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
2007-02-06 04:47:20 +08:00
}
2007-05-28 00:54:37 +08:00
php_stream_close ( newfile ) ;
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " illegal stub for phar \" %s \" " , phar - > fname ) ;
2007-05-28 00:54:37 +08:00
}
if ( free_user_stub ) {
efree ( user_stub ) ;
2007-01-10 02:54:37 +08:00
}
2007-05-28 00:54:37 +08:00
return EOF ;
}
len = pos - user_stub + 18 ;
if ( ( size_t ) len ! = php_stream_write ( newfile , user_stub , len )
2008-08-01 21:45:06 +08:00
| | 5 ! = php_stream_write ( newfile , " ?> \r \n " , 5 ) ) {
2007-05-28 00:54:37 +08:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to create stub from string in new phar \" %s \" " , phar - > fname ) ;
2007-05-28 00:54:37 +08:00
}
if ( free_user_stub ) {
efree ( user_stub ) ;
}
return EOF ;
}
2008-01-09 15:09:04 +08:00
phar - > halt_offset = len + 5 ;
2007-05-28 00:54:37 +08:00
if ( free_user_stub ) {
efree ( user_stub ) ;
2007-01-03 02:15:17 +08:00
}
2007-01-05 11:04:56 +08:00
} else {
2008-04-22 00:50:18 +08:00
size_t written ;
2008-02-25 06:29:06 +08:00
if ( ! user_stub & & phar - > halt_offset & & oldfile & & ! phar - > is_brandnew ) {
2008-04-22 00:50:18 +08:00
written = php_stream_copy_to_stream ( oldfile , newfile , phar - > halt_offset ) ;
newstub = NULL ;
2007-01-22 07:22:57 +08:00
} else {
2008-02-25 06:29:06 +08:00
/* this is either a brand new phar or a default stub overwrite */
2008-01-20 08:49:45 +08:00
newstub = phar_create_default_stub ( NULL , NULL , & ( phar - > halt_offset ) , NULL TSRMLS_CC ) ;
2008-04-22 00:50:18 +08:00
written = php_stream_write ( newfile , newstub , phar - > halt_offset ) ;
}
if ( phar - > halt_offset ! = written ) {
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
if ( error ) {
if ( newstub ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to create stub in new phar \" %s \" " , phar - > fname ) ;
2008-04-22 00:50:18 +08:00
} else {
spprintf ( error , 0 , " unable to copy stub of old phar to new phar \" %s \" " , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-10 02:54:37 +08:00
}
2008-04-22 00:50:18 +08:00
if ( newstub ) {
efree ( newstub ) ;
}
return EOF ;
}
if ( newstub ) {
2008-01-19 12:26:22 +08:00
efree ( newstub ) ;
2007-01-05 11:04:56 +08:00
}
2007-01-03 02:15:17 +08:00
}
2007-01-03 03:59:38 +08:00
manifest_ftell = php_stream_tell ( newfile ) ;
2007-01-22 07:22:57 +08:00
halt_offset = manifest_ftell ;
2007-01-28 07:02:42 +08:00
/* Check whether we can get rid of some of the deleted entries which are
* unused . However some might still be in use so even after this clean - up
* we need to skip entries marked is_deleted . */
2008-01-09 15:09:04 +08:00
zend_hash_apply ( & phar - > manifest , phar_flush_clean_deleted_apply TSRMLS_CC ) ;
2007-01-28 07:02:42 +08:00
2007-01-29 11:59:55 +08:00
/* compress as necessary, calculate crcs, serialize meta-data, manifest size, and file sizes */
2007-05-15 03:36:09 +08:00
main_metadata_str . c = 0 ;
2008-01-09 15:09:04 +08:00
if ( phar - > metadata ) {
2007-01-29 11:59:55 +08:00
PHP_VAR_SERIALIZE_INIT ( metadata_hash ) ;
2008-01-09 15:09:04 +08:00
php_var_serialize ( & main_metadata_str , & phar - > metadata , & metadata_hash TSRMLS_CC ) ;
2007-01-29 11:59:55 +08:00
PHP_VAR_SERIALIZE_DESTROY ( metadata_hash ) ;
} else {
2007-05-15 03:36:09 +08:00
main_metadata_str . len = 0 ;
2007-01-29 11:59:55 +08:00
}
2007-01-04 13:32:45 +08:00
new_manifest_count = 0 ;
offset = 0 ;
2008-01-09 15:09:04 +08:00
for ( zend_hash_internal_pointer_reset ( & phar - > manifest ) ;
2008-08-01 21:45:06 +08:00
zend_hash_has_more_elements ( & phar - > manifest ) = = SUCCESS ;
zend_hash_move_forward ( & phar - > manifest ) ) {
2008-01-09 15:09:04 +08:00
if ( zend_hash_get_current_data ( & phar - > manifest , ( void * * ) & entry ) = = FAILURE ) {
2007-01-03 02:15:17 +08:00
continue ;
}
2007-01-27 23:31:24 +08:00
if ( entry - > cfp ) {
/* did we forget to get rid of cfp last time? */
php_stream_close ( entry - > cfp ) ;
entry - > cfp = 0 ;
}
2008-05-08 10:58:45 +08:00
if ( entry - > is_deleted | | entry - > is_mounted ) {
2007-01-03 02:15:17 +08:00
/* remove this from the new phar */
continue ;
}
2008-04-27 15:04:56 +08:00
if ( ! entry - > is_modified & & entry - > fp_refcount ) {
/* open file pointers refer to this fp, do not free the stream */
switch ( entry - > fp_type ) {
case PHAR_FP :
free_fp = 0 ;
break ;
case PHAR_UFP :
free_ufp = 0 ;
default :
break ;
}
}
2007-01-04 13:32:45 +08:00
/* after excluding deleted files, calculate manifest size in bytes and number of entries */
+ + new_manifest_count ;
2008-10-13 05:09:10 +08:00
phar_add_virtual_dirs ( phar , entry - > filename , entry - > filename_len TSRMLS_CC ) ;
2007-01-04 13:32:45 +08:00
2008-01-20 02:30:30 +08:00
if ( entry - > is_dir ) {
/* we use this to calculate API version, 1.1.1 is used for phars with directories */
has_dirs = 1 ;
}
2007-05-15 02:59:04 +08:00
if ( entry - > metadata ) {
2007-05-15 03:14:00 +08:00
if ( entry - > metadata_str . c ) {
smart_str_free ( & entry - > metadata_str ) ;
}
2007-05-15 03:36:09 +08:00
entry - > metadata_str . c = 0 ;
entry - > metadata_str . len = 0 ;
2007-05-15 02:59:04 +08:00
PHP_VAR_SERIALIZE_INIT ( metadata_hash ) ;
2007-05-15 03:14:00 +08:00
php_var_serialize ( & entry - > metadata_str , & entry - > metadata , & metadata_hash TSRMLS_CC ) ;
2007-05-15 02:59:04 +08:00
PHP_VAR_SERIALIZE_DESTROY ( metadata_hash ) ;
2007-05-15 03:14:00 +08:00
} else {
2008-01-28 16:52:08 +08:00
if ( entry - > metadata_str . c ) {
smart_str_free ( & entry - > metadata_str ) ;
}
2007-05-15 03:36:09 +08:00
entry - > metadata_str . c = 0 ;
2007-05-15 03:14:00 +08:00
entry - > metadata_str . len = 0 ;
2007-05-15 02:59:04 +08:00
}
2008-01-09 11:47:22 +08:00
/* 32 bits for filename length, length of filename, manifest + metadata, and add 1 for trailing / if a directory */
offset + = 4 + entry - > filename_len + sizeof ( entry_buffer ) + entry - > metadata_str . len + ( entry - > is_dir ? 1 : 0 ) ;
2007-05-15 03:14:00 +08:00
2007-01-27 23:31:24 +08:00
/* compress and rehash as necessary */
2008-04-14 23:21:41 +08:00
if ( ( oldfile & & ! entry - > is_modified ) | | entry - > is_dir ) {
2008-04-24 12:56:22 +08:00
if ( entry - > fp_type = = PHAR_UFP ) {
/* reset so we can copy the compressed data over */
entry - > fp_type = PHAR_FP ;
}
2007-01-22 11:41:41 +08:00
continue ;
}
2008-04-21 14:17:51 +08:00
if ( ! phar_get_efp ( entry , 0 TSRMLS_CC ) ) {
2007-08-17 12:47:50 +08:00
/* re-open internal file pointer just-in-time */
2008-09-14 06:31:18 +08:00
newentry = phar_open_jit ( phar , entry , error TSRMLS_CC ) ;
2007-08-17 12:47:50 +08:00
if ( ! newentry ) {
/* major problem re-opening, so we ignore this file and the error */
efree ( * error ) ;
* error = NULL ;
continue ;
}
entry = newentry ;
2007-01-22 11:41:41 +08:00
}
2008-04-21 14:17:51 +08:00
file = phar_get_efp ( entry , 0 TSRMLS_CC ) ;
if ( - 1 = = phar_seek_efp ( entry , 0 , SEEK_SET , 0 , 1 TSRMLS_CC ) ) {
2008-01-28 16:52:08 +08:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
2007-08-30 10:30:16 +08:00
}
2008-01-28 16:52:08 +08:00
php_stream_close ( newfile ) ;
if ( error ) {
spprintf ( error , 0 , " unable to seek to start of file \" %s \" while creating new phar \" %s \" " , entry - > filename , phar - > fname ) ;
}
return EOF ;
2007-08-30 10:30:16 +08:00
}
2007-01-22 11:41:41 +08:00
newcrc32 = ~ 0 ;
mytime = entry - > uncompressed_filesize ;
2008-03-23 06:11:49 +08:00
for ( loc = 0 ; loc < mytime ; + + loc ) {
2007-01-22 11:41:41 +08:00
CRC32 ( newcrc32 , php_stream_getc ( file ) ) ;
}
entry - > crc32 = ~ newcrc32 ;
entry - > is_crc_checked = 1 ;
if ( ! ( entry - > flags & PHAR_ENT_COMPRESSION_MASK ) ) {
2007-01-27 23:31:24 +08:00
/* not compressed */
2007-05-27 23:47:52 +08:00
entry - > compressed_filesize = entry - > uncompressed_filesize ;
2007-01-22 11:41:41 +08:00
continue ;
}
filter = php_stream_filter_create ( phar_compress_filter ( entry , 0 ) , NULL , 0 TSRMLS_CC ) ;
if ( ! filter ) {
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-22 10:04:51 +08:00
php_stream_close ( oldfile ) ;
2007-01-03 05:01:44 +08:00
}
2007-01-22 11:41:41 +08:00
php_stream_close ( newfile ) ;
if ( entry - > flags & PHAR_ENT_COMPRESSED_GZ ) {
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to gzip compress file \" %s \" to new phar \" %s \" " , entry - > filename , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-22 11:41:41 +08:00
} else {
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to bzip2 compress file \" %s \" to new phar \" %s \" " , entry - > filename , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-22 11:41:41 +08:00
}
return EOF ;
2007-01-03 02:15:17 +08:00
}
2007-01-22 11:41:41 +08:00
/* create new file that holds the compressed version */
/* work around inability to specify freedom in write and strictness
in read count */
2007-01-27 23:31:24 +08:00
entry - > cfp = php_stream_fopen_tmpfile ( ) ;
2007-02-06 06:11:27 +08:00
if ( ! entry - > cfp ) {
if ( error ) {
spprintf ( error , 0 , " unable to create temporary file " ) ;
}
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
return EOF ;
}
2007-05-27 23:47:52 +08:00
php_stream_flush ( file ) ;
2008-04-21 14:17:51 +08:00
if ( - 1 = = phar_seek_efp ( entry , 0 , SEEK_SET , 0 , 0 TSRMLS_CC ) ) {
2008-01-28 16:52:08 +08:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
2007-08-30 10:30:16 +08:00
}
2008-01-28 16:52:08 +08:00
php_stream_close ( newfile ) ;
if ( error ) {
spprintf ( error , 0 , " unable to seek to start of file \" %s \" while creating new phar \" %s \" " , entry - > filename , phar - > fname ) ;
}
return EOF ;
}
php_stream_filter_append ( ( & entry - > cfp - > writefilters ) , filter ) ;
if ( entry - > uncompressed_filesize ! = php_stream_copy_to_stream ( file , entry - > cfp , entry - > uncompressed_filesize ) ) {
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
if ( error ) {
spprintf ( error , 0 , " unable to copy compressed file contents of file \" %s \" while creating new phar \" %s \" " , entry - > filename , phar - > fname ) ;
}
return EOF ;
2007-08-30 10:30:16 +08:00
}
2007-12-14 13:39:20 +08:00
php_stream_filter_flush ( filter , 1 ) ;
2008-01-28 16:52:08 +08:00
php_stream_flush ( entry - > cfp ) ;
2007-01-22 11:41:41 +08:00
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
2008-01-28 16:52:08 +08:00
php_stream_seek ( entry - > cfp , 0 , SEEK_END ) ;
entry - > compressed_filesize = ( php_uint32 ) php_stream_tell ( entry - > cfp ) ;
2007-01-22 11:41:41 +08:00
/* generate crc on compressed file */
2007-01-27 23:31:24 +08:00
php_stream_rewind ( entry - > cfp ) ;
2007-08-17 12:47:50 +08:00
entry - > old_flags = entry - > flags ;
2007-01-22 11:41:41 +08:00
entry - > is_modified = 1 ;
global_flags | = ( entry - > flags & PHAR_ENT_COMPRESSION_MASK ) ;
2007-01-03 02:15:17 +08:00
}
2007-01-14 00:17:04 +08:00
global_flags | = PHAR_HDR_SIGNATURE ;
2007-01-04 13:32:45 +08:00
/* write out manifest pre-header */
2007-01-14 00:17:04 +08:00
/* 4: manifest length
* 4 : manifest entry count
* 2 : phar version
* 4 : phar global flags
2007-01-29 11:59:55 +08:00
* 4 : alias length
* ? : the alias itself
* 4 : phar metadata length
* ? : phar metadata
2007-01-14 00:17:04 +08:00
*/
2008-01-09 15:09:04 +08:00
restore_alias_len = phar - > alias_len ;
2008-02-11 14:46:44 +08:00
if ( phar - > is_temporary_alias ) {
2008-01-09 15:09:04 +08:00
phar - > alias_len = 0 ;
2007-01-05 12:45:52 +08:00
}
2007-01-09 07:03:41 +08:00
2008-01-09 15:09:04 +08:00
manifest_len = offset + phar - > alias_len + sizeof ( manifest ) + main_metadata_str . len ;
2007-01-27 23:31:24 +08:00
phar_set_32 ( manifest , manifest_len ) ;
2007-01-14 00:17:04 +08:00
phar_set_32 ( manifest + 4 , new_manifest_count ) ;
2008-01-20 02:30:30 +08:00
if ( has_dirs ) {
* ( manifest + 8 ) = ( unsigned char ) ( ( ( PHAR_API_VERSION ) > > 8 ) & 0xFF ) ;
* ( manifest + 9 ) = ( unsigned char ) ( ( ( PHAR_API_VERSION ) & 0xF0 ) ) ;
} else {
* ( manifest + 8 ) = ( unsigned char ) ( ( ( PHAR_API_VERSION_NODIR ) > > 8 ) & 0xFF ) ;
* ( manifest + 9 ) = ( unsigned char ) ( ( ( PHAR_API_VERSION_NODIR ) & 0xF0 ) ) ;
}
2007-01-14 00:17:04 +08:00
phar_set_32 ( manifest + 10 , global_flags ) ;
2008-01-09 15:09:04 +08:00
phar_set_32 ( manifest + 14 , phar - > alias_len ) ;
2007-01-04 13:32:45 +08:00
/* write the manifest header */
2007-01-14 00:17:04 +08:00
if ( sizeof ( manifest ) ! = php_stream_write ( newfile , manifest , sizeof ( manifest ) )
2008-01-09 15:09:04 +08:00
| | ( size_t ) phar - > alias_len ! = php_stream_write ( newfile , phar - > alias , phar - > alias_len ) ) {
2008-08-01 21:45:06 +08:00
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-10 06:30:56 +08:00
php_stream_close ( oldfile ) ;
2007-01-10 02:54:37 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-03 23:43:07 +08:00
php_stream_close ( newfile ) ;
2008-01-09 15:09:04 +08:00
phar - > alias_len = restore_alias_len ;
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to write manifest header of new phar \" %s \" " , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-08 00:01:35 +08:00
return EOF ;
2007-01-03 05:01:44 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
phar - > alias_len = restore_alias_len ;
2008-08-01 21:45:06 +08:00
2007-05-15 03:36:09 +08:00
phar_set_32 ( manifest , main_metadata_str . len ) ;
2008-04-22 00:46:01 +08:00
if ( 4 ! = php_stream_write ( newfile , manifest , 4 ) | | ( main_metadata_str . len
& & main_metadata_str . len ! = php_stream_write ( newfile , main_metadata_str . c , main_metadata_str . len ) ) ) {
smart_str_free ( & main_metadata_str ) ;
2008-08-01 21:45:06 +08:00
2008-04-22 00:46:01 +08:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
2007-01-29 11:59:55 +08:00
}
2008-08-01 21:45:06 +08:00
2008-04-22 00:46:01 +08:00
php_stream_close ( newfile ) ;
phar - > alias_len = restore_alias_len ;
2008-08-01 21:45:06 +08:00
2008-04-22 00:46:01 +08:00
if ( error ) {
spprintf ( error , 0 , " unable to write manifest meta-data of new phar \" %s \" " , phar - > fname ) ;
}
2008-08-01 21:45:06 +08:00
2008-04-22 00:46:01 +08:00
return EOF ;
2008-08-01 21:45:06 +08:00
}
2007-05-15 03:36:09 +08:00
smart_str_free ( & main_metadata_str ) ;
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
/* re-calculate the manifest location to simplify later code */
manifest_ftell = php_stream_tell ( newfile ) ;
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
/* now write the manifest */
2008-01-09 15:09:04 +08:00
for ( zend_hash_internal_pointer_reset ( & phar - > manifest ) ;
2008-08-01 21:45:06 +08:00
zend_hash_has_more_elements ( & phar - > manifest ) = = SUCCESS ;
zend_hash_move_forward ( & phar - > manifest ) ) {
2008-01-09 15:09:04 +08:00
if ( zend_hash_get_current_data ( & phar - > manifest , ( void * * ) & entry ) = = FAILURE ) {
2007-01-03 02:15:17 +08:00
continue ;
}
2008-08-01 21:45:06 +08:00
2008-05-08 10:58:45 +08:00
if ( entry - > is_deleted | | entry - > is_mounted ) {
/* remove this from the new phar if deleted, ignore if mounted */
2007-01-03 02:15:17 +08:00
continue ;
}
2008-08-01 21:45:06 +08:00
2008-01-09 11:47:22 +08:00
if ( entry - > is_dir ) {
/* add 1 for trailing slash */
phar_set_32 ( entry_buffer , entry - > filename_len + 1 ) ;
} else {
phar_set_32 ( entry_buffer , entry - > filename_len ) ;
}
2008-08-01 21:45:06 +08:00
2007-01-10 07:57:03 +08:00
if ( 4 ! = php_stream_write ( newfile , entry_buffer , 4 )
2008-04-22 00:42:53 +08:00
| | entry - > filename_len ! = php_stream_write ( newfile , entry - > filename , entry - > filename_len )
| | ( entry - > is_dir & & 1 ! = php_stream_write ( newfile , " / " , 1 ) ) ) {
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-10 06:30:56 +08:00
php_stream_close ( oldfile ) ;
2007-01-10 02:54:37 +08:00
}
2007-01-04 13:32:45 +08:00
php_stream_close ( newfile ) ;
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-04-22 00:42:53 +08:00
if ( entry - > is_dir ) {
spprintf ( error , 0 , " unable to write filename of directory \" %s \" to manifest of new phar \" %s \" " , entry - > filename , phar - > fname ) ;
} else {
spprintf ( error , 0 , " unable to write filename of file \" %s \" to manifest of new phar \" %s \" " , entry - > filename , phar - > fname ) ;
}
2008-01-09 06:14:16 +08:00
}
return EOF ;
}
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
/* set the manifest meta-data:
2007-01-03 02:15:17 +08:00
4 : uncompressed filesize
4 : creation timestamp
4 : compressed filesize
4 : crc32
2007-01-14 00:17:04 +08:00
4 : flags
2007-01-22 04:12:50 +08:00
4 : metadata - len
+ : metadata
2007-01-03 02:15:17 +08:00
*/
2007-01-22 11:41:41 +08:00
mytime = time ( NULL ) ;
2007-01-10 07:57:03 +08:00
phar_set_32 ( entry_buffer , entry - > uncompressed_filesize ) ;
2007-01-22 11:41:41 +08:00
phar_set_32 ( entry_buffer + 4 , mytime ) ;
2007-01-10 07:57:03 +08:00
phar_set_32 ( entry_buffer + 8 , entry - > compressed_filesize ) ;
phar_set_32 ( entry_buffer + 12 , entry - > crc32 ) ;
2007-01-14 00:17:04 +08:00
phar_set_32 ( entry_buffer + 16 , entry - > flags ) ;
2007-05-15 03:14:00 +08:00
phar_set_32 ( entry_buffer + 20 , entry - > metadata_str . len ) ;
2008-08-01 21:45:06 +08:00
2007-01-22 04:12:50 +08:00
if ( sizeof ( entry_buffer ) ! = php_stream_write ( newfile , entry_buffer , sizeof ( entry_buffer ) )
2007-05-15 03:14:00 +08:00
| | entry - > metadata_str . len ! = php_stream_write ( newfile , entry - > metadata_str . c , entry - > metadata_str . len ) ) {
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-10 06:30:56 +08:00
php_stream_close ( oldfile ) ;
2007-01-10 02:54:37 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-03 23:43:07 +08:00
php_stream_close ( newfile ) ;
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to write temporary manifest of file \" %s \" to manifest of new phar \" %s \" " , entry - > filename , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-08 00:01:35 +08:00
return EOF ;
2007-01-04 13:32:45 +08:00
}
}
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
/* now copy the actual file data to the new phar */
2008-01-28 16:52:08 +08:00
offset = php_stream_tell ( newfile ) ;
2008-01-09 15:09:04 +08:00
for ( zend_hash_internal_pointer_reset ( & phar - > manifest ) ;
2008-08-01 21:45:06 +08:00
zend_hash_has_more_elements ( & phar - > manifest ) = = SUCCESS ;
zend_hash_move_forward ( & phar - > manifest ) ) {
2008-01-09 15:09:04 +08:00
if ( zend_hash_get_current_data ( & phar - > manifest , ( void * * ) & entry ) = = FAILURE ) {
2007-01-04 13:32:45 +08:00
continue ;
}
2008-08-01 21:45:06 +08:00
2008-05-08 10:58:45 +08:00
if ( entry - > is_deleted | | entry - > is_dir | | entry - > is_mounted ) {
2007-01-04 13:32:45 +08:00
continue ;
}
2008-08-01 21:45:06 +08:00
2007-01-27 23:31:24 +08:00
if ( entry - > cfp ) {
file = entry - > cfp ;
php_stream_rewind ( file ) ;
2007-01-04 13:32:45 +08:00
} else {
2008-04-21 14:17:51 +08:00
file = phar_get_efp ( entry , 0 TSRMLS_CC ) ;
if ( - 1 = = phar_seek_efp ( entry , 0 , SEEK_SET , 0 , 0 TSRMLS_CC ) ) {
2007-02-07 01:09:37 +08:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to seek to start of file \" %s \" while creating new phar \" %s \" " , entry - > filename , phar - > fname ) ;
2007-02-07 01:09:37 +08:00
}
return EOF ;
}
2008-01-28 16:52:08 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( ! file ) {
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
2007-01-04 13:32:45 +08:00
}
2008-01-28 16:52:08 +08:00
php_stream_close ( newfile ) ;
if ( error ) {
spprintf ( error , 0 , " unable to seek to start of file \" %s \" while creating new phar \" %s \" " , entry - > filename , phar - > fname ) ;
}
return EOF ;
2007-01-04 13:32:45 +08:00
}
2008-08-01 21:45:06 +08:00
/* this will have changed for all files that have either changed compression or been modified */
2008-01-28 16:52:08 +08:00
entry - > offset = entry - > offset_abs = offset ;
2007-01-04 13:32:45 +08:00
offset + = entry - > compressed_filesize ;
2007-01-27 23:31:24 +08:00
wrote = php_stream_copy_to_stream ( file , newfile , entry - > compressed_filesize ) ;
2008-08-01 21:45:06 +08:00
2007-01-27 23:31:24 +08:00
if ( entry - > compressed_filesize ! = wrote ) {
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-10 06:30:56 +08:00
php_stream_close ( oldfile ) ;
2007-01-10 02:54:37 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-04 13:32:45 +08:00
php_stream_close ( newfile ) ;
2008-08-01 21:45:06 +08:00
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to write contents of file \" %s \" to new phar \" %s \" " , entry - > filename , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-08 00:01:35 +08:00
return EOF ;
2007-01-04 13:32:45 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-26 22:52:10 +08:00
entry - > is_modified = 0 ;
2008-08-01 21:45:06 +08:00
2007-01-27 23:31:24 +08:00
if ( entry - > cfp ) {
php_stream_close ( entry - > cfp ) ;
2008-01-28 16:52:08 +08:00
entry - > cfp = NULL ;
2007-01-27 23:31:24 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( entry - > fp_type = = PHAR_MOD ) {
2008-08-01 21:45:06 +08:00
/* this fp is in use by a phar_entry_data returned by phar_get_entry_data, it will be closed when the phar_entry_data is phar_entry_delref'ed */
2008-01-28 16:52:08 +08:00
if ( entry - > fp_refcount = = 0 & & entry - > fp ! = phar - > fp & & entry - > fp ! = phar - > ufp ) {
2007-08-30 10:30:16 +08:00
php_stream_close ( entry - > fp ) ;
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
entry - > fp = NULL ;
entry - > fp_type = PHAR_FP ;
} else if ( entry - > fp_type = = PHAR_UFP ) {
entry - > fp_type = PHAR_FP ;
2007-08-17 12:47:50 +08:00
}
2007-01-03 02:15:17 +08:00
}
2007-01-04 13:32:45 +08:00
2007-01-09 07:03:41 +08:00
/* append signature */
if ( global_flags & PHAR_HDR_SIGNATURE ) {
char sig_buf [ 4 ] ;
php_stream_rewind ( newfile ) ;
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
if ( phar - > signature ) {
efree ( phar - > signature ) ;
2008-08-01 21:45:06 +08:00
phar - > signature = NULL ;
2007-01-27 23:31:24 +08:00
}
2007-03-26 05:43:49 +08:00
2008-08-01 21:45:06 +08:00
switch ( phar - > sig_flags ) {
2008-10-09 08:51:27 +08:00
# ifndef PHAR_HASH_OK
2008-08-01 21:45:06 +08:00
case PHAR_SIG_SHA512 :
case PHAR_SIG_SHA256 :
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
if ( error ) {
spprintf ( error , 0 , " unable to write contents of file \" %s \" to new phar \" %s \" with requested hash type " , entry - > filename , phar - > fname ) ;
}
return EOF ;
2007-03-26 05:43:49 +08:00
# endif
2008-08-01 21:45:06 +08:00
default : {
2009-01-03 04:43:58 +08:00
char * digest = NULL ;
2008-08-01 21:45:06 +08:00
int digest_len ;
2007-01-09 07:03:41 +08:00
2008-08-01 21:45:06 +08:00
if ( FAILURE = = phar_create_signature ( phar , newfile , & digest , & digest_len , error TSRMLS_CC ) ) {
if ( error ) {
char * save = * error ;
spprintf ( error , 0 , " phar error: unable to write signature: %s " , save ) ;
efree ( save ) ;
}
2009-01-03 04:43:58 +08:00
if ( digest ) {
efree ( digest ) ;
}
2008-08-01 21:45:06 +08:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
return EOF ;
}
php_stream_write ( newfile , digest , digest_len ) ;
efree ( digest ) ;
if ( phar - > sig_flags = = PHAR_SIG_OPENSSL ) {
phar_set_32 ( sig_buf , digest_len ) ;
php_stream_write ( newfile , sig_buf , 4 ) ;
}
break ;
2007-01-09 07:03:41 +08:00
}
}
2008-08-01 21:45:06 +08:00
phar_set_32 ( sig_buf , phar - > sig_flags ) ;
2007-01-09 07:03:41 +08:00
php_stream_write ( newfile , sig_buf , 4 ) ;
php_stream_write ( newfile , " GBMB " , 4 ) ;
}
2007-01-03 02:15:17 +08:00
/* finally, close the temp file, rename the original phar,
move the temp to the old phar , unlink the old phar , and reload it into memory
*/
2008-04-27 15:04:56 +08:00
if ( phar - > fp & & free_fp ) {
2008-01-09 15:09:04 +08:00
php_stream_close ( phar - > fp ) ;
2007-01-27 23:31:24 +08:00
}
2008-08-01 21:45:06 +08:00
2008-01-28 16:52:08 +08:00
if ( phar - > ufp ) {
2008-04-27 15:04:56 +08:00
if ( free_ufp ) {
php_stream_close ( phar - > ufp ) ;
}
2008-01-28 16:52:08 +08:00
phar - > ufp = NULL ;
}
2008-08-01 21:45:06 +08:00
2007-01-29 05:26:54 +08:00
if ( closeoldfile ) {
2007-01-29 03:56:09 +08:00
php_stream_close ( oldfile ) ;
2007-01-03 02:15:17 +08:00
}
2007-01-29 03:56:09 +08:00
2008-01-09 15:09:04 +08:00
phar - > internal_file_start = halt_offset + manifest_len + 4 ;
2008-01-28 16:52:08 +08:00
phar - > halt_offset = halt_offset ;
2008-01-09 15:09:04 +08:00
phar - > is_brandnew = 0 ;
2007-01-29 05:26:54 +08:00
php_stream_rewind ( newfile ) ;
2007-01-03 02:15:17 +08:00
2008-01-09 15:09:04 +08:00
if ( phar - > donotflush ) {
2007-01-29 03:56:09 +08:00
/* deferred flush */
2008-01-09 15:09:04 +08:00
phar - > fp = newfile ;
2007-01-29 03:56:09 +08:00
} else {
2008-01-09 15:09:04 +08:00
phar - > fp = php_stream_open_wrapper ( phar - > fname , " w+b " , IGNORE_URL | STREAM_MUST_SEEK | REPORT_ERRORS , NULL ) ;
if ( ! phar - > fp ) {
phar - > fp = newfile ;
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 16:45:00 +08:00
spprintf ( error , 4096 , " unable to open new phar \" %s \" for writing " , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-29 03:56:09 +08:00
return EOF ;
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
if ( phar - > flags & PHAR_FILE_COMPRESSED_GZ ) {
/* to properly compress, we have to tell zlib to add a zlib header */
zval filterparams ;
array_init ( & filterparams ) ;
2008-01-09 16:45:00 +08:00
add_assoc_long ( & filterparams , " window " , MAX_WBITS + 16 ) ;
2008-01-09 15:09:04 +08:00
filter = php_stream_filter_create ( " zlib.deflate " , & filterparams , php_stream_is_persistent ( phar - > fp ) TSRMLS_CC ) ;
2008-02-08 13:41:59 +08:00
zval_dtor ( & filterparams ) ;
2008-08-01 21:45:06 +08:00
2008-01-09 16:45:00 +08:00
if ( ! filter ) {
if ( error ) {
spprintf ( error , 4096 , " unable to compress all contents of phar \" %s \" using zlib, PHP versions older than 5.2.6 have a buggy zlib " , phar - > fname ) ;
}
return EOF ;
}
2008-08-01 21:45:06 +08:00
2008-01-09 15:09:04 +08:00
php_stream_filter_append ( & phar - > fp - > writefilters , filter ) ;
php_stream_copy_to_stream ( newfile , phar - > fp , PHP_STREAM_COPY_ALL ) ;
php_stream_filter_flush ( filter , 1 ) ;
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
php_stream_close ( phar - > fp ) ;
/* use the temp stream as our base */
phar - > fp = newfile ;
} else if ( phar - > flags & PHAR_FILE_COMPRESSED_BZ2 ) {
filter = php_stream_filter_create ( " bzip2.compress " , NULL , php_stream_is_persistent ( phar - > fp ) TSRMLS_CC ) ;
php_stream_filter_append ( & phar - > fp - > writefilters , filter ) ;
php_stream_copy_to_stream ( newfile , phar - > fp , PHP_STREAM_COPY_ALL ) ;
php_stream_filter_flush ( filter , 1 ) ;
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
php_stream_close ( phar - > fp ) ;
/* use the temp stream as our base */
phar - > fp = newfile ;
} else {
php_stream_copy_to_stream ( newfile , phar - > fp , PHP_STREAM_COPY_ALL ) ;
/* we could also reopen the file in "rb" mode but there is no need for that */
php_stream_close ( newfile ) ;
}
2007-01-03 02:15:17 +08:00
}
2008-01-09 15:09:04 +08:00
if ( - 1 = = php_stream_seek ( phar - > fp , phar - > halt_offset , SEEK_SET ) ) {
2007-01-29 14:02:19 +08:00
if ( error ) {
2008-01-09 15:09:04 +08:00
spprintf ( error , 0 , " unable to seek to __HALT_COMPILER(); in new phar \" %s \" " , phar - > fname ) ;
2007-01-29 14:02:19 +08:00
}
2007-01-08 00:01:35 +08:00
return EOF ;
2007-01-03 02:15:17 +08:00
}
2007-01-05 11:04:56 +08:00
2007-01-03 02:15:17 +08:00
return EOF ;
}
/* }}} */
2006-01-03 23:50:46 +08:00
# ifdef COMPILE_DL_PHAR
ZEND_GET_MODULE ( phar )
# endif
/* {{{ phar_functions[]
*
* Every user visible function must have an entry in phar_functions [ ] .
*/
function_entry phar_functions [ ] = {
2008-08-01 21:45:06 +08:00
{ NULL , NULL , NULL } /* Must be the last line in phar_functions[] */
2006-02-28 09:36:30 +08:00
} ;
2007-01-24 07:31:14 +08:00
/* }}}*/
2006-01-03 23:50:46 +08:00
2008-03-17 05:06:54 +08:00
static size_t phar_zend_stream_reader ( void * handle , char * buf , size_t len TSRMLS_DC ) /* { { { */
{
2008-08-01 21:45:06 +08:00
return php_stream_read ( phar_get_pharfp ( ( phar_archive_data * ) handle TSRMLS_CC ) , buf , len ) ;
2008-03-17 05:06:54 +08:00
}
/* }}} */
2008-08-01 21:45:06 +08:00
# if PHP_VERSION_ID >= 50300
2008-03-17 05:06:54 +08:00
static size_t phar_zend_stream_fsizer ( void * handle TSRMLS_DC ) /* { { { */
{
return ( ( phar_archive_data * ) handle ) - > halt_offset + 32 ;
} /* }}} */
# else /* PHP_VERSION_ID */
2008-08-01 21:45:06 +08:00
static long phar_stream_fteller_for_zend ( void * handle TSRMLS_DC ) /* { { { */
2008-01-09 16:45:00 +08:00
{
2008-08-01 21:45:06 +08:00
return ( long ) php_stream_tell ( phar_get_pharfp ( ( phar_archive_data * ) handle TSRMLS_CC ) ) ;
2008-01-09 16:45:00 +08:00
}
/* }}} */
2008-03-17 05:06:54 +08:00
# endif
2008-01-09 16:45:00 +08:00
2008-01-12 12:32:19 +08:00
zend_op_array * ( * phar_orig_compile_file ) ( zend_file_handle * file_handle , int type TSRMLS_DC ) ;
2008-03-12 11:55:12 +08:00
# if PHP_VERSION_ID >= 50300
# define phar_orig_zend_open zend_stream_open_function
2008-09-14 06:31:18 +08:00
static char * phar_resolve_path ( const char * filename , int filename_len TSRMLS_DC )
2008-03-12 11:55:12 +08:00
{
2008-03-21 07:59:07 +08:00
return phar_find_in_include_path ( ( char * ) filename , filename_len , NULL TSRMLS_CC ) ;
2008-03-12 11:55:12 +08:00
}
2008-03-23 05:54:55 +08:00
# else
int ( * phar_orig_zend_open ) ( const char * filename , zend_file_handle * handle TSRMLS_DC ) ;
# endif
2008-01-12 12:32:19 +08:00
2007-12-10 05:57:44 +08:00
static zend_op_array * phar_compile_file ( zend_file_handle * file_handle , int type TSRMLS_DC ) /* { { { */
{
zend_op_array * res ;
2008-01-01 06:42:40 +08:00
char * name = NULL ;
2008-01-10 23:13:00 +08:00
int failed ;
2008-01-07 13:41:09 +08:00
phar_archive_data * phar ;
2007-12-10 05:57:44 +08:00
2008-09-30 10:40:37 +08:00
if ( ! file_handle | | ! file_handle - > filename ) {
return phar_orig_compile_file ( file_handle , type TSRMLS_CC ) ;
}
2008-01-08 15:08:46 +08:00
if ( strstr ( file_handle - > filename , " .phar " ) & & ! strstr ( file_handle - > filename , " :// " ) ) {
2008-05-31 06:39:33 +08:00
if ( SUCCESS = = phar_open_from_filename ( file_handle - > filename , strlen ( file_handle - > filename ) , NULL , 0 , 0 , & phar , NULL TSRMLS_CC ) ) {
2008-01-07 13:41:09 +08:00
if ( phar - > is_zip | | phar - > is_tar ) {
2008-01-08 06:21:10 +08:00
zend_file_handle f = * file_handle ;
/* zip or tar-based phar */
2008-01-07 13:41:09 +08:00
spprintf ( & name , 4096 , " phar://%s/%s " , file_handle - > filename , " .phar/stub.php " ) ;
2008-01-10 23:13:00 +08:00
if ( SUCCESS = = phar_orig_zend_open ( ( const char * ) name , file_handle TSRMLS_CC ) ) {
2008-01-08 06:21:10 +08:00
efree ( name ) ;
name = NULL ;
file_handle - > filename = f . filename ;
2008-03-12 11:55:12 +08:00
if ( file_handle - > opened_path ) {
efree ( file_handle - > opened_path ) ;
}
2008-01-08 06:21:10 +08:00
file_handle - > opened_path = f . opened_path ;
file_handle - > free_filename = f . free_filename ;
} else {
* file_handle = f ;
2008-01-07 13:41:09 +08:00
}
2008-01-09 16:45:00 +08:00
} else if ( phar - > flags & PHAR_FILE_COMPRESSION_MASK ) {
/* compressed phar */
2008-05-14 02:35:25 +08:00
# if PHP_VERSION_ID >= 50300
2008-03-17 05:06:54 +08:00
file_handle - > type = ZEND_HANDLE_STREAM ;
2008-08-01 21:45:06 +08:00
/* we do our own reading directly from the phar, don't change the next line */
2008-03-17 05:06:54 +08:00
file_handle - > handle . stream . handle = phar ;
file_handle - > handle . stream . reader = phar_zend_stream_reader ;
file_handle - > handle . stream . closer = NULL ;
file_handle - > handle . stream . fsizer = phar_zend_stream_fsizer ;
file_handle - > handle . stream . isatty = 0 ;
2008-08-01 21:45:06 +08:00
phar - > is_persistent ?
php_stream_rewind ( PHAR_GLOBALS - > cached_fp [ phar - > phar_pos ] . fp ) :
php_stream_rewind ( phar - > fp ) ;
2008-03-17 05:06:54 +08:00
memset ( & file_handle - > handle . stream . mmap , 0 , sizeof ( file_handle - > handle . stream . mmap ) ) ;
# else /* PHP_VERSION_ID */
2008-01-09 16:45:00 +08:00
file_handle - > type = ZEND_HANDLE_STREAM ;
2008-08-01 21:45:06 +08:00
/* we do our own reading directly from the phar, don't change the next line */
file_handle - > handle . stream . handle = phar ;
file_handle - > handle . stream . reader = phar_zend_stream_reader ;
2008-01-09 16:45:00 +08:00
file_handle - > handle . stream . closer = NULL ; /* don't close - let phar handle this one */
2008-08-01 21:45:06 +08:00
file_handle - > handle . stream . fteller = phar_stream_fteller_for_zend ;
2008-01-09 16:45:00 +08:00
file_handle - > handle . stream . interactive = 0 ;
2008-08-01 21:45:06 +08:00
phar - > is_persistent ?
php_stream_rewind ( PHAR_GLOBALS - > cached_fp [ phar - > phar_pos ] . fp ) :
php_stream_rewind ( phar - > fp ) ;
2008-03-17 05:06:54 +08:00
# endif
2008-01-04 09:45:37 +08:00
}
2008-01-03 12:45:00 +08:00
}
}
2008-08-01 21:45:06 +08:00
2008-01-10 23:13:00 +08:00
zend_try {
failed = 0 ;
2008-02-13 23:00:31 +08:00
res = phar_orig_compile_file ( file_handle , type TSRMLS_CC ) ;
2008-01-10 23:13:00 +08:00
} zend_catch {
failed = 1 ;
} zend_end_try ( ) ;
2008-08-01 21:45:06 +08:00
2008-01-10 23:13:00 +08:00
if ( name ) {
efree ( name ) ;
}
2008-08-01 21:45:06 +08:00
2008-01-10 23:13:00 +08:00
if ( failed ) {
zend_bailout ( ) ;
}
2008-08-01 21:45:06 +08:00
2008-01-10 23:13:00 +08:00
return res ;
}
/* }}} */
2008-03-12 11:55:12 +08:00
# if PHP_VERSION_ID < 50300
2008-01-12 12:32:19 +08:00
int phar_zend_open ( const char * filename , zend_file_handle * handle TSRMLS_DC ) /* { { { */
2008-01-10 23:13:00 +08:00
{
char * arch , * entry ;
2008-03-12 11:55:12 +08:00
int arch_len , entry_len ;
2008-01-10 23:13:00 +08:00
2008-03-12 11:55:12 +08:00
/* this code is obsoleted in php 5.3 */
2008-01-10 23:13:00 +08:00
entry = ( char * ) filename ;
2008-04-14 12:47:34 +08:00
if ( ! IS_ABSOLUTE_PATH ( entry , strlen ( entry ) ) & & ! strstr ( entry , " :// " ) ) {
2008-03-12 11:55:12 +08:00
phar_archive_data * * pphar = NULL ;
char * fname ;
int fname_len ;
fname = zend_get_executed_filename ( TSRMLS_C ) ;
fname_len = strlen ( fname ) ;
2008-08-01 21:45:06 +08:00
2008-03-12 11:55:12 +08:00
if ( fname_len > 7 & & ! strncasecmp ( fname , " phar:// " , 7 ) ) {
2008-04-18 12:13:13 +08:00
if ( SUCCESS = = phar_split_fname ( fname , fname_len , & arch , & arch_len , & entry , & entry_len , 1 , 0 TSRMLS_CC ) ) {
2008-03-12 11:55:12 +08:00
zend_hash_find ( & ( PHAR_GLOBALS - > phar_fname_map ) , arch , arch_len , ( void * * ) & pphar ) ;
2008-08-01 21:45:06 +08:00
if ( ! pphar & & PHAR_G ( manifest_cached ) ) {
zend_hash_find ( & cached_phars , arch , arch_len , ( void * * ) & pphar ) ;
}
2008-03-12 11:55:12 +08:00
efree ( arch ) ;
efree ( entry ) ;
}
}
2008-08-01 21:45:06 +08:00
2008-03-12 11:55:12 +08:00
/* retrieving an include within the current directory, so use this if possible */
2008-03-23 13:39:58 +08:00
if ( ! ( entry = phar_find_in_include_path ( ( char * ) filename , strlen ( filename ) , NULL TSRMLS_CC ) ) ) {
2008-03-12 11:55:12 +08:00
/* this file is not in the phar, use the original path */
goto skip_phar ;
}
2008-08-01 21:45:06 +08:00
2008-03-12 11:55:12 +08:00
if ( SUCCESS = = phar_orig_zend_open ( entry , handle TSRMLS_CC ) ) {
if ( ! handle - > opened_path ) {
handle - > opened_path = entry ;
}
2008-03-23 05:54:55 +08:00
if ( entry ! = filename ) {
handle - > free_filename = 1 ;
}
2008-03-12 11:55:12 +08:00
return SUCCESS ;
}
2008-08-01 21:45:06 +08:00
2008-03-12 11:55:12 +08:00
if ( entry ! = filename ) {
efree ( entry ) ;
}
2008-08-01 21:45:06 +08:00
2008-03-12 11:55:12 +08:00
return FAILURE ;
}
2007-12-10 05:57:44 +08:00
skip_phar :
2008-01-10 23:13:00 +08:00
return phar_orig_zend_open ( filename , handle TSRMLS_CC ) ;
}
/* }}} */
2008-03-12 11:55:12 +08:00
# endif
2008-04-15 12:56:34 +08:00
typedef zend_op_array * ( zend_compile_t ) ( zend_file_handle * , int TSRMLS_DC ) ;
typedef zend_compile_t * ( compile_hook ) ( zend_compile_t * ptr ) ;
2008-01-10 23:13:00 +08:00
2008-08-14 21:02:13 +08:00
PHP_GINIT_FUNCTION ( phar ) /* {{{ */
2006-01-03 23:50:46 +08:00
{
2008-08-01 21:45:06 +08:00
phar_mime_type mime ;
2008-08-14 21:02:13 +08:00
memset ( phar_globals , 0 , sizeof ( zend_phar_globals ) ) ;
phar_globals - > readonly = 1 ;
2008-08-01 21:45:06 +08:00
2008-08-14 21:02:13 +08:00
zend_hash_init ( & phar_globals - > mime_types , 0 , NULL , NULL , 1 ) ;
2008-08-01 21:45:06 +08:00
# define PHAR_SET_MIME(mimetype, ret, fileext) \
mime . mime = mimetype ; \
mime . len = sizeof ( ( mimetype ) ) + 1 ; \
mime . type = ret ; \
2008-08-14 21:02:13 +08:00
zend_hash_add ( & phar_globals - > mime_types , fileext , sizeof ( fileext ) - 1 , ( void * ) & mime , sizeof ( phar_mime_type ) , NULL ) ; \
2008-08-01 21:45:06 +08:00
PHAR_SET_MIME ( " text/html " , PHAR_MIME_PHPS , " phps " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " c " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " cc " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " cpp " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " c++ " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " dtd " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " h " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " log " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " rng " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " txt " )
PHAR_SET_MIME ( " text/plain " , PHAR_MIME_OTHER , " xsd " )
PHAR_SET_MIME ( " " , PHAR_MIME_PHP , " php " )
PHAR_SET_MIME ( " " , PHAR_MIME_PHP , " inc " )
PHAR_SET_MIME ( " video/avi " , PHAR_MIME_OTHER , " avi " )
PHAR_SET_MIME ( " image/bmp " , PHAR_MIME_OTHER , " bmp " )
PHAR_SET_MIME ( " text/css " , PHAR_MIME_OTHER , " css " )
PHAR_SET_MIME ( " image/gif " , PHAR_MIME_OTHER , " gif " )
PHAR_SET_MIME ( " text/html " , PHAR_MIME_OTHER , " htm " )
PHAR_SET_MIME ( " text/html " , PHAR_MIME_OTHER , " html " )
PHAR_SET_MIME ( " text/html " , PHAR_MIME_OTHER , " htmls " )
PHAR_SET_MIME ( " image/x-ico " , PHAR_MIME_OTHER , " ico " )
PHAR_SET_MIME ( " image/jpeg " , PHAR_MIME_OTHER , " jpe " )
PHAR_SET_MIME ( " image/jpeg " , PHAR_MIME_OTHER , " jpg " )
PHAR_SET_MIME ( " image/jpeg " , PHAR_MIME_OTHER , " jpeg " )
PHAR_SET_MIME ( " application/x-javascript " , PHAR_MIME_OTHER , " js " )
PHAR_SET_MIME ( " audio/midi " , PHAR_MIME_OTHER , " midi " )
PHAR_SET_MIME ( " audio/midi " , PHAR_MIME_OTHER , " mid " )
PHAR_SET_MIME ( " audio/mod " , PHAR_MIME_OTHER , " mod " )
PHAR_SET_MIME ( " movie/quicktime " , PHAR_MIME_OTHER , " mov " )
PHAR_SET_MIME ( " audio/mp3 " , PHAR_MIME_OTHER , " mp3 " )
PHAR_SET_MIME ( " video/mpeg " , PHAR_MIME_OTHER , " mpg " )
PHAR_SET_MIME ( " video/mpeg " , PHAR_MIME_OTHER , " mpeg " )
PHAR_SET_MIME ( " application/pdf " , PHAR_MIME_OTHER , " pdf " )
PHAR_SET_MIME ( " image/png " , PHAR_MIME_OTHER , " png " )
PHAR_SET_MIME ( " application/shockwave-flash " , PHAR_MIME_OTHER , " swf " )
PHAR_SET_MIME ( " image/tiff " , PHAR_MIME_OTHER , " tif " )
PHAR_SET_MIME ( " image/tiff " , PHAR_MIME_OTHER , " tiff " )
PHAR_SET_MIME ( " audio/wav " , PHAR_MIME_OTHER , " wav " )
PHAR_SET_MIME ( " image/xbm " , PHAR_MIME_OTHER , " xbm " )
PHAR_SET_MIME ( " text/xml " , PHAR_MIME_OTHER , " xml " )
2008-08-14 21:02:13 +08:00
phar_restore_orig_functions ( TSRMLS_C ) ;
}
/* }}} */
PHP_GSHUTDOWN_FUNCTION ( phar ) /* {{{ */
{
zend_hash_destroy ( & phar_globals - > mime_types ) ;
}
/* }}} */
PHP_MINIT_FUNCTION ( phar ) /* {{{ */
{
REGISTER_INI_ENTRIES ( ) ;
phar_orig_compile_file = zend_compile_file ;
zend_compile_file = phar_compile_file ;
# if PHP_VERSION_ID >= 50300
phar_save_resolve_path = zend_resolve_path ;
zend_resolve_path = phar_resolve_path ;
# else
phar_orig_zend_open = zend_stream_open_function ;
zend_stream_open_function = phar_zend_open ;
# endif
phar_object_init ( TSRMLS_C ) ;
phar_intercept_functions_init ( TSRMLS_C ) ;
phar_save_orig_functions ( TSRMLS_C ) ;
2006-01-03 23:50:46 +08:00
return php_register_url_stream_wrapper ( " phar " , & php_stream_phar_wrapper TSRMLS_CC ) ;
}
/* }}} */
2006-03-08 08:56:31 +08:00
PHP_MSHUTDOWN_FUNCTION ( phar ) /* {{{ */
2006-01-03 23:50:46 +08:00
{
2008-08-01 21:45:06 +08:00
php_unregister_url_stream_wrapper ( " phar " TSRMLS_CC ) ;
phar_intercept_functions_shutdown ( TSRMLS_C ) ;
2007-12-12 03:28:35 +08:00
if ( zend_compile_file = = phar_compile_file ) {
2007-12-19 01:01:24 +08:00
zend_compile_file = phar_orig_compile_file ;
2007-12-12 03:28:35 +08:00
}
2008-04-15 12:56:34 +08:00
2008-03-12 11:55:12 +08:00
# if PHP_VERSION_ID < 50300
2008-01-10 23:13:00 +08:00
if ( zend_stream_open_function = = phar_zend_open ) {
zend_stream_open_function = phar_orig_zend_open ;
}
2008-03-12 11:55:12 +08:00
# endif
2008-08-01 21:45:06 +08:00
if ( PHAR_G ( manifest_cached ) ) {
zend_hash_destroy ( & ( cached_phars ) ) ;
zend_hash_destroy ( & ( cached_alias ) ) ;
}
return SUCCESS ;
2006-01-03 23:50:46 +08:00
}
/* }}} */
2007-05-17 07:16:51 +08:00
void phar_request_initialize ( TSRMLS_D ) /* { { { */
{
if ( ! PHAR_GLOBALS - > request_init )
{
2008-08-01 21:45:06 +08:00
PHAR_G ( last_phar ) = NULL ;
PHAR_G ( last_phar_name ) = PHAR_G ( last_alias ) = NULL ;
2008-05-18 04:07:38 +08:00
PHAR_G ( has_bz2 ) = zend_hash_exists ( & module_registry , " bz2 " , sizeof ( " bz2 " ) ) ;
PHAR_G ( has_zlib ) = zend_hash_exists ( & module_registry , " zlib " , sizeof ( " zlib " ) ) ;
2007-05-17 07:16:51 +08:00
PHAR_GLOBALS - > request_init = 1 ;
2007-05-21 05:46:54 +08:00
PHAR_GLOBALS - > request_ends = 0 ;
PHAR_GLOBALS - > request_done = 0 ;
2008-08-01 21:45:06 +08:00
zend_hash_init ( & ( PHAR_GLOBALS - > phar_fname_map ) , 5 , zend_get_hash_value , destroy_phar_data , 0 ) ;
2008-10-13 03:40:30 +08:00
zend_hash_init ( & ( PHAR_GLOBALS - > phar_persist_map ) , 5 , zend_get_hash_value , NULL , 0 ) ;
2008-08-01 21:45:06 +08:00
zend_hash_init ( & ( PHAR_GLOBALS - > phar_alias_map ) , 5 , zend_get_hash_value , NULL , 0 ) ;
if ( PHAR_G ( manifest_cached ) ) {
phar_archive_data * * pphar ;
phar_entry_fp * stuff = ( phar_entry_fp * ) ecalloc ( zend_hash_num_elements ( & cached_phars ) , sizeof ( phar_entry_fp ) ) ;
for ( zend_hash_internal_pointer_reset ( & cached_phars ) ;
zend_hash_get_current_data ( & cached_phars , ( void * * ) & pphar ) = = SUCCESS ;
zend_hash_move_forward ( & cached_phars ) ) {
stuff [ pphar [ 0 ] - > phar_pos ] . manifest = ( phar_entry_fp_info * ) ecalloc ( zend_hash_num_elements ( & ( pphar [ 0 ] - > manifest ) ) , sizeof ( phar_entry_fp_info ) ) ;
}
PHAR_GLOBALS - > cached_fp = stuff ;
}
PHAR_GLOBALS - > phar_SERVER_mung_list = 0 ;
2008-01-11 05:21:38 +08:00
PHAR_G ( cwd ) = NULL ;
PHAR_G ( cwd_len ) = 0 ;
2008-02-13 23:00:31 +08:00
PHAR_G ( cwd_init ) = 0 ;
2007-05-17 07:16:51 +08:00
}
}
2006-01-03 23:50:46 +08:00
/* }}} */
2006-03-08 08:56:31 +08:00
PHP_RSHUTDOWN_FUNCTION ( phar ) /* {{{ */
2006-01-03 23:50:46 +08:00
{
2008-08-01 21:45:06 +08:00
int i ;
2007-03-28 05:28:22 +08:00
PHAR_GLOBALS - > request_ends = 1 ;
2008-08-01 21:45:06 +08:00
2007-05-17 07:16:51 +08:00
if ( PHAR_GLOBALS - > request_init )
{
2008-01-11 15:30:03 +08:00
phar_release_functions ( TSRMLS_C ) ;
2007-05-17 07:16:51 +08:00
zend_hash_destroy ( & ( PHAR_GLOBALS - > phar_alias_map ) ) ;
2008-01-04 09:45:37 +08:00
PHAR_GLOBALS - > phar_alias_map . arBuckets = NULL ;
2007-05-17 07:16:51 +08:00
zend_hash_destroy ( & ( PHAR_GLOBALS - > phar_fname_map ) ) ;
2008-01-04 09:45:37 +08:00
PHAR_GLOBALS - > phar_fname_map . arBuckets = NULL ;
2008-10-13 03:40:30 +08:00
zend_hash_destroy ( & ( PHAR_GLOBALS - > phar_persist_map ) ) ;
PHAR_GLOBALS - > phar_persist_map . arBuckets = NULL ;
2008-08-01 21:45:06 +08:00
PHAR_GLOBALS - > phar_SERVER_mung_list = 0 ;
if ( PHAR_GLOBALS - > cached_fp ) {
for ( i = 0 ; i < zend_hash_num_elements ( & cached_phars ) ; + + i ) {
if ( PHAR_GLOBALS - > cached_fp [ i ] . fp ) {
php_stream_close ( PHAR_GLOBALS - > cached_fp [ i ] . fp ) ;
}
if ( PHAR_GLOBALS - > cached_fp [ i ] . ufp ) {
php_stream_close ( PHAR_GLOBALS - > cached_fp [ i ] . ufp ) ;
}
efree ( PHAR_GLOBALS - > cached_fp [ i ] . manifest ) ;
}
efree ( PHAR_GLOBALS - > cached_fp ) ;
PHAR_GLOBALS - > cached_fp = 0 ;
}
2007-05-21 06:14:07 +08:00
PHAR_GLOBALS - > request_init = 0 ;
2008-08-01 21:45:06 +08:00
2008-01-10 23:13:00 +08:00
if ( PHAR_G ( cwd ) ) {
efree ( PHAR_G ( cwd ) ) ;
}
2008-08-01 21:45:06 +08:00
2008-01-10 23:13:00 +08:00
PHAR_G ( cwd ) = NULL ;
PHAR_G ( cwd_len ) = 0 ;
2008-02-13 23:00:31 +08:00
PHAR_G ( cwd_init ) = 0 ;
2007-05-17 07:16:51 +08:00
}
2008-08-01 21:45:06 +08:00
2007-01-27 23:31:24 +08:00
PHAR_GLOBALS - > request_done = 1 ;
2006-01-03 23:50:46 +08:00
return SUCCESS ;
}
/* }}} */
2006-03-08 08:56:31 +08:00
PHP_MINFO_FUNCTION ( phar ) /* {{{ */
2006-01-03 23:50:46 +08:00
{
2008-05-18 04:07:38 +08:00
phar_request_initialize ( TSRMLS_C ) ;
2006-01-03 23:50:46 +08:00
php_info_print_table_start ( ) ;
2006-01-13 05:16:29 +08:00
php_info_print_table_header ( 2 , " Phar: PHP Archive support " , " enabled " ) ;
2008-03-23 01:09:24 +08:00
php_info_print_table_row ( 2 , " Phar EXT version " , PHP_PHAR_VERSION ) ;
php_info_print_table_row ( 2 , " Phar API version " , PHP_PHAR_API_VERSION ) ;
2006-01-03 23:50:46 +08:00
php_info_print_table_row ( 2 , " CVS revision " , " $Revision$ " ) ;
2008-01-05 00:10:49 +08:00
php_info_print_table_row ( 2 , " Phar-based phar archives " , " enabled " ) ;
php_info_print_table_row ( 2 , " Tar-based phar archives " , " enabled " ) ;
2008-01-28 16:52:08 +08:00
php_info_print_table_row ( 2 , " ZIP-based phar archives " , " enabled " ) ;
2008-08-01 21:45:06 +08:00
2008-05-18 04:07:38 +08:00
if ( PHAR_G ( has_zlib ) ) {
2008-01-05 00:10:49 +08:00
php_info_print_table_row ( 2 , " gzip compression " , " enabled " ) ;
2007-11-25 13:04:40 +08:00
} else {
2008-01-12 13:17:12 +08:00
php_info_print_table_row ( 2 , " gzip compression " , " disabled (install ext/zlib) " ) ;
2007-11-25 13:04:40 +08:00
}
2008-08-01 21:45:06 +08:00
2008-05-18 04:07:38 +08:00
if ( PHAR_G ( has_bz2 ) ) {
2008-01-05 00:10:49 +08:00
php_info_print_table_row ( 2 , " bzip2 compression " , " enabled " ) ;
2007-11-24 12:06:44 +08:00
} else {
2008-01-05 00:10:49 +08:00
php_info_print_table_row ( 2 , " bzip2 compression " , " disabled (install pecl/bz2) " ) ;
2007-11-24 12:06:44 +08:00
}
2008-08-01 21:45:06 +08:00
# ifdef PHAR_HAVE_OPENSSL
php_info_print_table_row ( 2 , " Native OpenSSL support " , " enabled " ) ;
# else
if ( zend_hash_exists ( & module_registry , " openssl " , sizeof ( " openssl " ) ) ) {
php_info_print_table_row ( 2 , " OpenSSL support " , " enabled " ) ;
} else {
php_info_print_table_row ( 2 , " OpenSSL support " , " disabled (install ext/openssl) " ) ;
}
# endif
2006-01-03 23:50:46 +08:00
php_info_print_table_end ( ) ;
2007-03-26 03:03:38 +08:00
php_info_print_box_start ( 0 ) ;
PUTS ( " Phar based on pear/PHP_Archive, original concept by Davey Shafik. " ) ;
2008-08-01 21:45:06 +08:00
PUTS ( ! sapi_module . phpinfo_as_text ? " <br /> " : " \n " ) ;
2007-03-26 03:03:38 +08:00
PUTS ( " Phar fully realized by Gregory Beaver and Marcus Boerger. " ) ;
2008-08-01 21:45:06 +08:00
PUTS ( ! sapi_module . phpinfo_as_text ? " <br /> " : " \n " ) ;
2008-12-31 19:12:40 +08:00
PUTS ( " Portions of tar implementation Copyright (c) 2003-2009 Tim Kientzle. " ) ;
2007-03-26 03:03:38 +08:00
php_info_print_box_end ( ) ;
2007-01-08 00:01:35 +08:00
DISPLAY_INI_ENTRIES ( ) ;
2006-01-03 23:50:46 +08:00
}
/* }}} */
/* {{{ phar_module_entry
*/
2006-01-13 05:16:29 +08:00
static zend_module_dep phar_deps [ ] = {
2008-04-15 12:56:34 +08:00
ZEND_MOD_OPTIONAL ( " apc " )
2008-08-01 21:45:06 +08:00
ZEND_MOD_OPTIONAL ( " bz2 " )
ZEND_MOD_OPTIONAL ( " openssl " )
ZEND_MOD_OPTIONAL ( " zlib " )
ZEND_MOD_OPTIONAL ( " standard " )
2007-01-21 23:25:50 +08:00
# if HAVE_SPL
2006-02-28 09:36:30 +08:00
ZEND_MOD_REQUIRED ( " spl " )
2007-01-21 23:25:50 +08:00
# endif
2006-01-13 05:16:29 +08:00
{ NULL , NULL , NULL }
} ;
zend_module_entry phar_module_entry = {
STANDARD_MODULE_HEADER_EX , NULL ,
phar_deps ,
2006-01-04 10:26:15 +08:00
" Phar " ,
2006-01-03 23:50:46 +08:00
phar_functions ,
PHP_MINIT ( phar ) ,
PHP_MSHUTDOWN ( phar ) ,
2007-05-17 07:20:31 +08:00
NULL ,
2006-01-03 23:50:46 +08:00
PHP_RSHUTDOWN ( phar ) ,
PHP_MINFO ( phar ) ,
2008-03-23 01:09:24 +08:00
PHP_PHAR_VERSION ,
2008-08-14 21:02:13 +08:00
PHP_MODULE_GLOBALS ( phar ) , /* globals descriptor */
PHP_GINIT ( phar ) , /* globals ctor */
PHP_GSHUTDOWN ( phar ) , /* globals dtor */
NULL , /* post deactivate */
STANDARD_MODULE_PROPERTIES_EX
2006-01-03 23:50:46 +08:00
} ;
/* }}} */
2005-12-05 04:35:38 +08:00
/*
* 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
*/