major improvement of zip/tar-based phar stub execution, now __FILE__ says it is the phar, and not phar/.phar/stub.php,
so that the same stub can be used for phar or tar/zip-based phars
ridiculous speedup of rename() within a phar (something like 1000%)
last of the tar-based phar fixes
new tests for tar-based phars, fix existing tests to use new format of __FILE__
}
if (data->fname) {
efree(data->fname);
+ data->fname = NULL;
}
if (data->signature) {
efree(data->signature);
} else {
register_alias = alias ? 1 : 0;
}
- mydata->alias = alias ? estrndup(alias, alias_len) : mydata->fname;
+ mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, alias_len);
mydata->alias_len = alias ? alias_len : fname_len;
mydata->is_zip = 1;
mydata->zip = zip;
/* ignore all errors in loading up manifest */
zip_error_clear(zip);
- zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
+ zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
if (register_alias) {
mydata->is_explicit_alias = 1;
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
phar_unixify_path_separators(mydata->fname, fname_len);
#endif
mydata->fname_len = fname_len;
- mydata->alias = alias ? estrndup(alias, alias_len) : mydata->fname;
+ mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(fname, fname_len);
mydata->alias_len = alias ? alias_len : fname_len;
mydata->sig_flags = sig_flags;
mydata->sig_len = sig_len;
#endif
}
mydata->fname_len = fname_len;
- mydata->alias = alias ? estrndup(alias, alias_len) : mydata->fname;
+ mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
mydata->alias_len = alias ? alias_len : fname_len;
snprintf(mydata->version, sizeof(mydata->version), "%s", PHAR_API_VERSION_STR);
mydata->is_explicit_alias = alias ? 1 : 0;
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
- if (strstr(fname, "phar://") && strstr(fname, ".phar/stub.php")) {
- char *arch, *entry;
- int arch_len, entry_len;
- phar_archive_data *phar;
-
- if (SUCCESS != phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
- efree(entry);
- efree(arch);
- goto regular_error;
- }
- if (strcmp(entry, "/.phar/stub.php")) {
- efree(entry);
- efree(arch);
- goto regular_error;
- }
-
- /* we're running from inside a zip-based phar */
- efree(entry);
- entry = fname;
- fname = arch;
- fname_len = arch_len;
- if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &phar, 0 TSRMLS_CC) && phar && (phar->is_zip || phar->is_tar)) {
- efree(arch);
- return SUCCESS;
- }
- /* restore original value for error purpose */
- fname = entry;
- }
-regular_error:
-
if (phar_open_loaded(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, 0 TSRMLS_CC) == SUCCESS) {
return SUCCESS;
}
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, *error, *plain_map;
- phar_entry_data *fromdata, *todata;
+ char *error, *plain_map;
+ phar_archive_data *phar;
+ phar_entry_info *entry;
uint host_len;
+ error = NULL;
if (PHAR_G(readonly)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: write operations disabled by INI setting");
return 0;
phar_request_initialize(TSRMLS_C);
if (zend_hash_find(&(PHAR_GLOBALS->phar_plain_map), resource_from->host, host_len+1, (void **)&plain_map) == SUCCESS) {
/*TODO:use php_stream_rename() once available*/
+ 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\" from extracted phar archive", url_from, url_to);
return 0;
}
- /* 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);
+ if (SUCCESS != phar_get_archive(&phar, resource_from->host, strlen(resource_from->host), NULL, 0, &error TSRMLS_CC)) {
php_url_free(resource_from);
php_url_free(resource_to);
- return 0;
- }
- if (error) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, 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);
return 0;
}
- 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 (SUCCESS == zend_hash_find(&(phar->manifest), resource_from->path+1, strlen(resource_from->path)-1, (void **)&entry)) {
+ phar_entry_info new;
+
+ /* perform rename magic */
+ if (entry->is_deleted) {
+ 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\" from extracted phar archive, source has been deleted", url_from, url_to);
+ return 0;
+ }
+ /* transfer all data over to the new entry */
+ memcpy((void *) &new, (void *) entry, sizeof(phar_entry_info));
+ /* mark the old one for deletion */
+ entry->is_deleted = 1;
+ entry->fp = NULL;
+ entry->metadata = 0;
+ entry->link = NULL;
+#if HAVE_ZIP
+ entry->zip = NULL;
+#endif
+
+ zend_hash_add(&(phar->manifest), resource_to->path+1, strlen(resource_to->path)-1, (void **)&new, sizeof(phar_entry_info), (void **) &entry);
+ if (!entry->is_modified) {
+ /* copy file contents into a new temp stream */
+ if (!phar_open_jit(phar, entry, phar->fp, &error, 1 TSRMLS_CC)) {
+ 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\": %s", url_from, url_to, error);
+ efree(error);
+ return 0;
+ }
+ }
+ entry->is_modified = 1;
+ entry->filename = estrdup(resource_to->path+1);
+ entry->filename_len = strlen(entry->filename);
+ phar_flush(phar, 0, 0, &error TSRMLS_CC);
if (error) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
+ 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\": %s", url_from, url_to, error);
efree(error);
+ return 0;
}
- efree(from_file);
- efree(to_file);
- php_url_free(resource_from);
- php_url_free(resource_to);
- return 0;
- }
- 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);
- return 0;
}
- 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);
- return 0;
- }
-
- php_stream_seek(fromdata->internal_file->fp, 0 + fromdata->zero, 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);
- return 0;
- }
- todata->internal_file->uncompressed_filesize = todata->internal_file->compressed_filesize = fromdata->internal_file->uncompressed_filesize;
- phar_entry_delref(fromdata TSRMLS_CC);
- phar_entry_delref(todata TSRMLS_CC);
- 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);
- return 0;
- }
- 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);
return 1;
}
/* }}} */
if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, ":\\")) {
if (SUCCESS == phar_open_filename(file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
if (phar->is_zip || phar->is_tar) {
- /* zip-based phar */
+ zend_file_handle f = *file_handle;
+
+ /* zip or tar-based phar */
spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
- file_handle->type = ZEND_HANDLE_FILENAME;
- file_handle->free_filename = 1;
- file_handle->filename = name;
- if (file_handle->opened_path) {
- efree(file_handle->opened_path);
+ if (SUCCESS == zend_stream_open_function((const char *)name, file_handle TSRMLS_CC)) {
+ efree(name);
+ name = NULL;
+ file_handle->filename = f.filename;
+ file_handle->opened_path = f.opened_path;
+ file_handle->free_filename = f.free_filename;
+ } else {
+ *file_handle = f;
}
goto skip_phar;
}
/* auto-convert to phar:// */
spprintf(&name, 4096, "phar://%s/%s", arch, entry);
efree(arch);
+ if (file_handle->type == ZEND_HANDLE_FP) {
+ // clean up
+ fclose(file_handle->handle.fp);
+ }
file_handle->type = ZEND_HANDLE_FILENAME;
file_handle->free_filename = 1;
file_handle->filename = name;
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
- if (strstr(fname, "://")) {
- char *arch, *entry;
- int arch_len, entry_len;
- phar_archive_data *mphar;
-
- /* running within a zip-based phar, acquire the actual name */
- if (SUCCESS != phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
- efree(entry);
- efree(arch);
- return; /* this, incidentally, should be impossible */
- }
-
- efree(entry);
- entry = fname;
- fname = arch;
- fname_len = arch_len;
- if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &mphar, 0 TSRMLS_CC) && mphar && (mphar->is_zip || mphar->is_tar)) {
- efree(arch);
- fname = mphar->fname;
- fname_len = mphar->fname_len;
- } else {
- efree(arch);
- fname = entry;
- }
- }
#ifdef PHP_WIN32
fname = estrndup(fname, fname_len);
phar_unixify_path_separators(fname, fname_len);
size_t pos = 0, read;
tar_header *hdr;
php_uint32 sum1, sum2, size, old;
- phar_archive_data *myphar;
+ phar_archive_data *myphar, **retdata;
if (error) {
*error = NULL;
myphar->fname_len = fname_len;
myphar->fp = fp;
phar_request_initialize(TSRMLS_C);
- zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
+ zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
if (actual_alias) {
myphar->is_explicit_alias = 1;
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
} else {
+ myphar->alias = estrndup(fname, fname_len);
+ myphar->alias_len = fname_len;
myphar->is_explicit_alias = 0;
}
if (pphar) {
entry.flags = PHAR_ENT_PERM_DEF_FILE;
entry.timestamp = time(NULL);
entry.is_modified = 1;
+ entry.is_crc_checked = 1;
entry.is_tar = 1;
entry.tar_type = '0';
entry.phar = archive;
--EXPECTHEADERS--
Content-type: text/html
--EXPECTF--
-Fatal error: Uncaught exception 'UnexpectedValueException' with message 'phar rewrite value for "/hi" was not a string' in %sfrontcontroller10.phar.php/.phar/stub.php:2
+Fatal error: Uncaught exception 'UnexpectedValueException' with message 'phar rewrite value for "/hi" was not a string' in %sfrontcontroller10.phar.php:2
Stack trace:
-#0 %sfrontcontroller10.phar.php/.phar/stub.php(2): Phar::webPhar('whatever', 'index.php', '', Array, Array)
+#0 %sfrontcontroller10.phar.php(2): Phar::webPhar('whatever', 'index.php', '', Array, Array)
#1 {main}
- thrown in %sfrontcontroller10.phar.php/.phar/stub.php on line 2
\ No newline at end of file
+ thrown in %sfrontcontroller10.phar.php on line 2
\ No newline at end of file
--EXPECTHEADERS--
Content-type: text/html
--EXPECTF--
-Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Key of MIME type overrides array must be a file extension, was "0"' in %sfrontcontroller11.phar.php/.phar/stub.php:2
+Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Key of MIME type overrides array must be a file extension, was "0"' in %sfrontcontroller11.phar.php:2
Stack trace:
-#0 %sfrontcontroller11.phar.php/.phar/stub.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
+#0 %sfrontcontroller11.phar.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller11.phar.php/.phar/stub.php on line 2
\ No newline at end of file
+ thrown in %sfrontcontroller11.phar.php on line 2
\ No newline at end of file
--EXPECTHEADERS--
Content-type: text/html
--EXPECTF--
-Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed' in %sfrontcontroller12.phar.php/.phar/stub.php:2
+Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed' in %sfrontcontroller12.phar.php:2
Stack trace:
-#0 %sfrontcontroller12.phar.php/.phar/stub.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
+#0 %sfrontcontroller12.phar.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller12.phar.php/.phar/stub.php on line 2
\ No newline at end of file
+ thrown in %sfrontcontroller12.phar.php on line 2
\ No newline at end of file
--EXPECTHEADERS--
Content-type: text/html
--EXPECTF--
-Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed' in %sfrontcontroller13.phar.php/.phar/stub.php:2
+Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed' in %sfrontcontroller13.phar.php:2
Stack trace:
-#0 %sfrontcontroller13.phar.php/.phar/stub.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
+#0 %sfrontcontroller13.phar.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller13.phar.php/.phar/stub.php on line 2
\ No newline at end of file
+ thrown in %sfrontcontroller13.phar.php on line 2
\ No newline at end of file
--FILE_EXTERNAL--
frontcontroller9.phar.tar
--EXPECTF--
-Fatal error: Uncaught exception 'UnexpectedValueException' with message 'No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME' in %sfrontcontroller18.phar.php/.phar/stub.php:2
+Fatal error: Uncaught exception 'UnexpectedValueException' with message 'No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME' in %sfrontcontroller18.phar.php:2
Stack trace:
-#0 %sfrontcontroller18.phar.php/.phar/stub.php(2): Phar::mungServer(Array)
+#0 %sfrontcontroller18.phar.php(2): Phar::mungServer(Array)
#1 {main}
- thrown in %sfrontcontroller18.phar.php/.phar/stub.php on line 2
+ thrown in %sfrontcontroller18.phar.php on line 2
--FILE_EXTERNAL--
frontcontroller10.phar.tar
--EXPECTF--
-Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME' in %sfrontcontroller19.phar.php/.phar/stub.php:2
+Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME' in %sfrontcontroller19.phar.php:2
Stack trace:
-#0 %sfrontcontroller19.phar.php/.phar/stub.php(2): Phar::mungServer(Array)
+#0 %sfrontcontroller19.phar.php(2): Phar::mungServer(Array)
#1 {main}
- thrown in %sfrontcontroller19.phar.php/.phar/stub.php on line 2
+ thrown in %sfrontcontroller19.phar.php on line 2
--FILE_EXTERNAL--
frontcontroller11.phar.tar
--EXPECTF--
-Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME' in %sfrontcontroller20.phar.php/.phar/stub.php:2
+Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME' in %sfrontcontroller20.phar.php:2
Stack trace:
-#0 %sfrontcontroller20.phar.php/.phar/stub.php(2): Phar::mungServer(Array)
+#0 %sfrontcontroller20.phar.php(2): Phar::mungServer(Array)
#1 {main}
- thrown in %sfrontcontroller20.phar.php/.phar/stub.php on line 2
+ thrown in %sfrontcontroller20.phar.php on line 2
--- /dev/null
+--TEST--
+Phar::setStub()/stopBuffering() tar-based
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+$p = new Phar(dirname(__FILE__) . '/brandnewphar.phar.tar', 0, 'brandnewphar.phar');
+$p['file1.txt'] = 'hi';
+$p->stopBuffering();
+var_dump($p->getStub());
+$p->setStub("<?php
+function __autoload(\$class)
+{
+ include 'phar://' . str_replace('_', '/', \$class);
+}
+Phar::mapPhar('brandnewphar.phar');
+include 'phar://brandnewphar.phar/startup.php';
+__HALT_COMPILER();
+?>");
+var_dump($p->getStub());
+var_dump($p->isTar());
+?>
+===DONE===
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/brandnewphar.phar.tar');
+?>
+--EXPECT--
+string(60) "<?php // tar-based phar archive stub file
+__HALT_COMPILER();"
+string(200) "<?php
+function __autoload($class)
+{
+ include 'phar://' . str_replace('_', '/', $class);
+}
+Phar::mapPhar('brandnewphar.phar');
+include 'phar://brandnewphar.phar/startup.php';
+__HALT_COMPILER(); ?>
+"
+bool(true)
+===DONE===
\ No newline at end of file
--- /dev/null
+--TEST--
+Phar: copy() tar-based
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+<?php if (!extension_loaded("spl")) die("skip SPL not available"); ?>
+<?php if (!extension_loaded("zlib")) die("skip zlib not available"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=1
+--FILE--
+<?php
+
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar.php';
+$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '2.phar.php';
+
+$pname = 'phar://'.$fname;
+$iname = '/file.txt';
+$ename = '/error/';
+
+$p = new Phar($fname);
+
+try
+{
+ $p['a'] = 'hi';
+ $p->startBuffering();
+ $p->copy('a', 'b');
+ echo file_get_contents($p['b']->getPathName());
+ $p->copy('b', 'c');
+ $p->stopBuffering();
+ echo file_get_contents($p['c']->getPathName());
+ copy($fname, $fname2);
+ var_dump($p->isTar());
+ $p->copy('a', $ename);
+}
+catch(Exception $e)
+{
+ echo $e->getMessage() . "\n";
+}
+ini_set('phar.readonly',1);
+$p2 = new Phar($fname2);
+var_dump($p2->isTar());
+echo "\n";
+echo 'a: ' , file_get_contents($p2['a']->getPathName());
+echo 'b: ' ,file_get_contents($p2['b']->getPathName());
+echo 'c: ' ,file_get_contents($p2['c']->getPathName());
+?>
+===DONE===
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.tar.php'); ?>
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '2.phar.php'); ?>
+--EXPECTF--
+hihibool(true)
+file "/error/" contains invalid characters empty directory, cannot be copied from "a" in phar %s
+bool(true)
+
+a: hib: hic: hi===DONE===
\ No newline at end of file
--- /dev/null
+--TEST--
+Phar: include/fopen magic tar-based
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar.php';
+$p = new Phar($fname);
+var_dump($p->isTar());
+$p['a'] = '<?php include "b/c.php";' . "\n";
+$p['b/c.php'] = '<?php echo "in b\n";$a = fopen("a", "r", true);echo stream_get_contents($a);fclose($a);include dirname(__FILE__) . "/../d";';
+$p['d'] = "in d\n";
+$p->setStub('<?php
+include "phar://" . __FILE__ . "/a";
+__HALT_COMPILER();');
+include $fname;
+?>
+===DONE===
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.tar.php');
+__HALT_COMPILER();
+?>
+--EXPECTF--
+bool(true)
+in b
+<?php include "b/c.php";
+in d
+===DONE===
--- /dev/null
+--TEST--
+Phar::setAlias() tar-based
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+include dirname(__FILE__) . '/tarmaker.php.inc';
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$a = new tarmaker($fname, 'none');
+$a->init();
+$a->addFile('.phar/stub.php', '<?php echo "first stub\n"; __HALT_COMPILER(); ?>');
+
+$files = array();
+$files['a'] = 'a';
+$files['b'] = 'b';
+$files['c'] = 'c';
+$files['.phar/alias.txt'] = 'hio';
+foreach ($files as $n => $file) {
+$a->addFile($n, $file);
+}
+$a->close();
+
+$phar = new Phar($fname);
+echo $phar->getAlias() . "\n";
+$phar->setAlias('test');
+echo $phar->getAlias() . "\n";
+?>
+===DONE===
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php');
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phartmp.php');
+__HALT_COMPILER();
+?>
+--EXPECT--
+hio
+test
+===DONE===
--- /dev/null
+--TEST--
+Phar::setAlias() error tar-based
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+include dirname(__FILE__) . '/tarmaker.php.inc';
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$a = new tarmaker($fname, 'none');
+$a->init();
+$a->addFile('.phar/stub.php', '<?php echo "first stub\n"; __HALT_COMPILER(); ?>');
+
+$files = array();
+$files['a'] = 'a';
+$files['b'] = 'b';
+$files['c'] = 'c';
+$files['.phar/alias.txt'] = 'hio';
+foreach ($files as $n => $file) {
+$a->addFile($n, $file);
+}
+$a->close();
+
+$phar = new Phar($fname);
+echo $phar->getAlias() . "\n";
+$phar->setAlias('test');
+echo $phar->getAlias() . "\n";
+$phar = new Phar(dirname(__FILE__) . '/notphar.phar');
+try {
+ $phar->setAlias('test');
+} catch (Exception $e) {
+ echo $e->getMessage() . "\n";
+}
+?>
+===DONE===
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php');
+unlink(dirname(__FILE__) . '/notphar.phar');
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phartmp.php');
+__HALT_COMPILER();
+?>
+--EXPECTF--
+hio
+test
+alias "test" is already used for archive "%sphar_setalias2.phar.php" and cannot be used for other archives
+===DONE===
--- /dev/null
+--TEST--
+Phar::setStub()/getStub()
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+include dirname(__FILE__) . '/tarmaker.php.inc';
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$a = new tarmaker($fname, 'none');
+$a->init();
+$a->addFile('.phar/stub.php', $stub = '<?php echo "first stub\n"; __HALT_COMPILER(); ?>');
+
+$files = array();
+$files['a'] = 'a';
+$files['.phar/alias.txt'] = 'hio';
+foreach ($files as $n => $file) {
+$a->addFile($n, $file);
+}
+$a->close();
+
+$phar = new Phar($fname);
+var_dump($stub);
+var_dump($phar->getStub());
+var_dump($phar->getStub() == $stub);
+
+$newstub = '<?php echo "second stub\n"; _x_HALT_COMPILER(); ?>';
+try
+{
+ $phar->setStub($newstub);
+}
+catch(exception $e)
+{
+ echo 'Exception: ' . $e->getMessage() . "\n";
+}
+var_dump($phar->getStub());
+var_dump($phar->getStub() == $stub);
+$phar->stopBuffering();
+var_dump($phar->getStub());
+var_dump($phar->getStub() == $stub);
+
+?>
+===DONE===
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php');
+__HALT_COMPILER();
+?>
+--EXPECTF--
+string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
+string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
+bool(true)
+Exception: illegal stub for tar-based phar "%sphar_stub_error.phar.php"
+string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
+bool(true)
+string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
+bool(true)
+===DONE===
--- /dev/null
+--TEST--
+Phar: test that refcounting avoids problems with deleting a file tar-based
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+<?php if (!extension_loaded("spl")) die("skip SPL not available"); ?>
+<?php if (version_compare(PHP_VERSION, "5.3", "<")) die("skip requires 5.3 or later"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+include dirname(__FILE__) . '/tarmaker.php.inc';
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$a = new tarmaker($fname, 'none');
+$a->init();
+$a->addFile('.phar/stub.php', "<?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"; ?>';
+$files['.phar/alias.txt'] = 'hio';
+foreach ($files as $n => $file) {
+$a->addFile($n, $file);
+}
+$a->close();
+
+$fp = fopen($pname . '/b/c.php', 'wb');
+fwrite($fp, "extra");
+fclose($fp);
+echo "===CLOSE===\n";
+$p = new Phar($fname);
+$b = fopen($pname . '/b/c.php', 'rb');
+$a = $p['b/c.php'];
+var_dump($a);
+var_dump(fread($b, 20));
+rewind($b);
+echo "===UNLINK===\n";
+unlink($pname . '/b/c.php');
+var_dump($a);
+var_dump(fread($b, 20));
+include $pname . '/b/c.php';
+?>
+
+===DONE===
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
+--EXPECTF--
+===CLOSE===
+object(PharFileInfo)#%d (2) {
+ ["pathName":"SplFileInfo":private]=>
+ string(%d) "phar://%srefcount1.phar.php/b"
+ ["fileName":"SplFileInfo":private]=>
+ string(%d) "phar://%srefcount1.phar.php/b/c.php"
+}
+string(5) "extra"
+===UNLINK===
+
+Warning: unlink(): phar error: "b/c.php" in phar "%srefcount1.phar.php", has open file pointers, cannot unlink in %srefcount1.php on line %d
+object(PharFileInfo)#%d (2) {
+ ["pathName":"SplFileInfo":private]=>
+ string(%d) "phar://%srefcount1.phar.php/b"
+ ["fileName":"SplFileInfo":private]=>
+ string(%s) "phar://%srefcount1.phar.php/b/c.php"
+}
+string(5) "extra"
+extra
+===DONE===
--- /dev/null
+--TEST--
+Phar: test that refcounting avoids problems with deleting a file tar-based
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+<?php if (!extension_loaded("spl")) die("skip SPL not available"); ?>
+<?php if (version_compare(PHP_VERSION, "5.2", ">")) die("skip requires 5.2 or earlier"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+include dirname(__FILE__) . '/tarmaker.php.inc';
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$a = new tarmaker($fname, 'none');
+$a->init();
+$a->addFile('.phar/stub.php', "<?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"; ?>';
+$files['.phar/alias.txt'] = 'hio';
+foreach ($files as $n => $file) {
+$a->addFile($n, $file);
+}
+$a->close();
+
+$fp = fopen($pname . '/b/c.php', 'wb');
+fwrite($fp, "extra");
+fclose($fp);
+echo "===CLOSE===\n";
+$p = new Phar($fname);
+$b = fopen($pname . '/b/c.php', 'rb');
+$a = $p['b/c.php'];
+var_dump($a);
+var_dump(fread($b, 20));
+rewind($b);
+echo "===UNLINK===\n";
+unlink($pname . '/b/c.php');
+var_dump($a);
+var_dump(fread($b, 20));
+include $pname . '/b/c.php';
+?>
+
+===DONE===
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
+--EXPECTF--
+===CLOSE===
+object(PharFileInfo)#%d (0) {
+}
+string(5) "extra"
+===UNLINK===
+
+Warning: unlink(): phar error: "b/c.php" in phar "%sefcount1.phar.php", has open file pointers, cannot unlink in %sefcount1.php on line %d
+object(PharFileInfo)#%d (0) {
+}
+string(5) "extra"
+extra
+===DONE===
--- /dev/null
+--TEST--
+Phar: rename test
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+include dirname(__FILE__) . '/tarmaker.php.inc';
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$a = new tarmaker($fname, 'none');
+$a->init();
+$a->addFile('.phar/stub.php', "<?php
+Phar::mapPhar('hio');
+__HALT_COMPILER(); ?>");
+
+$files = array();
+$files['a'] = 'a';
+foreach ($files as $n => $file) {
+$a->addFile($n, $file);
+}
+$a->close();
+
+include $fname;
+
+echo file_get_contents($pname . '/a') . "\n";
+rename($pname . '/a', $pname . '/b');
+echo file_get_contents($pname . '/b') . "\n";
+echo file_get_contents($pname . '/a') . "\n";
+?>
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
+--EXPECTF--
+a
+a
+
+Warning: file_get_contents(phar://%srename.phar.php/a): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.php" in %srename.php on line %d
\ No newline at end of file
$a->addFile('.phar/stub.php', '<?php
Phar::mapPhar();
var_dump("it worked");
-include "tar_004.php";
+include "phar://" . __FILE__ . "/tar_004.php";
');
$a->close();