2005-12-04 20:35:38 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-12-04 22:50:54 +00:00
| phar php single - file executable PHP extension |
2005-12-04 20:35:38 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2007-02-05 21:38:50 +00:00
| Copyright ( c ) 2005 - 2007 The PHP Group |
2005-12-04 20:35:38 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-12-04 22:50:54 +00:00
| This source file is subject to version 3.01 of the PHP license , |
2005-12-04 20:35:38 +00: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-04 22:50:54 +00:00
| http : //www.php.net/license/3_01.txt. |
2005-12-04 20:35:38 +00: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 13:18:31 +00:00
| Authors : Gregory Beaver < cellog @ php . net > |
| Marcus Boerger < helly @ php . net > |
2005-12-04 20:35:38 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
2007-01-21 15:25:50 +00:00
# define PHAR_MAIN
# include "phar_internal.h"
2007-03-25 19:03:38 +00:00
# include "SAPI.h"
2006-01-10 06:46:17 +00:00
2005-12-04 20:35:38 +00:00
ZEND_DECLARE_MODULE_GLOBALS ( phar )
2007-01-20 22:40:47 +00: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-23 23:31:14 +00:00
ZEND_INI_MH ( phar_ini_modify_handler ) /* {{{ */
2007-01-20 22:40:47 +00:00
{
2007-02-06 22:41:39 +00:00
zend_bool old , ini ;
2007-01-20 22:40:47 +00:00
2007-02-06 22:41:39 +00:00
if ( entry - > name_length = = 14 ) {
old = PHAR_G ( readonly_orig ) ;
} else {
old = PHAR_G ( require_hash_orig ) ;
}
2007-01-20 22:40:47 +00:00
2007-02-06 22:41:39 +00:00
if ( new_value_length = = 2 & & ! strcasecmp ( " on " , new_value ) ) {
ini = ( zend_bool ) 1 ;
2007-01-20 22:40:47 +00:00
}
2007-02-06 22:41:39 +00:00
else if ( new_value_length = = 3 & & ! strcasecmp ( " yes " , new_value ) ) {
ini = ( zend_bool ) 1 ;
2007-01-20 22:40:47 +00:00
}
2007-02-06 22:41:39 +00:00
else if ( new_value_length = = 4 & & ! strcasecmp ( " true " , new_value ) ) {
ini = ( zend_bool ) 1 ;
2007-01-20 22:40:47 +00:00
}
else {
2007-02-06 22:41:39 +00:00
ini = ( zend_bool ) atoi ( new_value ) ;
2007-01-20 22:40:47 +00:00
}
2007-02-06 22:41:39 +00:00
/* do not allow unsetting in runtime */
if ( stage = = ZEND_INI_STAGE_STARTUP ) {
if ( entry - > name_length = = 14 ) {
PHAR_G ( readonly_orig ) = ini ;
} else {
PHAR_G ( require_hash_orig ) = ini ;
2007-01-20 22:40:47 +00:00
}
2007-02-06 22:41:39 +00:00
} else if ( old & & ! ini ) {
return FAILURE ;
2007-01-20 22:40:47 +00:00
}
2007-02-06 22:41:39 +00:00
if ( entry - > name_length = = 14 ) {
PHAR_G ( readonly ) = ini ;
} else {
PHAR_G ( require_hash ) = ini ;
}
2007-01-20 22:40:47 +00:00
return SUCCESS ;
}
2007-01-23 23:31:14 +00:00
/* }}}*/
2007-01-20 22:40:47 +00:00
2007-03-25 19:03:38 +00:00
static void phar_split_extract_list ( TSRMLS_D )
{
char * tmp = estrdup ( PHAR_GLOBALS - > extract_list ) ;
char * key ;
char * lasts ;
char * q ;
int keylen ;
zend_hash_clean ( & ( PHAR_GLOBALS - > phar_plain_map ) ) ;
for ( key = php_strtok_r ( tmp , " , " , & lasts ) ;
key ;
key = php_strtok_r ( NULL , " , " , & lasts ) )
{
char * val = strchr ( key , ' = ' ) ;
if ( val ) {
* val + + = ' \0 ' ;
for ( q = key ; * q ; q + + ) {
* q = tolower ( * q ) ;
}
keylen = q - key + 1 ;
zend_hash_add ( & ( PHAR_GLOBALS - > phar_plain_map ) , key , keylen , val , strlen ( val ) + 1 , NULL ) ;
}
}
efree ( tmp ) ;
}
/* }}} */
ZEND_INI_MH ( phar_ini_extract_list ) /* {{{ */
{
PHAR_G ( extract_list ) = new_value ;
if ( stage = = ZEND_INI_STAGE_RUNTIME ) {
phar_split_extract_list ( TSRMLS_C ) ;
}
return SUCCESS ;
}
/* }}} */
ZEND_INI_DISP ( phar_ini_extract_list_disp ) /*void name(zend_ini_entry *ini_entry, int type) {{{ */
{
char * value ;
if ( type = = ZEND_INI_DISPLAY_ORIG & & ini_entry - > modified ) {
value = ini_entry - > orig_value ;
} else if ( ini_entry - > value ) {
value = ini_entry - > value ;
} else {
value = NULL ;
}
if ( value ) {
char * tmp = strdup ( value ) ;
char * key ;
char * lasts ;
char * q ;
if ( ! sapi_module . phpinfo_as_text ) {
php_printf ( " <ul> " ) ;
}
for ( key = php_strtok_r ( tmp , " , " , & lasts ) ;
key ;
key = php_strtok_r ( NULL , " , " , & lasts ) )
{
char * val = strchr ( key , ' = ' ) ;
if ( val ) {
* val + + = ' \0 ' ;
for ( q = key ; * q ; q + + ) {
* q = tolower ( * q ) ;
}
if ( sapi_module . phpinfo_as_text ) {
php_printf ( " %s => %s " , key , val ) ;
} else {
php_printf ( " <li>%s => %s</li> " , key , val ) ;
}
}
}
if ( ! sapi_module . phpinfo_as_text ) {
php_printf ( " </ul> " ) ;
}
free ( tmp ) ;
}
}
/* }}} */
2007-01-07 16:01:35 +00:00
PHP_INI_BEGIN ( )
2007-03-25 19:03:38 +00:00
STD_PHP_INI_BOOLEAN ( " phar.readonly " , " 1 " , PHP_INI_ALL , phar_ini_modify_handler , readonly , zend_phar_globals , phar_globals )
STD_PHP_INI_BOOLEAN ( " phar.require_hash " , " 1 " , PHP_INI_ALL , phar_ini_modify_handler , require_hash , zend_phar_globals , phar_globals )
STD_PHP_INI_ENTRY_EX ( " phar.extract_list " , " " , PHP_INI_ALL , phar_ini_extract_list , extract_list , zend_phar_globals , phar_globals , phar_ini_extract_list_disp )
2007-01-07 16:01:35 +00:00
PHP_INI_END ( )
2007-01-02 00:04:30 +00:00
/**
* When all uses of a phar have been concluded , this frees the manifest
* and the phar slot
*/
2007-01-28 12:18:07 +00:00
static void phar_destroy_phar_data ( phar_archive_data * data TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2006-01-11 21:19:46 +00:00
if ( data - > alias & & data - > alias ! = data - > fname ) {
efree ( data - > alias ) ;
2006-02-28 01:36:30 +00:00
data - > alias = NULL ;
2006-01-11 21:19:46 +00:00
}
2007-02-03 04:04:18 +00:00
if ( data - > fname ) {
efree ( data - > fname ) ;
}
2007-01-09 00:27:13 +00:00
if ( data - > signature ) {
efree ( data - > signature ) ;
}
2007-01-03 15:43:07 +00:00
if ( data - > manifest . arBuckets ) {
zend_hash_destroy ( & data - > manifest ) ;
}
2007-01-29 03:59:55 +00:00
if ( data - > metadata ) {
zval_ptr_dtor ( & data - > metadata ) ;
data - > metadata = 0 ;
}
2006-01-10 06:46:17 +00:00
if ( data - > fp ) {
php_stream_close ( data - > fp ) ;
2007-01-26 14:52:10 +00:00
data - > fp = 0 ;
2006-01-10 06:46:17 +00:00
}
2007-01-09 23:23:12 +00:00
2006-03-08 20:07:25 +00:00
efree ( data ) ;
2005-12-04 20:35:38 +00:00
}
2006-01-04 15:50:45 +00:00
/* }}}*/
2005-12-04 20:35:38 +00:00
2007-01-26 19:58:22 +00:00
/**
* Delete refcount and destruct if needed . On destruct return 1 else 0.
*/
int phar_archive_delref ( phar_archive_data * phar TSRMLS_DC ) /* { { { */
{
if ( - - phar - > refcount < 0 ) {
2007-01-27 15:31:24 +00:00
if ( PHAR_GLOBALS - > request_done
| | zend_hash_del ( & ( PHAR_GLOBALS - > phar_fname_map ) , phar - > fname , phar - > fname_len ) ! = SUCCESS ) {
2007-01-26 19:58:22 +00:00
phar_destroy_phar_data ( phar TSRMLS_CC ) ;
}
return 1 ;
}
return 0 ;
}
/* }}}*/
2007-01-10 00:38:17 +00: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 04:04:18 +00:00
if ( EG ( exception ) | | - - phar_data - > refcount < 0 ) {
2007-01-10 00:38:17 +00: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 02:27:12 +00:00
static int phar_unalias_apply ( void * pDest , void * argument TSRMLS_DC ) /* { { { */
{
return * ( void * * ) pDest = = argument ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_KEEP ;
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Filename map destructor
*/
2006-03-08 00:56:31 +00:00
static void destroy_phar_data ( void * pDest ) /* { { { */
{
2006-03-08 20:07:25 +00:00
phar_archive_data * phar_data = * ( phar_archive_data * * ) pDest ;
2007-01-09 02:27:12 +00:00
TSRMLS_FETCH ( ) ;
2007-01-08 19:30:52 +00:00
2007-01-09 02:27:12 +00:00
zend_hash_apply_with_argument ( & ( PHAR_GLOBALS - > phar_alias_map ) , phar_unalias_apply , phar_data TSRMLS_CC ) ;
if ( - - phar_data - > refcount < 0 ) {
2006-03-08 20:07:25 +00:00
phar_destroy_phar_data ( phar_data TSRMLS_CC ) ;
}
2006-03-08 00:56:31 +00:00
}
/* }}}*/
2007-01-02 00:04:30 +00:00
/**
* destructor for the manifest hash , frees each file ' s entry
*/
2006-01-04 15:50:45 +00:00
static void destroy_phar_manifest ( void * pDest ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2006-02-28 01:36:30 +00:00
phar_entry_info * entry = ( phar_entry_info * ) pDest ;
2007-01-10 00:07:45 +00:00
TSRMLS_FETCH ( ) ;
2006-01-04 15:27:18 +00:00
2007-01-27 15:31:24 +00:00
if ( entry - > cfp ) {
php_stream_close ( entry - > cfp ) ;
entry - > cfp = 0 ;
}
2006-01-10 06:46:17 +00:00
if ( entry - > fp ) {
php_stream_close ( entry - > fp ) ;
2007-01-26 14:52:10 +00:00
entry - > fp = 0 ;
2007-01-02 21:21:18 +00:00
}
2007-01-21 06:30:55 +00:00
if ( entry - > metadata ) {
2007-01-21 15:28:56 +00:00
zval_ptr_dtor ( & entry - > metadata ) ;
2007-01-21 06:30:55 +00:00
entry - > metadata = 0 ;
}
2006-01-04 15:27:18 +00:00
efree ( entry - > filename ) ;
2005-12-04 20:35:38 +00:00
}
2006-01-04 15:50:45 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 00:04:30 +00:00
/**
* Looks up a phar archive in the filename map , connecting it to the alias
* ( if any ) or returns null
*/
2007-01-29 06:02:19 +00:00
static int phar_get_archive ( phar_archive_data * * archive , char * fname , int fname_len , char * alias , int alias_len , char * * error TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2006-03-04 02:12:22 +00:00
phar_archive_data * fd , * * fd_ptr ;
2006-01-11 01:51:47 +00:00
2007-01-29 06:02:19 +00:00
if ( error ) {
* error = NULL ;
}
2007-01-29 07:59:19 +00:00
* archive = NULL ;
2006-01-11 01:51:47 +00:00
if ( alias & & alias_len ) {
2006-01-11 21:19:46 +00:00
if ( SUCCESS = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * * ) & fd_ptr ) ) {
if ( fname & & ( fname_len ! = ( * fd_ptr ) - > fname_len | | strncmp ( fname , ( * fd_ptr ) - > fname , fname_len ) ) ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " alias \" %s \" is already used for archive \" %s \" cannot be overloaded with \" %s \" " , alias , ( * fd_ptr ) - > fname , fname ) ;
}
return FAILURE ;
2006-01-11 21:19:46 +00:00
}
2007-01-29 06:02:19 +00:00
* archive = * fd_ptr ;
return SUCCESS ;
2006-01-11 01:51:47 +00:00
}
}
if ( fname & & fname_len ) {
2006-03-08 20:07:25 +00:00
if ( SUCCESS = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_fname_map ) , fname , fname_len , ( void * * ) & fd_ptr ) ) {
2007-01-29 06:02:19 +00:00
* archive = * fd_ptr ;
2006-03-08 20:07:25 +00:00
fd = * fd_ptr ;
2006-01-11 21:19:46 +00:00
if ( alias & & alias_len ) {
2006-03-04 02:12:22 +00:00
zend_hash_add ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * ) & fd , sizeof ( phar_archive_data * ) , NULL ) ;
2006-01-11 21:19:46 +00:00
}
2007-01-29 06:02:19 +00:00
return SUCCESS ;
2006-01-11 01:51:47 +00:00
}
2006-01-11 21:19:46 +00:00
if ( SUCCESS = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_alias_map ) , fname , fname_len , ( void * * ) & fd_ptr ) ) {
2007-01-29 06:02:19 +00:00
* archive = * fd_ptr ;
return SUCCESS ;
2006-01-11 01:51:47 +00:00
}
}
2007-01-29 06:02:19 +00:00
return FAILURE ;
2006-01-11 01:51:47 +00:00
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* retrieve information on a file contained within a phar , or null if it ain ' t there
*/
2007-02-04 20:10:03 +00:00
phar_entry_info * phar_get_entry_info ( phar_archive_data * phar , char * path , int path_len , char * * error TSRMLS_DC ) /* { { { */
2006-02-28 01:36:30 +00:00
{
2007-02-04 20:10:03 +00:00
const char * pcr_error ;
2006-02-28 01:36:30 +00:00
phar_entry_info * entry ;
2007-02-04 20:10:03 +00:00
if ( error ) {
* error = NULL ;
}
if ( phar_path_check ( & path , & path_len , & pcr_error ) > pcr_is_ok ) {
if ( error ) {
spprintf ( error , 0 , " phar error: invalid path \" %s \" contains %s " , path , pcr_error ) ;
}
return NULL ;
2006-02-28 01:36:30 +00:00
}
2007-02-04 20:10:03 +00:00
2007-01-03 15:43:07 +00:00
if ( ! & phar - > manifest . arBuckets ) {
return NULL ;
}
2006-02-28 01:36:30 +00:00
if ( SUCCESS = = zend_hash_find ( & phar - > manifest , path , path_len , ( void * * ) & entry ) ) {
2007-01-13 17:10:18 +00:00
if ( entry - > is_deleted ) {
2007-01-05 02:04:07 +00:00
/* entry is deleted, but has not been flushed to disk yet */
return NULL ;
}
2006-02-28 01:36:30 +00:00
return entry ;
}
return NULL ;
}
/* }}} */
2007-02-04 20:10:03 +00:00
# if defined(PHP_VERSION_ID) && PHP_VERSION_ID < 50202
2007-01-27 21:34:40 +00:00
typedef struct {
char * data ;
size_t fpos ;
size_t fsize ;
size_t smax ;
int mode ;
php_stream * * owner_ptr ;
} php_stream_memory_data ;
# endif
2007-01-02 00:04:30 +00:00
/**
* Retrieve a copy of the file information on a single file within a phar , or null .
* This also transfers the open file pointer , if any , to the entry .
*/
2007-01-27 18:27:19 +00:00
static int phar_get_entry_data ( phar_entry_data * * ret , char * fname , int fname_len , char * path , int path_len , char * mode , char * * error TSRMLS_DC ) /* { { { */
2006-01-11 01:51:47 +00:00
{
2006-03-04 02:12:22 +00:00
phar_archive_data * phar ;
2006-02-28 01:36:30 +00:00
phar_entry_info * entry ;
2007-01-27 15:31:24 +00:00
int for_write = mode [ 0 ] ! = ' r ' | | mode [ 1 ] = = ' + ' ;
int for_append = mode [ 0 ] = = ' a ' ;
int for_create = mode [ 0 ] ! = ' r ' ;
int for_trunc = mode [ 0 ] = = ' w ' ;
2007-01-26 14:52:10 +00:00
if ( ! ret ) {
return FAILURE ;
}
* ret = NULL ;
2007-01-27 21:23:02 +00:00
if ( error ) {
* error = NULL ;
}
2007-01-27 15:31:24 +00:00
if ( for_write & & PHAR_G ( readonly ) ) {
2007-01-27 18:27:19 +00:00
if ( error ) {
2007-01-27 21:23:02 +00:00
spprintf ( error , 0 , " phar error: file \" %s \" cannot opened for writing, disabled by ini setting " , fname ) ;
2007-01-27 18:27:19 +00:00
}
2007-01-27 15:31:24 +00:00
return FAILURE ;
}
2007-01-29 06:02:19 +00:00
if ( FAILURE = = phar_get_archive ( & phar , fname , fname_len , NULL , 0 , error TSRMLS_CC ) ) {
return FAILURE ;
}
2007-02-04 20:10:03 +00:00
if ( ( entry = phar_get_entry_info ( phar , path , path_len , for_create & & ! PHAR_G ( readonly ) ? NULL : error TSRMLS_CC ) ) = = NULL ) {
2007-01-29 06:02:19 +00:00
if ( for_create & & ! PHAR_G ( readonly ) ) {
return SUCCESS ;
}
return FAILURE ;
}
if ( entry - > is_modified & & ! for_write ) {
if ( error ) {
spprintf ( error , 0 , " phar error: file \" %s \" cannot opened for reading, writable file pointers are open " , fname ) ;
}
return FAILURE ;
}
if ( entry - > fp_refcount & & for_write ) {
if ( error ) {
spprintf ( error , 0 , " phar error: file \" %s \" cannot opened for writing, readable file pointers are open " , fname ) ;
}
return FAILURE ;
}
if ( entry - > is_deleted ) {
if ( ! for_create ) {
return FAILURE ;
}
entry - > is_deleted = 0 ;
}
* ret = ( phar_entry_data * ) emalloc ( sizeof ( phar_entry_data ) ) ;
( * ret ) - > position = 0 ;
( * ret ) - > phar = phar ;
( * ret ) - > internal_file = entry ;
if ( entry - > fp ) {
/* make a copy */
if ( for_trunc ) {
2007-02-04 20:10:03 +00:00
# if PHP_VERSION_ID >= 50202
php_stream_truncate_set_size ( entry - > fp , 0 ) ;
# else
2007-01-29 06:02:19 +00:00
if ( php_stream_is ( entry - > fp , PHP_STREAM_IS_TEMP ) ) {
if ( php_stream_is ( * ( php_stream * * ) entry - > fp - > abstract , PHP_STREAM_IS_MEMORY ) ) {
php_stream * inner = * ( php_stream * * ) entry - > fp - > abstract ;
php_stream_memory_data * memfp = ( php_stream_memory_data * ) inner - > abstract ;
memfp - > fpos = 0 ;
memfp - > fsize = 0 ;
} else if ( php_stream_is ( * ( php_stream * * ) entry - > fp - > abstract , PHP_STREAM_IS_STDIO ) ) {
php_stream_truncate_set_size ( * ( php_stream * * ) entry - > fp - > abstract , 0 ) ;
} else {
efree ( * ret ) ;
* ret = NULL ;
if ( error ) {
spprintf ( error , 0 , " phar error: file \" %s \" cannot opened for writing, no truncate support " , fname ) ;
}
return FAILURE ;
2007-01-27 18:27:19 +00:00
}
2007-01-29 06:02:19 +00:00
} else if ( php_stream_is ( entry - > fp , PHP_STREAM_IS_STDIO ) ) {
php_stream_truncate_set_size ( entry - > fp , 0 ) ;
} else {
efree ( * ret ) ;
* ret = NULL ;
2007-01-27 18:27:19 +00:00
if ( error ) {
2007-01-29 06:02:19 +00:00
spprintf ( error , 0 , " phar error: file \" %s \" cannot opened for writing, no truncate support " , fname ) ;
2007-01-27 18:27:19 +00:00
}
2007-01-26 14:52:10 +00:00
return FAILURE ;
}
2007-01-27 21:34:40 +00:00
# endif
2007-01-29 06:02:19 +00:00
entry - > is_modified = 1 ;
phar - > is_modified = 1 ;
/* reset file size */
entry - > uncompressed_filesize = 0 ;
entry - > compressed_filesize = 0 ;
entry - > crc32 = 0 ;
} else if ( for_append ) {
php_stream_seek ( entry - > fp , 0 , SEEK_END ) ;
}
( * ret ) - > fp = entry - > fp ;
} else {
( * ret ) - > fp = 0 ;
if ( for_write ) {
/* open a new temp file for writing */
entry - > fp = php_stream_fopen_tmpfile ( ) ;
2007-02-05 22:11:27 +00:00
if ( ! entry - > fp ) {
if ( error ) {
spprintf ( error , 0 , " phar error: unable to create temprary file " ) ;
}
return FAILURE ;
}
2007-01-29 06:02:19 +00:00
( * ret ) - > fp = entry - > fp ;
entry - > is_modified = 1 ;
phar - > is_modified = 1 ;
/* reset file size */
entry - > uncompressed_filesize = 0 ;
entry - > compressed_filesize = 0 ;
entry - > crc32 = 0 ;
entry - > flags = PHAR_ENT_PERM_DEF_FILE ;
}
}
entry - > fp_refcount + + ;
entry - > phar - > refcount + + ;
return SUCCESS ;
2007-01-26 14:52:10 +00:00
}
/* }}} */
2007-01-27 15:31:24 +00:00
int phar_entry_delref ( phar_entry_data * idata TSRMLS_DC ) /* { { { */
{
int ret = 0 ;
if ( - - idata - > internal_file - > fp_refcount < = 0 ) {
idata - > internal_file - > fp_refcount = 0 ;
}
if ( idata - > fp & & idata - > fp ! = idata - > internal_file - > fp ) {
php_stream_close ( idata - > fp ) ;
}
phar_archive_delref ( idata - > internal_file - > phar TSRMLS_CC ) ;
efree ( idata ) ;
return ret ;
}
2007-02-06 21:04:22 +00:00
/* }}} */
2007-01-27 15:31:24 +00:00
2007-01-26 14:52:10 +00:00
/**
2007-01-27 15:31:24 +00:00
* Removes an entry , either by actually removingit or by marking it .
2007-01-26 14:52:10 +00:00
*/
2007-01-29 06:02:19 +00:00
void phar_entry_remove ( phar_entry_data * idata , char * * error TSRMLS_DC ) /* { { { */
2007-01-26 14:52:10 +00:00
{
2007-01-27 15:31:24 +00:00
if ( ! idata - > phar - > donotflush ) {
2007-01-29 06:02:19 +00:00
phar_flush ( idata - > internal_file - > phar , 0 , 0 , error TSRMLS_CC ) ;
2007-01-27 15:31:24 +00:00
}
if ( idata - > internal_file - > fp_refcount < 2 ) {
if ( idata - > fp & & idata - > fp ! = idata - > internal_file - > fp ) {
php_stream_close ( idata - > fp ) ;
2007-01-26 14:52:10 +00:00
}
2007-01-27 17:27:48 +00:00
zend_hash_del ( & idata - > phar - > manifest , idata - > internal_file - > filename , idata - > internal_file - > filename_len ) ;
2007-01-27 22:23:52 +00:00
idata - > phar - > refcount - - ;
2007-01-26 14:52:10 +00:00
efree ( idata ) ;
2007-01-27 15:31:24 +00:00
} else {
idata - > internal_file - > is_deleted = 1 ;
phar_entry_delref ( idata TSRMLS_CC ) ;
2007-01-26 14:52:10 +00:00
}
2005-12-04 20:35:38 +00:00
}
2006-01-04 15:50:45 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 18:15:17 +00:00
/**
* Create a new dummy file slot within a writeable phar for a newly created file
*/
2007-01-27 18:27:19 +00:00
phar_entry_data * phar_get_or_create_entry_data ( char * fname , int fname_len , char * path , int path_len , char * mode , char * * error TSRMLS_DC ) /* { { { */
2007-01-02 18:15:17 +00:00
{
phar_archive_data * phar ;
phar_entry_info * entry , etemp ;
phar_entry_data * ret ;
2007-02-04 13:21:40 +00:00
const char * pcr_error ;
2007-01-29 06:02:19 +00:00
if ( FAILURE = = phar_get_archive ( & phar , fname , fname_len , NULL , 0 , error TSRMLS_CC ) ) {
2007-01-02 18:15:17 +00:00
return NULL ;
}
2007-01-07 16:01:35 +00:00
2007-01-27 18:27:19 +00:00
if ( FAILURE = = phar_get_entry_data ( & ret , fname , fname_len , path , path_len , mode , error TSRMLS_CC ) ) {
2007-01-26 14:52:10 +00:00
return NULL ;
2007-02-04 13:21:40 +00:00
} else if ( ret ) {
2007-01-02 19:59:38 +00:00
return ret ;
}
2007-01-07 16:01:35 +00:00
2007-02-04 20:10:03 +00:00
if ( phar_path_check ( & path , & path_len , & pcr_error ) > pcr_is_ok ) {
if ( error ) {
spprintf ( error , 0 , " phar error: invalid path \" %s \" contains %s " , path , pcr_error ) ;
}
return NULL ;
}
2007-01-05 01:50:26 +00:00
/* create a new phar data holder */
ret = ( phar_entry_data * ) emalloc ( sizeof ( phar_entry_data ) ) ;
2007-01-26 14:52:10 +00:00
/* create an entry, this is a new file */
memset ( & etemp , 0 , sizeof ( phar_entry_info ) ) ;
etemp . filename_len = path_len ;
etemp . fp = php_stream_fopen_tmpfile ( ) ;
2007-02-05 22:11:27 +00:00
if ( ! etemp . fp ) {
if ( error ) {
spprintf ( error , 0 , " phar error: unable to create temorary file " ) ;
}
return NULL ;
}
2007-01-26 14:52:10 +00:00
etemp . fp_refcount = 1 ;
etemp . is_modified = 1 ;
etemp . filename = estrndup ( path , path_len ) ;
etemp . timestamp = time ( 0 ) ;
etemp . offset_within_phar = - 1 ;
etemp . is_crc_checked = 1 ;
etemp . flags = PHAR_ENT_PERM_DEF_FILE ;
etemp . phar = phar ;
zend_hash_add ( & phar - > manifest , etemp . filename , path_len , ( void * ) & etemp , sizeof ( phar_entry_info ) , NULL ) ;
/* retrieve the phar manifest copy */
2007-02-04 20:10:03 +00:00
entry = phar_get_entry_info ( phar , path , path_len , error TSRMLS_CC ) ;
if ( ! entry ) {
2007-02-04 20:35:59 +00:00
return NULL ;
2007-02-04 20:10:03 +00:00
}
2007-01-26 14:52:10 +00:00
2007-01-27 15:31:24 +00:00
phar - > refcount + + ;
2007-01-02 18:15:17 +00:00
ret - > phar = phar ;
2007-01-26 14:52:10 +00:00
ret - > fp = entry - > fp ;
ret - > position = 0 ;
2007-01-02 18:15:17 +00:00
ret - > internal_file = entry ;
return ret ;
}
/* }}} */
2006-01-04 02:26:15 +00:00
# define MAPPHAR_ALLOC_FAIL(msg) \
php_stream_close ( fp ) ; \
2007-01-29 06:02:19 +00:00
if ( error ) { \
spprintf ( error , 0 , msg , fname ) ; \
} \
2006-01-04 02:26:15 +00:00
return FAILURE ;
# define MAPPHAR_FAIL(msg) \
efree ( savebuf ) ; \
2007-01-09 00:27:13 +00:00
if ( mydata ) { \
2007-02-03 04:04:18 +00:00
phar_destroy_phar_data ( mydata TSRMLS_CC ) ; \
2007-01-09 00:27:13 +00:00
} \
if ( signature ) { \
efree ( signature ) ; \
} \
2006-01-04 02:26:15 +00:00
MAPPHAR_ALLOC_FAIL ( msg )
2006-01-05 00:39:31 +00:00
# ifdef WORDS_BIGENDIAN
2006-01-10 06:46:17 +00:00
# define PHAR_GET_32(buffer, var) \
2007-02-06 21:43:46 +00:00
var = ( ( ( ( unsigned char * ) ( buffer ) ) [ 3 ] ) < < 24 ) \
| ( ( ( ( unsigned char * ) ( buffer ) ) [ 2 ] ) < < 16 ) \
| ( ( ( ( unsigned char * ) ( buffer ) ) [ 1 ] ) < < 8 ) \
| ( ( ( unsigned char * ) ( buffer ) ) [ 0 ] ) ; \
2007-01-21 06:30:55 +00:00
( buffer ) + = 4
# define PHAR_GET_16(buffer, var) \
2007-02-06 21:43:46 +00:00
var = ( ( ( ( unsigned char * ) ( buffer ) ) [ 1 ] ) < < 8 ) \
| ( ( ( unsigned char * ) ( buffer ) ) [ 0 ] ) ; \
2007-01-21 06:30:55 +00:00
( buffer ) + = 2
2006-01-05 00:39:31 +00:00
# else
2006-01-10 06:46:17 +00:00
# define PHAR_GET_32(buffer, var) \
2006-01-05 22:24:41 +00:00
var = * ( php_uint32 * ) ( buffer ) ; \
2006-01-05 00:39:31 +00:00
buffer + = 4
2007-01-21 06:30:55 +00:00
# define PHAR_GET_16(buffer, var) \
var = * ( php_uint16 * ) ( buffer ) ; \
buffer + = 2
2006-01-05 00:39:31 +00:00
# endif
2007-01-02 00:04:30 +00:00
/**
2007-01-11 01:04:47 +00:00
* Open an already loaded phar
*/
2007-01-29 06:02:19 +00:00
static int phar_open_loaded ( char * fname , int fname_len , char * alias , int alias_len , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2007-01-11 01:04:47 +00:00
{
phar_archive_data * phar ;
2007-01-29 07:59:19 +00:00
if ( error ) {
* error = NULL ;
}
2007-01-29 06:02:19 +00:00
if ( SUCCESS = = phar_get_archive ( & phar , fname , fname_len , alias , alias_len , error TSRMLS_CC )
2007-01-26 14:52:10 +00:00
& & fname_len = = phar - > fname_len
& & ! strncmp ( fname , phar - > fname , fname_len )
) {
2007-01-11 01:04:47 +00:00
if ( pphar ) {
* pphar = phar ;
}
return SUCCESS ;
} else {
if ( pphar ) {
* pphar = NULL ;
}
if ( phar & & alias & & ( options & REPORT_ERRORS ) ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
2007-01-29 07:59:19 +00:00
spprintf ( error , 0 , " alias \" %s \" is already used for archive \" %s \" cannot be overloaded with \" %s \" " , alias , phar - > fname , fname ) ;
2007-01-29 06:02:19 +00:00
}
2007-01-11 01:04:47 +00:00
}
return FAILURE ;
}
}
/* }}}*/
2007-01-21 06:30:55 +00:00
/**
* Parse out metadata from the manifest for a single file
*
* Meta - data is in this format :
2007-01-21 20:12:50 +00:00
* [ len32 ] [ data . . . ]
2007-01-21 06:30:55 +00:00
*
2007-01-21 20:12:50 +00:00
* data is the serialized zval
2007-01-21 06:30:55 +00:00
*/
2007-01-21 20:12:50 +00:00
static int phar_parse_metadata ( php_stream * fp , char * * buffer , char * endbuffer , zval * * metadata TSRMLS_DC ) /* { { { */
2007-01-21 06:30:55 +00:00
{
2007-01-21 20:12:50 +00:00
const unsigned char * p ;
php_uint32 buf_len ;
php_unserialize_data_t var_hash ;
PHAR_GET_32 ( * buffer , buf_len ) ;
if ( buf_len ) {
ALLOC_INIT_ZVAL ( * metadata ) ;
p = ( const unsigned char * ) * buffer ;
PHP_VAR_UNSERIALIZE_INIT ( var_hash ) ;
if ( ! php_var_unserialize ( metadata , & p , p + buf_len , & var_hash TSRMLS_CC ) ) {
PHP_VAR_UNSERIALIZE_DESTROY ( var_hash ) ;
zval_ptr_dtor ( metadata ) ;
* metadata = NULL ;
2007-01-21 06:30:55 +00:00
return FAILURE ;
}
2007-01-21 20:12:50 +00:00
PHP_VAR_UNSERIALIZE_DESTROY ( var_hash ) ;
2007-02-06 23:19:10 +00:00
} else {
* metadata = NULL ;
2007-01-21 20:12:50 +00:00
}
* buffer + = buf_len ;
2007-01-21 06:30:55 +00:00
return SUCCESS ;
}
/* }}}*/
2007-02-24 02:08:08 +00:00
static const char hexChars [ ] = " 0123456789ABCDEF " ;
static int phar_hex_str ( const char * digest , size_t digest_len , char * * signature )
{
int pos = - 1 ;
size_t len ;
* signature = ( char * ) safe_emalloc ( digest_len , 2 , 1 ) ;
for ( len = 0 ; len < digest_len ; + + len ) {
( * signature ) [ + + pos ] = hexChars [ ( ( const unsigned char * ) digest ) [ len ] > > 4 ] ;
( * signature ) [ + + pos ] = hexChars [ ( ( const unsigned char * ) digest ) [ len ] & 0x0F ] ;
}
( * signature ) [ + + pos ] = ' \0 ' ;
return pos ;
}
2007-01-11 01:04:47 +00:00
/**
* Does not check for a previously opened phar in the cache .
*
* Parse a new one and add it to the cache , returning either SUCCESS or
* FAILURE , and setting pphar to the pointer to the manifest entry
2007-01-02 00:04:30 +00:00
*
* This is used by phar_open_filename to process the manifest , but can be called
* directly .
*/
2007-01-29 06:02:19 +00:00
int phar_open_file ( php_stream * fp , char * fname , int fname_len , char * alias , int alias_len , long halt_offset , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2006-01-10 06:46:17 +00:00
char b32 [ 4 ] , * buffer , * endbuffer , * savebuf ;
2007-01-09 00:27:13 +00:00
phar_archive_data * mydata = NULL ;
2006-02-28 01:36:30 +00:00
phar_entry_info entry ;
2007-01-13 16:17:04 +00:00
php_uint32 manifest_len , manifest_count , manifest_flags , manifest_index , tmp_len , sig_flags ;
php_uint16 manifest_ver ;
2006-01-10 06:46:17 +00:00
long offset ;
2007-01-09 00:27:13 +00:00
int register_alias , sig_len ;
char * signature = NULL ;
2005-12-04 20:35:38 +00:00
2007-01-04 05:32:45 +00:00
if ( pphar ) {
2006-02-28 01:36:30 +00:00
* pphar = NULL ;
}
2007-01-29 06:02:19 +00:00
if ( error ) {
* error = NULL ;
}
2006-02-28 01:36:30 +00:00
2005-12-08 07:38:44 +00:00
/* check for ?>\n and increment accordingly */
2005-12-08 07:08:49 +00:00
if ( - 1 = = php_stream_seek ( fp , halt_offset , SEEK_SET ) ) {
2005-12-08 07:34:16 +00:00
MAPPHAR_ALLOC_FAIL ( " cannot seek to __HALT_COMPILER(); location in phar \" %s \" " )
2005-12-08 06:46:02 +00:00
}
2006-01-10 06:46:17 +00:00
buffer = b32 ;
2005-12-07 06:39:03 +00:00
if ( 3 ! = php_stream_read ( fp , buffer , 3 ) ) {
2006-01-10 06:46:17 +00:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest) " )
2005-12-04 20:35:38 +00:00
}
2007-01-28 21:26:54 +00:00
if ( ( * buffer = = ' ' | | * buffer = = ' \n ' ) & & * ( buffer + 1 ) = = ' ? ' & & * ( buffer + 2 ) = = ' > ' ) {
2005-12-04 20:35:38 +00:00
int nextchar ;
2005-12-07 01:18:54 +00:00
halt_offset + = 3 ;
2005-12-07 06:39:03 +00:00
if ( EOF = = ( nextchar = php_stream_getc ( fp ) ) ) {
2006-01-10 06:46:17 +00:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest) " )
2005-12-07 06:39:03 +00:00
}
2005-12-04 20:35:38 +00:00
if ( ( char ) nextchar = = ' \r ' ) {
2005-12-07 06:39:03 +00:00
if ( EOF = = ( nextchar = php_stream_getc ( fp ) ) ) {
2006-01-10 06:46:17 +00:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest) " )
2005-12-07 06:39:03 +00:00
}
2005-12-04 20:35:38 +00:00
halt_offset + + ;
}
if ( ( char ) nextchar = = ' \n ' ) {
halt_offset + + ;
}
}
2005-12-08 07:38:44 +00:00
/* make sure we are at the right location to read the manifest */
2005-12-08 07:08:49 +00:00
if ( - 1 = = php_stream_seek ( fp , halt_offset , SEEK_SET ) ) {
2006-01-10 06:46:17 +00:00
MAPPHAR_ALLOC_FAIL ( " cannot seek to __HALT_COMPILER(); location in phar \" %s \" " )
2005-12-08 07:08:49 +00:00
}
2005-12-04 20:35:38 +00:00
2005-12-08 07:38:44 +00:00
/* read in manifest */
2006-01-10 06:46:17 +00:00
buffer = b32 ;
2005-12-07 06:39:03 +00:00
if ( 4 ! = php_stream_read ( fp , buffer , 4 ) ) {
2006-01-10 06:46:17 +00:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest) " )
2005-12-07 06:39:03 +00:00
}
2006-01-10 06:46:17 +00:00
PHAR_GET_32 ( buffer , manifest_len ) ;
2005-12-08 07:34:16 +00:00
if ( manifest_len > 1048576 ) {
/* prevent serious memory issues by limiting manifest to at most 1 MB in length */
2006-01-10 06:46:17 +00:00
MAPPHAR_ALLOC_FAIL ( " manifest cannot be larger than 1 MB in phar \" %s \" " )
2005-12-07 06:39:03 +00:00
}
2006-01-10 06:46:17 +00:00
buffer = ( char * ) emalloc ( manifest_len ) ;
2005-12-04 20:35:38 +00:00
savebuf = buffer ;
endbuffer = buffer + manifest_len ;
2005-12-07 06:39:03 +00:00
if ( manifest_len ! = php_stream_read ( fp , buffer , manifest_len ) ) {
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest) " )
}
2006-01-11 00:50:07 +00:00
if ( manifest_len < 10 ) {
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest header) " )
}
2006-01-10 06:46:17 +00:00
2005-12-08 07:38:44 +00:00
/* extract the number of entries */
2006-01-10 06:46:17 +00:00
PHAR_GET_32 ( buffer , manifest_count ) ;
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 00:39:31 +00:00
}
2006-01-10 06:46:17 +00:00
2007-01-13 16:17:04 +00:00
/* extract API version, lowest nibble currently unused */
manifest_ver = ( ( ( unsigned char ) buffer [ 0 ] ) < < 8 )
+ ( ( unsigned char ) buffer [ 1 ] ) ;
2006-01-10 06:46:17 +00:00
buffer + = 2 ;
2007-01-13 16:44:54 +00:00
if ( ( manifest_ver & PHAR_API_VER_MASK ) < PHAR_API_MIN_READ ) {
2006-01-10 06:46:17 +00:00
efree ( savebuf ) ;
2007-01-11 01:04:47 +00:00
php_stream_close ( fp ) ;
2007-01-29 06:02:19 +00: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 06:46:17 +00:00
return FAILURE ;
}
2007-01-08 23:03:41 +00:00
2007-01-13 16:17:04 +00:00
PHAR_GET_32 ( buffer , manifest_flags ) ;
2007-01-14 00:32:38 +00:00
manifest_flags & = ~ PHAR_HDR_COMPRESSION_MASK ;
2007-01-13 16:17:04 +00:00
2007-01-20 05:28:48 +00:00
/* The lowest nibble contains the phar wide flags. The compression flags can */
2006-01-12 21:16:29 +00:00
/* be ignored on reading because it is being generated anyways. */
2007-01-13 16:17:04 +00:00
if ( manifest_flags & PHAR_HDR_SIGNATURE ) {
2007-01-08 23:03:41 +00:00
unsigned char buf [ 1024 ] ;
int read_size , len ;
char sig_buf [ 8 ] , * sig_ptr = sig_buf ;
off_t read_len ;
if ( - 1 = = php_stream_seek ( fp , - 8 , SEEK_END )
| | ( read_len = php_stream_tell ( fp ) ) < 20
| | 8 ! = php_stream_read ( fp , sig_buf , 8 )
| | memcmp ( sig_buf + 4 , " GBMB " , 4 ) ) {
efree ( savebuf ) ;
2007-01-11 01:04:47 +00:00
php_stream_close ( fp ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
2007-01-08 23:03:41 +00:00
return FAILURE ;
}
PHAR_GET_32 ( sig_ptr , sig_flags ) ;
switch ( sig_flags ) {
2007-03-25 21:43:49 +00:00
# if HAVE_HASH_EXT
case PHAR_SIG_SHA512 : {
unsigned char digest [ 64 ] , saved [ 64 ] ;
PHP_SHA512_CTX context ;
php_stream_rewind ( fp ) ;
PHP_SHA512Init ( & context ) ;
read_len - = sizeof ( digest ) ;
if ( read_len > sizeof ( buf ) ) {
read_size = sizeof ( buf ) ;
} else {
read_size = ( int ) read_len ;
}
while ( ( len = php_stream_read ( fp , ( char * ) buf , read_size ) ) > 0 ) {
PHP_SHA512Update ( & context , buf , len ) ;
read_len - = ( off_t ) len ;
if ( read_len < read_size ) {
read_size = ( int ) read_len ;
}
}
PHP_SHA512Final ( digest , & context ) ;
if ( read_len > 0
| | php_stream_read ( fp , ( char * ) saved , sizeof ( saved ) ) ! = sizeof ( saved )
| | memcmp ( digest , saved , sizeof ( digest ) ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
return FAILURE ;
}
sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & signature ) ;
break ;
}
case PHAR_SIG_SHA256 : {
unsigned char digest [ 32 ] , saved [ 32 ] ;
PHP_SHA256_CTX context ;
php_stream_rewind ( fp ) ;
PHP_SHA256Init ( & context ) ;
read_len - = sizeof ( digest ) ;
if ( read_len > sizeof ( buf ) ) {
read_size = sizeof ( buf ) ;
} else {
read_size = ( int ) read_len ;
}
while ( ( len = php_stream_read ( fp , ( char * ) buf , read_size ) ) > 0 ) {
PHP_SHA256Update ( & context , buf , len ) ;
read_len - = ( off_t ) len ;
if ( read_len < read_size ) {
read_size = ( int ) read_len ;
}
}
PHP_SHA256Final ( digest , & context ) ;
if ( read_len > 0
| | php_stream_read ( fp , ( char * ) saved , sizeof ( saved ) ) ! = sizeof ( saved )
| | memcmp ( digest , saved , sizeof ( digest ) ) ) {
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
return FAILURE ;
}
sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & signature ) ;
break ;
}
# else
case PHAR_SIG_SHA512 :
case PHAR_SIG_SHA256 :
efree ( savebuf ) ;
php_stream_close ( fp ) ;
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a unsupported signature " , fname ) ;
}
return FAILURE ;
# endif
2007-01-08 23:03:41 +00:00
case PHAR_SIG_SHA1 : {
unsigned char digest [ 20 ] , saved [ 20 ] ;
PHP_SHA1_CTX context ;
php_stream_rewind ( fp ) ;
PHP_SHA1Init ( & context ) ;
read_len - = sizeof ( digest ) ;
if ( read_len > sizeof ( buf ) ) {
read_size = sizeof ( buf ) ;
} else {
read_size = ( int ) read_len ;
}
while ( ( len = php_stream_read ( fp , ( char * ) buf , read_size ) ) > 0 ) {
PHP_SHA1Update ( & context , buf , len ) ;
read_len - = ( off_t ) len ;
if ( read_len < read_size ) {
read_size = ( int ) read_len ;
}
}
PHP_SHA1Final ( digest , & context ) ;
if ( read_len > 0
| | php_stream_read ( fp , ( char * ) saved , sizeof ( saved ) ) ! = sizeof ( saved )
| | memcmp ( digest , saved , sizeof ( digest ) ) ) {
efree ( savebuf ) ;
2007-01-11 01:04:47 +00:00
php_stream_close ( fp ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
2007-01-08 23:03:41 +00:00
return FAILURE ;
}
2006-01-10 06:46:17 +00:00
2007-03-25 19:03:38 +00:00
sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & signature ) ;
2007-01-08 23:03:41 +00:00
break ;
}
case PHAR_SIG_MD5 : {
unsigned char digest [ 16 ] , saved [ 16 ] ;
PHP_MD5_CTX context ;
php_stream_rewind ( fp ) ;
PHP_MD5Init ( & context ) ;
read_len - = sizeof ( digest ) ;
if ( read_len > sizeof ( buf ) ) {
read_size = sizeof ( buf ) ;
} else {
read_size = ( int ) read_len ;
}
while ( ( len = php_stream_read ( fp , ( char * ) buf , read_size ) ) > 0 ) {
PHP_MD5Update ( & context , buf , len ) ;
read_len - = ( off_t ) len ;
if ( read_len < read_size ) {
read_size = ( int ) read_len ;
}
}
PHP_MD5Final ( digest , & context ) ;
if ( read_len > 0
| | php_stream_read ( fp , ( char * ) saved , sizeof ( saved ) ) ! = sizeof ( saved )
| | memcmp ( digest , saved , sizeof ( digest ) ) ) {
efree ( savebuf ) ;
2007-01-11 01:04:47 +00:00
php_stream_close ( fp ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" has a broken signature " , fname ) ;
}
2007-01-08 23:03:41 +00:00
return FAILURE ;
}
2007-03-25 19:03:38 +00:00
sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & signature ) ;
2007-01-08 23:03:41 +00:00
break ;
}
default :
efree ( savebuf ) ;
2007-01-11 01:04:47 +00:00
php_stream_close ( fp ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
2007-03-25 21:43:49 +00:00
spprintf ( error , 0 , " phar \" %s \" has a broken or unsupported signature " , fname ) ;
2007-01-29 06:02:19 +00:00
}
2007-01-08 23:03:41 +00:00
return FAILURE ;
}
} else if ( PHAR_G ( require_hash ) ) {
efree ( savebuf ) ;
2007-01-11 01:04:47 +00:00
php_stream_close ( fp ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " phar \" %s \" does not have a signature " , fname ) ;
}
2007-01-08 23:03:41 +00:00
return FAILURE ;
2007-01-09 00:27:13 +00:00
} else {
sig_flags = 0 ;
sig_len = 0 ;
2007-01-08 23:03:41 +00:00
}
2006-01-10 06:46:17 +00:00
/* extract alias */
PHAR_GET_32 ( buffer , tmp_len ) ;
2006-01-11 00:50:07 +00:00
if ( buffer + tmp_len > endbuffer ) {
2006-01-10 06:46:17 +00:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (buffer overrun) " ) ;
}
2006-01-11 00:50:07 +00:00
if ( manifest_len < 10 + tmp_len ) {
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest header) " )
}
/* tmp_len = 0 says alias length is 0, which means the alias is not stored in the phar */
2006-01-10 06:46:17 +00:00
if ( tmp_len ) {
/* if the alias is stored we enforce it (implicit overrides explicit) */
2007-02-05 20:34:23 +00:00
if ( alias & & alias_len & & ( alias_len ! = ( int ) tmp_len | | strncmp ( alias , buffer , tmp_len ) ) )
2006-01-10 06:46:17 +00:00
{
buffer [ tmp_len ] = ' \0 ' ;
efree ( savebuf ) ;
2007-01-11 01:04:47 +00:00
php_stream_close ( fp ) ;
2007-01-09 00:27:13 +00:00
if ( signature ) {
efree ( signature ) ;
}
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " cannot load phar \" %s \" with implicit alias \" %s \" under different alias \" %s \" " , fname , buffer , alias ) ;
}
2006-01-10 06:46:17 +00:00
return FAILURE ;
}
alias_len = tmp_len ;
alias = buffer ;
buffer + = tmp_len ;
2006-01-11 21:19:46 +00:00
register_alias = 1 ;
2006-01-10 06:46:17 +00:00
} else if ( ! alias_len | | ! alias ) {
/* if we neither have an explicit nor an implicit alias, we use the filename */
2006-01-11 21:19:46 +00:00
alias = NULL ;
alias_len = 0 ;
register_alias = 0 ;
} else {
register_alias = 1 ;
2006-01-10 06:46:17 +00:00
}
2006-01-11 00:50:07 +00: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) " )
}
2007-01-09 18:54:37 +00:00
mydata = ecalloc ( sizeof ( phar_archive_data ) , 1 ) ;
2007-02-06 23:19:10 +00:00
2007-03-21 17:14:46 +00:00
/* check whether we have meta data, zero check works regardless of byte order */
2007-02-06 23:19:10 +00:00
if ( phar_parse_metadata ( fp , & buffer , endbuffer , & mydata - > metadata TSRMLS_CC ) = = FAILURE ) {
MAPPHAR_FAIL ( " unable to read phar metadata in .phar file \" %s \" " ) ;
2007-01-29 03:59:55 +00:00
}
/* set up our manifest */
2006-03-08 20:07:25 +00:00
zend_hash_init ( & mydata - > manifest , sizeof ( phar_entry_info ) ,
2005-12-04 20:35:38 +00:00
zend_get_hash_value , destroy_phar_manifest , 0 ) ;
2006-01-10 06:46:17 +00:00
offset = 0 ;
2005-12-04 20:35:38 +00:00
for ( manifest_index = 0 ; manifest_index < manifest_count ; manifest_index + + ) {
2006-01-05 00:39:31 +00:00
if ( buffer + 4 > endbuffer ) {
2006-01-11 00:50:07 +00:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest entry) " )
2005-12-07 06:39:03 +00:00
}
2007-01-13 17:10:18 +00:00
memset ( & entry , 0 , sizeof ( phar_entry_info ) ) ;
2006-01-10 06:46:17 +00:00
PHAR_GET_32 ( buffer , entry . filename_len ) ;
if ( entry . filename_len = = 0 ) {
MAPPHAR_FAIL ( " zero-length filename encountered in phar \" %s \" " ) ;
}
2007-01-13 16:17:04 +00:00
if ( buffer + entry . filename_len + 20 > endbuffer ) {
2006-01-11 00:50:07 +00:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (truncated manifest entry) " ) ;
2006-01-05 00:39:31 +00:00
}
2006-01-04 15:27:18 +00:00
entry . filename = estrndup ( buffer , entry . filename_len ) ;
2005-12-05 04:21:36 +00:00
buffer + = entry . filename_len ;
2006-01-10 06:46:17 +00:00
PHAR_GET_32 ( buffer , entry . uncompressed_filesize ) ;
PHAR_GET_32 ( buffer , entry . timestamp ) ;
2006-03-02 22:44:39 +00:00
if ( offset = = 0 ) {
2006-03-08 20:07:25 +00:00
mydata - > min_timestamp = entry . timestamp ;
mydata - > max_timestamp = entry . timestamp ;
2006-03-02 22:44:39 +00:00
} else {
2006-03-08 20:07:25 +00: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-02 22:44:39 +00:00
}
}
2006-01-10 06:46:17 +00:00
PHAR_GET_32 ( buffer , entry . compressed_filesize ) ;
PHAR_GET_32 ( buffer , entry . crc32 ) ;
2007-01-13 16:17:04 +00:00
PHAR_GET_32 ( buffer , entry . flags ) ;
2007-02-06 23:19:10 +00:00
if ( phar_parse_metadata ( fp , & buffer , endbuffer , & entry . metadata TSRMLS_CC ) = = FAILURE ) {
efree ( entry . filename ) ;
MAPPHAR_FAIL ( " unable to read file metadata in .phar file \" %s \" " ) ;
2007-01-21 06:30:55 +00:00
}
2006-01-10 06:46:17 +00:00
entry . offset_within_phar = offset ;
offset + = entry . compressed_filesize ;
2006-01-12 21:16:29 +00:00
switch ( entry . flags & PHAR_ENT_COMPRESSION_MASK ) {
case PHAR_ENT_COMPRESSED_GZ :
2006-01-11 23:55:57 +00:00
# if !HAVE_ZLIB
2007-02-03 04:04:18 +00:00
if ( entry . metadata ) {
zval_ptr_dtor ( & entry . metadata ) ;
}
efree ( entry . filename ) ;
2006-02-28 01:36:30 +00:00
MAPPHAR_FAIL ( " zlib extension is required for gz compressed .phar file \" %s \" " ) ;
2006-01-06 17:23:42 +00:00
# endif
2006-01-12 21:16:29 +00:00
break ;
case PHAR_ENT_COMPRESSED_BZ2 :
# if !HAVE_BZ2
2007-02-03 04:04:18 +00:00
if ( entry . metadata ) {
zval_ptr_dtor ( & entry . metadata ) ;
}
efree ( entry . filename ) ;
2006-02-28 01:36:30 +00:00
MAPPHAR_FAIL ( " bz2 extension is required for bzip2 compressed .phar file \" %s \" " ) ;
2006-01-12 21:16:29 +00:00
# endif
break ;
default :
if ( entry . uncompressed_filesize ! = entry . compressed_filesize ) {
2007-02-03 04:04:18 +00:00
if ( entry . metadata ) {
zval_ptr_dtor ( & entry . metadata ) ;
}
efree ( entry . filename ) ;
2006-01-12 21:16:29 +00:00
MAPPHAR_FAIL ( " internal corruption of phar \" %s \" (compressed and uncompressed size does not match for uncompressed entry) " ) ;
}
break ;
2006-01-05 22:24:41 +00:00
}
2007-01-13 16:17:04 +00:00
manifest_flags | = ( entry . flags & PHAR_ENT_COMPRESSION_MASK ) ;
2007-01-13 17:10:18 +00:00
entry . is_crc_checked = 0 ;
2006-01-05 22:24:41 +00:00
entry . fp = NULL ;
2007-01-22 00:13:20 +00:00
entry . phar = mydata ;
2006-03-08 20:07:25 +00:00
zend_hash_add ( & mydata - > manifest , entry . filename , entry . filename_len , ( void * ) & entry , sizeof ( phar_entry_info ) , NULL ) ;
}
2007-01-13 16:17:04 +00:00
snprintf ( mydata - > version , sizeof ( mydata - > version ) , " %u.%u.%u " , manifest_ver > > 12 , ( manifest_ver > > 8 ) & 0xF , ( manifest_ver > > 4 ) & 0xF ) ;
2006-03-08 20:07:25 +00:00
mydata - > internal_file_start = halt_offset + manifest_len + 4 ;
2007-01-02 18:15:17 +00:00
mydata - > halt_offset = halt_offset ;
2007-01-13 16:17:04 +00:00
mydata - > flags = manifest_flags ;
2006-03-08 20:07:25 +00:00
mydata - > fp = fp ;
2007-01-04 05:32:45 +00:00
mydata - > fname = estrndup ( fname , fname_len ) ;
mydata - > fname_len = fname_len ;
mydata - > alias = alias ? estrndup ( alias , alias_len ) : mydata - > fname ;
mydata - > alias_len = alias ? alias_len : fname_len ;
2007-01-09 00:27:13 +00:00
mydata - > sig_flags = sig_flags ;
mydata - > sig_len = sig_len ;
mydata - > signature = signature ;
zend_hash_add ( & ( PHAR_GLOBALS - > phar_fname_map ) , fname , fname_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ;
2007-01-04 05:32:45 +00:00
if ( register_alias ) {
2007-01-13 17:10:18 +00:00
mydata - > is_explicit_alias = 1 ;
2007-01-04 05:32:45 +00:00
zend_hash_add ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ;
2007-01-05 04:45:52 +00:00
} else {
2007-01-13 17:10:18 +00:00
mydata - > is_explicit_alias = 0 ;
2006-01-11 21:19:46 +00:00
}
2005-12-04 20:35:38 +00:00
efree ( savebuf ) ;
2006-01-04 02:26:15 +00:00
2007-01-04 05:32:45 +00:00
if ( pphar ) {
2006-03-08 20:07:25 +00:00
* pphar = mydata ;
2006-02-28 01:36:30 +00:00
}
2006-01-04 02:26:15 +00:00
return SUCCESS ;
}
/* }}} */
2007-01-02 18:15:17 +00:00
/**
* Create or open a phar for writing
*/
2007-01-29 06:02:19 +00:00
int phar_open_or_create_filename ( char * fname , int fname_len , char * alias , int alias_len , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2007-01-02 18:15:17 +00:00
{
phar_archive_data * mydata ;
int register_alias ;
php_stream * fp ;
2007-01-14 00:32:38 +00:00
if ( ! pphar ) {
pphar = & mydata ;
}
2007-01-29 06:02:19 +00:00
if ( error ) {
* error = NULL ;
}
2007-01-14 00:32:38 +00:00
2007-01-29 06:02:19 +00:00
if ( phar_open_loaded ( fname , fname_len , alias , alias_len , options , pphar , 0 TSRMLS_CC ) = = SUCCESS ) {
2007-01-28 10:32:45 +00:00
if ( ! PHAR_G ( readonly ) ) {
( * pphar ) - > is_writeable = 1 ;
}
2007-01-11 01:04:47 +00:00
return SUCCESS ;
2007-01-02 18:15:17 +00:00
}
2007-01-02 19:59:38 +00: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 ;
}
2007-01-28 10:32:45 +00:00
fp = php_stream_open_wrapper ( fname , PHAR_G ( readonly ) ? " rb " : " r+b " , IGNORE_URL | STREAM_MUST_SEEK | 0 , NULL ) ;
2007-01-02 19:59:38 +00:00
2007-01-29 06:02:19 +00:00
if ( fp & & phar_open_fp ( fp , fname , fname_len , alias , alias_len , options , pphar , 0 TSRMLS_CC ) = = SUCCESS ) {
2007-01-28 10:32:45 +00:00
if ( ! PHAR_G ( readonly ) ) {
( * pphar ) - > is_writeable = 1 ;
}
2007-01-11 01:04:47 +00:00
return SUCCESS ;
2007-01-07 16:01:35 +00:00
}
if ( PHAR_G ( readonly ) ) {
if ( options & REPORT_ERRORS ) {
2007-01-29 07:59:19 +00:00
if ( error ) {
2007-01-29 06:02:19 +00:00
spprintf ( error , 0 , " creating archive \" %s \" disabled by INI setting " , fname ) ;
}
2007-01-07 16:01:35 +00:00
}
return FAILURE ;
2007-01-02 19:59:38 +00:00
}
2007-01-09 18:54:37 +00:00
2007-01-02 18:15:17 +00:00
/* set up our manifest */
2007-01-09 18:54:37 +00:00
mydata = ecalloc ( sizeof ( phar_archive_data ) , 1 ) ;
2007-01-28 05:40:18 +00:00
if ( pphar ) {
* pphar = mydata ;
}
2007-01-02 18:15:17 +00:00
zend_hash_init ( & mydata - > manifest , sizeof ( phar_entry_info ) ,
zend_get_hash_value , destroy_phar_manifest , 0 ) ;
mydata - > fname = estrndup ( fname , fname_len ) ;
mydata - > fname_len = fname_len ;
mydata - > alias = alias ? estrndup ( alias , alias_len ) : mydata - > fname ;
mydata - > alias_len = alias ? alias_len : fname_len ;
2007-02-03 13:20:12 +00:00
snprintf ( mydata - > version , sizeof ( mydata - > version ) , " %s " , PHAR_API_VERSION_STR ) ;
2007-01-13 17:10:18 +00:00
mydata - > is_explicit_alias = alias ? 1 : 0 ;
2007-01-02 18:15:17 +00:00
mydata - > internal_file_start = - 1 ;
mydata - > fp = fp ;
2007-01-14 00:32:38 +00:00
mydata - > is_writeable = 1 ;
2007-01-28 21:26:54 +00:00
mydata - > is_brandnew = 1 ;
2007-01-02 18:15:17 +00:00
if ( ! alias_len | | ! alias ) {
/* if we neither have an explicit nor an implicit alias, we use the filename */
alias = NULL ;
alias_len = 0 ;
register_alias = 0 ;
} else {
register_alias = 1 ;
}
2007-01-09 02:27:12 +00:00
zend_hash_add ( & ( PHAR_GLOBALS - > phar_fname_map ) , fname , fname_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ;
2007-01-02 18:15:17 +00:00
if ( register_alias ) {
zend_hash_add ( & ( PHAR_GLOBALS - > phar_alias_map ) , alias , alias_len , ( void * ) & mydata , sizeof ( phar_archive_data * ) , NULL ) ;
}
return SUCCESS ;
}
2007-01-23 23:31:14 +00:00
/* }}}*/
2007-01-02 18:15:17 +00:00
2007-01-02 00:04:30 +00:00
/**
2007-01-11 01:04:47 +00:00
* Return an already opened filename .
*
* Or scan a phar file for the required __HALT_COMPILER ( ) ; ? > token and verify
2007-01-02 00:04:30 +00:00
* that the manifest is proper , then pass it to phar_open_file ( ) . SUCCESS
* or FAILURE is returned and pphar is set to a pointer to the phar ' s manifest
*/
2007-01-29 06:02:19 +00:00
int phar_open_filename ( char * fname , int fname_len , char * alias , int alias_len , int options , phar_archive_data * * pphar , char * * error TSRMLS_DC ) /* { { { */
2006-01-04 02:26:15 +00:00
{
php_stream * fp ;
2007-01-29 06:02:19 +00:00
if ( error ) {
* error = NULL ;
}
2006-02-28 01:36:30 +00:00
2007-01-29 06:02:19 +00:00
if ( phar_open_loaded ( fname , fname_len , alias , alias_len , options , pphar , error TSRMLS_CC ) = = SUCCESS ) {
2007-01-11 01:04:47 +00:00
return SUCCESS ;
2007-01-29 06:02:19 +00:00
} else if ( * error ) {
return FAILURE ;
2006-02-28 01:36:30 +00:00
}
2006-01-04 02:26:15 +00:00
2006-03-08 20:31:23 +00:00
# if PHP_MAJOR_VERSION < 6
2006-01-05 11:32:05 +00:00
if ( PG ( safe_mode ) & & ( ! php_checkuid ( fname , NULL , CHECKUID_ALLOW_ONLY_FILE ) ) ) {
return FAILURE ;
}
2006-03-08 20:31:23 +00:00
# endif
2006-01-05 11:32:05 +00:00
if ( php_check_open_basedir ( fname TSRMLS_CC ) ) {
return FAILURE ;
}
2006-01-04 02:26:15 +00:00
fp = php_stream_open_wrapper ( fname , " rb " , IGNORE_URL | STREAM_MUST_SEEK | REPORT_ERRORS , NULL ) ;
2007-01-11 01:04:47 +00:00
2006-01-04 02:26:15 +00:00
if ( ! fp ) {
2007-01-07 16:01:35 +00:00
if ( options & REPORT_ERRORS ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to open phar for reading \" %s \" " , fname ) ;
}
2007-01-07 16:01:35 +00:00
}
2006-01-04 02:26:15 +00:00
return FAILURE ;
}
2007-01-29 06:02:19 +00:00
return phar_open_fp ( fp , fname , fname_len , alias , alias_len , options , pphar , error TSRMLS_CC ) ;
2007-01-11 01:04:47 +00:00
}
/* }}}*/
/**
* Scan an open fp for the required __HALT_COMPILER ( ) ; ? > token and verify
* that the manifest is proper , then pass it to phar_open_file ( ) . SUCCESS
* or FAILURE is returned and pphar is set to a pointer to the phar ' s manifest
*/
2007-01-29 06:02:19 +00:00
static int phar_open_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 01:04:47 +00:00
{
const char token [ ] = " __HALT_COMPILER(); " ;
char * pos , buffer [ 1024 + sizeof ( token ) ] ;
const long readsize = sizeof ( buffer ) - sizeof ( token ) ;
const long tokenlen = sizeof ( token ) - 1 ;
long halt_offset ;
2007-02-06 22:12:21 +00:00
size_t got ;
2007-01-11 01:04:47 +00:00
2006-01-04 02:26:15 +00: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. */
2007-01-29 06:02:19 +00:00
if ( error ) {
* error = NULL ;
}
2007-01-11 01:04:47 +00:00
if ( - 1 = = php_stream_rewind ( fp ) ) {
2006-01-05 00:39:31 +00:00
MAPPHAR_ALLOC_FAIL ( " cannot rewind phar \" %s \" " )
2006-01-04 02:26:15 +00:00
}
buffer [ sizeof ( buffer ) - 1 ] = ' \0 ' ;
memset ( buffer , 32 , sizeof ( token ) ) ;
halt_offset = 0 ;
while ( ! php_stream_eof ( fp ) ) {
2007-02-06 22:12:21 +00:00
if ( ( got = php_stream_read ( fp , buffer + tokenlen , readsize ) ) < tokenlen ) {
2006-01-04 02:26:15 +00:00
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (truncated manifest) " )
}
if ( ( pos = strstr ( buffer , token ) ) ! = NULL ) {
2006-01-05 00:39:31 +00:00
halt_offset + = ( pos - buffer ) ; /* no -tokenlen+tokenlen here */
2007-01-29 06:02:19 +00:00
return phar_open_file ( fp , fname , fname_len , alias , alias_len , halt_offset , pphar , error TSRMLS_CC ) ;
2006-01-04 02:26:15 +00:00
}
2007-02-06 22:12:21 +00:00
halt_offset + = got ;
memmove ( buffer , buffer + tokenlen , got + 1 ) ;
2006-01-04 02:26:15 +00:00
}
MAPPHAR_ALLOC_FAIL ( " internal corruption of phar \" %s \" (__HALT_COMPILER(); not found) " )
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Process a phar stream name , ensuring we can handle any of :
*
* - phar : //whatever.phar
* - whatever . phar
* - whatever . phar . gz
* - whatever . phar . bz2
*
* This is used by phar_open_url ( )
*/
2007-01-21 15:25:50 +00:00
int phar_split_fname ( char * filename , int filename_len , char * * arch , int * arch_len , char * * entry , int * entry_len TSRMLS_DC ) /* { { { */
2006-01-04 02:26:15 +00:00
{
2007-01-02 00:04:30 +00:00
char * pos_p , * pos_z , * pos_b , * ext_str ;
2006-02-28 01:36:30 +00:00
int ext_len ;
2006-01-04 02:26:15 +00:00
if ( ! strncasecmp ( filename , " phar:// " , 7 ) ) {
filename + = 7 ;
2006-02-28 01:36:30 +00:00
filename_len - = 7 ;
}
pos_p = strstr ( filename , " .phar.php " ) ;
pos_z = strstr ( filename , " .phar.gz " ) ;
2007-01-02 00:04:30 +00:00
pos_b = strstr ( filename , " .phar.bz2 " ) ;
2006-02-28 01:36:30 +00:00
if ( pos_p ) {
if ( pos_z ) {
return FAILURE ;
}
ext_str = pos_p ;
ext_len = 9 ;
} else if ( pos_z ) {
ext_str = pos_z ;
ext_len = 8 ;
2007-01-02 00:04:30 +00:00
} else if ( pos_b ) {
ext_str = pos_b ;
ext_len = 9 ;
2006-02-28 01:36:30 +00:00
} else if ( ( pos_p = strstr ( filename , " .phar " ) ) ! = NULL ) {
ext_str = pos_p ;
ext_len = 5 ;
} else {
return FAILURE ;
}
* arch_len = ext_str - filename + ext_len ;
* arch = estrndup ( filename , * arch_len ) ;
if ( ext_str [ ext_len ] ) {
* entry_len = filename_len - * arch_len ;
* entry = estrndup ( ext_str + ext_len , * entry_len ) ;
} else {
* entry_len = 1 ;
* entry = estrndup ( " / " , 1 ) ;
}
return SUCCESS ;
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Open a phar file for streams API
*/
2006-02-28 01:36:30 +00:00
static php_url * phar_open_url ( php_stream_wrapper * wrapper , char * filename , char * mode , int options TSRMLS_DC ) /* { { { */
{
php_url * resource ;
2007-01-29 06:02:19 +00:00
char * arch , * entry , * error ;
2006-02-28 01:36:30 +00:00
int arch_len , entry_len ;
if ( ! strncasecmp ( filename , " phar:// " , 7 ) ) {
2007-01-14 00:32:38 +00:00
if ( mode [ 0 ] = = ' a ' ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: open mode append not supported " ) ;
return NULL ;
}
2006-02-28 01:36:30 +00:00
if ( phar_split_fname ( filename , strlen ( filename ) , & arch , & arch_len , & entry , & entry_len TSRMLS_CC ) = = FAILURE ) {
2007-01-02 00:04:30 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" (cannot contain .phar.php and .phar.gz/.phar.bz2) " , filename ) ;
2006-11-12 17:37:51 +00:00
efree ( arch ) ;
efree ( entry ) ;
2006-01-04 02:26:15 +00:00
return NULL ;
}
2006-02-28 01:36:30 +00:00
resource = ecalloc ( 1 , sizeof ( php_url ) ) ;
2006-01-04 02:26:15 +00:00
resource - > scheme = estrndup ( " phar " , 4 ) ;
2006-02-28 01:36:30 +00:00
resource - > host = arch ;
resource - > path = entry ;
2006-01-04 02:26:15 +00:00
# if MBO_0
if ( resource ) {
fprintf ( stderr , " Alias: %s \n " , alias ) ;
fprintf ( stderr , " Scheme: %s \n " , resource - > scheme ) ;
/* fprintf(stderr, "User: %s\n", resource->user);*/
/* fprintf(stderr, "Pass: %s\n", resource->pass ? "***" : NULL);*/
fprintf ( stderr , " Host: %s \n " , resource - > host ) ;
/* fprintf(stderr, "Port: %d\n", resource->port);*/
fprintf ( stderr , " Path: %s \n " , resource - > path ) ;
/* fprintf(stderr, "Query: %s\n", resource->query);*/
/* fprintf(stderr, "Fragment: %s\n", resource->fragment);*/
}
# endif
2007-01-14 00:32:38 +00:00
if ( mode [ 0 ] = = ' w ' | | ( mode [ 0 ] = = ' r ' & & mode [ 1 ] = = ' + ' ) ) {
2007-01-28 10:32:45 +00:00
if ( PHAR_G ( readonly ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: write operations disabled by INI setting " ) ;
php_url_free ( resource ) ;
return NULL ;
}
2007-01-29 06:02:19 +00:00
if ( phar_open_or_create_filename ( resource - > host , arch_len , NULL , 0 , options , NULL , & error TSRMLS_CC ) = = FAILURE )
2007-01-02 18:15:17 +00:00
{
2007-01-29 06:02:19 +00:00
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
}
2007-01-02 18:15:17 +00:00
php_url_free ( resource ) ;
return NULL ;
}
} else {
2007-01-29 06:02:19 +00:00
if ( phar_open_filename ( resource - > host , arch_len , NULL , 0 , options , NULL , & error TSRMLS_CC ) = = FAILURE )
2007-01-02 18:15:17 +00:00
{
2007-01-29 06:02:19 +00:00
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
}
2007-01-02 18:15:17 +00:00
php_url_free ( resource ) ;
return NULL ;
}
}
2006-01-04 02:26:15 +00:00
return resource ;
}
return NULL ;
2005-12-04 20:35:38 +00:00
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Invoked when a user calls Phar : : mapPhar ( ) from within an executing . phar
* to set up its manifest directly
*/
2007-01-29 06:02:19 +00:00
int phar_open_compiled_file ( char * alias , int alias_len , char * * error TSRMLS_DC ) /* { { { */
2006-01-04 02:26:15 +00:00
{
char * fname ;
long halt_offset ;
zval * halt_constant ;
php_stream * fp ;
2007-01-11 01:04:47 +00:00
int fname_len ;
2006-01-04 02:26:15 +00:00
2007-01-29 06:02:19 +00:00
if ( error ) {
* error = NULL ;
}
2006-01-04 02:26:15 +00:00
fname = zend_get_executed_filename ( TSRMLS_C ) ;
2007-01-11 01:04:47 +00:00
fname_len = strlen ( fname ) ;
2007-01-29 06:02:19 +00:00
if ( alias & & phar_open_loaded ( fname , fname_len , alias , alias_len , REPORT_ERRORS , NULL , 0 TSRMLS_CC ) = = SUCCESS ) {
2007-01-11 01:04:47 +00:00
return SUCCESS ;
}
2006-01-04 02:26:15 +00:00
if ( ! strcmp ( fname , " [no active file] " ) ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " cannot initialize a phar outside of PHP execution " ) ;
}
2006-01-04 02:26:15 +00:00
return FAILURE ;
}
MAKE_STD_ZVAL ( halt_constant ) ;
if ( 0 = = zend_get_constant ( " __COMPILER_HALT_OFFSET__ " , 24 , halt_constant TSRMLS_CC ) ) {
2006-01-06 20:43:19 +00:00
FREE_ZVAL ( halt_constant ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " __HALT_COMPILER(); must be declared in a phar " ) ;
}
2006-01-04 02:26:15 +00:00
return FAILURE ;
}
halt_offset = Z_LVAL ( * halt_constant ) ;
2007-01-11 01:04:47 +00:00
FREE_ZVAL ( halt_constant ) ;
2006-01-04 02:26:15 +00:00
fp = php_stream_open_wrapper ( fname , " rb " , IGNORE_URL | STREAM_MUST_SEEK | REPORT_ERRORS , NULL ) ;
if ( ! fp ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to open phar for reading \" %s \" " , fname ) ;
}
2006-01-04 02:26:15 +00:00
return FAILURE ;
}
2007-01-29 06:02:19 +00:00
return phar_open_file ( fp , fname , fname_len , alias , alias_len , halt_offset , NULL , error TSRMLS_CC ) ;
2006-01-04 02:26:15 +00:00
}
/* }}} */
2005-12-04 20:35:38 +00:00
static php_stream_ops phar_ops = {
2007-01-08 19:30:52 +00:00
phar_stream_write , /* write */
phar_stream_read , /* read */
phar_stream_close , /* close */
phar_stream_flush , /* flush */
2005-12-04 20:35:38 +00:00
" phar stream " ,
2007-01-13 16:17:04 +00:00
phar_stream_seek , /* seek */
NULL , /* cast */
phar_stream_stat , /* stat */
2005-12-08 07:38:44 +00:00
NULL , /* set option */
2005-12-04 20:35:38 +00:00
} ;
static php_stream_ops phar_dir_ops = {
2007-01-13 16:17:04 +00:00
phar_dir_write , /* write */
phar_dir_read , /* read */
2007-01-08 19:30:52 +00:00
phar_dir_close , /* close */
2007-01-13 16:17:04 +00:00
phar_dir_flush , /* flush */
" phar dir " ,
phar_dir_seek , /* seek */
NULL , /* cast */
phar_dir_stat , /* stat */
2005-12-08 07:38:44 +00:00
NULL , /* set option */
2005-12-04 20:35:38 +00:00
} ;
static php_stream_wrapper_ops phar_stream_wops = {
2007-01-08 19:30:52 +00:00
phar_wrapper_open_url ,
2007-01-13 16:17:04 +00:00
NULL , /* phar_wrapper_close */
NULL , /* phar_wrapper_stat, */
phar_wrapper_stat , /* stat_url */
2007-01-08 19:30:52 +00:00
phar_wrapper_open_dir , /* opendir */
2005-12-04 20:35:38 +00:00
" phar " ,
2007-01-13 16:17:04 +00:00
phar_wrapper_unlink , /* unlink */
2007-01-28 22:43:38 +00:00
phar_wrapper_rename , /* rename */
2007-01-13 16:17:04 +00:00
NULL , /* create directory */
NULL , /* remove directory */
2005-12-04 20:35:38 +00:00
} ;
php_stream_wrapper php_stream_phar_wrapper = {
& phar_stream_wops ,
NULL ,
0 /* is_url */
} ;
2007-01-02 00:04:30 +00:00
/**
* Validate the CRC32 of a file opened from within the phar
*/
2006-02-28 01:36:30 +00:00
static int phar_postprocess_file ( php_stream_wrapper * wrapper , int options , phar_entry_data * idata , php_uint32 crc32 TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2007-01-07 19:05:12 +00:00
php_uint32 crc = ~ 0 ;
2006-01-05 22:24:41 +00:00
int len = idata - > internal_file - > uncompressed_filesize ;
2007-01-09 23:57:03 +00:00
php_stream * fp = idata - > fp ;
2006-01-05 00:39:31 +00:00
2007-01-09 23:57:03 +00:00
php_stream_seek ( fp , 0 , SEEK_SET ) ;
2006-01-05 22:24:41 +00:00
while ( len - - ) {
2007-01-09 23:57:03 +00:00
CRC32 ( crc , php_stream_getc ( fp ) ) ;
2005-12-04 20:35:38 +00:00
}
2007-01-09 23:57:03 +00:00
php_stream_seek ( fp , 0 , SEEK_SET ) ;
2005-12-04 20:35:38 +00:00
if ( ~ crc = = crc32 ) {
2006-01-05 22:24:41 +00:00
return SUCCESS ;
2005-12-04 20:35:38 +00:00
} else {
2006-01-11 21:19:46 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: internal corruption of phar \" %s \" (crc32 mismatch on file \" %s \" ) " , idata - > phar - > fname , idata - > internal_file - > filename ) ;
2006-01-05 22:24:41 +00:00
return FAILURE ;
2005-12-04 20:35:38 +00:00
}
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-09 22:30:56 +00:00
/**
* Determine which stream compression filter ( if any ) we need to read this file
*/
static char * phar_compress_filter ( phar_entry_info * entry , int return_unknown ) /* { { { */
{
switch ( entry - > flags & PHAR_ENT_COMPRESSION_MASK ) {
case PHAR_ENT_COMPRESSED_GZ :
return " zlib.deflate " ;
case PHAR_ENT_COMPRESSED_BZ2 :
return " bzip2.compress " ;
default :
return return_unknown ? " unknown " : NULL ;
}
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Determine which stream decompression filter ( if any ) we need to read this file
*/
static char * phar_decompress_filter ( phar_entry_info * entry , int return_unknown ) /* { { { */
2006-01-12 21:16:29 +00:00
{
switch ( entry - > flags & PHAR_ENT_COMPRESSION_MASK ) {
case PHAR_ENT_COMPRESSED_GZ :
return " zlib.inflate " ;
case PHAR_ENT_COMPRESSED_BZ2 :
return " bzip2.decompress " ;
default :
2007-01-02 00:04:30 +00:00
return return_unknown ? " unknown " : NULL ;
2006-01-12 21:16:29 +00:00
}
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* used for fopen ( ' phar : //...') and company
*/
2007-01-08 19:30:52 +00:00
static php_stream * phar_wrapper_open_url ( php_stream_wrapper * wrapper , char * path , char * mode , int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2006-02-28 01:36:30 +00:00
phar_entry_data * idata ;
2005-12-04 20:35:38 +00:00
char * internal_file ;
char * buffer ;
2007-01-27 18:27:19 +00:00
char * error ;
2006-01-12 21:16:29 +00:00
char * filter_name ;
2007-03-25 19:03:38 +00:00
char * plain_map ;
2006-01-05 22:24:41 +00:00
char tmpbuf [ 8 ] ;
2007-01-28 03:25:53 +00:00
HashTable * pharcontext ;
2005-12-04 20:35:38 +00:00
php_url * resource = NULL ;
2006-01-11 23:55:57 +00:00
php_stream * fp , * fpf ;
2007-01-26 14:52:10 +00:00
php_stream_filter * filter /*, *consumed */ ;
2007-01-22 03:41:41 +00:00
php_uint32 offset , read , total , toread ;
2007-01-28 03:25:53 +00:00
zval * * pzoption , * metadata ;
2007-03-25 19:03:38 +00:00
uint host_len ;
2005-12-04 20:35:38 +00:00
2005-12-07 06:39:03 +00:00
resource = php_url_parse ( path ) ;
2006-01-04 02:26:15 +00:00
2006-01-04 09:26:32 +00:00
if ( ! resource & & ( resource = phar_open_url ( wrapper , path , mode , options TSRMLS_CC ) ) = = NULL ) {
2006-01-04 02:26:15 +00:00
return NULL ;
}
2006-01-01 20:40:43 +00:00
/* we must have at the very least phar://alias.phar/internalfile.php */
2006-02-28 01:36:30 +00:00
if ( ! resource - > scheme | | ! resource - > host | | ! resource - > path ) {
php_url_free ( resource ) ;
2005-12-11 00:00:31 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" " , path ) ;
2005-12-07 06:39:03 +00:00
return NULL ;
2005-12-04 20:35:38 +00:00
}
if ( strcasecmp ( " phar " , resource - > scheme ) ) {
2006-02-28 01:36:30 +00:00
php_url_free ( resource ) ;
2005-12-11 00:00:31 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: not a phar stream url \" %s \" " , path ) ;
2005-12-07 06:39:03 +00:00
return NULL ;
2005-12-04 20:35:38 +00:00
}
2007-03-25 19:03:38 +00:00
host_len = strlen ( resource - > host ) ;
if ( zend_hash_find ( & ( PHAR_GLOBALS - > phar_plain_map ) , resource - > host , host_len + 1 , ( void * * ) & plain_map ) = = SUCCESS ) {
spprintf ( & internal_file , 0 , " %s%s " , plain_map , resource - > path ) ;
fp = php_stream_open_wrapper_ex ( internal_file , mode , options , opened_path , context ) ;
if ( ! fp ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: file \" %s \" extracted from \" %s \" could not be opened " , internal_file , resource - > host ) ;
}
2007-03-26 16:42:47 +00:00
php_url_free ( resource ) ;
2007-03-25 19:03:38 +00:00
efree ( internal_file ) ;
return fp ;
}
2005-12-09 23:37:03 +00:00
/* strip leading "/" */
2006-01-04 15:27:18 +00:00
internal_file = estrdup ( resource - > path + 1 ) ;
2007-01-14 00:32:38 +00:00
if ( mode [ 0 ] = = ' w ' | | ( mode [ 0 ] = = ' r ' & & mode [ 1 ] = = ' + ' ) ) {
2007-03-25 19:03:38 +00:00
if ( NULL = = ( idata = phar_get_or_create_entry_data ( resource - > host , host_len , internal_file , strlen ( internal_file ) , mode , & error TSRMLS_CC ) ) ) {
2007-01-27 21:23:02 +00:00
if ( error ) {
2007-01-27 18:27:19 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
2007-01-27 21:23:02 +00:00
efree ( error ) ;
2007-02-04 13:21:40 +00:00
} else {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: file \" %s \" could not be created in phar \" %s \" " , internal_file , resource - > host ) ;
2007-01-27 18:27:19 +00:00
}
2007-01-02 18:15:17 +00:00
efree ( internal_file ) ;
php_url_free ( resource ) ;
return NULL ;
}
2007-01-28 03:25:53 +00:00
if ( error ) {
efree ( error ) ;
}
2007-01-02 19:59:38 +00:00
fpf = php_stream_alloc ( & phar_ops , idata , NULL , mode ) ;
2007-01-07 18:35:48 +00:00
php_url_free ( resource ) ;
2007-01-02 19:59:38 +00:00
efree ( internal_file ) ;
2007-01-28 03:25:53 +00:00
if ( context & & context - > options & & zend_hash_find ( HASH_OF ( context - > options ) , " phar " , sizeof ( " phar " ) , ( void * * ) & pzoption ) = = SUCCESS ) {
pharcontext = HASH_OF ( * pzoption ) ;
if ( idata - > internal_file - > uncompressed_filesize = = 0
& & idata - > internal_file - > compressed_filesize = = 0
& & zend_hash_find ( pharcontext , " compress " , sizeof ( " compress " ) , ( void * * ) & pzoption ) = = SUCCESS
& & Z_TYPE_PP ( pzoption ) = = IS_LONG
& & ( Z_LVAL_PP ( pzoption ) & ~ PHAR_ENT_COMPRESSION_MASK ) = = 0
) {
idata - > internal_file - > flags & = ~ PHAR_ENT_COMPRESSION_MASK ;
idata - > internal_file - > flags | = Z_LVAL_PP ( pzoption ) ;
}
if ( zend_hash_find ( pharcontext , " metadata " , sizeof ( " metadata " ) , ( void * * ) & pzoption ) = = SUCCESS ) {
if ( idata - > internal_file - > metadata ) {
zval_ptr_dtor ( & idata - > internal_file - > metadata ) ;
idata - > internal_file - > metadata = NULL ;
}
MAKE_STD_ZVAL ( idata - > internal_file - > metadata ) ;
metadata = * pzoption ;
ZVAL_ZVAL ( idata - > internal_file - > metadata , metadata , 1 , 0 ) ;
idata - > phar - > is_modified = 1 ;
}
2007-01-21 23:22:57 +00:00
}
2007-01-02 19:59:38 +00:00
return fpf ;
2007-01-02 18:15:17 +00:00
} else {
2007-03-25 19:03:38 +00:00
if ( ( FAILURE = = phar_get_entry_data ( & idata , resource - > host , host_len , internal_file , strlen ( internal_file ) , " r " , & error TSRMLS_CC ) ) | | ! idata ) {
2007-01-27 21:23:02 +00:00
if ( error ) {
2007-01-27 18:27:19 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
2007-01-27 21:23:02 +00:00
efree ( error ) ;
2007-01-27 18:27:19 +00:00
}
2007-01-02 18:15:17 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" is not a file in phar \" %s \" " , internal_file , resource - > host ) ;
efree ( internal_file ) ;
php_url_free ( resource ) ;
return NULL ;
}
2005-12-04 20:35:38 +00:00
}
2006-02-28 01:36:30 +00:00
php_url_free ( resource ) ;
2006-01-04 15:27:18 +00:00
# if MBO_0
2006-01-10 06:46:17 +00:00
fprintf ( stderr , " Pharname: %s \n " , idata - > phar - > filename ) ;
fprintf ( stderr , " Filename: %s \n " , internal_file ) ;
fprintf ( stderr , " Entry: %s \n " , idata - > internal_file - > filename ) ;
fprintf ( stderr , " Size: %u \n " , idata - > internal_file - > uncompressed_filesize ) ;
fprintf ( stderr , " Compressed: %u \n " , idata - > internal_file - > flags ) ;
fprintf ( stderr , " Offset: %u \n " , idata - > internal_file - > offset_within_phar ) ;
fprintf ( stderr , " Cached: %s \n " , idata - > internal_file - > filedata ? " yes " : " no " ) ;
2006-01-04 15:27:18 +00:00
# endif
2005-12-04 20:35:38 +00:00
2006-01-04 15:27:18 +00:00
/* do we have the data already? */
2006-01-05 22:24:41 +00:00
if ( idata - > fp ) {
2006-01-11 23:55:57 +00:00
fpf = php_stream_alloc ( & phar_ops , idata , NULL , mode ) ;
2006-01-04 15:27:18 +00:00
efree ( internal_file ) ;
2006-01-11 23:55:57 +00:00
return fpf ;
2006-01-04 15:27:18 +00:00
}
2005-12-04 20:35:38 +00:00
2006-03-08 20:31:23 +00:00
# if PHP_MAJOR_VERSION < 6
2006-01-11 21:19:46 +00:00
if ( PG ( safe_mode ) & & ( ! php_checkuid ( idata - > phar - > fname , NULL , CHECKUID_ALLOW_ONLY_FILE ) ) ) {
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2005-12-09 23:37:03 +00:00
efree ( internal_file ) ;
2005-12-05 04:47:29 +00:00
return NULL ;
}
2006-03-08 20:31:23 +00:00
# endif
2006-01-04 15:27:18 +00:00
2006-01-11 21:19:46 +00:00
if ( php_check_open_basedir ( idata - > phar - > fname TSRMLS_CC ) ) {
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2005-12-09 23:37:03 +00:00
efree ( internal_file ) ;
2005-12-05 04:47:29 +00:00
return NULL ;
2005-12-04 20:35:38 +00:00
}
2005-12-05 04:47:29 +00:00
2006-01-04 15:27:18 +00:00
fp = idata - > phar - > fp ;
2005-12-05 04:47:29 +00:00
2005-12-04 20:35:38 +00:00
if ( ! fp ) {
2006-01-11 21:19:46 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: cannot open phar \" %s \" " , idata - > phar - > fname ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2005-12-09 23:37:03 +00:00
efree ( internal_file ) ;
2005-12-04 20:35:38 +00:00
return NULL ;
}
/* seek to start of internal file and read it */
2006-01-04 15:27:18 +00:00
offset = idata - > phar - > internal_file_start + idata - > internal_file - > offset_within_phar ;
if ( - 1 = = php_stream_seek ( fp , offset , SEEK_SET ) ) {
2005-12-11 00:00:31 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: internal corruption of phar \" %s \" (cannot seek to start of file \" %s \" at offset \" %d \" ) " ,
2006-01-11 21:19:46 +00:00
idata - > phar - > fname , internal_file , offset ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2005-12-11 00:00:31 +00:00
efree ( internal_file ) ;
2005-12-09 23:37:03 +00:00
return NULL ;
}
2006-01-04 15:27:18 +00:00
2006-01-12 21:16:29 +00:00
if ( ( idata - > internal_file - > flags & PHAR_ENT_COMPRESSION_MASK ) ! = 0 ) {
if ( ( filter_name = phar_decompress_filter ( idata - > internal_file , 0 ) ) ! = NULL ) {
filter = php_stream_filter_create ( phar_decompress_filter ( idata - > internal_file , 0 ) , NULL , php_stream_is_persistent ( fp ) TSRMLS_CC ) ;
} else {
filter = NULL ;
}
2006-01-11 23:55:57 +00:00
if ( ! filter ) {
2006-01-12 21:16:29 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: unable to read phar \" %s \" (cannot create %s filter while decompressing file \" %s \" ) " , idata - > phar - > fname , phar_decompress_filter ( idata - > internal_file , 1 ) , internal_file ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2005-12-11 00:00:31 +00:00
efree ( internal_file ) ;
2006-01-11 23:55:57 +00:00
return NULL ;
2005-12-04 20:35:38 +00:00
}
2007-01-22 03:41:41 +00:00
buffer = ( char * ) emalloc ( 8192 ) ;
read = 0 ;
total = 0 ;
2005-12-04 20:35:38 +00:00
2006-01-11 23:55:57 +00:00
idata - > fp = php_stream_temp_new ( ) ;
2007-01-26 14:52:10 +00:00
idata - > internal_file - > fp = idata - > fp ;
2007-01-22 03:41:41 +00:00
php_stream_filter_append ( & idata - > fp - > writefilters , filter ) ;
do {
if ( ( total + 8192 ) > idata - > internal_file - > compressed_filesize ) {
toread = idata - > internal_file - > compressed_filesize - total ;
} else {
toread = 8192 ;
}
read = php_stream_read ( fp , buffer , toread ) ;
if ( read ) {
total + = read ;
if ( read ! = php_stream_write ( idata - > fp , buffer , read ) ) {
efree ( buffer ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: internal corruption of phar \" %s \" (actual filesize mismatch on file \" %s \" ) " , idata - > phar - > fname , internal_file ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2007-01-22 03:41:41 +00:00
efree ( internal_file ) ;
return NULL ;
}
if ( total = = idata - > internal_file - > compressed_filesize ) {
read = 0 ;
}
}
} while ( read ) ;
efree ( buffer ) ;
2006-01-11 23:55:57 +00:00
php_stream_filter_flush ( filter , 1 ) ;
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
2007-02-05 20:34:23 +00:00
if ( php_stream_tell ( fp ) ! = ( off_t ) ( offset + idata - > internal_file - > compressed_filesize ) ) {
2007-01-22 01:01:50 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: internal corruption of phar \" %s \" (actual filesize mismatch on file \" %s \" ) " , idata - > phar - > fname , internal_file ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2007-01-26 14:52:10 +00:00
efree ( internal_file ) ;
return NULL ;
}
2007-02-05 20:34:23 +00:00
if ( php_stream_tell ( idata - > fp ) ! = ( off_t ) idata - > internal_file - > uncompressed_filesize ) {
2007-01-26 14:52:10 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: internal corruption of phar \" %s \" (actual filesize mismatch on file \" %s \" ) " , idata - > phar - > fname , internal_file ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2006-01-12 02:33:28 +00:00
efree ( internal_file ) ;
return NULL ;
}
2006-01-11 23:55:57 +00:00
php_stream_seek ( fp , offset + idata - > internal_file - > compressed_filesize , SEEK_SET ) ;
2006-01-01 22:11:03 +00:00
} else { /* from here is for non-compressed */
2006-01-05 22:24:41 +00:00
buffer = & tmpbuf [ 0 ] ;
/* bypass to temp stream */
idata - > fp = php_stream_temp_new ( ) ;
2007-01-26 14:52:10 +00:00
idata - > internal_file - > fp = idata - > fp ;
2006-01-10 06:46:17 +00:00
if ( php_stream_copy_to_stream ( fp , idata - > fp , idata - > internal_file - > uncompressed_filesize ) ! = idata - > internal_file - > uncompressed_filesize ) {
2007-01-22 01:01:50 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: internal corruption of phar \" %s \" (actual filesize mismatch on file \" %s \" ) " , idata - > phar - > fname , internal_file ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2005-12-11 00:00:31 +00:00
efree ( internal_file ) ;
2005-12-04 20:35:38 +00:00
return NULL ;
}
}
2006-01-11 23:55:57 +00:00
/* check length, crc32 */
if ( phar_postprocess_file ( wrapper , options , idata , idata - > internal_file - > crc32 TSRMLS_CC ) ! = SUCCESS ) {
2007-01-07 18:35:48 +00:00
/* already issued the error */
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2006-01-11 23:55:57 +00:00
efree ( internal_file ) ;
return NULL ;
}
2007-01-13 17:10:18 +00:00
idata - > internal_file - > is_crc_checked = 1 ;
2006-01-11 23:55:57 +00:00
fpf = php_stream_alloc ( & phar_ops , idata , NULL , mode ) ;
2005-12-09 23:37:03 +00:00
efree ( internal_file ) ;
2006-01-11 23:55:57 +00:00
return fpf ;
2005-12-04 20:35:38 +00:00
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Used for fclose ( $ fp ) where $ fp is a phar archive
*/
2007-01-08 19:30:52 +00:00
static int phar_stream_close ( php_stream * stream , int close_handle TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2007-01-27 15:31:24 +00:00
phar_entry_delref ( ( phar_entry_data * ) stream - > abstract TSRMLS_CC ) ;
2006-01-05 22:24:41 +00:00
2005-12-04 20:35:38 +00:00
return 0 ;
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 00:04:30 +00:00
/**
* Used for closedir ( $ fp ) where $ fp is an opendir ( ' phar : //...') directory handle
*/
2007-01-08 19:30:52 +00:00
static int phar_dir_close ( php_stream * stream , int close_handle TSRMLS_DC ) /* { { { */
2005-12-05 08:31:05 +00:00
{
HashTable * data = ( HashTable * ) stream - > abstract ;
2007-01-03 15:43:07 +00:00
if ( data & & data - > arBuckets )
2006-01-01 22:19:51 +00:00
{
zend_hash_destroy ( data ) ;
2007-01-03 15:43:07 +00:00
data - > arBuckets = 0 ;
2006-01-01 22:19:51 +00:00
FREE_HASHTABLE ( data ) ;
stream - > abstract = NULL ;
}
2005-12-05 08:31:05 +00:00
return 0 ;
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-05 08:31:05 +00:00
2007-01-02 00:04:30 +00:00
/**
* Used for seeking on a phar directory handle
*/
2007-01-08 19:30:52 +00:00
static int phar_dir_seek ( php_stream * stream , off_t offset , int whence , off_t * newoffset TSRMLS_DC ) /* { { { */
2006-01-04 02:26:15 +00:00
{
HashTable * data = ( HashTable * ) stream - > abstract ;
if ( data )
{
if ( whence = = SEEK_END ) {
whence = SEEK_SET ;
offset = zend_hash_num_elements ( data ) + offset ;
}
if ( whence = = SEEK_SET ) {
zend_hash_internal_pointer_reset ( data ) ;
}
if ( offset < 0 ) {
php_stream_wrapper_log_error ( stream - > wrapper , stream - > flags TSRMLS_CC , " phar error: cannot seek because the resulting seek is negative " ) ;
return - 1 ;
} else {
* newoffset = 0 ;
while ( * newoffset < offset & & zend_hash_move_forward ( data ) = = SUCCESS ) {
( * newoffset ) + + ;
}
return 0 ;
}
}
return - 1 ;
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* used for fread ( $ fp ) and company on a fopen ( ) ed phar file handle
*/
2007-01-08 19:30:52 +00:00
static size_t phar_stream_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2006-02-28 01:36:30 +00:00
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
2007-01-16 03:41:52 +00:00
size_t got ;
if ( data - > internal_file - > is_deleted ) {
stream - > eof = 1 ;
return 0 ;
}
2007-01-26 14:52:10 +00:00
/* use our proxy position */
php_stream_seek ( data - > fp , data - > position , SEEK_SET ) ;
2006-02-28 14:44:23 +00:00
2007-01-26 14:52:10 +00:00
got = php_stream_read ( data - > fp , buf , count ) ;
2006-02-28 14:44:23 +00:00
if ( data - > fp - > eof ) {
stream - > eof = 1 ;
}
2007-01-26 14:52:10 +00:00
/* note the position, and restore the stream for the next fp */
data - > position = php_stream_tell ( data - > fp ) ;
2006-02-28 14:44:23 +00:00
return got ;
2005-12-04 20:35:38 +00:00
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 00:04:30 +00:00
/**
* Used for readdir ( ) on an opendir ( ) ed phar directory handle
*/
2007-01-08 19:30:52 +00:00
static size_t phar_dir_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
size_t to_read ;
2005-12-05 08:31:05 +00:00
HashTable * data = ( HashTable * ) stream - > abstract ;
char * key ;
uint keylen ;
ulong unused ;
2005-12-04 20:35:38 +00:00
2005-12-05 08:31:05 +00:00
if ( FAILURE = = zend_hash_has_more_elements ( data ) ) {
return 0 ;
}
if ( HASH_KEY_NON_EXISTANT = = zend_hash_get_current_key_ex ( data , & key , & keylen , & unused , 0 , NULL ) ) {
2005-12-04 20:35:38 +00:00
return 0 ;
}
2005-12-05 08:31:05 +00:00
zend_hash_move_forward ( data ) ;
to_read = MIN ( keylen , count ) ;
if ( to_read = = 0 | | count < keylen ) {
return 0 ;
}
memset ( buf , 0 , sizeof ( php_stream_dirent ) ) ;
memcpy ( ( ( php_stream_dirent * ) buf ) - > d_name , key , to_read ) ;
( ( php_stream_dirent * ) buf ) - > d_name [ to_read + 1 ] = ' \0 ' ;
2005-12-04 20:35:38 +00:00
2005-12-05 08:31:05 +00:00
return sizeof ( php_stream_dirent ) ;
2005-12-04 20:35:38 +00:00
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 00:04:30 +00:00
/**
* Used for fseek ( $ fp ) on a phar file handle
*/
2007-01-08 19:30:52 +00:00
static int phar_stream_seek ( php_stream * stream , off_t offset , int whence , off_t * newoffset TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2006-02-28 01:36:30 +00:00
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
2006-01-05 22:24:41 +00:00
2007-01-26 14:52:10 +00:00
int res ;
if ( whence ! = SEEK_SET ) {
/* use our proxy position, so the relative stuff works */
php_stream_seek ( data - > fp , data - > position , SEEK_SET ) ;
}
/* now do the actual seek */
res = php_stream_seek ( data - > fp , offset , whence ) ;
2006-01-05 22:24:41 +00:00
* newoffset = php_stream_tell ( data - > fp ) ;
2007-01-26 14:52:10 +00:00
data - > position = * newoffset ;
2006-01-05 22:24:41 +00:00
return res ;
2005-12-04 20:35:38 +00:00
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 00:04:30 +00:00
/**
* Used for writing to a phar file
*/
2007-01-08 19:30:52 +00:00
static size_t phar_stream_write ( php_stream * stream , const char * buf , size_t count TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2007-01-02 18:15:17 +00:00
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
2007-01-26 14:52:10 +00:00
php_stream_seek ( data - > fp , data - > position , SEEK_SET ) ;
if ( count ! = php_stream_write ( data - > fp , buf , count ) ) {
2007-01-29 06:02:19 +00:00
php_stream_wrapper_log_error ( stream - > wrapper , stream - > flags TSRMLS_CC , " phar error: Could not write %d characters to \" %s \" in phar \" %s \" " , ( int ) count , data - > internal_file - > filename , data - > phar - > fname ) ;
2007-01-02 18:15:17 +00:00
return - 1 ;
}
2007-01-26 14:52:10 +00:00
data - > position = php_stream_tell ( data - > fp ) ;
2007-02-05 20:34:23 +00:00
if ( data - > position > ( off_t ) data - > internal_file - > uncompressed_filesize ) {
2007-01-27 15:31:24 +00:00
data - > internal_file - > uncompressed_filesize = data - > position ;
}
2007-01-02 21:21:18 +00:00
data - > internal_file - > compressed_filesize = data - > internal_file - > uncompressed_filesize ;
2007-01-27 15:31:24 +00:00
data - > internal_file - > is_modified = 1 ;
2007-01-05 03:04:56 +00:00
return count ;
2005-12-04 20:35:38 +00:00
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 18:15:17 +00:00
/**
* Dummy : Used for writing to a phar directory ( i . e . not used )
*/
2007-01-08 19:30:52 +00:00
static size_t phar_dir_write ( php_stream * stream , const char * buf , size_t count TSRMLS_DC ) /* { { { */
2007-01-02 18:15:17 +00:00
{
return 0 ;
}
/* }}} */
2007-01-02 20:25:04 +00:00
static inline void phar_set_32 ( char * buffer , int var ) /* { { { */
{
# ifdef WORDS_BIGENDIAN
2007-01-02 22:57:47 +00:00
* ( ( buffer ) + 3 ) = ( unsigned char ) ( ( ( var ) > > 24 ) & 0xFF ) ;
* ( ( buffer ) + 2 ) = ( unsigned char ) ( ( ( var ) > > 16 ) & 0xFF ) ;
* ( ( buffer ) + 1 ) = ( unsigned char ) ( ( ( var ) > > 8 ) & 0xFF ) ;
2007-01-02 20:25:04 +00:00
* ( ( buffer ) + 0 ) = ( unsigned char ) ( ( var ) & 0xFF ) ;
# else
2007-01-02 21:01:44 +00:00
* ( php_uint32 * ) ( buffer ) = ( php_uint32 ) ( var ) ;
2007-01-02 20:25:04 +00:00
# endif
} /* }}} */
2007-01-02 22:57:47 +00:00
/**
* The only purpose of this is to store the API version , which was stored bigendian for some reason
* in the original PHP_Archive , so we will do the same
*/
2007-01-02 20:25:04 +00:00
static inline void phar_set_16 ( char * buffer , int var ) /* { { { */
{
2007-01-02 18:15:17 +00:00
# ifdef WORDS_BIGENDIAN
2007-01-02 22:57:47 +00:00
* ( ( buffer ) + 1 ) = ( unsigned char ) ( ( ( var ) > > 8 ) & 0xFF ) ; \
2007-01-02 18:15:17 +00:00
* ( buffer ) = ( unsigned char ) ( ( var ) & 0xFF ) ;
# else
2007-01-02 21:01:44 +00:00
* ( php_uint16 * ) ( buffer ) = ( php_uint16 ) ( var ) ;
2007-01-02 18:15:17 +00:00
# endif
2007-01-02 20:25:04 +00:00
} /* }}} */
2007-01-02 18:15:17 +00:00
2007-01-27 23:02:42 +00: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 ;
}
}
/* }}} */
2007-01-21 23:22:57 +00: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
*/
2007-01-29 06:02:19 +00:00
int phar_flush ( phar_archive_data * archive , char * user_stub , long len , char * * error TSRMLS_DC ) /* { { { */
2007-01-07 19:45:31 +00:00
{
2007-01-21 23:22:57 +00:00
static const char newstub [ ] = " <?php __HALT_COMPILER(); " ;
2007-01-02 18:15:17 +00:00
phar_entry_info * entry ;
2007-02-05 20:34:23 +00:00
int halt_offset , restore_alias_len , global_flags = 0 , closeoldfile ;
2007-02-05 20:47:20 +00:00
char * buf , * pos ;
2007-01-21 06:30:55 +00:00
char manifest [ 18 ] , entry_buffer [ 24 ] ;
2007-01-09 23:57:03 +00:00
off_t manifest_ftell ;
2007-01-04 05:32:45 +00:00
long offset ;
2007-02-05 20:34:23 +00:00
size_t wrote , read ;
2007-01-27 15:31:24 +00:00
php_uint32 manifest_len , mytime , loc , new_manifest_count ;
2007-01-07 19:05:12 +00:00
php_uint32 newcrc32 ;
2007-01-27 15:31:24 +00:00
php_stream * file , * oldfile , * newfile , * stubfile ;
2007-01-02 18:15:17 +00:00
php_stream_filter * filter ;
2007-01-21 20:12:50 +00:00
php_serialize_data_t metadata_hash ;
smart_str metadata_str = { 0 } ;
2007-01-02 18:15:17 +00:00
2007-02-06 17:09:37 +00:00
if ( error ) {
* error = NULL ;
}
2007-01-07 16:01:35 +00:00
if ( PHAR_G ( readonly ) ) {
return EOF ;
}
2007-01-09 22:30:56 +00:00
2007-01-28 21:26:54 +00:00
if ( archive - > fp & & ! archive - > is_brandnew ) {
2007-01-28 19:56:09 +00:00
oldfile = archive - > fp ;
2007-01-28 21:26:54 +00:00
closeoldfile = 0 ;
php_stream_rewind ( oldfile ) ;
2007-01-28 19:56:09 +00:00
} else {
oldfile = php_stream_open_wrapper ( archive - > fname , " rb " , 0 , NULL ) ;
2007-01-28 21:26:54 +00:00
closeoldfile = oldfile ! = NULL ;
2007-01-26 14:52:10 +00:00
}
2007-01-02 18:15:17 +00:00
newfile = php_stream_fopen_tmpfile ( ) ;
2007-02-05 22:11:27 +00:00
if ( ! newfile ) {
if ( error ) {
spprintf ( error , 0 , " unable to create temporary file " ) ;
}
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
return EOF ;
}
2007-01-02 18:15:17 +00:00
2007-01-27 15:31:24 +00:00
if ( user_stub ) {
2007-01-21 23:22:57 +00:00
if ( len < 0 ) {
/* resource passed in */
if ( ! ( php_stream_from_zval_no_verify ( stubfile , ( zval * * ) user_stub ) ) ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-21 23:22:57 +00:00
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to read resource to copy stub to new phar \" %s \" " , archive - > fname ) ;
}
2007-01-21 23:22:57 +00:00
return EOF ;
}
if ( len = = - 1 ) {
len = PHP_STREAM_COPY_ALL ;
} else {
len = - len ;
}
2007-01-22 00:59:02 +00:00
offset = php_stream_copy_to_stream ( stubfile , newfile , len ) ;
if ( len ! = offset & & len ! = PHP_STREAM_COPY_ALL ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-21 23:22:57 +00:00
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to copy stub from resource to new phar \" %s \" " , archive - > fname ) ;
}
2007-01-21 23:22:57 +00:00
return EOF ;
}
2007-01-27 15:31:24 +00:00
archive - > halt_offset = offset ;
2007-01-21 23:22:57 +00:00
} else {
2007-02-05 20:47:20 +00:00
if ( ( pos = strstr ( user_stub , " __HALT_COMPILER(); " ) ) = = NULL )
{
2007-02-06 17:09:37 +00:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-02-05 20:47:20 +00:00
if ( error ) {
spprintf ( error , 0 , " illegal stub for phar \" %s \" " , archive - > fname ) ;
}
return EOF ;
}
2007-02-05 20:34:23 +00:00
if ( ( size_t ) len ! = php_stream_write ( newfile , user_stub , len ) ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-21 23:22:57 +00:00
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to create stub from string in new phar \" %s \" " , archive - > fname ) ;
}
2007-01-21 23:22:57 +00:00
return EOF ;
2007-01-09 18:54:37 +00:00
}
2007-01-27 15:31:24 +00:00
archive - > halt_offset = len ;
2007-01-02 18:15:17 +00:00
}
2007-01-05 03:04:56 +00:00
} else {
2007-01-28 21:26:54 +00:00
if ( archive - > halt_offset & & oldfile & & ! archive - > is_brandnew ) {
2007-01-28 19:56:09 +00:00
if ( archive - > halt_offset ! = php_stream_copy_to_stream ( oldfile , newfile , archive - > halt_offset ) ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
2007-01-21 23:22:57 +00:00
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to copy stub of old phar to new phar \" %s \" " , archive - > fname ) ;
}
2007-01-21 23:22:57 +00:00
return EOF ;
}
} else {
/* this is a brand new phar */
2007-01-27 15:31:24 +00:00
archive - > halt_offset = sizeof ( newstub ) - 1 ;
2007-01-21 23:22:57 +00:00
if ( sizeof ( newstub ) - 1 ! = php_stream_write ( newfile , newstub , sizeof ( newstub ) - 1 ) ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-21 23:22:57 +00:00
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to create stub in new phar \" %s \" " , archive - > fname ) ;
}
2007-01-21 23:22:57 +00:00
return EOF ;
2007-01-09 18:54:37 +00:00
}
2007-01-05 03:04:56 +00:00
}
2007-01-02 18:15:17 +00:00
}
2007-01-02 19:59:38 +00:00
manifest_ftell = php_stream_tell ( newfile ) ;
2007-01-21 23:22:57 +00:00
halt_offset = manifest_ftell ;
2007-01-27 23:02:42 +00: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 . */
zend_hash_apply ( & archive - > manifest , phar_flush_clean_deleted_apply TSRMLS_CC ) ;
2007-01-29 03:59:55 +00:00
/* compress as necessary, calculate crcs, serialize meta-data, manifest size, and file sizes */
metadata_str . c = 0 ;
if ( archive - > metadata ) {
PHP_VAR_SERIALIZE_INIT ( metadata_hash ) ;
php_var_serialize ( & metadata_str , & archive - > metadata , & metadata_hash TSRMLS_CC ) ;
PHP_VAR_SERIALIZE_DESTROY ( metadata_hash ) ;
} else {
metadata_str . len = 0 ;
}
2007-01-04 05:32:45 +00:00
new_manifest_count = 0 ;
offset = 0 ;
2007-01-22 03:41:41 +00:00
buf = ( char * ) emalloc ( 8192 ) ;
2007-01-27 15:31:24 +00:00
for ( zend_hash_internal_pointer_reset ( & archive - > manifest ) ;
zend_hash_has_more_elements ( & archive - > manifest ) = = SUCCESS ;
zend_hash_move_forward ( & archive - > manifest ) ) {
if ( zend_hash_get_current_data ( & archive - > manifest , ( void * * ) & entry ) = = FAILURE ) {
2007-01-02 18:15:17 +00:00
continue ;
}
2007-01-27 15:31:24 +00:00
if ( entry - > cfp ) {
/* did we forget to get rid of cfp last time? */
php_stream_close ( entry - > cfp ) ;
entry - > cfp = 0 ;
}
2007-01-13 17:10:18 +00:00
if ( entry - > is_deleted ) {
2007-01-02 18:15:17 +00:00
/* remove this from the new phar */
continue ;
}
2007-01-04 05:32:45 +00:00
/* after excluding deleted files, calculate manifest size in bytes and number of entries */
+ + new_manifest_count ;
2007-01-13 16:17:04 +00:00
offset + = 4 + entry - > filename_len + sizeof ( entry_buffer ) ;
2007-01-04 05:32:45 +00:00
2007-01-27 15:31:24 +00:00
/* compress and rehash as necessary */
2007-01-28 21:26:54 +00:00
if ( oldfile & & ! entry - > is_modified ) {
2007-01-22 03:41:41 +00:00
continue ;
}
2007-01-26 14:52:10 +00:00
if ( ! entry - > fp ) {
/* this should never happen */
2007-01-22 03:41:41 +00:00
continue ;
}
2007-01-26 14:52:10 +00:00
file = entry - > fp ;
2007-01-22 03:41:41 +00:00
php_stream_rewind ( file ) ;
newcrc32 = ~ 0 ;
mytime = entry - > uncompressed_filesize ;
for ( loc = 0 ; loc < mytime ; loc + + ) {
CRC32 ( newcrc32 , php_stream_getc ( file ) ) ;
}
entry - > crc32 = ~ newcrc32 ;
entry - > is_crc_checked = 1 ;
if ( ! ( entry - > flags & PHAR_ENT_COMPRESSION_MASK ) ) {
2007-01-27 15:31:24 +00:00
/* not compressed */
2007-01-22 03:41:41 +00:00
continue ;
}
php_stream_rewind ( file ) ;
filter = php_stream_filter_create ( phar_compress_filter ( entry , 0 ) , NULL , 0 TSRMLS_CC ) ;
if ( ! filter ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-22 02:04:51 +00:00
php_stream_close ( oldfile ) ;
2007-01-02 21:01:44 +00:00
}
2007-01-22 03:41:41 +00:00
php_stream_close ( newfile ) ;
if ( entry - > flags & PHAR_ENT_COMPRESSED_GZ ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to gzip compress file \" %s \" to new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
2007-01-22 03:41:41 +00:00
} else {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to bzip2 compress file \" %s \" to new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
2007-01-22 03:41:41 +00:00
}
efree ( buf ) ;
return EOF ;
2007-01-02 18:15:17 +00:00
}
2007-01-22 03:41:41 +00:00
php_stream_filter_append ( & file - > readfilters , filter ) ;
/* create new file that holds the compressed version */
/* work around inability to specify freedom in write and strictness
in read count */
entry - > compressed_filesize = 0 ;
2007-01-27 15:31:24 +00:00
entry - > cfp = php_stream_fopen_tmpfile ( ) ;
2007-02-05 22:11:27 +00:00
if ( ! entry - > cfp ) {
if ( error ) {
spprintf ( error , 0 , " unable to create temporary file " ) ;
}
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
efree ( buf ) ;
return EOF ;
}
2007-01-22 03:41:41 +00:00
do {
read = php_stream_read ( file , buf , 8192 ) ;
if ( read ) {
2007-01-27 15:31:24 +00:00
if ( read ! = php_stream_write ( entry - > cfp , buf , read ) ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to write to file \" %s \" while creating new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
2007-01-22 03:41:41 +00:00
efree ( buf ) ;
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
2007-01-27 15:31:24 +00:00
php_stream_close ( entry - > cfp ) ;
entry - > cfp = 0 ;
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-28 19:56:09 +00:00
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
2007-01-22 03:41:41 +00:00
return EOF ;
2007-01-04 05:32:45 +00:00
}
2007-01-22 03:41:41 +00:00
entry - > compressed_filesize + = read ;
2007-01-04 05:32:45 +00:00
}
2007-01-22 03:41:41 +00:00
} while ( read ) ;
php_stream_filter_remove ( filter , 1 TSRMLS_CC ) ;
/* generate crc on compressed file */
2007-01-27 15:31:24 +00:00
php_stream_rewind ( entry - > cfp ) ;
2007-01-22 03:41:41 +00:00
entry - > is_modified = 1 ;
global_flags | = ( entry - > flags & PHAR_ENT_COMPRESSION_MASK ) ;
2007-01-02 18:15:17 +00:00
}
2007-01-22 03:41:41 +00:00
efree ( buf ) ;
2007-01-13 16:17:04 +00:00
global_flags | = PHAR_HDR_SIGNATURE ;
2007-01-04 05:32:45 +00:00
/* write out manifest pre-header */
2007-01-13 16:17:04 +00:00
/* 4: manifest length
* 4 : manifest entry count
* 2 : phar version
* 4 : phar global flags
2007-01-29 03:59:55 +00:00
* 4 : alias length
* ? : the alias itself
* 4 : phar metadata length
* ? : phar metadata
2007-01-13 16:17:04 +00:00
*/
2007-01-27 15:31:24 +00:00
restore_alias_len = archive - > alias_len ;
if ( ! archive - > is_explicit_alias ) {
archive - > alias_len = 0 ;
2007-01-05 04:45:52 +00:00
}
2007-01-08 23:03:41 +00:00
2007-01-29 03:59:55 +00:00
manifest_len = offset + archive - > alias_len + sizeof ( manifest ) + metadata_str . len ;
2007-01-27 15:31:24 +00:00
phar_set_32 ( manifest , manifest_len ) ;
2007-01-13 16:17:04 +00:00
phar_set_32 ( manifest + 4 , new_manifest_count ) ;
2007-01-04 05:32:45 +00:00
* ( manifest + 8 ) = ( unsigned char ) ( ( ( PHAR_API_VERSION ) > > 8 ) & 0xFF ) ;
2007-01-13 16:17:04 +00:00
* ( manifest + 9 ) = ( unsigned char ) ( ( ( PHAR_API_VERSION ) & 0xF0 ) ) ;
phar_set_32 ( manifest + 10 , global_flags ) ;
2007-01-27 15:31:24 +00:00
phar_set_32 ( manifest + 14 , archive - > alias_len ) ;
2007-01-04 05:32:45 +00:00
/* write the manifest header */
2007-01-13 16:17:04 +00:00
if ( sizeof ( manifest ) ! = php_stream_write ( newfile , manifest , sizeof ( manifest ) )
2007-02-05 20:34:23 +00:00
| | ( size_t ) archive - > alias_len ! = php_stream_write ( newfile , archive - > alias , archive - > alias_len ) ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-09 22:30:56 +00:00
php_stream_close ( oldfile ) ;
2007-01-09 18:54:37 +00:00
}
2007-01-03 15:43:07 +00:00
php_stream_close ( newfile ) ;
2007-01-27 15:31:24 +00:00
archive - > alias_len = restore_alias_len ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to write manifest header of new phar \" %s \" " , archive - > fname ) ;
}
2007-01-07 16:01:35 +00:00
return EOF ;
2007-01-02 21:01:44 +00:00
}
2007-01-29 03:59:55 +00:00
2007-01-27 15:31:24 +00:00
archive - > alias_len = restore_alias_len ;
2007-01-04 05:32:45 +00:00
2007-01-29 03:59:55 +00:00
metadata_str . c = 0 ;
phar_set_32 ( manifest , metadata_str . len ) ;
if ( metadata_str . len ) {
if ( 4 ! = php_stream_write ( newfile , manifest , 4 ) | |
metadata_str . len ! = php_stream_write ( newfile , metadata_str . c , metadata_str . len ) ) {
smart_str_free ( & metadata_str ) ;
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
archive - > alias_len = restore_alias_len ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to write manifest meta-data of new phar \" %s \" " , archive - > fname ) ;
}
2007-01-29 03:59:55 +00:00
return EOF ;
}
} else {
if ( 4 ! = php_stream_write ( newfile , manifest , 4 ) ) {
smart_str_free ( & metadata_str ) ;
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
archive - > alias_len = restore_alias_len ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to write manifest header of new phar \" %s \" " , archive - > fname ) ;
}
2007-01-29 03:59:55 +00:00
return EOF ;
}
}
smart_str_free ( & metadata_str ) ;
2007-01-04 05:32:45 +00:00
/* re-calculate the manifest location to simplify later code */
manifest_ftell = php_stream_tell ( newfile ) ;
/* now write the manifest */
2007-01-27 15:31:24 +00:00
for ( zend_hash_internal_pointer_reset ( & archive - > manifest ) ;
zend_hash_has_more_elements ( & archive - > manifest ) = = SUCCESS ;
zend_hash_move_forward ( & archive - > manifest ) ) {
if ( zend_hash_get_current_data ( & archive - > manifest , ( void * * ) & entry ) = = FAILURE ) {
2007-01-02 18:15:17 +00:00
continue ;
}
2007-01-13 17:10:18 +00:00
if ( entry - > is_deleted ) {
2007-01-04 05:32:45 +00:00
/* remove this from the new phar */
2007-01-02 18:15:17 +00:00
continue ;
}
2007-01-09 23:57:03 +00:00
phar_set_32 ( entry_buffer , entry - > filename_len ) ;
if ( 4 ! = php_stream_write ( newfile , entry_buffer , 4 )
| | entry - > filename_len ! = php_stream_write ( newfile , entry - > filename , entry - > filename_len ) ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-09 22:30:56 +00:00
php_stream_close ( oldfile ) ;
2007-01-09 18:54:37 +00:00
}
2007-01-04 05:32:45 +00:00
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to write filename of file \" %s \" to manifest of new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
2007-01-07 16:01:35 +00:00
return EOF ;
2007-01-04 05:32:45 +00:00
}
/* set the manifest meta-data:
2007-01-02 18:15:17 +00:00
4 : uncompressed filesize
4 : creation timestamp
4 : compressed filesize
4 : crc32
2007-01-13 16:17:04 +00:00
4 : flags
2007-01-21 20:12:50 +00:00
4 : metadata - len
+ : metadata
2007-01-02 18:15:17 +00:00
*/
2007-01-21 20:12:50 +00:00
metadata_str . c = 0 ;
if ( entry - > metadata ) {
PHP_VAR_SERIALIZE_INIT ( metadata_hash ) ;
php_var_serialize ( & metadata_str , & entry - > metadata , & metadata_hash TSRMLS_CC ) ;
PHP_VAR_SERIALIZE_DESTROY ( metadata_hash ) ;
}
2007-01-22 03:41:41 +00:00
mytime = time ( NULL ) ;
2007-01-09 23:57:03 +00:00
phar_set_32 ( entry_buffer , entry - > uncompressed_filesize ) ;
2007-01-22 03:41:41 +00:00
phar_set_32 ( entry_buffer + 4 , mytime ) ;
2007-01-09 23:57:03 +00:00
phar_set_32 ( entry_buffer + 8 , entry - > compressed_filesize ) ;
phar_set_32 ( entry_buffer + 12 , entry - > crc32 ) ;
2007-01-13 16:17:04 +00:00
phar_set_32 ( entry_buffer + 16 , entry - > flags ) ;
2007-01-21 20:12:50 +00:00
phar_set_32 ( entry_buffer + 20 , metadata_str . len ) ;
if ( sizeof ( entry_buffer ) ! = php_stream_write ( newfile , entry_buffer , sizeof ( entry_buffer ) )
2007-01-28 03:25:53 +00:00
| | metadata_str . len ! = php_stream_write ( newfile , metadata_str . c , metadata_str . len ) ) {
2007-01-21 20:12:50 +00:00
smart_str_free ( & metadata_str ) ;
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-09 22:30:56 +00:00
php_stream_close ( oldfile ) ;
2007-01-09 18:54:37 +00:00
}
2007-01-03 15:43:07 +00:00
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to write temporary manifest of file \" %s \" to manifest of new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
2007-01-07 16:01:35 +00:00
return EOF ;
2007-01-04 05:32:45 +00:00
}
2007-01-21 20:12:50 +00:00
smart_str_free ( & metadata_str ) ;
2007-01-04 05:32:45 +00:00
}
/* now copy the actual file data to the new phar */
offset = 0 ;
2007-01-27 15:31:24 +00:00
for ( zend_hash_internal_pointer_reset ( & archive - > manifest ) ;
zend_hash_has_more_elements ( & archive - > manifest ) = = SUCCESS ;
zend_hash_move_forward ( & archive - > manifest ) ) {
if ( zend_hash_get_current_data ( & archive - > manifest , ( void * * ) & entry ) = = FAILURE ) {
2007-01-04 05:32:45 +00:00
continue ;
}
2007-01-13 17:10:18 +00:00
if ( entry - > is_deleted ) {
2007-01-04 05:32:45 +00:00
continue ;
}
2007-01-27 15:31:24 +00:00
if ( entry - > cfp ) {
file = entry - > cfp ;
php_stream_rewind ( file ) ;
2007-02-06 17:09:37 +00:00
} else if ( entry - > fp & & ( entry - > is_modified | | ! oldfile ) ) {
2007-01-26 14:52:10 +00:00
file = entry - > fp ;
2007-01-27 15:31:24 +00:00
php_stream_rewind ( file ) ;
2007-01-04 05:32:45 +00:00
} else {
2007-02-06 17:09:37 +00:00
if ( ! oldfile ) {
if ( closeoldfile ) {
php_stream_close ( oldfile ) ;
}
php_stream_close ( newfile ) ;
if ( error ) {
spprintf ( error , 0 , " unable to seek to start of file \" %s \" while creating new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
return EOF ;
}
2007-01-27 15:31:24 +00:00
if ( - 1 = = php_stream_seek ( oldfile , entry - > offset_within_phar + archive - > internal_file_start , SEEK_SET ) ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-09 22:30:56 +00:00
php_stream_close ( oldfile ) ;
2007-01-09 18:54:37 +00:00
}
2007-01-04 05:32:45 +00:00
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to seek to start of file \" %s \" while creating new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
2007-01-07 16:01:35 +00:00
return EOF ;
2007-01-04 05:32:45 +00:00
}
2007-01-09 22:30:56 +00:00
file = oldfile ;
2007-01-04 05:32:45 +00:00
}
/* this will have changed for all files that have either
changed compression or been modified */
entry - > offset_within_phar = offset ;
offset + = entry - > compressed_filesize ;
2007-01-27 15:31:24 +00:00
wrote = php_stream_copy_to_stream ( file , newfile , entry - > compressed_filesize ) ;
if ( entry - > compressed_filesize ! = wrote ) {
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-09 22:30:56 +00:00
php_stream_close ( oldfile ) ;
2007-01-09 18:54:37 +00:00
}
2007-01-04 05:32:45 +00:00
php_stream_close ( newfile ) ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to write contents of file \" %s \" to new phar \" %s \" " , entry - > filename , archive - > fname ) ;
}
2007-01-07 16:01:35 +00:00
return EOF ;
2007-01-04 05:32:45 +00:00
}
2007-01-26 14:52:10 +00:00
entry - > is_modified = 0 ;
2007-01-27 15:31:24 +00:00
if ( entry - > cfp ) {
php_stream_close ( entry - > cfp ) ;
entry - > cfp = 0 ;
}
2007-01-02 18:15:17 +00:00
}
2007-01-04 05:32:45 +00:00
2007-01-08 23:03:41 +00:00
/* append signature */
if ( global_flags & PHAR_HDR_SIGNATURE ) {
unsigned char buf [ 1024 ] ;
2007-02-24 02:08:08 +00:00
int sig_flags = 0 , sig_len ;
2007-01-08 23:03:41 +00:00
char sig_buf [ 4 ] ;
php_stream_rewind ( newfile ) ;
2007-01-27 15:31:24 +00:00
if ( archive - > signature ) {
efree ( archive - > signature ) ;
}
2007-03-26 00:00:56 +00:00
switch ( archive - > sig_flags ) {
2007-03-25 21:43:49 +00:00
# if HAVE_HASH_EXT
case PHAR_SIG_SHA512 : {
unsigned char digest [ 64 ] ;
PHP_SHA512_CTX context ;
PHP_SHA512Init ( & context ) ;
while ( ( sig_len = php_stream_read ( newfile , ( char * ) buf , sizeof ( buf ) ) ) > 0 ) {
PHP_SHA512Update ( & context , buf , sig_len ) ;
}
PHP_SHA512Final ( digest , & context ) ;
php_stream_write ( newfile , ( char * ) digest , sizeof ( digest ) ) ;
sig_flags | = PHAR_SIG_SHA512 ;
archive - > sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & archive - > signature ) ;
break ;
}
case PHAR_SIG_SHA256 : {
unsigned char digest [ 32 ] ;
PHP_SHA256_CTX context ;
PHP_SHA256Init ( & context ) ;
while ( ( sig_len = php_stream_read ( newfile , ( char * ) buf , sizeof ( buf ) ) ) > 0 ) {
PHP_SHA256Update ( & context , buf , sig_len ) ;
}
PHP_SHA256Final ( digest , & context ) ;
php_stream_write ( newfile , ( char * ) digest , sizeof ( digest ) ) ;
sig_flags | = PHAR_SIG_SHA256 ;
archive - > sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & archive - > signature ) ;
break ;
}
# else
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 , archive - > fname ) ;
}
return EOF ;
# endif
2007-03-26 00:00:56 +00:00
case PHAR_SIG_PGP :
/* TODO: currently fall back to sha1,later do both */
2007-03-25 23:42:49 +00:00
default :
2007-01-08 23:03:41 +00:00
case PHAR_SIG_SHA1 : {
unsigned char digest [ 20 ] ;
PHP_SHA1_CTX context ;
PHP_SHA1Init ( & context ) ;
2007-01-27 15:31:24 +00:00
while ( ( sig_len = php_stream_read ( newfile , ( char * ) buf , sizeof ( buf ) ) ) > 0 ) {
PHP_SHA1Update ( & context , buf , sig_len ) ;
2007-01-08 23:03:41 +00:00
}
PHP_SHA1Final ( digest , & context ) ;
2007-01-20 05:28:48 +00:00
php_stream_write ( newfile , ( char * ) digest , sizeof ( digest ) ) ;
2007-01-08 23:03:41 +00:00
sig_flags | = PHAR_SIG_SHA1 ;
2007-03-25 19:03:38 +00:00
archive - > sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & archive - > signature ) ;
2007-01-08 23:03:41 +00:00
break ;
}
case PHAR_SIG_MD5 : {
unsigned char digest [ 16 ] ;
PHP_MD5_CTX context ;
PHP_MD5Init ( & context ) ;
2007-01-27 15:31:24 +00:00
while ( ( sig_len = php_stream_read ( newfile , ( char * ) buf , sizeof ( buf ) ) ) > 0 ) {
PHP_MD5Update ( & context , buf , sig_len ) ;
2007-01-08 23:03:41 +00:00
}
PHP_MD5Final ( digest , & context ) ;
2007-01-20 05:28:48 +00:00
php_stream_write ( newfile , ( char * ) digest , sizeof ( digest ) ) ;
2007-01-08 23:03:41 +00:00
sig_flags | = PHAR_SIG_MD5 ;
2007-03-25 19:03:38 +00:00
archive - > sig_len = phar_hex_str ( ( const char * ) digest , sizeof ( digest ) , & archive - > signature ) ;
2007-01-08 23:03:41 +00:00
break ;
}
}
phar_set_32 ( sig_buf , sig_flags ) ;
php_stream_write ( newfile , sig_buf , 4 ) ;
php_stream_write ( newfile , " GBMB " , 4 ) ;
2007-01-27 15:31:24 +00:00
archive - > sig_flags = sig_flags ;
2007-01-08 23:03:41 +00:00
}
2007-01-02 18:15:17 +00: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
*/
2007-01-28 21:26:54 +00:00
if ( archive - > fp ) {
2007-01-27 15:31:24 +00:00
php_stream_close ( archive - > fp ) ;
}
2007-01-28 21:26:54 +00:00
if ( closeoldfile ) {
2007-01-28 19:56:09 +00:00
php_stream_close ( oldfile ) ;
2007-01-02 18:15:17 +00:00
}
2007-01-28 19:56:09 +00:00
2007-01-27 15:31:24 +00:00
archive - > internal_file_start = halt_offset + manifest_len + 4 ;
2007-01-28 21:26:54 +00:00
archive - > is_brandnew = 0 ;
php_stream_rewind ( newfile ) ;
2007-01-02 18:15:17 +00:00
2007-01-28 19:56:09 +00:00
if ( archive - > donotflush ) {
/* deferred flush */
archive - > fp = newfile ;
} else {
2007-01-28 21:26:54 +00:00
archive - > fp = php_stream_open_wrapper ( archive - > fname , " w+b " , IGNORE_URL | STREAM_MUST_SEEK | REPORT_ERRORS , NULL ) ;
2007-01-28 19:56:09 +00:00
if ( ! archive - > fp ) {
archive - > fp = newfile ;
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to open new phar \" %s \" for writing " , archive - > fname ) ;
}
2007-01-28 19:56:09 +00:00
return EOF ;
}
php_stream_copy_to_stream ( newfile , archive - > fp , PHP_STREAM_COPY_ALL ) ;
php_stream_close ( newfile ) ;
/* we could also reopen the file in "rb" mode but there is no need for that */
2007-01-02 18:15:17 +00:00
}
2007-01-27 15:31:24 +00:00
if ( - 1 = = php_stream_seek ( archive - > fp , archive - > halt_offset , SEEK_SET ) ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
spprintf ( error , 0 , " unable to seek to __HALT_COMPILER(); in new phar \" %s \" " , archive - > fname ) ;
}
2007-01-07 16:01:35 +00:00
return EOF ;
2007-01-02 18:15:17 +00:00
}
2007-01-05 03:04:56 +00:00
2007-01-02 18:15:17 +00:00
return EOF ;
}
/* }}} */
2007-01-08 19:30:52 +00:00
/**
* Used to save work done on a writeable phar
*/
static int phar_stream_flush ( php_stream * stream TSRMLS_DC ) /* { { { */
{
2007-01-29 06:02:19 +00:00
char * error ;
int ret ;
2007-01-14 00:32:38 +00:00
if ( stream - > mode [ 0 ] = = ' w ' | | ( stream - > mode [ 0 ] = = ' r ' & & stream - > mode [ 1 ] = = ' + ' ) ) {
2007-01-29 06:02:19 +00:00
ret = phar_flush ( ( ( phar_entry_data * ) stream - > abstract ) - > internal_file - > phar , 0 , 0 , & error TSRMLS_CC ) ;
if ( error ) {
php_stream_wrapper_log_error ( stream - > wrapper , REPORT_ERRORS TSRMLS_CC , error ) ;
efree ( error ) ;
}
return ret ;
2007-01-14 00:32:38 +00:00
} else {
2007-01-08 19:30:52 +00:00
return EOF ;
}
}
/* }}} */
2007-01-02 18:15:17 +00:00
/**
* Dummy : Used for flushing writes to a phar directory ( i . e . not used )
*/
2007-01-08 19:30:52 +00:00
static int phar_dir_flush ( php_stream * stream TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
return EOF ;
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2006-03-02 22:44:39 +00:00
/* {{{ phar_dostat */
2007-01-02 00:04:30 +00:00
/**
* stat an opened phar file handle stream , used by phar_stat ( )
*/
2006-03-04 02:12:22 +00:00
static void phar_dostat ( phar_archive_data * phar , phar_entry_info * data , php_stream_statbuf * ssb ,
2006-03-02 22:44:39 +00:00
zend_bool is_dir , char * alias , int alias_len TSRMLS_DC )
2005-12-04 20:35:38 +00:00
{
2006-01-01 07:40:36 +00:00
char * tmp ;
int tmp_len ;
2005-12-04 20:35:38 +00:00
memset ( ssb , 0 , sizeof ( php_stream_statbuf ) ) ;
if ( ! is_dir ) {
ssb - > sb . st_size = data - > uncompressed_filesize ;
2007-01-20 05:28:48 +00:00
ssb - > sb . st_mode = data - > flags & PHAR_ENT_PERM_MASK ;
2005-12-11 07:25:30 +00:00
ssb - > sb . st_mode | = S_IFREG ; /* regular file */
/* timestamp is just the timestamp when this was added to the phar */
2005-12-04 20:35:38 +00:00
# ifdef NETWARE
ssb - > sb . st_mtime . tv_sec = data - > timestamp ;
ssb - > sb . st_atime . tv_sec = data - > timestamp ;
ssb - > sb . st_ctime . tv_sec = data - > timestamp ;
# else
ssb - > sb . st_mtime = data - > timestamp ;
ssb - > sb . st_atime = data - > timestamp ;
ssb - > sb . st_ctime = data - > timestamp ;
# endif
} else {
ssb - > sb . st_size = 0 ;
2007-01-14 00:32:38 +00:00
ssb - > sb . st_mode = 0777 ;
2005-12-11 07:25:30 +00:00
ssb - > sb . st_mode | = S_IFDIR ; /* regular directory */
2005-12-04 20:35:38 +00:00
# ifdef NETWARE
2006-03-02 22:44:39 +00:00
ssb - > sb . st_mtime . tv_sec = phar - > max_timestamp ;
ssb - > sb . st_atime . tv_sec = phar - > max_timestamp ;
ssb - > sb . st_ctime . tv_sec = phar - > max_timestamp ;
2005-12-04 20:35:38 +00:00
# else
2006-03-02 22:44:39 +00:00
ssb - > sb . st_mtime = phar - > max_timestamp ;
ssb - > sb . st_atime = phar - > max_timestamp ;
ssb - > sb . st_ctime = phar - > max_timestamp ;
2005-12-04 20:35:38 +00:00
# endif
}
2007-01-28 10:32:45 +00:00
if ( ! phar - > is_writeable ) {
2007-01-14 00:32:38 +00:00
ssb - > sb . st_mode = ( ssb - > sb . st_mode & 0555 ) | ( ssb - > sb . st_mode & ~ 0777 ) ;
}
2005-12-04 20:35:38 +00:00
ssb - > sb . st_nlink = 1 ;
ssb - > sb . st_rdev = - 1 ;
2006-01-01 07:40:36 +00:00
if ( data ) {
tmp_len = data - > filename_len + alias_len ;
} else {
tmp_len = alias_len + 1 ;
}
tmp = ( char * ) emalloc ( tmp_len ) ;
memcpy ( tmp , alias , alias_len ) ;
if ( data ) {
memcpy ( tmp + alias_len , data - > filename , data - > filename_len ) ;
} else {
* ( tmp + alias_len ) = ' / ' ;
}
/* this is only for APC, so use /dev/null device - no chance of conflict there! */
ssb - > sb . st_dev = 0xc ;
/* generate unique inode number for alias/filename, so no phars will conflict */
2007-02-05 20:34:23 +00:00
ssb - > sb . st_ino = ( unsigned short ) zend_get_hash_value ( tmp , tmp_len ) ;
2006-01-01 07:40:36 +00:00
efree ( tmp ) ;
2005-12-07 01:18:54 +00:00
# ifndef PHP_WIN32
2005-12-04 20:35:38 +00:00
ssb - > sb . st_blksize = - 1 ;
ssb - > sb . st_blocks = - 1 ;
2005-12-07 01:18:54 +00:00
# endif
2005-12-04 20:35:38 +00:00
}
2006-01-03 15:59:07 +00:00
/* }}}*/
2005-12-04 20:35:38 +00:00
2007-01-02 00:04:30 +00:00
/**
* Stat an opened phar file handle
*/
2007-01-08 19:30:52 +00:00
static int phar_stream_stat ( php_stream * stream , php_stream_statbuf * ssb TSRMLS_DC ) /* { { { */
{
2007-01-13 16:17:04 +00:00
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
2007-01-08 19:30:52 +00:00
/* If ssb is NULL then someone is misbehaving */
2007-01-13 16:17:04 +00:00
if ( ! ssb ) {
return - 1 ;
}
2007-01-08 19:30:52 +00:00
phar_dostat ( data - > phar , data - > internal_file , ssb , 0 , data - > phar - > alias , data - > phar - > alias_len TSRMLS_CC ) ;
return 0 ;
}
/* }}} */
/**
* Stat a dir in a phar
*/
static int phar_dir_stat ( php_stream * stream , php_stream_statbuf * ssb TSRMLS_DC ) /* { { { */
2006-03-02 22:44:39 +00:00
{
2007-01-13 16:17:04 +00:00
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
2006-03-02 22:44:39 +00:00
/* If ssb is NULL then someone is misbehaving */
2007-01-13 16:17:04 +00:00
if ( ! ssb ) {
return - 1 ;
}
2006-03-02 22:44:39 +00:00
phar_dostat ( data - > phar , data - > internal_file , ssb , 0 , data - > phar - > alias , data - > phar - > alias_len TSRMLS_CC ) ;
return 0 ;
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Stream wrapper stat implementation of stat ( )
*/
2007-01-08 19:30:52 +00:00
static int phar_wrapper_stat ( php_stream_wrapper * wrapper , char * url , int flags ,
2006-01-03 15:59:07 +00:00
php_stream_statbuf * ssb , php_stream_context * context TSRMLS_DC ) /* {{{ */
2005-12-04 20:35:38 +00:00
{
php_url * resource = NULL ;
2007-03-26 19:20:00 +00:00
char * internal_file , * key , * error , * plain_map ;
2005-12-04 20:35:38 +00:00
uint keylen ;
ulong unused ;
2006-03-04 02:12:22 +00:00
phar_archive_data * phar ;
2006-02-28 01:36:30 +00:00
phar_entry_info * entry ;
2007-03-26 19:20:00 +00:00
uint host_len ;
int retval ;
2005-12-04 20:35:38 +00:00
resource = php_url_parse ( url ) ;
2006-01-04 02:26:15 +00:00
2006-01-04 09:26:32 +00:00
if ( ! resource & & ( resource = phar_open_url ( wrapper , url , " r " , 0 TSRMLS_CC ) ) = = NULL ) {
2006-01-04 02:26:15 +00:00
return - 1 ;
}
2006-01-01 20:40:43 +00:00
/* we must have at the very least phar://alias.phar/internalfile.php */
2006-02-28 01:36:30 +00:00
if ( ! resource - > scheme | | ! resource - > host | | ! resource - > path ) {
php_url_free ( resource ) ;
2005-12-11 00:00:31 +00:00
php_stream_wrapper_log_error ( wrapper , flags TSRMLS_CC , " phar error: invalid url \" %s \" " , url ) ;
2005-12-04 20:35:38 +00:00
return - 1 ;
}
if ( strcasecmp ( " phar " , resource - > scheme ) ) {
2005-12-07 06:39:03 +00:00
php_url_free ( resource ) ;
2005-12-11 00:00:31 +00:00
php_stream_wrapper_log_error ( wrapper , flags TSRMLS_CC , " phar error: not a phar url \" %s \" " , url ) ;
2005-12-07 06:39:03 +00:00
return - 1 ;
2005-12-04 20:35:38 +00:00
}
2007-03-26 19:20:00 +00:00
host_len = strlen ( resource - > host ) ;
if ( zend_hash_find ( & ( PHAR_GLOBALS - > phar_plain_map ) , resource - > host , host_len + 1 , ( void * * ) & plain_map ) = = SUCCESS ) {
spprintf ( & internal_file , 0 , " %s%s " , plain_map , resource - > path ) ;
retval = php_stream_stat_path_ex ( internal_file , flags , ssb , context ) ;
if ( retval = = - 1 ) {
php_stream_wrapper_log_error ( wrapper , 0 /* TODO:options */ TSRMLS_CC , " phar error: file \" %s \" extracted from \" %s \" could not be opened " , internal_file , resource - > host ) ;
}
php_url_free ( resource ) ;
efree ( internal_file ) ;
return retval ;
}
2005-12-04 20:35:38 +00:00
internal_file = resource - > path + 1 ; /* strip leading "/" */
2006-01-01 20:40:43 +00:00
/* find the phar in our trusty global hash indexed by alias (host of phar://blah.phar/file.whatever) */
2007-01-29 06:02:19 +00:00
if ( FAILURE = = phar_get_archive ( & phar , resource - > host , strlen ( resource - > host ) , NULL , 0 , & error TSRMLS_CC ) ) {
php_url_free ( resource ) ;
if ( error ) {
php_stream_wrapper_log_error ( wrapper , flags TSRMLS_CC , error ) ;
efree ( error ) ;
2007-01-03 15:43:07 +00:00
}
2007-01-29 06:02:19 +00:00
return 0 ;
}
if ( error ) {
efree ( error ) ;
}
if ( * internal_file = = ' \0 ' ) {
/* root directory requested */
phar_dostat ( phar , NULL , ssb , 1 , phar - > alias , phar - > alias_len TSRMLS_CC ) ;
php_url_free ( resource ) ;
return 0 ;
}
if ( ! phar - > manifest . arBuckets ) {
php_url_free ( resource ) ;
return 0 ;
}
/* search through the manifest of files, and if we have an exact match, it's a file */
if ( SUCCESS = = zend_hash_find ( & phar - > manifest , internal_file , strlen ( internal_file ) , ( void * * ) & entry ) ) {
phar_dostat ( phar , entry , ssb , 0 , phar - > alias , phar - > alias_len TSRMLS_CC ) ;
} else {
/* search for directory (partial match of a file) */
zend_hash_internal_pointer_reset ( & phar - > manifest ) ;
while ( FAILURE ! = zend_hash_has_more_elements ( & phar - > manifest ) ) {
if ( HASH_KEY_NON_EXISTANT ! =
zend_hash_get_current_key_ex (
& phar - > manifest , & key , & keylen , & unused , 0 , NULL ) ) {
if ( 0 = = memcmp ( internal_file , key , strlen ( internal_file ) ) ) {
/* directory found, all dirs have the same stat */
if ( key [ strlen ( internal_file ) ] = = ' / ' ) {
phar_dostat ( phar , NULL , ssb , 1 , phar - > alias , phar - > alias_len TSRMLS_CC ) ;
break ;
2005-12-04 20:35:38 +00:00
}
}
2007-01-29 06:02:19 +00:00
}
if ( SUCCESS ! = zend_hash_move_forward ( & phar - > manifest ) ) {
break ;
2005-12-04 20:35:38 +00:00
}
}
}
php_url_free ( resource ) ;
return 0 ;
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-04 20:35:38 +00:00
2007-01-02 00:04:30 +00:00
/**
* add an empty element with a char * key to a hash table , avoiding duplicates
*
* This is used to get a unique listing of virtual directories within a phar ,
* for iterating over opendir ( ) ed phar directories .
*/
2006-01-03 15:59:07 +00:00
static int phar_add_empty ( HashTable * ht , char * arKey , uint nKeyLength ) /* { { { */
2005-12-05 08:31:05 +00:00
{
void * dummy = ( void * ) 1 ;
return zend_hash_update ( ht , arKey , nKeyLength , & dummy , sizeof ( void * ) , NULL ) ;
}
2006-01-03 15:59:07 +00:00
/* }}} */
2005-12-05 08:31:05 +00:00
2007-01-02 00:04:30 +00:00
/**
* Used for sorting directories alphabetically
*/
2007-01-08 19:30:52 +00:00
static int phar_compare_dir_name ( const void * a , const void * b TSRMLS_DC ) /* { { { */
2006-01-01 20:16:09 +00:00
{
Bucket * f ;
Bucket * s ;
int result ;
f = * ( ( Bucket * * ) a ) ;
s = * ( ( Bucket * * ) b ) ;
2006-02-28 01:36:30 +00:00
# if (PHP_MAJOR_VERSION < 6)
result = zend_binary_strcmp ( f - > arKey , f - > nKeyLength , s - > arKey , s - > nKeyLength ) ;
# else
result = zend_binary_strcmp ( f - > key . arKey . s , f - > nKeyLength , s - > key . arKey . s , s - > nKeyLength ) ;
# endif
2006-01-01 20:16:09 +00:00
if ( result < 0 ) {
return - 1 ;
} else if ( result > 0 ) {
return 1 ;
} else {
return 0 ;
}
}
2006-01-03 15:59:07 +00:00
/* }}} */
2006-01-01 20:16:09 +00:00
2007-01-02 00:04:30 +00:00
/**
* Create a opendir ( ) directory stream handle by iterating over each of the
* files in a phar and retrieving its relative path . From this , construct
* a list of files / directories that are " in " the directory represented by dir
*/
2006-01-03 15:59:07 +00:00
static php_stream * phar_make_dirstream ( char * dir , HashTable * manifest TSRMLS_DC ) /* { { { */
2005-12-04 20:35:38 +00:00
{
2005-12-05 08:31:05 +00:00
HashTable * data ;
2005-12-04 20:35:38 +00:00
int dirlen = strlen ( dir ) ;
char * save , * found , * key ;
uint keylen ;
ulong unused ;
2005-12-05 08:31:05 +00:00
char * entry ;
ALLOC_HASHTABLE ( data ) ;
zend_hash_init ( data , 64 , zend_get_hash_value , NULL , 0 ) ;
2005-12-04 20:35:38 +00:00
2007-01-28 05:40:18 +00:00
if ( * dir = = ' / ' & & dirlen = = 1 & & ( manifest - > nNumOfElements = = 0 ) ) {
2007-02-04 20:35:59 +00:00
/* make empty root directory for empty phar */
2007-01-28 05:40:18 +00:00
efree ( dir ) ;
return php_stream_alloc ( & phar_dir_ops , data , NULL , " r " ) ;
}
2005-12-04 20:35:38 +00:00
zend_hash_internal_pointer_reset ( manifest ) ;
2006-01-11 01:51:47 +00:00
while ( FAILURE ! = zend_hash_has_more_elements ( manifest ) ) {
2005-12-05 08:31:05 +00:00
if ( HASH_KEY_NON_EXISTANT = = zend_hash_get_current_key_ex ( manifest , & key , & keylen , & unused , 0 , NULL ) ) {
2005-12-11 08:14:44 +00:00
break ;
2005-12-04 20:35:38 +00:00
}
if ( * dir = = ' / ' ) {
2005-12-11 08:14:44 +00:00
/* root directory */
2005-12-05 08:31:05 +00:00
if ( NULL ! = ( found = ( char * ) memchr ( key , ' / ' , keylen ) ) ) {
2005-12-08 07:38:44 +00:00
/* the entry has a path separator and is a subdirectory */
2007-02-05 20:34:23 +00:00
entry = ( char * ) safe_emalloc ( found - key , 1 , 1 ) ;
2005-12-11 08:14:44 +00:00
memcpy ( entry , key , found - key ) ;
keylen = found - key ;
entry [ keylen ] = ' \0 ' ;
} else {
2007-02-05 20:34:23 +00:00
entry = ( char * ) safe_emalloc ( keylen , 1 , 1 ) ;
2005-12-11 08:14:44 +00:00
memcpy ( entry , key , keylen ) ;
entry [ keylen ] = ' \0 ' ;
2005-12-04 20:35:38 +00:00
}
2005-12-11 08:14:44 +00:00
goto PHAR_ADD_ENTRY ;
2005-12-04 20:35:38 +00:00
} else {
if ( 0 ! = memcmp ( key , dir , dirlen ) ) {
2005-12-08 07:38:44 +00:00
/* entry in directory not found */
2005-12-11 08:14:44 +00:00
if ( SUCCESS ! = zend_hash_move_forward ( manifest ) ) {
break ;
}
2005-12-04 20:35:38 +00:00
continue ;
2005-12-11 08:14:44 +00:00
} else {
if ( key [ dirlen ] ! = ' / ' ) {
if ( SUCCESS ! = zend_hash_move_forward ( manifest ) ) {
break ;
}
continue ;
}
2005-12-04 20:35:38 +00:00
}
}
save = key ;
2005-12-08 07:38:44 +00:00
save + = dirlen + 1 ; /* seek to just past the path separator */
2005-12-04 20:35:38 +00:00
if ( NULL ! = ( found = ( char * ) memchr ( save , ' / ' , keylen - dirlen - 1 ) ) ) {
2005-12-08 07:38:44 +00:00
/* is subdirectory */
2005-12-05 08:31:05 +00:00
save - = dirlen + 1 ;
2007-02-05 20:34:23 +00:00
entry = ( char * ) safe_emalloc ( found - save + dirlen , 1 , 1 ) ;
2005-12-11 08:14:44 +00:00
memcpy ( entry , save + dirlen + 1 , found - save - dirlen - 1 ) ;
keylen = found - save - dirlen - 1 ;
entry [ keylen ] = ' \0 ' ;
2005-12-04 20:35:38 +00:00
} else {
2005-12-08 07:38:44 +00:00
/* is file */
2005-12-05 08:31:05 +00:00
save - = dirlen + 1 ;
2007-02-05 20:34:23 +00:00
entry = ( char * ) safe_emalloc ( keylen - dirlen , 1 , 1 ) ;
2005-12-11 08:14:44 +00:00
memcpy ( entry , save + dirlen + 1 , keylen - dirlen - 1 ) ;
entry [ keylen - dirlen - 1 ] = ' \0 ' ;
keylen = keylen - dirlen - 1 ;
2005-12-04 20:35:38 +00:00
}
2005-12-11 08:14:44 +00:00
PHAR_ADD_ENTRY :
2005-12-05 08:31:05 +00:00
phar_add_empty ( data , entry , keylen ) ;
efree ( entry ) ;
2005-12-11 08:14:44 +00:00
if ( SUCCESS ! = zend_hash_move_forward ( manifest ) ) {
break ;
}
}
2006-01-11 01:51:47 +00:00
if ( FAILURE ! = zend_hash_has_more_elements ( data ) ) {
2005-12-11 08:14:44 +00:00
efree ( dir ) ;
2007-01-08 19:30:52 +00:00
if ( zend_hash_sort ( data , zend_qsort , phar_compare_dir_name , 0 TSRMLS_CC ) = = FAILURE ) {
2006-01-01 20:16:09 +00:00
FREE_HASHTABLE ( data ) ;
return NULL ;
}
2005-12-11 08:14:44 +00:00
return php_stream_alloc ( & phar_dir_ops , data , NULL , " r " ) ;
} else {
efree ( dir ) ;
FREE_HASHTABLE ( data ) ;
return NULL ;
2005-12-04 20:35:38 +00:00
}
}
2006-01-03 15:59:07 +00:00
/* }}}*/
2005-12-04 20:35:38 +00:00
2007-03-26 19:20:00 +00:00
# if defined(PHP_VERSION_ID) && PHP_VERSION_ID < 50300
static int _php_stream_unlink ( char * url , int options , php_stream_context * context TSRMLS_DC )
{
php_stream_wrapper * wrapper = php_stream_locate_url_wrapper ( url , NULL , options TSRMLS_CC ) ;
if ( ! wrapper | | ! wrapper - > wops ) {
return 0 ;
}
if ( ! wrapper - > wops - > unlink ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " %s does not allow unlinking " , wrapper - > wops - > label ? wrapper - > wops - > label : " Wrapper " ) ;
return 0 ;
}
return wrapper - > wops - > unlink ( wrapper , url , ENFORCE_SAFE_MODE | REPORT_ERRORS , context TSRMLS_CC ) ;
}
# define php_stream_unlink(url, options, context) _php_stream_unlink((url), (options), (context) TSRMLS_CC)
# endif
2007-01-03 15:53:29 +00:00
/**
* Unlink a file within a phar archive
*/
2007-01-08 19:30:52 +00:00
static int phar_wrapper_unlink ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC ) /* { { { */
2007-01-03 15:53:29 +00:00
{
php_url * resource ;
2007-03-26 19:20:00 +00:00
char * internal_file , * error , * plain_map ;
2007-01-03 15:53:29 +00:00
phar_entry_data * idata ;
2007-03-26 19:20:00 +00:00
uint host_len ;
int retval ;
2007-01-28 22:43:38 +00:00
2007-01-03 15:53:29 +00:00
resource = php_url_parse ( url ) ;
if ( ! resource & & ( resource = phar_open_url ( wrapper , url , " rb " , options TSRMLS_CC ) ) = = NULL ) {
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-03 15:53:29 +00:00
}
/* we must have at the very least phar://alias.phar/internalfile.php */
if ( ! resource - > scheme | | ! resource - > host | | ! resource - > path ) {
php_url_free ( resource ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" " , url ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-03 15:53:29 +00:00
}
if ( strcasecmp ( " phar " , resource - > scheme ) ) {
php_url_free ( resource ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: not a phar stream url \" %s \" " , url ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
}
host_len = strlen ( resource - > host ) ;
if ( zend_hash_find ( & ( PHAR_GLOBALS - > phar_plain_map ) , resource - > host , host_len + 1 , ( void * * ) & plain_map ) = = SUCCESS ) {
spprintf ( & internal_file , 0 , " %s%s " , plain_map , resource - > path ) ;
retval = php_stream_unlink ( internal_file , options , context ) ;
if ( ! retval ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: file \" %s \" extracted from \" %s \" could not be opened " , internal_file , resource - > host ) ;
}
php_url_free ( resource ) ;
efree ( internal_file ) ;
return retval ;
2007-01-03 15:53:29 +00:00
}
2007-01-07 16:01:35 +00:00
if ( PHAR_G ( readonly ) ) {
2007-01-07 18:35:48 +00:00
php_url_free ( resource ) ;
2007-01-07 16:01:35 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: write operations disabled by INI setting " ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-07 16:01:35 +00:00
}
2007-01-28 22:43:38 +00:00
2007-01-07 18:35:48 +00:00
/* need to copy to strip leading "/", will get touched again */
2007-01-03 15:53:29 +00:00
internal_file = estrdup ( resource - > path + 1 ) ;
2007-01-27 18:27:19 +00:00
if ( FAILURE = = phar_get_entry_data ( & idata , resource - > host , strlen ( resource - > host ) , internal_file , strlen ( internal_file ) , " r " , & error TSRMLS_CC ) ) {
2007-01-26 14:52:10 +00:00
/* constraints of fp refcount were not met */
2007-01-27 21:23:02 +00:00
if ( error ) {
2007-01-27 18:27:19 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
2007-01-27 21:23:02 +00:00
efree ( error ) ;
2007-01-27 18:27:19 +00:00
}
2007-01-26 14:52:10 +00:00
efree ( internal_file ) ;
php_url_free ( resource ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-26 14:52:10 +00:00
}
2007-01-28 03:25:53 +00:00
if ( error ) {
efree ( error ) ;
}
2007-01-26 14:52:10 +00:00
if ( ! idata ) {
2007-01-03 15:53:29 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" is not a file in phar \" %s \" , cannot unlink " , internal_file , resource - > host ) ;
efree ( internal_file ) ;
php_url_free ( resource ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-03 15:53:29 +00:00
}
2007-01-27 15:31:24 +00:00
if ( idata - > internal_file - > fp_refcount > 1 ) {
2007-01-26 14:52:10 +00:00
/* more than just our fp resource is open for this file */
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" in phar \" %s \" , has open file pointers, cannot unlink " , internal_file , resource - > host ) ;
efree ( internal_file ) ;
php_url_free ( resource ) ;
2007-01-27 15:31:24 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-26 14:52:10 +00:00
}
2007-01-27 18:27:19 +00:00
php_url_free ( resource ) ;
2007-01-07 18:35:48 +00:00
efree ( internal_file ) ;
2007-01-29 06:02:19 +00:00
phar_entry_remove ( idata , & error TSRMLS_CC ) ;
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
}
2007-03-26 19:20:00 +00:00
return 1 ;
2007-01-03 15:53:29 +00:00
}
/* }}} */
2007-01-28 22:43:38 +00:00
static int phar_wrapper_rename ( php_stream_wrapper * wrapper , char * url_from , char * url_to , int options , php_stream_context * context TSRMLS_DC ) /* { { { */
{
php_url * resource_from , * resource_to ;
char * from_file , * to_file ;
char * error ;
phar_entry_data * fromdata , * todata ;
if ( PHAR_G ( readonly ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: write operations disabled by INI setting " ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
resource_from = php_url_parse ( url_from ) ;
resource_to = php_url_parse ( url_from ) ;
if ( ! resource_from & & ( resource_from = phar_open_url ( wrapper , url_from , " r+b " , options TSRMLS_CC ) ) = = NULL ) {
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( ! resource_to & & ( resource_to = phar_open_url ( wrapper , url_to , " wb " , options TSRMLS_CC ) ) = = NULL ) {
php_url_free ( resource_from ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
/* we must have at the very least phar://alias.phar/internalfile.php */
if ( ! resource_from - > scheme | | ! resource_from - > host | | ! resource_from - > path ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" " , url_from ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( ! resource_to - > scheme | | ! resource_to - > host | | ! resource_to - > path ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" " , url_to ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( strcasecmp ( " phar " , resource_from - > scheme ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: not a phar stream url \" %s \" " , url_from ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( strcasecmp ( " phar " , resource_to - > scheme ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: not a phar stream url \" %s \" " , url_to ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
2007-03-26 19:20:00 +00:00
/*TODO: handle extract_list */
2007-01-28 22:43:38 +00:00
if ( strcmp ( resource_from - > host , resource_to - > host ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: cannot rename \" %s \" to \" %s \" , not within the same phar archive " , url_from , url_to ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
/* need to copy to strip leading "/", will get touched again */
from_file = estrdup ( resource_from - > path + 1 ) ;
to_file = estrdup ( resource_to - > path + 1 ) ;
if ( FAILURE = = phar_get_entry_data ( & fromdata , resource_from - > host , strlen ( resource_from - > host ) , from_file , strlen ( from_file ) , " r " , & error TSRMLS_CC ) ) {
/* constraints of fp refcount were not met */
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
}
efree ( from_file ) ;
efree ( to_file ) ;
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( error ) {
efree ( error ) ;
}
if ( ! fromdata ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" is not a file in phar \" %s \" , cannot rename " , from_file , resource_from - > host ) ;
efree ( from_file ) ;
efree ( to_file ) ;
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( ! ( todata = phar_get_or_create_entry_data ( resource_to - > host , strlen ( resource_to - > host ) , to_file , strlen ( to_file ) , " w " , & error TSRMLS_CC ) ) ) {
/* constraints of fp refcount were not met */
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
}
efree ( from_file ) ;
efree ( to_file ) ;
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( error ) {
efree ( error ) ;
}
if ( fromdata - > internal_file - > fp_refcount > 1 ) {
/* more than just our fp resource is open for this file */
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" in phar \" %s \" , has open file pointers, cannot rename " , from_file , resource_from - > host ) ;
efree ( from_file ) ;
efree ( to_file ) ;
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
phar_entry_delref ( fromdata TSRMLS_CC ) ;
phar_entry_delref ( todata TSRMLS_CC ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
if ( todata - > internal_file - > fp_refcount > 1 ) {
/* more than just our fp resource is open for this file */
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" in phar \" %s \" , has open file pointers, cannot rename " , to_file , resource_to - > host ) ;
efree ( from_file ) ;
efree ( to_file ) ;
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
phar_entry_delref ( fromdata TSRMLS_CC ) ;
phar_entry_delref ( todata TSRMLS_CC ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
php_stream_seek ( fromdata - > internal_file - > fp , 0 , SEEK_SET ) ;
if ( fromdata - > internal_file - > uncompressed_filesize ! = php_stream_copy_to_stream ( fromdata - > internal_file - > fp , todata - > internal_file - > fp , PHP_STREAM_COPY_ALL ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: rename failed \" %s \" to \" %s \" " , url_from , url_to ) ;
efree ( from_file ) ;
efree ( to_file ) ;
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
phar_entry_delref ( fromdata TSRMLS_CC ) ;
phar_entry_delref ( todata TSRMLS_CC ) ;
2007-03-26 19:20:00 +00:00
return 0 ;
2007-01-28 22:43:38 +00:00
}
phar_entry_delref ( fromdata TSRMLS_CC ) ;
phar_entry_delref ( todata TSRMLS_CC ) ;
efree ( from_file ) ;
efree ( to_file ) ;
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
phar_wrapper_unlink ( wrapper , url_from , 0 , 0 TSRMLS_CC ) ;
2007-03-26 19:20:00 +00:00
return 1 ;
2007-01-28 22:43:38 +00:00
}
/* }}} */
2007-01-02 00:04:30 +00:00
/**
* Open a directory handle within a phar archive
*/
2007-01-08 19:30:52 +00:00
static php_stream * phar_wrapper_open_dir ( php_stream_wrapper * wrapper , char * path , char * mode ,
2006-01-03 15:59:07 +00:00
int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC ) /* {{{ */
2005-12-04 20:35:38 +00:00
{
php_url * resource = NULL ;
php_stream * ret ;
2007-03-26 19:20:00 +00:00
char * internal_file , * key , * error , * plain_map ;
2005-12-04 20:35:38 +00:00
uint keylen ;
ulong unused ;
2006-03-04 02:12:22 +00:00
phar_archive_data * phar ;
2006-02-28 01:36:30 +00:00
phar_entry_info * entry ;
2007-03-26 19:20:00 +00:00
uint host_len ;
2005-12-04 20:35:38 +00:00
2007-01-08 19:30:52 +00:00
resource = php_url_parse ( path ) ;
2006-01-04 02:26:15 +00:00
2007-01-08 19:30:52 +00:00
if ( ! resource & & ( resource = phar_open_url ( wrapper , path , mode , options TSRMLS_CC ) ) = = NULL ) {
2006-01-04 02:26:15 +00:00
return NULL ;
}
2006-01-01 20:40:43 +00:00
/* we must have at the very least phar://alias.phar/ */
2006-02-28 01:36:30 +00:00
if ( ! resource - > scheme | | ! resource - > host | | ! resource - > path ) {
if ( resource - > host & & ! resource - > path ) {
2007-02-03 04:04:18 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: no directory in \" %s \" , must have at least phar://%s/ for root directory (always use full path to a new phar) " , path , resource - > host ) ;
2005-12-11 07:25:30 +00:00
php_url_free ( resource ) ;
return NULL ;
}
2006-02-28 01:36:30 +00:00
php_url_free ( resource ) ;
2007-01-08 19:30:52 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" , must have at least phar://%s/ " , path , path ) ;
2005-12-07 06:39:03 +00:00
return NULL ;
2005-12-04 20:35:38 +00:00
}
if ( strcasecmp ( " phar " , resource - > scheme ) ) {
2005-12-07 06:39:03 +00:00
php_url_free ( resource ) ;
2007-01-08 19:30:52 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: not a phar url \" %s \" " , path ) ;
2005-12-07 06:39:03 +00:00
return NULL ;
2005-12-04 20:35:38 +00:00
}
2007-03-26 19:20:00 +00:00
host_len = strlen ( resource - > host ) ;
if ( zend_hash_find ( & ( PHAR_GLOBALS - > phar_plain_map ) , resource - > host , host_len + 1 , ( void * * ) & plain_map ) = = SUCCESS ) {
spprintf ( & internal_file , 0 , " %s%s " , plain_map , resource - > path ) ;
ret = php_stream_opendir ( internal_file , options , context ) ;
if ( ! ret ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: file \" %s \" extracted from \" %s \" could not be opened " , internal_file , resource - > host ) ;
}
php_url_free ( resource ) ;
efree ( internal_file ) ;
return ret ;
}
2005-12-04 20:35:38 +00:00
internal_file = resource - > path + 1 ; /* strip leading "/" */
2007-03-26 19:20:00 +00:00
if ( FAILURE = = phar_get_archive ( & phar , resource - > host , host_len , NULL , 0 , & error TSRMLS_CC ) ) {
2007-01-29 06:02:19 +00:00
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
2007-01-03 15:43:07 +00:00
}
2007-01-29 06:02:19 +00:00
php_url_free ( resource ) ;
return NULL ;
}
if ( error ) {
efree ( error ) ;
}
if ( * internal_file = = ' \0 ' ) {
/* root directory requested */
internal_file = estrndup ( internal_file - 1 , 1 ) ;
ret = phar_make_dirstream ( internal_file , & phar - > manifest TSRMLS_CC ) ;
php_url_free ( resource ) ;
return ret ;
}
if ( ! phar - > manifest . arBuckets ) {
php_url_free ( resource ) ;
return NULL ;
}
if ( SUCCESS = = zend_hash_find ( & phar - > manifest , internal_file , strlen ( internal_file ) , ( void * * ) & entry ) ) {
php_url_free ( resource ) ;
return NULL ;
} else {
/* search for directory */
zend_hash_internal_pointer_reset ( & phar - > manifest ) ;
while ( FAILURE ! = zend_hash_has_more_elements ( & phar - > manifest ) ) {
if ( HASH_KEY_NON_EXISTANT ! =
zend_hash_get_current_key_ex (
& phar - > manifest , & key , & keylen , & unused , 0 , NULL ) ) {
if ( 0 = = memcmp ( key , internal_file , strlen ( internal_file ) ) ) {
/* directory found */
internal_file = estrndup ( internal_file ,
strlen ( internal_file ) ) ;
php_url_free ( resource ) ;
return phar_make_dirstream ( internal_file , & phar - > manifest TSRMLS_CC ) ;
2005-12-11 08:14:44 +00:00
}
2005-12-04 20:35:38 +00:00
}
2007-01-29 06:02:19 +00:00
if ( SUCCESS ! = zend_hash_move_forward ( & phar - > manifest ) ) {
break ;
}
2005-12-04 20:35:38 +00:00
}
}
php_url_free ( resource ) ;
return NULL ;
}
2006-01-03 15:59:07 +00:00
/* }}} */
2006-01-03 15:50:46 +00: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 [ ] = {
2007-01-21 15:25:50 +00:00
{ NULL , NULL , NULL } /* Must be the last line in phar_functions[] */
2006-02-28 01:36:30 +00:00
} ;
2007-01-23 23:31:14 +00:00
/* }}}*/
2006-01-03 15:50:46 +00:00
/* {{{ php_phar_init_globals
*/
static void php_phar_init_globals_module ( zend_phar_globals * phar_globals )
{
memset ( phar_globals , 0 , sizeof ( zend_phar_globals ) ) ;
2007-01-07 16:01:35 +00:00
phar_globals - > readonly = 1 ;
2006-01-03 15:50:46 +00:00
}
/* }}} */
2006-03-08 00:56:31 +00:00
PHP_MINIT_FUNCTION ( phar ) /* {{{ */
2006-01-03 15:50:46 +00:00
{
ZEND_INIT_MODULE_GLOBALS ( phar , php_phar_init_globals_module , NULL ) ;
2007-01-07 16:01:35 +00:00
REGISTER_INI_ENTRIES ( ) ;
2006-01-03 15:50:46 +00:00
2007-01-21 15:25:50 +00:00
phar_object_init ( TSRMLS_C ) ;
2006-01-04 02:26:15 +00:00
2006-01-03 15:50:46 +00:00
return php_register_url_stream_wrapper ( " phar " , & php_stream_phar_wrapper TSRMLS_CC ) ;
}
/* }}} */
2006-03-08 00:56:31 +00:00
PHP_MSHUTDOWN_FUNCTION ( phar ) /* {{{ */
2006-01-03 15:50:46 +00:00
{
return php_unregister_url_stream_wrapper ( " phar " TSRMLS_CC ) ;
}
/* }}} */
2006-03-08 00:56:31 +00:00
PHP_RINIT_FUNCTION ( phar ) /* {{{ */
2006-01-03 15:50:46 +00:00
{
2007-01-27 15:31:24 +00:00
PHAR_GLOBALS - > request_done = 0 ;
2007-01-09 02:27:12 +00:00
zend_hash_init ( & ( PHAR_GLOBALS - > phar_fname_map ) , sizeof ( phar_archive_data * ) , zend_get_hash_value , destroy_phar_data , 0 ) ;
2006-03-04 02:12:22 +00:00
zend_hash_init ( & ( PHAR_GLOBALS - > phar_alias_map ) , sizeof ( phar_archive_data * ) , zend_get_hash_value , NULL , 0 ) ;
2007-03-25 19:03:38 +00:00
zend_hash_init ( & ( PHAR_GLOBALS - > phar_plain_map ) , sizeof ( const char * ) , zend_get_hash_value , NULL , 0 ) ;
phar_split_extract_list ( TSRMLS_C ) ;
2006-01-03 15:50:46 +00:00
return SUCCESS ;
}
/* }}} */
2006-03-08 00:56:31 +00:00
PHP_RSHUTDOWN_FUNCTION ( phar ) /* {{{ */
2006-01-03 15:50:46 +00:00
{
2006-01-11 21:19:46 +00:00
zend_hash_destroy ( & ( PHAR_GLOBALS - > phar_alias_map ) ) ;
2007-03-25 19:03:38 +00:00
PHAR_GLOBALS - > phar_fname_map . pDestructor = destroy_phar_data_only ;
2006-01-11 21:19:46 +00:00
zend_hash_destroy ( & ( PHAR_GLOBALS - > phar_fname_map ) ) ;
2007-03-25 19:03:38 +00:00
zend_hash_destroy ( & ( PHAR_GLOBALS - > phar_plain_map ) ) ;
2007-01-27 15:31:24 +00:00
PHAR_GLOBALS - > request_done = 1 ;
2006-01-03 15:50:46 +00:00
return SUCCESS ;
}
/* }}} */
2006-03-08 00:56:31 +00:00
PHP_MINFO_FUNCTION ( phar ) /* {{{ */
2006-01-03 15:50:46 +00:00
{
php_info_print_table_start ( ) ;
2006-01-12 21:16:29 +00:00
php_info_print_table_header ( 2 , " Phar: PHP Archive support " , " enabled " ) ;
2007-02-03 13:20:12 +00:00
php_info_print_table_row ( 2 , " Phar EXT version " , PHAR_EXT_VERSION_STR ) ;
php_info_print_table_row ( 2 , " Phar API version " , PHAR_API_VERSION_STR ) ;
2006-01-03 15:50:46 +00:00
php_info_print_table_row ( 2 , " CVS revision " , " $Revision$ " ) ;
2006-01-12 21:16:29 +00:00
php_info_print_table_row ( 2 , " gzip compression " ,
2006-01-11 23:55:57 +00:00
# if HAVE_ZLIB
2006-01-03 15:50:46 +00:00
" enabled " ) ;
# else
" disabled " ) ;
2006-01-12 21:16:29 +00:00
# endif
php_info_print_table_row ( 2 , " bzip2 compression " ,
# if HAVE_BZ2
" enabled " ) ;
# else
" disabled " ) ;
2006-01-03 15:50:46 +00:00
# endif
php_info_print_table_end ( ) ;
2007-03-25 19:03:38 +00:00
php_info_print_box_start ( 0 ) ;
PUTS ( " Phar based on pear/PHP_Archive, original concept by Davey Shafik. " ) ;
PUTS ( ! sapi_module . phpinfo_as_text ? " <br /> " : " \n " ) ;
PUTS ( " Phar fully realized by Gregory Beaver and Marcus Boerger. " ) ;
php_info_print_box_end ( ) ;
2007-01-07 16:01:35 +00:00
DISPLAY_INI_ENTRIES ( ) ;
2006-01-03 15:50:46 +00:00
}
/* }}} */
/* {{{ phar_module_entry
*/
2006-01-12 21:16:29 +00:00
static zend_module_dep phar_deps [ ] = {
# if HAVE_ZLIB
ZEND_MOD_REQUIRED ( " zlib " )
# endif
# if HAVE_BZ2
ZEND_MOD_REQUIRED ( " bz2 " )
2006-01-03 15:50:46 +00:00
# endif
2007-01-21 15:25:50 +00:00
# if HAVE_SPL
2006-02-28 01:36:30 +00:00
ZEND_MOD_REQUIRED ( " spl " )
2007-01-21 15:25:50 +00:00
# endif
2006-01-12 21:16:29 +00:00
{ NULL , NULL , NULL }
} ;
zend_module_entry phar_module_entry = {
STANDARD_MODULE_HEADER_EX , NULL ,
phar_deps ,
2006-01-04 02:26:15 +00:00
" Phar " ,
2006-01-03 15:50:46 +00:00
phar_functions ,
PHP_MINIT ( phar ) ,
PHP_MSHUTDOWN ( phar ) ,
PHP_RINIT ( phar ) ,
PHP_RSHUTDOWN ( phar ) ,
PHP_MINFO ( phar ) ,
2007-02-03 13:20:12 +00:00
PHAR_EXT_VERSION_STR ,
2006-01-03 15:50:46 +00:00
STANDARD_MODULE_PROPERTIES
} ;
/* }}} */
2005-12-04 20:35:38 +00: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
*/