Browse Source

- Fix a memleak

- Fix uninitialized mem access
- Fix/improve error handling
- Add INI entry phar.readonly
- Add tests
migration/RELEASE_1_0_0
Marcus Boerger 20 years ago
parent
commit
0d8ec844d6
  1. 119
      ext/phar/phar.c
  2. 2
      ext/phar/tests/create_new_phar.phpt
  3. 28
      ext/phar/tests/create_new_phar_b.phpt
  4. 9
      ext/phar/tests/delete_in_phar.phpt
  5. 56
      ext/phar/tests/delete_in_phar_b.phpt
  6. 2
      ext/phar/tests/open_for_write_existing.phpt
  7. 43
      ext/phar/tests/open_for_write_existing_b.phpt
  8. 2
      ext/phar/tests/open_for_write_newfile.phpt
  9. 53
      ext/phar/tests/open_for_write_newfile_b.phpt
  10. 2
      ext/phar/tests/phar_oo_011.phpt
  11. 37
      ext/phar/tests/phar_oo_011b.phpt
  12. 2
      ext/phar/tests/phar_oo_012.phpt
  13. 39
      ext/phar/tests/phar_oo_012b.phpt

119
ext/phar/phar.c

@ -81,10 +81,15 @@
ZEND_BEGIN_MODULE_GLOBALS(phar)
HashTable phar_fname_map;
HashTable phar_alias_map;
int readonly;
ZEND_END_MODULE_GLOBALS(phar)
ZEND_DECLARE_MODULE_GLOBALS(phar)
PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("phar.readonly", "1", PHP_INI_SYSTEM, OnUpdateBool, readonly, zend_phar_globals, phar_globals)
PHP_INI_END()
#ifndef php_uint16
# if SIZEOF_SHORT == 2
# define php_uint16 unsigned short
@ -157,7 +162,7 @@ union _phar_entry_object {
};
/* {{{ forward declarations */
static int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar TSRMLS_DC);
static int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC);
static php_stream *php_stream_phar_url_wrapper(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
static int phar_close(php_stream *stream, int close_handle TSRMLS_DC);
@ -372,6 +377,7 @@ static phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len
if ((phar = phar_get_archive(fname, fname_len, NULL, 0 TSRMLS_CC)) == NULL) {
return NULL;
}
if (NULL != (ret = phar_get_entry_data(fname, fname_len, path, path_len TSRMLS_CC))) {
/* reset file size */
ret->internal_file->uncompressed_filesize = 0;
@ -379,6 +385,13 @@ static phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len
ret->internal_file->crc32 = 0;
return ret;
}
if (PHAR_G(readonly)) {
/*no need to issue an error here */
/*php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "phar error: write operations disabled by INI setting");*/
return NULL;
}
/* create a new phar data holder */
ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
if ((entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC)) == NULL) {
@ -437,6 +450,14 @@ PHP_METHOD(Phar, canCompress)
}
/* }}} */
/* {{{ proto bool canWrite()
* Returns whether phar extension supports writing and creating phars */
PHP_METHOD(Phar, canWrite)
{
RETURN_BOOL(PHAR_G(readonly));
}
/* }}} */
#define MAPPHAR_ALLOC_FAIL(msg) \
php_stream_close(fp);\
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, msg, fname);\
@ -698,7 +719,7 @@ static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alia
/**
* Create or open a phar for writing
*/
static int phar_create_or_open_filename(char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
static int phar_create_or_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
{
phar_archive_data *mydata;
int register_alias;
@ -711,7 +732,9 @@ static int phar_create_or_open_filename(char *fname, int fname_len, char *alias,
if ((phar = phar_get_archive(fname, fname_len, alias, alias_len TSRMLS_CC)) != NULL) {
if (fname_len != phar->fname_len || strncmp(fname, phar->fname, fname_len)) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, phar->fname, fname);
if (options & REPORT_ERRORS) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, phar->fname, fname);
}
return FAILURE;
} else {
if (pphar) {
@ -731,12 +754,19 @@ static int phar_create_or_open_filename(char *fname, int fname_len, char *alias,
return FAILURE;
}
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, NULL);
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL);
if (fp) {
/* open an existing phar */
php_stream_close(fp);
return phar_open_filename(fname, fname_len, alias, alias_len, pphar TSRMLS_CC);
return phar_open_filename(fname, fname_len, alias, alias_len, options, pphar TSRMLS_CC);
}
if (PHAR_G(readonly)) {
if (options & REPORT_ERRORS) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "creating archive \"%s\" disabled by INI setting", fname);
}
return FAILURE;
}
/* set up our manifest */
mydata = emalloc(sizeof(phar_archive_data));
@ -749,6 +779,7 @@ static int phar_create_or_open_filename(char *fname, int fname_len, char *alias,
mydata->alias = alias ? estrndup(alias, alias_len) : mydata->fname;
mydata->alias_len = alias ? alias_len : fname_len;
snprintf(mydata->version, sizeof(mydata->version), "%s", PHAR_VERSION_STR);
mydata->explicit_alias = alias ? TRUE : FALSE;
mydata->internal_file_start = -1;
mydata->halt_offset = 0;
mydata->has_compressed_files = 0;
@ -774,7 +805,7 @@ static int phar_create_or_open_filename(char *fname, int fname_len, char *alias,
* that the manifest is proper, then pass it to phar_open_file(). SUCCESS
* or FAILURE is returned and pphar is set to a pointer to the phar's manifest
*/
static int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
static int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar TSRMLS_DC) /* {{{ */
{
const char token[] = "__HALT_COMPILER();";
char *pos, buffer[1024 + sizeof(token)];
@ -786,7 +817,9 @@ static int phar_open_filename(char *fname, int fname_len, char *alias, int alias
if ((phar = phar_get_archive(fname, fname_len, alias, alias_len TSRMLS_CC)) != NULL) {
if (fname_len != phar->fname_len || strncmp(fname, phar->fname, fname_len)) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, phar->fname, fname);
if (options & REPORT_ERRORS) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, phar->fname, fname);
}
return FAILURE;
} else {
if (pphar) {
@ -809,7 +842,9 @@ static int phar_open_filename(char *fname, int fname_len, char *alias, int alias
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, NULL);
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to open phar for reading \"%s\"", fname);
if (options & REPORT_ERRORS) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to open phar for reading \"%s\"", fname);
}
return FAILURE;
}
@ -929,13 +964,13 @@ static php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char
}
#endif
if (strcmp(mode, "wb") == 0 || strcmp(mode, "w") == 0) {
if (phar_create_or_open_filename(resource->host, arch_len, NULL, 0, NULL TSRMLS_CC) == FAILURE)
if (phar_create_or_open_filename(resource->host, arch_len, NULL, 0, options, NULL TSRMLS_CC) == FAILURE)
{
php_url_free(resource);
return NULL;
}
} else {
if (phar_open_filename(resource->host, arch_len, NULL, 0, NULL TSRMLS_CC) == FAILURE)
if (phar_open_filename(resource->host, arch_len, NULL, 0, options, NULL TSRMLS_CC) == FAILURE)
{
php_url_free(resource);
return NULL;
@ -1009,7 +1044,7 @@ PHP_METHOD(Phar, loadPhar)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &fname, &fname_len, &alias, &alias_len) == FAILURE) {
return;
}
RETURN_BOOL(phar_open_filename(fname, fname_len, alias, alias_len, NULL TSRMLS_CC) == SUCCESS);
RETURN_BOOL(phar_open_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL TSRMLS_CC) == SUCCESS);
} /* }}} */
static php_stream_ops phar_ops = {
@ -1475,7 +1510,7 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
{
phar_entry_data *data = (phar_entry_data *)stream->abstract;
phar_entry_info *entry;
int alias_len, fname_len, halt_offset;
int alias_len, fname_len, halt_offset, restore_alias_len;
char *buffer, *fname, *alias;
char *manifest;
off_t manifest_ftell, bufsize;
@ -1485,6 +1520,9 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
php_stream *file, *newfile, *compressedfile;
php_stream_filter *filter;
if (PHAR_G(readonly)) {
return EOF;
}
if (strcmp(stream->mode, "wb") != 0 && strcmp(stream->mode, "w") != 0) {
return EOF;
}
@ -1500,16 +1538,20 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
if (data->phar->halt_offset != php_stream_copy_to_stream(data->fp, newfile, data->phar->halt_offset))
{
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to copy prologue of old phar to new phar \"%s\"", data->phar->fname);
return EOF;
}
} else {
/* this is a brand new phar */
data->phar->halt_offset = sizeof("<?php __HALT_COMPILER(); ?>");
if (sizeof("<?php __HALT_COMPILER(); ?>") != php_stream_write(newfile, "<?php __HALT_COMPILER(); ?>" ,sizeof("<?php __HALT_COMPILER(); ?>"))) {
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to create prologue in new phar \"%s\"", data->phar->fname);
return EOF;
}
}
manifest_ftell = php_stream_tell(newfile);
@ -1561,9 +1603,11 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_stream_close(compressedfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, data->phar->fname);
return EOF;
}
file = data->fp;
copy = entry->uncompressed_filesize;
@ -1578,6 +1622,7 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_stream_close(compressedfile);
if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
@ -1585,6 +1630,7 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
} else {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to bzip2 compress file \"%s\" to new phar \"%s\"", entry->filename, data->phar->fname);
}
return EOF;
}
php_stream_filter_append(&file->readfilters, filter);
if (bufsize < entry->uncompressed_filesize) {
@ -1611,7 +1657,9 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(entry->temp_file);
entry->temp_file = NULL;
php_stream_close(newfile);
php_stream_close(compressedfile);
if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
@ -1619,6 +1667,7 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
} else {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to bzip2 compress file \"%s\" to new phar \"%s\"", entry->filename, data->phar->fname);
}
return EOF;
}
file = entry->temp_file;
entry->compressed_filesize = copy;
@ -1631,6 +1680,7 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
/* 4: manifest length, 4: manifest entry count, 2: phar version,
4: alias length, the rest is the alias itself
*/
restore_alias_len = data->phar->alias_len;
if (data->phar->explicit_alias) {
manifest = (char *) emalloc(14 + data->phar->alias_len);
phar_set_32(manifest, offset + data->phar->alias_len + 10); /* manifest length */
@ -1644,8 +1694,6 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
phar_set_32(manifest+4, new_manifest_count);
phar_set_32(manifest+10, 0);
data->phar->alias_len = 0;
efree(data->phar->alias);
data->phar->alias = 0;
}
*(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF);
*(manifest + 9) = (unsigned char) ((PHAR_API_VERSION) & 0xFF);
@ -1655,9 +1703,13 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to write manifest meta-data of new phar \"%s\"", data->phar->fname);
data->phar->alias_len = restore_alias_len;
return EOF;
}
data->phar->alias_len = restore_alias_len;
/* re-calculate the manifest location to simplify later code */
manifest_ftell = php_stream_tell(newfile);
@ -1679,16 +1731,20 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", entry->filename, data->phar->fname);
return EOF;
}
if ((entry->flags & PHAR_ENT_MODIFIED) && !entry->temp_file) {
/* nothing to do here - error out*/
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "internal error - unable to write temporary manifest of modified file \"%s\" to manifest of new phar \"%s\" temporary file was not open (please report to Phar developers)", entry->filename, data->phar->fname);
return EOF;
}
/* set the manifest meta-data:
4: uncompressed filesize
@ -1707,8 +1763,10 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", entry->filename, data->phar->fname);
return EOF;
}
}
@ -1736,9 +1794,11 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_stream_close(compressedfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, data->phar->fname);
return EOF;
}
file = data->fp;
}
@ -1750,8 +1810,10 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to write contents of file \"%s\" to new phar \"%s\"", entry->filename, data->phar->fname);
return EOF;
}
/* close the temporary file, no longer needed */
if (entry->flags & PHAR_ENT_MODIFIED) {
@ -1772,8 +1834,10 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
efree(buffer);
efree(manifest);
php_stream_close(data->fp);
data->fp = NULL;
php_stream_close(newfile);
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to open new phar \"%s\" for writing", data->phar->fname);
return EOF;
}
php_stream_copy_to_stream(newfile, file, PHP_STREAM_COPY_ALL);
php_stream_close(newfile);
@ -1786,13 +1850,16 @@ static int phar_flush(php_stream *stream TSRMLS_DC) /* {{{ */
if (!file) {
php_stream_close(data->fp);
data->fp = NULL;
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to open new phar \"%s\" for reading", data->phar->fname);
return EOF;
}
if (-1 == php_stream_seek(file, data->phar->halt_offset, SEEK_SET)) {
php_stream_close(data->fp);
data->fp = NULL;
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "unable to seek to __HALT_COMPILER(); in new phar \"%s\"", data->phar->fname);
return EOF;
}
if (data->fp) {
@ -2146,6 +2213,11 @@ static int phar_unlink(php_stream_wrapper *wrapper, char *url, int options, php_
return FAILURE;
}
if (PHAR_G(readonly)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: write operations disabled by INI setting");
return FAILURE;
}
/* strip leading "/" */
internal_file = estrdup(resource->path + 1);
if (NULL == (idata = phar_get_entry_data(resource->host, strlen(resource->host), internal_file, strlen(internal_file) TSRMLS_CC))) {
@ -2271,7 +2343,7 @@ PHP_METHOD(Phar, __construct)
return;
}
if (phar_open_filename(fname, fname_len, alias, alias_len, &phar_data TSRMLS_CC) == FAILURE) {
if (phar_open_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, &phar_data TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Cannot open phar file '%s' with alias '%s'", fname, alias);
return;
@ -2400,6 +2472,11 @@ PHP_METHOD(Phar, offsetSet)
php_stream *fp;
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
return;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fname, &fname_len, &contents, &contents_len) == FAILURE) {
return;
}
@ -2410,7 +2487,6 @@ PHP_METHOD(Phar, offsetSet)
fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
fp = php_stream_open_wrapper(fname, "wb", STREAM_MUST_SEEK|REPORT_ERRORS, NULL);
if (contents_len != php_stream_write(fp, contents, contents_len)) {
php_stream_close(fp);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname);
}
php_stream_close(fp);
@ -2428,6 +2504,11 @@ PHP_METHOD(Phar, offsetUnset)
phar_entry_info *entry;
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
return;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
return;
}
@ -2478,7 +2559,7 @@ PHP_METHOD(PharFileInfo, __construct)
return;
}
if (phar_open_filename(arch, arch_len, NULL, 0, &phar_data TSRMLS_CC) == FAILURE) {
if (phar_open_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data TSRMLS_CC) == FAILURE) {
efree(arch);
efree(entry);
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
@ -2616,6 +2697,7 @@ zend_function_entry php_archive_methods[] = {
/* static member functions */
PHP_ME(Phar, apiVersion, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, canCompress, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, canWrite, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
{NULL, NULL, NULL}
@ -2642,6 +2724,7 @@ zend_function_entry php_entry_methods[] = {
static void php_phar_init_globals_module(zend_phar_globals *phar_globals)
{
memset(phar_globals, 0, sizeof(zend_phar_globals));
phar_globals->readonly = 1;
}
/* }}} */
@ -2650,6 +2733,7 @@ PHP_MINIT_FUNCTION(phar) /* {{{ */
zend_class_entry ce;
ZEND_INIT_MODULE_GLOBALS(phar, php_phar_init_globals_module, NULL);
REGISTER_INI_ENTRIES();
INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator, NULL TSRMLS_CC);
@ -2705,6 +2789,7 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */
#endif
php_info_print_table_row(1, "Phar based on pear/PHP_Archive, original concept by Davey Shafik and fully realized by Gregory Beaver");
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
/* }}} */

2
ext/phar/tests/create_new_phar.phpt

@ -2,6 +2,8 @@
Phar: create a completely new phar
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=0
--FILE--
<?php

28
ext/phar/tests/create_new_phar_b.phpt

@ -0,0 +1,28 @@
--TEST--
Phar: create a completely new phar
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=1
--FILE--
<?php
file_put_contents('phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/a.php',
'brand new!');
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/a.php';
?>
===DONE===
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECTF--
Warning: file_put_contents(phar://%screate_new_phar_b.phar.php/a.php): failed to open stream: No such file or directory in %screate_new_phar_b.php on line %d
Warning: include(%screate_new_phar_b.phar.php): failed to open stream: No such file or directory in %screate_new_phar_b.php on line %d
Warning: include(phar://%screate_new_phar_b.phar.php/a.php): failed to open stream: No such file or directory in %screate_new_phar_b.php on line %d
Warning: include(): Failed opening 'phar://%screate_new_phar_b.phar.php/a.php' for inclusion (include_path='.') in %screate_new_phar_b.php on line %d
===DONE===

9
ext/phar/tests/delete_in_phar.phpt

@ -2,6 +2,8 @@
Phar: delete a file within a .phar
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=0
--FILE--
<?php
$file = "<?php __HALT_COMPILER(); ?>";
@ -47,5 +49,10 @@ This is b/c
===AFTER===
This is a
This is b
Warning: include(%selete_in_phar.phpt.phar.php/b/c.php): failed to open stream: phar error: "b/c.php" is not a file in phar "%selete_in_phar.phpt.phar.php" in %selete_in_phar.phpt on line %d
Warning: include(%sdelete_in_phar.phar.php/b/c.php): failed to open stream: phar error: "b/c.php" is not a file in phar "%sdelete_in_phar.phar.php" in %sdelete_in_phar.php on line %d
Warning: include(): Failed opening 'phar://%sdelete_in_phar.phar.php/b/c.php' for inclusion (include_path='.') in %sdelete_in_phar.php on line %d
===DONE===

56
ext/phar/tests/delete_in_phar_b.phpt

@ -0,0 +1,56 @@
--TEST--
Phar: delete a file within a .phar
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=1
--FILE--
<?php
$file = "<?php __HALT_COMPILER(); ?>";
$files = array();
$files['a.php'] = '<?php echo "This is a\n"; ?>';
$files['b.php'] = '<?php echo "This is b\n"; ?>';
$files['b/c.php'] = '<?php echo "This is b/c\n"; ?>';
$manifest = '';
foreach($files as $name => $cont) {
$len = strlen($cont);
$manifest .= pack('V', strlen($name)) . $name . pack('VVVVC', $len, time(), $len, crc32($cont), 0x00);
}
$alias = '';
$manifest = pack('VnV', count($files), 0x0800, strlen($alias)) . $alias . $manifest;
$file .= pack('V', strlen($manifest)) . $manifest;
foreach($files as $cont)
{
$file .= $cont;
}
file_put_contents(dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php', $file);
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/a.php';
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b.php';
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/c.php';
unlink('phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/c.php');
?>
===AFTER===
<?php
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/a.php';
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b.php';
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/c.php';
?>
===DONE===
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECTF--
This is a
This is b
This is b/c
Warning: unlink(): phar error: write operations disabled by INI setting in %sdelete_in_phar_b.php on line %d
===AFTER===
This is a
This is b
This is b/c
===DONE===

2
ext/phar/tests/open_for_write_existing.phpt

@ -2,6 +2,8 @@
Phar: fopen a .phar for writing (existing file)
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=0
--FILE--
<?php
$file = "<?php __HALT_COMPILER(); ?>";

43
ext/phar/tests/open_for_write_existing_b.phpt

@ -0,0 +1,43 @@
--TEST--
Phar: fopen a .phar for writing (existing file)
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=1
--FILE--
<?php
$file = "<?php __HALT_COMPILER(); ?>";
$files = array();
$files['a.php'] = '<?php echo "This is a\n"; ?>';
$files['b.php'] = '<?php echo "This is b\n"; ?>';
$files['b/c.php'] = '<?php echo "This is b/c\n"; ?>';
$manifest = '';
foreach($files as $name => $cont) {
$len = strlen($cont);
$manifest .= pack('V', strlen($name)) . $name . pack('VVVVC', $len, time(), $len, crc32($cont), 0x00);
}
$alias = '';
$manifest = pack('VnV', count($files), 0x0800, strlen($alias)) . $alias . $manifest;
$file .= pack('V', strlen($manifest)) . $manifest;
foreach($files as $cont)
{
$file .= $cont;
}
file_put_contents(dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php', $file);
$fp = fopen('phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/c.php', 'wb');
fwrite($fp, 'extra');
fclose($fp);
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/c.php';
?>
===DONE===
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECTF--
Warning: include(phar://%sopen_for_write_existing_b.phar.php/b/c.php): failed to open stream: phar error: internal corruption of phar "%sopen_for_write_existing_b.phar.php" (crc32 mismatch on file "b/c.php") in %sopen_for_write_existing_b.php on line %d
Warning: include(): Failed opening 'phar://%sopen_for_write_existing_b.phar.php/b/c.php' for inclusion (include_path='.') in %sopen_for_write_existing_b.php on line %d
===DONE===

2
ext/phar/tests/open_for_write_newfile.phpt

@ -2,6 +2,8 @@
Phar: fopen a .phar for writing (new file)
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=0
--FILE--
<?php
$file = "<?php __HALT_COMPILER(); ?>";

53
ext/phar/tests/open_for_write_newfile_b.phpt

@ -0,0 +1,53 @@
--TEST--
Phar: fopen a .phar for writing (new file)
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=1
--FILE--
<?php
$file = "<?php __HALT_COMPILER(); ?>";
$files = array();
$files['a.php'] = '<?php echo "This is a\n"; ?>';
$files['b.php'] = '<?php echo "This is b\n"; ?>';
$files['b/c.php'] = '<?php echo "This is b/c\n"; ?>';
$manifest = '';
foreach($files as $name => $cont) {
$len = strlen($cont);
$manifest .= pack('V', strlen($name)) . $name . pack('VVVVC', $len, time(), $len, crc32($cont), 0x00);
}
$alias = '';
$manifest = pack('VnV', count($files), 0x0800, strlen($alias)) . $alias . $manifest;
$file .= pack('V', strlen($manifest)) . $manifest;
foreach($files as $cont)
{
$file .= $cont;
}
file_put_contents(dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php', $file);
$fp = fopen('phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/new.php', 'wb');
fwrite($fp, 'extra');
fclose($fp);
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/c.php';
include 'phar://' . dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php/b/new.php';
?>
===DONE===
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECTF--
Warning: fopen(phar://%sopen_for_write_newfile_b.phar.php/b/new.php): failed to open stream: phar error: file "b/new.php" could not be created in phar "%sopen_for_write_newfile_b.phar.php" in %sopen_for_write_newfile_b.php on line %d
Warning: fwrite(): supplied argument is not a valid stream resource in %sopen_for_write_newfile_b.php on line %d
Warning: fclose(): supplied argument is not a valid stream resource in %sopen_for_write_newfile_b.php on line %d
This is b/c
Warning: include(phar://%sopen_for_write_newfile_b.phar.php/b/new.php): failed to open stream: phar error: "b/new.php" is not a file in phar "%sopen_for_write_newfile_b.phar.php" in %sopen_for_write_newfile_b.php on line %d
Warning: include(): Failed opening 'phar://%sopen_for_write_newfile_b.phar.php/b/new.php' for inclusion (include_path='.') in %sopen_for_write_newfile_b.php on line %d
===DONE===

2
ext/phar/tests/phar_oo_011.phpt

@ -2,6 +2,8 @@
Phar object: add file
--SKIPIF--
<?php if (!extension_loaded('phar')) die('skip'); ?>
--INI--
phar.readonly=0
--FILE--
<?php

37
ext/phar/tests/phar_oo_011b.phpt

@ -0,0 +1,37 @@
--TEST--
Phar object: add file
--SKIPIF--
<?php if (!extension_loaded('phar')) die('skip'); ?>
--INI--
phar.readonly=1
--FILE--
<?php
try
{
$pharconfig = 0;
require_once 'phar_oo_test.inc';
$phar = new Phar($fname);
$phar['f.php'] = 'hi';
var_dump(isset($phar['f.php']));
echo $phar['f.php'];
echo "\n";
}
catch (BadMethodCallException $e)
{
echo "Exception: " . $e->getMessage() . "\n";
}
?>
===DONE===
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/phar_oo_test.phar.php');
__halt_compiler();
?>
--EXPECTF--
Exception: Write operations disabled by INI setting
===DONE===

2
ext/phar/tests/phar_oo_012.phpt

@ -2,6 +2,8 @@
Phar object: unset file
--SKIPIF--
<?php if (!extension_loaded('phar')) die('skip'); ?>
--INI--
phar.readonly=0
--FILE--
<?php

39
ext/phar/tests/phar_oo_012b.phpt

@ -0,0 +1,39 @@
--TEST--
Phar object: unset file
--SKIPIF--
<?php if (!extension_loaded('phar')) die('skip'); ?>
--INI--
phar.readonly=1
--FILE--
<?php
try
{
$pharconfig = 0;
require_once 'phar_oo_test.inc';
$phar = new Phar($fname);
$phar['f.php'] = 'hi';
var_dump(isset($phar['f.php']));
echo $phar['f.php'];
echo "\n";
unset($phar['f.php']);
var_dump(isset($phar['f.php']));
}
catch (BadMethodCallException $e)
{
echo "Exception: " . $e->getMessage() . "\n";
}
?>
===DONE===
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/phar_oo_test.phar.php');
__halt_compiler();
?>
--EXPECTF--
Exception: Write operations disabled by INI setting
===DONE===
Loading…
Cancel
Save