summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/phar/TODO2
-rw-r--r--ext/phar/package.php13
-rwxr-xr-xext/phar/phar_internal.h2
-rwxr-xr-xext/phar/phar_object.c52
-rw-r--r--ext/phar/tests/delete.phpt31
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