diff options
-rw-r--r-- | ext/phar/TODO | 2 | ||||
-rw-r--r-- | ext/phar/package.php | 13 | ||||
-rwxr-xr-x | ext/phar/phar_internal.h | 2 | ||||
-rwxr-xr-x | ext/phar/phar_object.c | 52 | ||||
-rw-r--r-- | ext/phar/tests/delete.phpt | 31 |
5 files changed, 86 insertions, 14 deletions
diff --git a/ext/phar/TODO b/ext/phar/TODO index f4c920e146..3352eb9b6f 100644 --- a/ext/phar/TODO +++ b/ext/phar/TODO @@ -69,7 +69,7 @@ Version 1.3.0 * ability to match files containing a metadata key opendir('phar://a.phar/?mime-type=image/jpeg') or foreach ($p->match('mime-type', 'image/jpeg') as $file) * Phar::copy($from, $to); - * Phar::delete($what) + X Phar::delete($what) [Greg] * Phar::buildFromIterator($filename, Iterator $it, array $addinfo = null); $addinfo = array('alias','flags','metadata','stub'...) * Layout: Option to compress all content rather than single files. diff --git a/ext/phar/package.php b/ext/phar/package.php index 638a4d6bed..9701c4358e 100644 --- a/ext/phar/package.php +++ b/ext/phar/package.php @@ -1,18 +1,7 @@ <?php $notes = ' - * add Phar::setAlias() [Greg] - * fix too many open file handles issue [Greg] - * fix rename [Greg] - * add Phar::getAlias() [Marcus] - * Made -a optional in pack subcommand of phar.phar [Marcus] - * Fix issue with apache module and extracted archives [Marcus] - * Send all error messages to stderr in phar.phar [Marcus] - * Added new subcommands add and delete to phar.phar [Marcus] - * Made Phar::loadPhar() and Phar::mapPhar() ignore extracted archives [Marcus] - * Fix issue with compressed entries and uncompressing entries [Marcus] - * Verify stubs before writing [Marcus] - * Always use longest stub end to avoid issues with length field [Marcus] + * add Phar::delete() [Greg] '; if (!class_exists("Phar") && !extension_loaded("Phar")) { diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index ab7b14fa43..00ec29bb11 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -62,7 +62,7 @@ #define E_RECOVERABLE_ERROR E_ERROR #endif -#define PHAR_EXT_VERSION_STR "1.2.1" +#define PHAR_EXT_VERSION_STR "1.3.0" #define PHAR_API_VERSION_STR "1.1.0" /* x.y.z maps to 0xyz0 */ #define PHAR_API_VERSION 0x1100 diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 124c471a87..29f951389e 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -287,6 +287,51 @@ PHP_METHOD(Phar, count) } /* }}} */ +/* {{{ proto bool Phar::delete(string file) + * Delete a file from within the Phar + */ +PHP_METHOD(Phar, delete) +{ + char *fname; + int fname_len; + char *error; + phar_entry_info *entry; + PHAR_ARCHIVE_OBJECT(); + + if (PHAR_G(readonly)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, + "Cannot write out phar archive, phar is read-only"); + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) { + RETURN_FALSE; + } + + if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) { + if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) { + if (entry->is_deleted) { + /* entry is deleted, but has not been flushed to disk yet */ + RETURN_TRUE; + } else { + entry->is_deleted = 1; + entry->is_modified = 1; + phar_obj->arc.archive->is_modified = 1; + } + } + } else { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be deleted", fname); + RETURN_FALSE; + } + + phar_flush(phar_obj->arc.archive, NULL, 0, &error TSRMLS_CC); + if (error) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); + efree(error); + } + + RETURN_TRUE; +} + /* {{{ proto int Phar::getAlias() * Returns the alias for the PHAR or NULL */ @@ -309,6 +354,12 @@ PHP_METHOD(Phar, setAlias) phar_archive_data *fd, **fd_ptr; int alias_len; PHAR_ARCHIVE_OBJECT(); + + if (PHAR_G(readonly)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, + "Cannot write out phar archive, phar is read-only"); + } + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &alias, &alias_len) == SUCCESS) { if (alias_len == phar_obj->arc.archive->alias_len && memcmp(phar_obj->arc.archive->alias, alias, alias_len) == 0) { RETURN_TRUE; @@ -1450,6 +1501,7 @@ zend_function_entry php_archive_methods[] = { PHP_ME(Phar, compressAllFilesGZ, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, compressAllFilesBZIP2, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, count, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phar, delete, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC) PHP_ME(Phar, delMetadata, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, getAlias, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, getMetadata, NULL, ZEND_ACC_PUBLIC) diff --git a/ext/phar/tests/delete.phpt b/ext/phar/tests/delete.phpt new file mode 100644 index 0000000000..10bb89a61a --- /dev/null +++ b/ext/phar/tests/delete.phpt @@ -0,0 +1,31 @@ +--TEST-- +Phar: delete test +--SKIPIF-- +<?php if (!extension_loaded("phar")) print "skip"; ?> +--INI-- +phar.readonly=0 +phar.require_hash=0 +--FILE-- +<?php +$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; +$pname = 'phar://' . $fname; +$file = "<?php +Phar::mapPhar('hio'); +__HALT_COMPILER(); ?>"; + +$files = array(); +$files['a'] = 'a'; +include 'phar_test.inc'; +include $fname; +$phar = new Phar($fname); + +echo file_get_contents($pname . '/a') . "\n"; +$phar->delete('a'); +echo file_get_contents($pname . '/a') . "\n"; +?> +--CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?> +--EXPECTF-- +a + +Warning: file_get_contents(phar://%sdelete.phar.php/a): failed to open stream: phar error: "a" is not a file in phar "%sdelete.phar.php" in %sdelete.php on line 16
\ No newline at end of file |