mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
- This is as good as it gets in HEAD at present (~30% tests fail here)
This commit is contained in:
@@ -4,22 +4,42 @@ $(srcdir)/phar_path_check.c: $(srcdir)/phar_path_check.re
|
||||
|
||||
pharcmd: $(builddir)/phar.php $(builddir)/phar.phar
|
||||
|
||||
PHP_PHARCMD_SETTINGS = -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' -d phar.readonly=0
|
||||
PHP_PHARCMD_EXECUTABLE = ` \
|
||||
if test -x "$(top_builddir)/$(SAPI_CLI_PATH)"; then \
|
||||
$(top_srcdir)/build/shtool echo -n -- "$(top_builddir)/$(SAPI_CLI_PATH) -n"; \
|
||||
if test "x$(PHP_MODULES)" != "x"; then \
|
||||
$(top_srcdir)/build/shtool echo -n -- " -d extension_dir=$(top_builddir)/modules"; \
|
||||
for i in bz2 zlib phar; do \
|
||||
if test -f "$(top_builddir)/modules/$$i.la"; then \
|
||||
. $(top_builddir)/modules/$$i.la; $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \
|
||||
fi; \
|
||||
done; \
|
||||
fi; \
|
||||
else \
|
||||
$(top_srcdir)/build/shtool echo -n -- "$(PHP_EXECUTABLE)"; \
|
||||
fi;`
|
||||
PHP_PHARCMD_BANG = `if test -x "$(PHP_EXECUTABLE)"; then \
|
||||
$(top_srcdir)/build/shtool echo -n -- "$(PHP_EXECUTABLE)"; \
|
||||
else \
|
||||
$(top_srcdir)/build/shtool echo -n -- "$(INSTALL_ROOT)$(bindir)/$(program_prefix)php$(program_suffix)$(EXEEXT)"; \
|
||||
fi; `
|
||||
|
||||
$(builddir)/phar/phar.inc: $(srcdir)/phar/phar.inc
|
||||
-@test -d $(builddir)/phar || mkdir $(builddir)/phar
|
||||
-@test -f $(builddir)/phar/phar.inc || cp $(srcdir)/phar/phar.inc $(builddir)/phar/phar.inc
|
||||
|
||||
$(builddir)/phar.php: $(srcdir)/build_precommand.php $(srcdir)/phar/*.inc $(srcdir)/phar/*.php $(SAPI_CLI_PATH)
|
||||
if test -x "$(PHP_EXECUTABLE)"; then \
|
||||
export PHP="$(PHP_EXECUTABLE)"; \
|
||||
else \
|
||||
export PHP="$(top_builddir)/$(SAPI_CLI_PATH)"; \
|
||||
fi; \
|
||||
$$PHP $(srcdir)/build_precommand.php > $(builddir)/phar.php
|
||||
-@echo "Generating phar.php"
|
||||
@$(PHP_PHARCMD_EXECUTABLE) $(PHP_PHARCMD_SETTINGS) $(srcdir)/build_precommand.php > $(builddir)/phar.php
|
||||
|
||||
$(builddir)/phar.phar: $(builddir)/phar.php $(srcdir)/phar/*.inc $(srcdir)/phar/*.php $(SAPI_CLI_PATH)
|
||||
if test -x "$(PHP_EXECUTABLE)"; then \
|
||||
export PHP="$(PHP_EXECUTABLE)"; \
|
||||
export BANG="$(PHP_EXECUTABLE)"; \
|
||||
else \
|
||||
export PHP="$(top_builddir)/$(SAPI_CLI_PATH)"; \
|
||||
export BANG="$(INSTALL_ROOT)$(bindir)/$(program_prefix)php$(program_suffix)$(EXEEXT)"; \
|
||||
fi; \
|
||||
$$PHP -d phar.readonly=0 $(srcdir)/phar.php pack -f $(builddir)/phar.phar -a pharcommand -c auto -x CVS -p 0 -s $(srcdir)/phar/phar.php -h sha1 -b "$$BANG" $(srcdir)/phar/
|
||||
@chmod +x $(builddir)/phar.phar
|
||||
$(builddir)/phar.phar: $(builddir)/phar.php $(builddir)/phar/phar.inc $(srcdir)/phar/*.inc $(srcdir)/phar/*.php $(SAPI_CLI_PATH)
|
||||
-@echo "Generating phar.phar"
|
||||
-@rm -f $(builddir)/phar.phar
|
||||
-@rm -f $(srcdir)/phar.phar
|
||||
@$(PHP_PHARCMD_EXECUTABLE) $(PHP_PHARCMD_SETTINGS) $(builddir)/phar.php pack -f $(builddir)/phar.phar -a pharcommand -c auto -x CVS -p 0 -s $(srcdir)/phar/phar.php -h sha1 -b "$(PHP_PHARCMD_BANG)" $(srcdir)/phar/
|
||||
-@chmod +x $(builddir)/phar.phar
|
||||
|
||||
install-pharcmd: pharcmd
|
||||
-@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
|
||||
$(INSTALL) $(builddir)/phar.phar $(INSTALL_ROOT)$(bindir)
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
* @ingroup Phar
|
||||
* @brief class Phar Pre Command
|
||||
* @author Marcus Boerger
|
||||
* @date 2007 - 2007
|
||||
* @date 2007 - 2008
|
||||
*
|
||||
* Phar Command
|
||||
*/
|
||||
foreach(array("SPL", "Reflection", "Phar") as $ext)
|
||||
{
|
||||
if (!extension_loaded($ext))
|
||||
{
|
||||
foreach(array("SPL", "Reflection", "Phar") as $ext) {
|
||||
if (!extension_loaded($ext)) {
|
||||
echo "$argv[0] requires PHP extension $ext.\n";
|
||||
exit(1);
|
||||
}
|
||||
@@ -28,14 +26,12 @@ $classes = array(
|
||||
'PharCommand',
|
||||
);
|
||||
|
||||
foreach($classes as $name)
|
||||
{
|
||||
foreach($classes as $name) {
|
||||
echo "if (!class_exists('$name', 0))\n{\n";
|
||||
$f = file(dirname(__FILE__) . '/phar/' . strtolower($name) . '.inc');
|
||||
unset($f[0]);
|
||||
$c = count($f);
|
||||
while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n"))
|
||||
{
|
||||
while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n")) {
|
||||
unset($f[$c--]);
|
||||
}
|
||||
if (substr($f[$c], -2) == "\r\n") {
|
||||
@@ -47,8 +43,7 @@ foreach($classes as $name)
|
||||
if (substr($f[$c], -2) == '?>') {
|
||||
$f[$c] = substr($f[$c], 0,-2);
|
||||
}
|
||||
while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n"))
|
||||
{
|
||||
while ($c && (strlen($f[$c]) == 0 || $f[$c] == "\n" || $f[$c] == "\r\n")) {
|
||||
unset($f[$c--]);
|
||||
}
|
||||
echo join('', $f);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#!/bin/sh
|
||||
export SCRIPT_NAME=/front.phar.php
|
||||
export PATH_INFO=
|
||||
export PATH_INFO=/index.php
|
||||
export SCRIPT_FILENAME=/home/cellog/workspace/php5/ext/phar/tests/front.phar.php
|
||||
export PATH_TRANSLATED=/home/cellog/workspace/php5/ext/phar/tests/front.phar.php
|
||||
export REDIRECT_STATUS=1
|
||||
export REQUEST_METHOD=GET
|
||||
export REQUEST_URI=/front.phar.php
|
||||
cd /home/cellog/workspace/php5/
|
||||
export REQUEST_URI=/front.phar.php/index.php
|
||||
cd /home/cellog/workspace/php5
|
||||
ddd sapi/cgi/php-cgi &
|
||||
cd /home/cellog/workspace/php5/ext/phar
|
||||
|
||||
@@ -2,12 +2,23 @@ dnl $Id$
|
||||
dnl config.m4 for extension phar
|
||||
|
||||
PHP_ARG_ENABLE(phar, for phar archive support,
|
||||
[ --enable-phar Enable phar support])
|
||||
[ --enable-phar Enable phar support])
|
||||
|
||||
if test "$PHP_PHAR" != "no"; then
|
||||
PHP_NEW_EXTENSION(phar, util.c tar.c zip.c stream.c func_interceptors.c dirstream.c phar.c phar_object.c phar_path_check.c, $ext_shared)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/lib, 1)
|
||||
PHP_SUBST(PHAR_SHARED_LIBADD)
|
||||
AC_MSG_CHECKING([for phar openssl support])
|
||||
if test "$PHP_OPENSSL_SHARED" = "yes"; then
|
||||
AC_MSG_RESULT([no (shared openssl)])
|
||||
else
|
||||
if test "$PHP_OPENSSL" = "yes"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(PHAR_HAVE_OPENSSL,1,[ ])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
fi
|
||||
PHP_ADD_EXTENSION_DEP(phar, spl, true)
|
||||
PHP_ADD_MAKEFILE_FRAGMENT
|
||||
fi
|
||||
|
||||
@@ -2,11 +2,37 @@
|
||||
// vim:ft=javascript
|
||||
|
||||
ARG_ENABLE("phar", "enable phar support", "no");
|
||||
ARG_ENABLE("phar-native-ssl", "enable phar with native OpenSSL support", "no");
|
||||
|
||||
if (PHP_PHAR_NATIVE_SSL != "no") {
|
||||
PHP_PHAR = PHP_PHAR_NATIVE_SSL;
|
||||
PHP_PHAR_SHARED = PHP_PHAR_NATIVE_SSL_SHARED;
|
||||
}
|
||||
|
||||
if (PHP_PHAR != "no") {
|
||||
EXTENSION("phar", "dirstream.c func_interceptors.c phar.c phar_object.c phar_path_check.c stream.c tar.c util.c zip.c");
|
||||
if (PHP_PHAR_SHARED) {
|
||||
ADD_FLAG("CFLAGS_PHAR", "/D COMPILE_DL_PHAR ");
|
||||
}
|
||||
if (PHP_PHAR_NATIVE_SSL != "no") {
|
||||
if (CHECK_LIB("libeay32st.lib", "phar")) {
|
||||
/* We don't really need GDI for this, but there's no
|
||||
way to avoid linking it in the static openssl build */
|
||||
ADD_FLAG("LIBS_PHAR", "libeay32st.lib gdi32.lib");
|
||||
if (PHP_DEBUG == "no") {
|
||||
/* Silence irrelevant-to-us warning in release builds */
|
||||
ADD_FLAG("LDFLAGS_PHAR", "/IGNORE:4089 ");
|
||||
}
|
||||
AC_DEFINE('PHAR_HAVE_OPENSSL', 1);
|
||||
STDOUT.WriteLine(' Native OpenSSL support in Phar enabled');
|
||||
} else {
|
||||
WARNING('Could not enable native OpenSSL support in Phar');
|
||||
}
|
||||
} else {
|
||||
/* If ext/openssl is built-in we can at least use the API directly */
|
||||
if (PHP_OPENSSL != "no" && !PHP_OPENSSL_SHARED) {
|
||||
AC_DEFINE('PHAR_HAVE_OPENSSL', 1);
|
||||
}
|
||||
}
|
||||
ADD_EXTENSION_DEP('phar', 'spl', true);
|
||||
}
|
||||
|
||||
@@ -45,13 +45,13 @@ static int phar_dir_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{
|
||||
{
|
||||
HashTable *data = (HashTable *)stream->abstract;
|
||||
|
||||
if (data && data->arBuckets)
|
||||
{
|
||||
if (data && data->arBuckets) {
|
||||
zend_hash_destroy(data);
|
||||
data->arBuckets = 0;
|
||||
FREE_HASHTABLE(data);
|
||||
stream->abstract = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -63,14 +63,15 @@ static int phar_dir_seek(php_stream *stream, off_t offset, int whence, off_t *ne
|
||||
{
|
||||
HashTable *data = (HashTable *)stream->abstract;
|
||||
|
||||
if (!data)
|
||||
{
|
||||
if (!data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (whence == SEEK_END) {
|
||||
whence = SEEK_SET;
|
||||
offset = zend_hash_num_elements(data) + offset;
|
||||
}
|
||||
|
||||
if (whence == SEEK_SET) {
|
||||
zend_hash_internal_pointer_reset(data);
|
||||
}
|
||||
@@ -102,15 +103,19 @@ static size_t phar_dir_read(php_stream *stream, char *buf, size_t count TSRMLS_D
|
||||
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)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PHAR_STR(key, str_key);
|
||||
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, str_key, to_read);
|
||||
((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0';
|
||||
@@ -145,9 +150,9 @@ static int phar_dir_flush(php_stream *stream TSRMLS_DC) /* {{{ */
|
||||
*/
|
||||
static int phar_add_empty(HashTable *ht, char *arKey, uint nKeyLength) /* {{{ */
|
||||
{
|
||||
void *dummy = (void *) 1;
|
||||
void *dummy = (char *) 1;
|
||||
|
||||
return zend_hash_update(ht, arKey, nKeyLength, &dummy, sizeof(void *), NULL);
|
||||
return zend_hash_update(ht, arKey, nKeyLength, (void *) &dummy, sizeof(void *), NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -159,10 +164,9 @@ static int phar_compare_dir_name(const void *a, const void *b TSRMLS_DC) /* {{{
|
||||
Bucket *f;
|
||||
Bucket *s;
|
||||
int result;
|
||||
|
||||
|
||||
f = *((Bucket **) a);
|
||||
s = *((Bucket **) b);
|
||||
|
||||
#if (PHP_MAJOR_VERSION < 6)
|
||||
result = zend_binary_strcmp(f->arKey, f->nKeyLength, s->arKey, s->nKeyLength);
|
||||
#else
|
||||
@@ -202,12 +206,16 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
|
||||
efree(dir);
|
||||
return php_stream_alloc(&phar_dir_ops, data, NULL, "r");
|
||||
}
|
||||
|
||||
zend_hash_internal_pointer_reset(manifest);
|
||||
|
||||
while (FAILURE != zend_hash_has_more_elements(manifest)) {
|
||||
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) {
|
||||
break;
|
||||
}
|
||||
|
||||
PHAR_STR(key, str_key);
|
||||
|
||||
if (keylen <= (uint)dirlen) {
|
||||
if (keylen < (uint)dirlen || !strncmp(str_key, dir, dirlen)) {
|
||||
if (SUCCESS != zend_hash_move_forward(manifest)) {
|
||||
@@ -216,6 +224,7 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (*dir == '/') {
|
||||
/* root directory */
|
||||
if (keylen >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
|
||||
@@ -225,6 +234,7 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NULL != (found = (char *) memchr(str_key, '/', keylen))) {
|
||||
/* the entry has a path separator and is a subdirectory */
|
||||
entry = (char *) safe_emalloc(found - str_key, 1, 1);
|
||||
@@ -236,6 +246,7 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
|
||||
memcpy(entry, str_key, keylen);
|
||||
entry[keylen] = '\0';
|
||||
}
|
||||
|
||||
goto PHAR_ADD_ENTRY;
|
||||
} else {
|
||||
if (0 != memcmp(str_key, dir, dirlen)) {
|
||||
@@ -253,8 +264,10 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
save = str_key;
|
||||
save += dirlen + 1; /* seek to just past the path separator */
|
||||
|
||||
if (NULL != (found = (char *) memchr(save, '/', keylen - dirlen - 1))) {
|
||||
/* is subdirectory */
|
||||
save -= dirlen + 1;
|
||||
@@ -274,11 +287,14 @@ PHAR_ADD_ENTRY:
|
||||
if (keylen) {
|
||||
phar_add_empty(data, entry, keylen);
|
||||
}
|
||||
|
||||
efree(entry);
|
||||
|
||||
if (SUCCESS != zend_hash_move_forward(manifest)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILURE != zend_hash_has_more_elements(data)) {
|
||||
efree(dir);
|
||||
if (zend_hash_sort(data, zend_qsort, phar_compare_dir_name, 0 TSRMLS_CC) == FAILURE) {
|
||||
@@ -296,8 +312,7 @@ PHAR_ADD_ENTRY:
|
||||
/**
|
||||
* Open a directory handle within a phar archive
|
||||
*/
|
||||
php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode,
|
||||
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
|
||||
php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
php_url *resource = NULL;
|
||||
php_stream *ret;
|
||||
@@ -334,8 +349,8 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
|
||||
|
||||
host_len = strlen(resource->host);
|
||||
phar_request_initialize(TSRMLS_C);
|
||||
|
||||
internal_file = resource->path + 1; /* strip leading "/" */
|
||||
|
||||
if (FAILURE == phar_get_archive(&phar, resource->host, host_len, NULL, 0, &error TSRMLS_CC)) {
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
|
||||
@@ -346,9 +361,11 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
|
||||
php_url_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
efree(error);
|
||||
}
|
||||
|
||||
if (*internal_file == '\0') {
|
||||
/* root directory requested */
|
||||
internal_file = estrndup(internal_file - 1, 1);
|
||||
@@ -356,10 +373,12 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
|
||||
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) && !entry->is_dir) {
|
||||
php_url_free(resource);
|
||||
return NULL;
|
||||
@@ -389,6 +408,7 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char
|
||||
return phar_make_dirstream(internal_file, &phar->manifest TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCESS != zend_hash_move_forward(&phar->manifest)) {
|
||||
break;
|
||||
}
|
||||
@@ -415,43 +435,45 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
|
||||
/* pre-readonly check, we need to know if this is a data phar */
|
||||
if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, &entry2, &entry_len, 2, 2 TSRMLS_CC)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\", no phar archive specified", url_from);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
phar = NULL;
|
||||
}
|
||||
|
||||
efree(arch);
|
||||
efree(entry2);
|
||||
|
||||
if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\", write operations disabled", url_from);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((resource = phar_parse_url(wrapper, url_from, "w", options TSRMLS_CC)) == NULL) {
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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_from);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_from);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
host_len = strlen(resource->host);
|
||||
phar_request_initialize(TSRMLS_C);
|
||||
|
||||
if (FAILURE == phar_get_archive(&phar, resource->host, host_len, NULL, 0, &error TSRMLS_CC)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", resource->path+1, resource->host, error);
|
||||
efree(error);
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((e = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 2, &error, 1 TSRMLS_CC))) {
|
||||
@@ -462,25 +484,34 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
|
||||
}
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", directory already exists", resource->path+1, resource->host);
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
|
||||
efree(error);
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((e = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 0, &error, 1 TSRMLS_CC))) {
|
||||
/* entry exists as a file */
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", file already exists", resource->path+1, resource->host);
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
|
||||
efree(error);
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", unable to make cached phar writeable", resource->path+1, resource->host);
|
||||
php_url_free(resource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset((void *) &entry, 0, sizeof(phar_entry_info));
|
||||
@@ -489,11 +520,14 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
|
||||
if (phar->is_zip) {
|
||||
entry.is_zip = 1;
|
||||
}
|
||||
|
||||
entry.filename = estrdup(resource->path + 1);
|
||||
|
||||
if (phar->is_tar) {
|
||||
entry.is_tar = 1;
|
||||
entry.tar_type = TAR_DIR;
|
||||
}
|
||||
|
||||
entry.filename_len = strlen(resource->path + 1);
|
||||
php_url_free(resource);
|
||||
entry.is_dir = 1;
|
||||
@@ -502,20 +536,25 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
|
||||
entry.is_crc_checked = 1;
|
||||
entry.flags = PHAR_ENT_PERM_DEF_DIR;
|
||||
entry.old_flags = PHAR_ENT_PERM_DEF_DIR;
|
||||
|
||||
if (SUCCESS != zend_hash_add(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", entry.filename, phar->fname);
|
||||
efree(error);
|
||||
efree(entry.filename);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
|
||||
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", entry.filename, phar->fname, error);
|
||||
zend_hash_del(&phar->manifest, entry.filename, entry.filename_len);
|
||||
efree(error);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
return SUCCESS;
|
||||
|
||||
phar_add_virtual_dirs(phar, entry.filename, entry.filename_len TSRMLS_CC);
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -530,50 +569,60 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
|
||||
int arch_len, entry_len;
|
||||
php_url *resource = NULL;
|
||||
uint host_len;
|
||||
int key_type;
|
||||
phar_zstr key;
|
||||
char *str_key;
|
||||
uint key_len;
|
||||
ulong unused;
|
||||
uint path_len;
|
||||
|
||||
/* pre-readonly check, we need to know if this is a data phar */
|
||||
if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, &entry2, &entry_len, 2, 2 TSRMLS_CC)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
phar = NULL;
|
||||
}
|
||||
|
||||
efree(arch);
|
||||
efree(entry2);
|
||||
|
||||
if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot rmdir directory \"%s\", write operations disabled", url);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((resource = phar_parse_url(wrapper, url, "w", options TSRMLS_CC)) == NULL) {
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
host_len = strlen(resource->host);
|
||||
phar_request_initialize(TSRMLS_C);
|
||||
|
||||
if (FAILURE == phar_get_archive(&phar, resource->host, host_len, NULL, 0, &error TSRMLS_CC)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s", resource->path+1, resource->host, error);
|
||||
efree(error);
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path) - 1, 2, &error, 1 TSRMLS_CC))) {
|
||||
path_len = strlen(resource->path+1);
|
||||
|
||||
if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, path_len, 2, &error, 1 TSRMLS_CC))) {
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
|
||||
efree(error);
|
||||
@@ -581,21 +630,83 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", directory does not exist", resource->path+1, resource->host);
|
||||
}
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* now for the easy part */
|
||||
entry->is_deleted = 1;
|
||||
entry->is_modified = 1;
|
||||
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", entry->filename, phar->fname, error);
|
||||
zend_hash_del(&phar->manifest, entry->filename, entry->filename_len);
|
||||
if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", unable to make cached phar writeable", resource->path+1, resource->host);
|
||||
php_url_free(resource);
|
||||
efree(error);
|
||||
return FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (zend_hash_internal_pointer_reset(&phar->manifest);
|
||||
HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL));
|
||||
zend_hash_move_forward(&phar->manifest)) {
|
||||
|
||||
PHAR_STR(key, str_key);
|
||||
|
||||
if (!entry->is_deleted &&
|
||||
key_len > path_len &&
|
||||
memcmp(str_key, resource->path+1, path_len) == 0 &&
|
||||
IS_SLASH(str_key[path_len])) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty");
|
||||
if (entry->is_temp_dir) {
|
||||
efree(entry->filename);
|
||||
efree(entry);
|
||||
}
|
||||
php_url_free(resource);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (zend_hash_internal_pointer_reset(&phar->virtual_dirs);
|
||||
HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL));
|
||||
zend_hash_move_forward(&phar->virtual_dirs)) {
|
||||
|
||||
PHAR_STR(key, str_key);
|
||||
|
||||
if (!entry->is_deleted &&
|
||||
key_len > path_len &&
|
||||
memcmp(str_key, resource->path+1, path_len) == 0 &&
|
||||
IS_SLASH(str_key[path_len])) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty");
|
||||
if (entry->is_temp_dir) {
|
||||
efree(entry->filename);
|
||||
efree(entry);
|
||||
}
|
||||
php_url_free(resource);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry->is_temp_dir) {
|
||||
zend_hash_del(&phar->virtual_dirs, resource->path+1, path_len);
|
||||
efree(entry->filename);
|
||||
efree(entry);
|
||||
} else {
|
||||
entry->is_deleted = 1;
|
||||
entry->is_modified = 1;
|
||||
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
|
||||
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", entry->filename, phar->fname, error);
|
||||
php_url_free(resource);
|
||||
efree(error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
php_url_free(resource);
|
||||
return SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2006-2007 The PHP Group |
|
||||
| Copyright (c) 2006-2008 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
|
||||
@@ -29,9 +29,15 @@ PHAR_FUNC(phar_opendir) /* {{{ */
|
||||
int filename_len;
|
||||
zval *zcontext = NULL;
|
||||
|
||||
if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
if (!PHAR_G(intercepted)) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
|
||||
&& !cached_phars.arBuckets) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &zcontext) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@@ -97,13 +103,20 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
|
||||
long maxlen = PHP_STREAM_COPY_ALL;
|
||||
zval *zcontext = NULL;
|
||||
|
||||
if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
if (!PHAR_G(intercepted)) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
|
||||
&& !cached_phars.arBuckets) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
/* Parse arguments */
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
|
||||
return;
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
|
||||
char *arch, *entry, *fname;
|
||||
int arch_len, entry_len, fname_len;
|
||||
@@ -117,7 +130,7 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
|
||||
fname_len = strlen(fname);
|
||||
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
|
||||
char *name;
|
||||
phar_archive_data **pphar;
|
||||
phar_archive_data *phar;
|
||||
|
||||
efree(entry);
|
||||
entry = filename;
|
||||
@@ -131,7 +144,7 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
|
||||
}
|
||||
|
||||
/* retrieving a file defaults to within the current directory, so use this if possible */
|
||||
if (FAILURE == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
|
||||
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
efree(arch);
|
||||
goto skip_phar;
|
||||
}
|
||||
@@ -147,7 +160,7 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
|
||||
} else {
|
||||
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
|
||||
if (entry[0] == '/') {
|
||||
if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) {
|
||||
if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
|
||||
/* this file is not in the phar, use the original path */
|
||||
notfound:
|
||||
efree(arch);
|
||||
@@ -155,7 +168,7 @@ notfound:
|
||||
goto skip_phar;
|
||||
}
|
||||
} else {
|
||||
if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) {
|
||||
if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
|
||||
goto notfound;
|
||||
}
|
||||
}
|
||||
@@ -222,7 +235,12 @@ PHAR_FUNC(phar_readfile) /* {{{ */
|
||||
zval *zcontext = NULL;
|
||||
php_stream *stream;
|
||||
|
||||
if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
if (!PHAR_G(intercepted)) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
|
||||
&& !cached_phars.arBuckets) {
|
||||
goto skip_phar;
|
||||
}
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
|
||||
@@ -233,7 +251,7 @@ PHAR_FUNC(phar_readfile) /* {{{ */
|
||||
int arch_len, entry_len, fname_len;
|
||||
php_stream_context *context = NULL;
|
||||
char *name;
|
||||
phar_archive_data **pphar;
|
||||
phar_archive_data *phar;
|
||||
fname = zend_get_executed_filename(TSRMLS_C);
|
||||
|
||||
if (strncasecmp(fname, "phar://", 7)) {
|
||||
@@ -249,7 +267,7 @@ PHAR_FUNC(phar_readfile) /* {{{ */
|
||||
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
|
||||
entry_len = filename_len;
|
||||
/* retrieving a file defaults to within the current directory, so use this if possible */
|
||||
if (FAILURE == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
|
||||
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
efree(arch);
|
||||
goto skip_phar;
|
||||
}
|
||||
@@ -264,7 +282,7 @@ PHAR_FUNC(phar_readfile) /* {{{ */
|
||||
} else {
|
||||
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
|
||||
if (entry[0] == '/') {
|
||||
if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) {
|
||||
if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
|
||||
/* this file is not in the phar, use the original path */
|
||||
notfound:
|
||||
efree(entry);
|
||||
@@ -272,7 +290,7 @@ notfound:
|
||||
goto skip_phar;
|
||||
}
|
||||
} else {
|
||||
if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) {
|
||||
if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
|
||||
goto notfound;
|
||||
}
|
||||
}
|
||||
@@ -312,7 +330,12 @@ PHAR_FUNC(phar_fopen) /* {{{ */
|
||||
zval *zcontext = NULL;
|
||||
php_stream *stream;
|
||||
|
||||
if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
if (!PHAR_G(intercepted)) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
|
||||
&& !cached_phars.arBuckets) {
|
||||
/* no need to check, include_path not even specified in fopen/ no active phars */
|
||||
goto skip_phar;
|
||||
}
|
||||
@@ -324,7 +347,7 @@ PHAR_FUNC(phar_fopen) /* {{{ */
|
||||
int arch_len, entry_len, fname_len;
|
||||
php_stream_context *context = NULL;
|
||||
char *name;
|
||||
phar_archive_data **pphar;
|
||||
phar_archive_data *phar;
|
||||
fname = zend_get_executed_filename(TSRMLS_C);
|
||||
|
||||
if (strncasecmp(fname, "phar://", 7)) {
|
||||
@@ -340,7 +363,7 @@ PHAR_FUNC(phar_fopen) /* {{{ */
|
||||
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
|
||||
entry_len = filename_len;
|
||||
/* retrieving a file defaults to within the current directory, so use this if possible */
|
||||
if (FAILURE == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
|
||||
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
efree(arch);
|
||||
goto skip_phar;
|
||||
}
|
||||
@@ -355,7 +378,7 @@ PHAR_FUNC(phar_fopen) /* {{{ */
|
||||
} else {
|
||||
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
|
||||
if (entry[0] == '/') {
|
||||
if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) {
|
||||
if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
|
||||
/* this file is not in the phar, use the original path */
|
||||
notfound:
|
||||
efree(entry);
|
||||
@@ -363,7 +386,7 @@ notfound:
|
||||
goto skip_phar;
|
||||
}
|
||||
} else {
|
||||
if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) {
|
||||
if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
|
||||
/* this file is not in the phar, use the original path */
|
||||
goto notfound;
|
||||
}
|
||||
@@ -595,8 +618,7 @@ void phar_file_stat(const char *filename, php_stat_len filename_length, int type
|
||||
int arch_len, entry_len, fname_len;
|
||||
struct stat sb = {0};
|
||||
phar_entry_info *data = NULL;
|
||||
char *tmp;
|
||||
int tmp_len;
|
||||
phar_archive_data *phar;
|
||||
|
||||
fname = zend_get_executed_filename(TSRMLS_C);
|
||||
|
||||
@@ -607,28 +629,57 @@ void phar_file_stat(const char *filename, php_stat_len filename_length, int type
|
||||
goto skip_phar;
|
||||
}
|
||||
fname_len = strlen(fname);
|
||||
if (PHAR_G(last_phar) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
|
||||
arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
|
||||
arch_len = PHAR_G(last_phar_name_len);
|
||||
entry = estrndup(filename, filename_length);
|
||||
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
|
||||
entry_len = (int) filename_length;
|
||||
phar = PHAR_G(last_phar);
|
||||
goto splitted;
|
||||
}
|
||||
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
|
||||
phar_archive_data **pphar;
|
||||
|
||||
efree(entry);
|
||||
entry = estrndup(filename, filename_length);
|
||||
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
|
||||
entry_len = (int) filename_length;
|
||||
if (FAILURE == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
|
||||
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
efree(arch);
|
||||
goto skip_phar;
|
||||
}
|
||||
splitted:
|
||||
entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
|
||||
if (entry[0] == '/') {
|
||||
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &data)) {
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &data)) {
|
||||
efree(entry);
|
||||
goto stat_entry;
|
||||
}
|
||||
goto notfound;
|
||||
}
|
||||
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &data)) {
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &data)) {
|
||||
efree(entry);
|
||||
goto stat_entry;
|
||||
}
|
||||
if (zend_hash_exists(&(phar->virtual_dirs), entry, entry_len)) {
|
||||
efree(entry);
|
||||
efree(arch);
|
||||
if (IS_EXISTS_CHECK(type)) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
sb.st_size = 0;
|
||||
sb.st_mode = 0777;
|
||||
sb.st_mode |= S_IFDIR; /* regular directory */
|
||||
#ifdef NETWARE
|
||||
sb.st_mtime.tv_sec = phar->max_timestamp;
|
||||
sb.st_atime.tv_sec = phar->max_timestamp;
|
||||
sb.st_ctime.tv_sec = phar->max_timestamp;
|
||||
#else
|
||||
sb.st_mtime = phar->max_timestamp;
|
||||
sb.st_atime = phar->max_timestamp;
|
||||
sb.st_ctime = phar->max_timestamp;
|
||||
#endif
|
||||
goto statme_baby;
|
||||
} else {
|
||||
char *save, *save2, *actual;
|
||||
int save_len, save2_len, actual_len;
|
||||
@@ -647,54 +698,42 @@ notfound:
|
||||
PHAR_G(cwd_len) = 0;
|
||||
/* clean path without cwd */
|
||||
entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
|
||||
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &data)) {
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &data)) {
|
||||
PHAR_G(cwd) = save;
|
||||
PHAR_G(cwd_len) = save_len;
|
||||
efree(entry);
|
||||
efree(save2);
|
||||
if (IS_EXISTS_CHECK(type)) {
|
||||
efree(arch);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
goto stat_entry;
|
||||
} else {
|
||||
phar_archive_data *phar = *pphar;
|
||||
phar_zstr key;
|
||||
char *str_key;
|
||||
uint keylen;
|
||||
ulong unused;
|
||||
|
||||
}
|
||||
if (zend_hash_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
|
||||
PHAR_G(cwd) = save;
|
||||
PHAR_G(cwd_len) = save_len;
|
||||
/* original not found either, this is possibly a directory relative to cwd */
|
||||
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)) {
|
||||
PHAR_STR(key, str_key);
|
||||
if (!memcmp(actual, str_key, actual_len)) {
|
||||
efree(save2);
|
||||
efree(entry);
|
||||
/* directory found, all dirs have the same stat */
|
||||
if (str_key[actual_len] == '/') {
|
||||
sb.st_size = 0;
|
||||
sb.st_mode = 0777;
|
||||
sb.st_mode |= S_IFDIR; /* regular directory */
|
||||
#ifdef NETWARE
|
||||
sb.st_mtime.tv_sec = phar->max_timestamp;
|
||||
sb.st_atime.tv_sec = phar->max_timestamp;
|
||||
sb.st_ctime.tv_sec = phar->max_timestamp;
|
||||
#else
|
||||
sb.st_mtime = phar->max_timestamp;
|
||||
sb.st_atime = phar->max_timestamp;
|
||||
sb.st_ctime = phar->max_timestamp;
|
||||
#endif
|
||||
goto statme_baby;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SUCCESS != zend_hash_move_forward(&phar->manifest)) {
|
||||
break;
|
||||
}
|
||||
efree(entry);
|
||||
efree(save2);
|
||||
efree(arch);
|
||||
if (IS_EXISTS_CHECK(type)) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
sb.st_size = 0;
|
||||
sb.st_mode = 0777;
|
||||
sb.st_mode |= S_IFDIR; /* regular directory */
|
||||
#ifdef NETWARE
|
||||
sb.st_mtime.tv_sec = phar->max_timestamp;
|
||||
sb.st_atime.tv_sec = phar->max_timestamp;
|
||||
sb.st_ctime.tv_sec = phar->max_timestamp;
|
||||
#else
|
||||
sb.st_mtime = phar->max_timestamp;
|
||||
sb.st_atime = phar->max_timestamp;
|
||||
sb.st_ctime = phar->max_timestamp;
|
||||
#endif
|
||||
goto statme_baby;
|
||||
}
|
||||
PHAR_G(cwd) = save;
|
||||
PHAR_G(cwd_len) = save_len;
|
||||
efree(entry);
|
||||
efree(save2);
|
||||
efree(arch);
|
||||
@@ -705,6 +744,7 @@ notfound:
|
||||
RETURN_FALSE;
|
||||
}
|
||||
stat_entry:
|
||||
efree(arch);
|
||||
if (!data->is_dir) {
|
||||
sb.st_size = data->uncompressed_filesize;
|
||||
sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
|
||||
@@ -743,30 +783,18 @@ stat_entry:
|
||||
}
|
||||
|
||||
statme_baby:
|
||||
efree(arch);
|
||||
if (!(*pphar)->is_writeable) {
|
||||
if (!phar->is_writeable) {
|
||||
sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
|
||||
}
|
||||
|
||||
|
||||
sb.st_nlink = 1;
|
||||
sb.st_rdev = -1;
|
||||
if (data) {
|
||||
tmp_len = data->filename_len + (*pphar)->alias_len;
|
||||
} else {
|
||||
tmp_len = (*pphar)->alias_len + 1;
|
||||
}
|
||||
tmp = (char *) emalloc(tmp_len);
|
||||
memcpy(tmp, (*pphar)->alias, (*pphar)->alias_len);
|
||||
if (data) {
|
||||
memcpy(tmp + (*pphar)->alias_len, data->filename, data->filename_len);
|
||||
} else {
|
||||
*(tmp + (*pphar)->alias_len) = '/';
|
||||
}
|
||||
/* this is only for APC, so use /dev/null device - no chance of conflict there! */
|
||||
sb.st_dev = 0xc;
|
||||
/* generate unique inode number for alias/filename, so no phars will conflict */
|
||||
sb.st_ino = (unsigned short)zend_get_hash_value(tmp, tmp_len);
|
||||
efree(tmp);
|
||||
if (data) {
|
||||
sb.st_ino = data->inode;
|
||||
}
|
||||
#ifndef PHP_WIN32
|
||||
sb.st_blksize = -1;
|
||||
sb.st_blocks = -1;
|
||||
@@ -783,14 +811,18 @@ skip_phar:
|
||||
|
||||
#define PharFileFunction(fname, funcnum, orig) \
|
||||
void fname(INTERNAL_FUNCTION_PARAMETERS) { \
|
||||
char *filename; \
|
||||
int filename_len; \
|
||||
\
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
|
||||
return; \
|
||||
if (!PHAR_G(intercepted)) { \
|
||||
PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
|
||||
} else { \
|
||||
char *filename; \
|
||||
int filename_len; \
|
||||
\
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
|
||||
} \
|
||||
\
|
||||
phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -854,13 +886,13 @@ PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
|
||||
PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool is_executable(string filename)
|
||||
Returns true if file is executable */
|
||||
/* {{{ proto bool file_exists(string filename)
|
||||
Returns true if filename exists */
|
||||
PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool is_executable(string filename)
|
||||
Returns true if file is executable */
|
||||
/* {{{ proto bool is_dir(string filename)
|
||||
Returns true if file is directory */
|
||||
PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir)
|
||||
/* }}} */
|
||||
|
||||
@@ -869,7 +901,12 @@ PHAR_FUNC(phar_is_file) /* {{{ */
|
||||
char *filename;
|
||||
int filename_len;
|
||||
|
||||
if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
if (!PHAR_G(intercepted)) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
|
||||
&& !cached_phars.arBuckets) {
|
||||
goto skip_phar;
|
||||
}
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
|
||||
@@ -888,19 +925,19 @@ PHAR_FUNC(phar_is_file) /* {{{ */
|
||||
}
|
||||
fname_len = strlen(fname);
|
||||
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
|
||||
phar_archive_data **pphar;
|
||||
phar_archive_data *phar;
|
||||
|
||||
efree(entry);
|
||||
entry = filename;
|
||||
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
|
||||
entry_len = filename_len;
|
||||
/* retrieving a file within the current directory, so use this if possible */
|
||||
if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
|
||||
if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
phar_entry_info *etemp;
|
||||
|
||||
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
|
||||
if (entry[0] == '/') {
|
||||
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
|
||||
/* this file is not in the current directory, use the original path */
|
||||
found_it:
|
||||
efree(entry);
|
||||
@@ -908,7 +945,7 @@ found_it:
|
||||
RETURN_BOOL(!etemp->is_dir);
|
||||
}
|
||||
} else {
|
||||
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &etemp)) {
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &etemp)) {
|
||||
goto found_it;
|
||||
}
|
||||
}
|
||||
@@ -929,7 +966,12 @@ PHAR_FUNC(phar_is_link) /* {{{ */
|
||||
char *filename;
|
||||
int filename_len;
|
||||
|
||||
if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
if (!PHAR_G(intercepted)) {
|
||||
goto skip_phar;
|
||||
}
|
||||
|
||||
if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
|
||||
&& !cached_phars.arBuckets) {
|
||||
goto skip_phar;
|
||||
}
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
|
||||
@@ -948,19 +990,19 @@ PHAR_FUNC(phar_is_link) /* {{{ */
|
||||
}
|
||||
fname_len = strlen(fname);
|
||||
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
|
||||
phar_archive_data **pphar;
|
||||
phar_archive_data *phar;
|
||||
|
||||
efree(entry);
|
||||
entry = filename;
|
||||
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
|
||||
entry_len = filename_len;
|
||||
/* retrieving a file within the current directory, so use this if possible */
|
||||
if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
|
||||
if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
phar_entry_info *etemp;
|
||||
|
||||
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
|
||||
if (entry[0] == '/') {
|
||||
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
|
||||
/* this file is not in the current directory, use the original path */
|
||||
found_it:
|
||||
efree(entry);
|
||||
@@ -968,7 +1010,7 @@ found_it:
|
||||
RETURN_BOOL(etemp->link);
|
||||
}
|
||||
} else {
|
||||
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &etemp)) {
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &etemp)) {
|
||||
goto found_it;
|
||||
}
|
||||
}
|
||||
@@ -979,7 +1021,7 @@ found_it:
|
||||
}
|
||||
}
|
||||
skip_phar:
|
||||
PHAR_G(orig_file_exists)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
PHAR_G(orig_is_link)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -995,6 +1037,24 @@ PharFileFunction(phar_stat, FS_STAT, orig_stat)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void phar_intercept_functions(TSRMLS_D) */
|
||||
void phar_intercept_functions(TSRMLS_D)
|
||||
{
|
||||
if (!PHAR_G(request_init)) {
|
||||
PHAR_G(cwd) = NULL;
|
||||
PHAR_G(cwd_len) = 0;
|
||||
}
|
||||
PHAR_G(intercepted) = 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void phar_release_functions(TSRMLS_D) */
|
||||
void phar_release_functions(TSRMLS_D)
|
||||
{
|
||||
PHAR_G(intercepted) = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void phar_intercept_functions_init(TSRMLS_D) */
|
||||
#define PHAR_INTERCEPT(func) \
|
||||
PHAR_G(orig_##func) = NULL; \
|
||||
if (SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \
|
||||
@@ -1002,17 +1062,10 @@ PharFileFunction(phar_stat, FS_STAT, orig_stat)
|
||||
orig->internal_function.handler = phar_##func; \
|
||||
}
|
||||
|
||||
void phar_intercept_functions(TSRMLS_D)
|
||||
void phar_intercept_functions_init(TSRMLS_D)
|
||||
{
|
||||
zend_function *orig;
|
||||
|
||||
if (!PHAR_G(request_init)) {
|
||||
PHAR_G(cwd) = NULL;
|
||||
PHAR_G(cwd_len) = 0;
|
||||
} else if (PHAR_G(orig_fopen)) {
|
||||
/* don't double-intercept */
|
||||
return;
|
||||
}
|
||||
PHAR_INTERCEPT(fopen);
|
||||
PHAR_INTERCEPT(file_get_contents);
|
||||
PHAR_INTERCEPT(is_file);
|
||||
@@ -1035,17 +1088,18 @@ void phar_intercept_functions(TSRMLS_D)
|
||||
PHAR_INTERCEPT(lstat);
|
||||
PHAR_INTERCEPT(stat);
|
||||
PHAR_INTERCEPT(readfile);
|
||||
PHAR_G(intercepted) = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void phar_release_functions(TSRMLS_D) */
|
||||
/* {{{ void phar_intercept_functions_shutdown(TSRMLS_D) */
|
||||
#define PHAR_RELEASE(func) \
|
||||
if (PHAR_G(orig_##func) && SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \
|
||||
orig->internal_function.handler = PHAR_G(orig_##func); \
|
||||
} \
|
||||
PHAR_G(orig_##func) = NULL;
|
||||
|
||||
void phar_release_functions(TSRMLS_D)
|
||||
void phar_intercept_functions_shutdown(TSRMLS_D)
|
||||
{
|
||||
zend_function *orig;
|
||||
|
||||
@@ -1070,6 +1124,7 @@ void phar_release_functions(TSRMLS_D)
|
||||
PHAR_RELEASE(lstat);
|
||||
PHAR_RELEASE(stat);
|
||||
PHAR_RELEASE(readfile);
|
||||
PHAR_G(intercepted) = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2006-2007 The PHP Group |
|
||||
| Copyright (c) 2006-2008 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
@@ -22,6 +22,8 @@
|
||||
BEGIN_EXTERN_C()
|
||||
void phar_intercept_functions(TSRMLS_D);
|
||||
void phar_release_functions(TSRMLS_D);
|
||||
void phar_intercept_functions_init(TSRMLS_D);
|
||||
void phar_intercept_functions_shutdown(TSRMLS_D);
|
||||
END_EXTERN_C()
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,18 +4,18 @@ $s = str_replace("\r", '', file_get_contents(dirname(__FILE__) . '/shortarc.php'
|
||||
$s .= "\nExtract_Phar::go();\n__HALT_COMPILER();";
|
||||
$news = '';
|
||||
foreach (token_get_all($s) as $token) {
|
||||
if (is_array($token)) {
|
||||
if ($token[0] == T_COMMENT) {
|
||||
$token[1] = '';
|
||||
}
|
||||
if ($token[0] == T_WHITESPACE) {
|
||||
$n = str_repeat("\n", substr_count($token[1], "\n"));
|
||||
$token[1] = strlen($n) ? $n : ' ';
|
||||
}
|
||||
$news .= $token[1];
|
||||
} else {
|
||||
$news .= $token;
|
||||
}
|
||||
if (is_array($token)) {
|
||||
if ($token[0] == T_COMMENT) {
|
||||
$token[1] = '';
|
||||
}
|
||||
if ($token[0] == T_WHITESPACE) {
|
||||
$n = str_repeat("\n", substr_count($token[1], "\n"));
|
||||
$token[1] = strlen($n) ? $n : ' ';
|
||||
}
|
||||
$news .= $token[1];
|
||||
} else {
|
||||
$news .= $token;
|
||||
}
|
||||
}
|
||||
$s = $news . ' ?>';
|
||||
$slen = strlen($s) - strlen('index.php') - strlen("000");
|
||||
@@ -34,7 +34,7 @@ $stub = '/*
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension generated stub |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2005-' . date('Y') . ' The PHP Group |
|
||||
| Copyright (c) 2005-' . date('Y') . ' The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
@@ -57,50 +57,50 @@ $s1split = str_split($s1, 2046);
|
||||
$s3split = str_split($s3, 2046);
|
||||
$took = false;
|
||||
foreach ($s1split as $i => $chunk) {
|
||||
if ($took) {
|
||||
$s1split[$i] = substr($chunk, 1);
|
||||
$took = false;
|
||||
}
|
||||
if ($chunk[strlen($chunk) - 1] == '\\') {
|
||||
$s1split[$i] .= $s1split[$i + 1][0];
|
||||
$took = true;
|
||||
}
|
||||
if ($took) {
|
||||
$s1split[$i] = substr($chunk, 1);
|
||||
$took = false;
|
||||
}
|
||||
if ($chunk[strlen($chunk) - 1] == '\\') {
|
||||
$s1split[$i] .= $s1split[$i + 1][0];
|
||||
$took = true;
|
||||
}
|
||||
}
|
||||
foreach ($s3split as $i => $chunk) {
|
||||
if ($took) {
|
||||
$s3split[$i] = substr($chunk, 1);
|
||||
$took = false;
|
||||
}
|
||||
if ($chunk[strlen($chunk) - 1] == '\\') {
|
||||
$s3split[$i] .= $s3split[$i + 1][0];
|
||||
$took = true;
|
||||
}
|
||||
if ($took) {
|
||||
$s3split[$i] = substr($chunk, 1);
|
||||
$took = false;
|
||||
}
|
||||
if ($chunk[strlen($chunk) - 1] == '\\') {
|
||||
$s3split[$i] .= $s3split[$i + 1][0];
|
||||
$took = true;
|
||||
}
|
||||
}
|
||||
$stub .= "\tstatic const char newstub0[] = \"" . $webs . '";
|
||||
';
|
||||
foreach ($s1split as $i => $chunk) {
|
||||
$s1count = $i + 1;
|
||||
$stub .= "\tstatic const char newstub1_" . $i . '[] = "' . $chunk . '";
|
||||
$s1count = $i + 1;
|
||||
$stub .= "\tstatic const char newstub1_" . $i . '[] = "' . $chunk . '";
|
||||
';
|
||||
}
|
||||
$stub .= "\tstatic const char newstub2[] = \"" . $s2 . "\";
|
||||
";
|
||||
foreach ($s3split as $i => $chunk) {
|
||||
$s3count = $i + 1;
|
||||
$stub .= "\tstatic const char newstub3_" . $i . '[] = "' . $chunk . '";
|
||||
$s3count = $i + 1;
|
||||
$stub .= "\tstatic const char newstub3_" . $i . '[] = "' . $chunk . '";
|
||||
';
|
||||
}
|
||||
$stub .= "\n\tstatic const int newstub_len = " . $slen . ";
|
||||
|
||||
\t*len = spprintf(stub, name_len + web_len + newstub_len, \"%s%s" . str_repeat('%s', $s1count) . '%s%s%d'
|
||||
. str_repeat('%s', $s3count) . '", newstub0, web';
|
||||
. str_repeat('%s', $s3count) . '", newstub0, web';
|
||||
foreach ($s1split as $i => $unused) {
|
||||
$stub .= ', newstub1_' . $i;
|
||||
$stub .= ', newstub1_' . $i;
|
||||
}
|
||||
$stub .= ', index_php, newstub2';
|
||||
$stub .= ", name_len + web_len + newstub_len";
|
||||
foreach ($s3split as $i => $unused) {
|
||||
$stub .= ', newstub3_' . $i;
|
||||
$stub .= ', newstub3_' . $i;
|
||||
}
|
||||
$stub .= ");
|
||||
}";
|
||||
|
||||
@@ -53,29 +53,29 @@ require_once 'PEAR/PackageFileManager2.php';
|
||||
PEAR::setErrorHandling(PEAR_ERROR_DIE);
|
||||
|
||||
$options = array(
|
||||
'filelistgenerator' => 'CVS',
|
||||
'changelogoldtonew' => false,
|
||||
'simpleoutput' => true,
|
||||
'baseinstalldir' => '/',
|
||||
'packagedirectory' => dirname(__FILE__),
|
||||
'packagefile' => 'package.xml',
|
||||
'clearcontents' => true,
|
||||
'ignore' => array('package*.php', 'package*.xml'),
|
||||
'dir_roles' => array(
|
||||
'docs' => 'doc',
|
||||
'examples' => 'doc',
|
||||
'tests' => 'test',
|
||||
'phar' => 'src',
|
||||
),
|
||||
'exceptions' => array(
|
||||
'CREDITS' => 'doc',
|
||||
'EXPERIMENTAL' => 'doc',
|
||||
'LICENSE' => 'doc',
|
||||
'Makefile.frag' => 'src',
|
||||
'phar_path_check.re' => 'src',
|
||||
'TODO' => 'doc',
|
||||
'phar.phar' => 'script',
|
||||
),
|
||||
'filelistgenerator' => 'CVS',
|
||||
'changelogoldtonew' => false,
|
||||
'simpleoutput' => true,
|
||||
'baseinstalldir' => '/',
|
||||
'packagedirectory' => dirname(__FILE__),
|
||||
'packagefile' => 'package.xml',
|
||||
'clearcontents' => true,
|
||||
'ignore' => array('package*.php', 'package*.xml'),
|
||||
'dir_roles' => array(
|
||||
'docs' => 'doc',
|
||||
'examples' => 'doc',
|
||||
'tests' => 'test',
|
||||
'phar' => 'src',
|
||||
),
|
||||
'exceptions' => array(
|
||||
'CREDITS' => 'doc',
|
||||
'EXPERIMENTAL' => 'doc',
|
||||
'LICENSE' => 'doc',
|
||||
'Makefile.frag' => 'src',
|
||||
'phar_path_check.re' => 'src',
|
||||
'TODO' => 'doc',
|
||||
'phar.phar' => 'script',
|
||||
),
|
||||
);
|
||||
|
||||
$package = PEAR_PackageFileManager2::importOptions(dirname(__FILE__) . '/package.xml', $options);
|
||||
@@ -100,9 +100,9 @@ $package->setNotes("\n$notes\n");
|
||||
$package->generateContents();
|
||||
|
||||
if (isset($_GET['make']) || (isset($_SERVER['argv']) && @$_SERVER['argv'][1] == 'make')) {
|
||||
$package->writePackageFile();
|
||||
$package->writePackageFile();
|
||||
} else {
|
||||
$package->debugPackageFile();
|
||||
$package->debugPackageFile();
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
1582
ext/phar/phar.c
1582
ext/phar/phar.c
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2006-2007 The PHP Group |
|
||||
| Copyright (c) 2006-2008 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
@@ -72,7 +72,16 @@
|
||||
#endif
|
||||
|
||||
#ifndef E_RECOVERABLE_ERROR
|
||||
#define E_RECOVERABLE_ERROR E_ERROR
|
||||
# define E_RECOVERABLE_ERROR E_ERROR
|
||||
#endif
|
||||
|
||||
#ifndef pestrndup
|
||||
# define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
|
||||
#endif
|
||||
|
||||
#ifndef ALLOC_PERMANENT_ZVAL
|
||||
# define ALLOC_PERMANENT_ZVAL(z) \
|
||||
(z) = (zval*)malloc(sizeof(zval))
|
||||
#endif
|
||||
|
||||
/* PHP_ because this is public information via MINFO */
|
||||
@@ -103,7 +112,7 @@
|
||||
#define PHAR_SIG_SHA1 0x0002
|
||||
#define PHAR_SIG_SHA256 0x0003
|
||||
#define PHAR_SIG_SHA512 0x0004
|
||||
#define PHAR_SIG_PGP 0x0010
|
||||
#define PHAR_SIG_OPENSSL 0x0010
|
||||
|
||||
/* flags byte for each file adheres to these bitmasks.
|
||||
All unused values are reserved */
|
||||
@@ -132,15 +141,29 @@
|
||||
#define TAR_DIR '5'
|
||||
#define TAR_NEW '8'
|
||||
|
||||
#define PHAR_MUNG_PHP_SELF (1<<0)
|
||||
#define PHAR_MUNG_REQUEST_URI (1<<1)
|
||||
#define PHAR_MUNG_SCRIPT_NAME (1<<2)
|
||||
#define PHAR_MUNG_SCRIPT_FILENAME (1<<3)
|
||||
|
||||
typedef struct _phar_entry_fp phar_entry_fp;
|
||||
typedef struct _phar_archive_data phar_archive_data;
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(phar)
|
||||
HashTable phar_fname_map;
|
||||
/* for cached phars, this is a per-process store of fp/ufp */
|
||||
phar_entry_fp *cached_fp;
|
||||
HashTable phar_alias_map;
|
||||
HashTable phar_SERVER_mung_list;
|
||||
int phar_SERVER_mung_list;
|
||||
int readonly;
|
||||
char* cache_list;
|
||||
int manifest_cached;
|
||||
int persist;
|
||||
int has_zlib;
|
||||
int has_bz2;
|
||||
zend_bool readonly_orig;
|
||||
zend_bool require_hash_orig;
|
||||
zend_bool intercepted;
|
||||
int request_init;
|
||||
int require_hash;
|
||||
int request_done;
|
||||
@@ -171,6 +194,15 @@ ZEND_BEGIN_MODULE_GLOBALS(phar)
|
||||
char* cwd;
|
||||
int cwd_len;
|
||||
int cwd_init;
|
||||
char *openssl_privatekey;
|
||||
int openssl_privatekey_len;
|
||||
/* phar_get_archive cache */
|
||||
char* last_phar_name;
|
||||
int last_phar_name_len;
|
||||
char* last_alias;
|
||||
int last_alias_len;
|
||||
phar_archive_data* last_phar;
|
||||
HashTable mime_types;
|
||||
ZEND_END_MODULE_GLOBALS(phar)
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS(phar)
|
||||
@@ -213,7 +245,6 @@ enum phar_fp_type {
|
||||
PHAR_TMP
|
||||
};
|
||||
|
||||
typedef struct _phar_archive_data phar_archive_data;
|
||||
/* entry for one file in a phar file */
|
||||
typedef struct _phar_entry_info {
|
||||
/* first bytes are exactly as in file */
|
||||
@@ -226,6 +257,7 @@ typedef struct _phar_entry_info {
|
||||
/* when changing compression, save old flags in case fp is NULL */
|
||||
php_uint32 old_flags;
|
||||
zval *metadata;
|
||||
int metadata_len; /* only used for cached manifests */
|
||||
php_uint32 filename_len;
|
||||
char *filename;
|
||||
enum phar_fp_type fp_type;
|
||||
@@ -256,6 +288,12 @@ typedef struct _phar_entry_info {
|
||||
char tar_type;
|
||||
/* zip-based phar file stuff */
|
||||
int is_zip:1;
|
||||
/* for cached phar entries */
|
||||
int is_persistent:1;
|
||||
/* position in the manifest */
|
||||
uint manifest_pos;
|
||||
/* for stat */
|
||||
unsigned short inode;
|
||||
} phar_entry_info;
|
||||
|
||||
/* information about a phar file (the archive itself) */
|
||||
@@ -271,6 +309,8 @@ struct _phar_archive_data {
|
||||
size_t internal_file_start;
|
||||
size_t halt_offset;
|
||||
HashTable manifest;
|
||||
/* hash of virtual directories, as in path/to/file.txt has path/to and path as virtual directories */
|
||||
HashTable virtual_dirs;
|
||||
/* hash of mounted directory paths */
|
||||
HashTable mounted_dirs;
|
||||
php_uint32 flags;
|
||||
@@ -284,6 +324,7 @@ struct _phar_archive_data {
|
||||
int sig_len;
|
||||
char *signature;
|
||||
zval *metadata;
|
||||
int metadata_len; /* only used for cached manifests */
|
||||
/* if 1, then this alias was manually specified by the user and is not a permanent alias */
|
||||
int is_temporary_alias:1;
|
||||
int is_modified:1;
|
||||
@@ -297,8 +338,130 @@ struct _phar_archive_data {
|
||||
int is_tar:1;
|
||||
/* PharData variables */
|
||||
int is_data:1;
|
||||
/* for cached phar manifests */
|
||||
int is_persistent:1;
|
||||
uint phar_pos;
|
||||
};
|
||||
|
||||
typedef struct _phar_entry_fp_info {
|
||||
enum phar_fp_type fp_type;
|
||||
/* offset within fp of the file contents */
|
||||
long offset;
|
||||
} phar_entry_fp_info;
|
||||
|
||||
struct _phar_entry_fp {
|
||||
php_stream *fp;
|
||||
php_stream *ufp;
|
||||
phar_entry_fp_info *manifest;
|
||||
};
|
||||
|
||||
static inline php_stream *phar_get_entrypfp(phar_entry_info *entry TSRMLS_DC)
|
||||
{
|
||||
if (!entry->is_persistent) {
|
||||
return entry->phar->fp;
|
||||
}
|
||||
return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].fp;
|
||||
}
|
||||
|
||||
static inline php_stream *phar_get_entrypufp(phar_entry_info *entry TSRMLS_DC)
|
||||
{
|
||||
if (!entry->is_persistent) {
|
||||
return entry->phar->ufp;
|
||||
}
|
||||
return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].ufp;
|
||||
}
|
||||
|
||||
static inline void phar_set_entrypfp(phar_entry_info *entry, php_stream *fp TSRMLS_DC)
|
||||
{
|
||||
if (!entry->phar->is_persistent) {
|
||||
entry->phar->fp = fp;
|
||||
return;
|
||||
}
|
||||
|
||||
PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].fp = fp;
|
||||
}
|
||||
|
||||
static inline void phar_set_entrypufp(phar_entry_info *entry, php_stream *fp TSRMLS_DC)
|
||||
{
|
||||
if (!entry->phar->is_persistent) {
|
||||
entry->phar->ufp = fp;
|
||||
return;
|
||||
}
|
||||
|
||||
PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].ufp = fp;
|
||||
}
|
||||
|
||||
static inline php_stream *phar_get_pharfp(phar_archive_data *phar TSRMLS_DC)
|
||||
{
|
||||
if (!phar->is_persistent) {
|
||||
return phar->fp;
|
||||
}
|
||||
return PHAR_GLOBALS->cached_fp[phar->phar_pos].fp;
|
||||
}
|
||||
|
||||
static inline php_stream *phar_get_pharufp(phar_archive_data *phar TSRMLS_DC)
|
||||
{
|
||||
if (!phar->is_persistent) {
|
||||
return phar->ufp;
|
||||
}
|
||||
return PHAR_GLOBALS->cached_fp[phar->phar_pos].ufp;
|
||||
}
|
||||
|
||||
static inline void phar_set_pharfp(phar_archive_data *phar, php_stream *fp TSRMLS_DC)
|
||||
{
|
||||
if (!phar->is_persistent) {
|
||||
phar->fp = fp;
|
||||
return;
|
||||
}
|
||||
|
||||
PHAR_GLOBALS->cached_fp[phar->phar_pos].fp = fp;
|
||||
}
|
||||
|
||||
static inline void phar_set_pharufp(phar_archive_data *phar, php_stream *fp TSRMLS_DC)
|
||||
{
|
||||
if (!phar->is_persistent) {
|
||||
phar->ufp = fp;
|
||||
return;
|
||||
}
|
||||
|
||||
PHAR_GLOBALS->cached_fp[phar->phar_pos].ufp = fp;
|
||||
}
|
||||
|
||||
static inline void phar_set_fp_type(phar_entry_info *entry, enum phar_fp_type type, off_t offset TSRMLS_DC)
|
||||
{
|
||||
phar_entry_fp_info *data;
|
||||
|
||||
if (!entry->is_persistent) {
|
||||
entry->fp_type = type;
|
||||
entry->offset = offset;
|
||||
return;
|
||||
}
|
||||
data = &(PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos]);
|
||||
data->fp_type = type;
|
||||
data->offset = offset;
|
||||
}
|
||||
|
||||
static inline enum phar_fp_type phar_get_fp_type(phar_entry_info *entry TSRMLS_DC)
|
||||
{
|
||||
if (!entry->is_persistent) {
|
||||
return entry->fp_type;
|
||||
}
|
||||
return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].fp_type;
|
||||
}
|
||||
|
||||
static inline off_t phar_get_fp_offset(phar_entry_info *entry TSRMLS_DC)
|
||||
{
|
||||
if (!entry->is_persistent) {
|
||||
return entry->offset;
|
||||
}
|
||||
if (PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].fp_type == PHAR_FP) {
|
||||
if (!PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].offset) {
|
||||
PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].offset = entry->offset;
|
||||
}
|
||||
}
|
||||
return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].offset;
|
||||
}
|
||||
|
||||
#define PHAR_MIME_PHP '\0'
|
||||
#define PHAR_MIME_PHPS '\1'
|
||||
#define PHAR_MIME_OTHER '\2'
|
||||
@@ -330,8 +493,8 @@ union _phar_archive_object {
|
||||
zend_object std;
|
||||
spl_filesystem_object spl;
|
||||
struct {
|
||||
zend_object std;
|
||||
phar_archive_data *archive;
|
||||
zend_object std;
|
||||
phar_archive_data *archive;
|
||||
} arc;
|
||||
};
|
||||
#endif
|
||||
@@ -342,8 +505,8 @@ union _phar_entry_object {
|
||||
zend_object std;
|
||||
spl_filesystem_object spl;
|
||||
struct {
|
||||
zend_object std;
|
||||
phar_entry_info *entry;
|
||||
zend_object std;
|
||||
phar_entry_info *entry;
|
||||
} ent;
|
||||
};
|
||||
#endif
|
||||
@@ -357,11 +520,15 @@ extern char *(*phar_save_resolve_path)(const char *filename, int filename_len TS
|
||||
#if PHP_VERSION_ID >= 60000
|
||||
typedef zstr phar_zstr;
|
||||
#define PHAR_STR(a, b) \
|
||||
spprintf(&b, 0, "%r", a.s);
|
||||
spprintf(&b, 0, "%s", a.s);
|
||||
#define PHAR_ZSTR(a, b) \
|
||||
b = ZSTR(a);
|
||||
#else
|
||||
typedef char *phar_zstr;
|
||||
#define PHAR_STR(a, b) \
|
||||
b = a;
|
||||
#define PHAR_ZSTR(a, b) \
|
||||
b = a;
|
||||
#endif
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
@@ -391,6 +558,17 @@ static inline int phar_validate_alias(const char *alias, int alias_len) /* {{{ *
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static inline void phar_set_inode(phar_entry_info *entry TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char tmp[MAXPATHLEN];
|
||||
int tmp_len;
|
||||
|
||||
tmp_len = entry->filename_len + entry->phar->fname_len;
|
||||
memcpy(tmp, entry->phar->fname, entry->phar->fname_len);
|
||||
memcpy(tmp + entry->phar->fname_len, entry->filename, entry->filename_len);
|
||||
entry->inode = (unsigned short)zend_get_hash_value(tmp, tmp_len);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void phar_request_initialize(TSRMLS_D);
|
||||
|
||||
@@ -405,12 +583,15 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error TSRMLS_
|
||||
int phar_free_alias(phar_archive_data *phar, char *alias, int alias_len TSRMLS_DC);
|
||||
int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len, char *alias, int alias_len, char **error TSRMLS_DC);
|
||||
int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
|
||||
int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error TSRMLS_DC);
|
||||
int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, int *signature_length, char **error TSRMLS_DC);
|
||||
|
||||
/* utility functions */
|
||||
char *phar_create_default_stub(const char *index_php, const char *web_index, size_t *len, char **error TSRMLS_DC);
|
||||
char *phar_decompress_filter(phar_entry_info * entry, int return_unknown);
|
||||
char *phar_compress_filter(phar_entry_info * entry, int return_unknown);
|
||||
|
||||
void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC);
|
||||
int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len TSRMLS_DC);
|
||||
char *phar_find_in_include_path(char *file, int file_len, phar_archive_data **pphar TSRMLS_DC);
|
||||
char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC);
|
||||
@@ -426,6 +607,7 @@ phar_entry_info *phar_get_link_source(phar_entry_info *entry TSRMLS_DC);
|
||||
int phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error TSRMLS_DC);
|
||||
int phar_separate_entry_fp(phar_entry_info *entry, char **error TSRMLS_DC);
|
||||
int phar_open_archive_fp(phar_archive_data *phar TSRMLS_DC);
|
||||
int phar_copy_on_write(phar_archive_data **pphar TSRMLS_DC);
|
||||
|
||||
/* tar functions in tar.c */
|
||||
int phar_is_tar(char *buf, char *fname);
|
||||
@@ -441,6 +623,9 @@ int phar_zip_flush(phar_archive_data *archive, char *user_stub, long len, int de
|
||||
#ifdef PHAR_MAIN
|
||||
static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
|
||||
extern php_stream_wrapper php_stream_phar_wrapper;
|
||||
#else
|
||||
extern HashTable cached_phars;
|
||||
extern HashTable cached_alias;
|
||||
#endif
|
||||
|
||||
int phar_archive_delref(phar_archive_data *phar TSRMLS_DC);
|
||||
@@ -451,7 +636,7 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in
|
||||
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC);
|
||||
int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC);
|
||||
int phar_flush(phar_archive_data *archive, char *user_stub, long len, int convert, char **error TSRMLS_DC);
|
||||
int phar_detect_phar_fname_ext(const char *filename, int check_length, const char **ext_str, int *ext_len, int executable, int for_create, int is_complete TSRMLS_DC);
|
||||
int phar_detect_phar_fname_ext(const char *filename, int filename_len, const char **ext_str, int *ext_len, int executable, int for_create, int is_complete TSRMLS_DC);
|
||||
int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC);
|
||||
|
||||
typedef enum {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2007 The PHP Group |
|
||||
| Copyright (c) 2007-2008 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2007 The PHP Group |
|
||||
| Copyright (c) 2007-2008 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2005 The PHP Group |
|
||||
| Copyright (c) 2005-2008 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
@@ -22,7 +22,7 @@
|
||||
#ifndef PHP_PHAR_H
|
||||
#define PHP_PHAR_H
|
||||
|
||||
#define PHP_PHAR_VERSION "2.0.0b2-dev"
|
||||
#define PHP_PHAR_VERSION "2.0.0b2-dev"
|
||||
|
||||
#include "ext/standard/basic_functions.h"
|
||||
extern zend_module_entry phar_module_entry;
|
||||
@@ -34,7 +34,7 @@ extern zend_module_entry phar_module_entry;
|
||||
#define PHP_PHAR_API
|
||||
#endif
|
||||
|
||||
#endif /* PHP_PHAR_H */
|
||||
#endif /* PHP_PHAR_H */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -35,22 +35,22 @@ php_stream_ops phar_ops = {
|
||||
};
|
||||
|
||||
php_stream_wrapper_ops phar_stream_wops = {
|
||||
phar_wrapper_open_url,
|
||||
NULL, /* phar_wrapper_close */
|
||||
NULL, /* phar_wrapper_stat, */
|
||||
phar_wrapper_stat, /* stat_url */
|
||||
phar_wrapper_open_dir, /* opendir */
|
||||
"phar",
|
||||
phar_wrapper_unlink, /* unlink */
|
||||
phar_wrapper_rename, /* rename */
|
||||
phar_wrapper_mkdir, /* create directory */
|
||||
phar_wrapper_rmdir, /* remove directory */
|
||||
phar_wrapper_open_url,
|
||||
NULL, /* phar_wrapper_close */
|
||||
NULL, /* phar_wrapper_stat, */
|
||||
phar_wrapper_stat, /* stat_url */
|
||||
phar_wrapper_open_dir, /* opendir */
|
||||
"phar",
|
||||
phar_wrapper_unlink, /* unlink */
|
||||
phar_wrapper_rename, /* rename */
|
||||
phar_wrapper_mkdir, /* create directory */
|
||||
phar_wrapper_rmdir, /* remove directory */
|
||||
};
|
||||
|
||||
php_stream_wrapper php_stream_phar_wrapper = {
|
||||
&phar_stream_wops,
|
||||
NULL,
|
||||
0 /* is_url */
|
||||
php_stream_wrapper php_stream_phar_wrapper = {
|
||||
&phar_stream_wops,
|
||||
NULL,
|
||||
0 /* is_url */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -69,8 +69,8 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: open mode append not supported");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len, 2, (mode[0] == 'w' ? 2 : 0) TSRMLS_CC) == FAILURE) {
|
||||
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
|
||||
if (arch && !entry) {
|
||||
@@ -101,7 +101,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
}
|
||||
#endif
|
||||
if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) {
|
||||
phar_archive_data **pphar = NULL;
|
||||
phar_archive_data **pphar = NULL, *phar;
|
||||
|
||||
if (PHAR_GLOBALS->request_init && PHAR_GLOBALS->phar_fname_map.arBuckets && FAILURE == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **)&pphar)) {
|
||||
pphar = NULL;
|
||||
@@ -113,7 +113,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
php_url_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
if (phar_open_or_create_filename(resource->host, arch_len, NULL, 0, 0, options, NULL, &error TSRMLS_CC) == FAILURE)
|
||||
if (phar_open_or_create_filename(resource->host, arch_len, NULL, 0, 0, options, &phar, &error TSRMLS_CC) == FAILURE)
|
||||
{
|
||||
if (error) {
|
||||
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
|
||||
@@ -124,6 +124,17 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
php_url_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
|
||||
if (error) {
|
||||
spprintf(&error, 0, "Cannot open cached phar '%s' as writeable, copy on write failed", resource->host);
|
||||
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
|
||||
}
|
||||
efree(error);
|
||||
}
|
||||
php_url_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (phar_open_from_filename(resource->host, arch_len, NULL, 0, options, NULL, &error TSRMLS_CC) == FAILURE)
|
||||
{
|
||||
@@ -136,7 +147,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
php_url_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -146,6 +157,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
*/
|
||||
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) /* {{{ */
|
||||
{
|
||||
phar_archive_data *phar;
|
||||
phar_entry_data *idata;
|
||||
char *internal_file;
|
||||
char *error;
|
||||
@@ -223,8 +235,55 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
|
||||
}
|
||||
return fpf;
|
||||
} else {
|
||||
if (!*internal_file && (options & STREAM_OPEN_FOR_INCLUDE)) {
|
||||
/* retrieve the stub */
|
||||
if (FAILURE == phar_get_archive(&phar, resource->host, host_len, NULL, 0, NULL TSRMLS_CC)) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "file %s is not a valid phar archive");
|
||||
efree(internal_file);
|
||||
php_url_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
if (phar->is_tar || phar->is_zip) {
|
||||
if ((FAILURE == phar_get_entry_data(&idata, resource->host, host_len, ".phar/stub.php", sizeof(".phar/stub.php")-1, "r", 0, &error, 0 TSRMLS_CC)) || !idata) {
|
||||
goto idata_error;
|
||||
}
|
||||
efree(internal_file);
|
||||
if (opened_path) {
|
||||
spprintf(opened_path, MAXPATHLEN, "%s", phar->fname);
|
||||
}
|
||||
php_url_free(resource);
|
||||
goto phar_stub;
|
||||
} else {
|
||||
phar_entry_info *entry;
|
||||
|
||||
entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info));
|
||||
entry->is_temp_dir = 1;
|
||||
entry->filename = "";
|
||||
entry->filename_len = 0;
|
||||
entry->phar = phar;
|
||||
entry->offset = entry->offset_abs = 0;
|
||||
entry->compressed_filesize = entry->uncompressed_filesize = phar->halt_offset;
|
||||
entry->is_crc_checked = 1;
|
||||
|
||||
idata = (phar_entry_data *) ecalloc(1, sizeof(phar_entry_data));
|
||||
idata->fp = phar_get_pharfp(phar TSRMLS_CC);
|
||||
idata->phar = phar;
|
||||
idata->internal_file = entry;
|
||||
if (!phar->is_persistent) {
|
||||
++(entry->phar->refcount);
|
||||
}
|
||||
++(entry->fp_refcount);
|
||||
php_url_free(resource);
|
||||
if (opened_path) {
|
||||
spprintf(opened_path, MAXPATHLEN, "%s", phar->fname);
|
||||
}
|
||||
efree(internal_file);
|
||||
goto phar_stub;
|
||||
}
|
||||
}
|
||||
/* read-only access is allowed to magic files in .phar directory */
|
||||
if ((FAILURE == phar_get_entry_data(&idata, resource->host, host_len, internal_file, strlen(internal_file), "r", 0, &error, 0 TSRMLS_CC)) || !idata) {
|
||||
idata_error:
|
||||
if (error) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
|
||||
efree(error);
|
||||
@@ -237,7 +296,6 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
|
||||
}
|
||||
}
|
||||
php_url_free(resource);
|
||||
|
||||
#if MBO_0
|
||||
fprintf(stderr, "Pharname: %s\n", idata->phar->filename);
|
||||
fprintf(stderr, "Filename: %s\n", internal_file);
|
||||
@@ -272,11 +330,12 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
|
||||
PHAR_G(cwd) = NULL;
|
||||
}
|
||||
}
|
||||
fpf = php_stream_alloc(&phar_ops, idata, NULL, mode);
|
||||
if (opened_path) {
|
||||
spprintf(opened_path, MAXPATHLEN, "phar://%s/%s", idata->phar->fname, idata->internal_file->filename);
|
||||
}
|
||||
efree(internal_file);
|
||||
phar_stub:
|
||||
fpf = php_stream_alloc(&phar_ops, idata, NULL, mode);
|
||||
return fpf;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -286,8 +345,15 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
|
||||
*/
|
||||
static int phar_stream_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
phar_entry_info *entry = ((phar_entry_data *)stream->abstract)->internal_file;
|
||||
int is_temp_dir = entry->is_temp_dir;
|
||||
|
||||
phar_entry_delref((phar_entry_data *)stream->abstract TSRMLS_CC);
|
||||
|
||||
if (is_temp_dir) {
|
||||
/* phar archive stub, free it */
|
||||
efree(entry);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -299,7 +365,7 @@ static size_t phar_stream_read(php_stream *stream, char *buf, size_t count TSRML
|
||||
{
|
||||
phar_entry_data *data = (phar_entry_data *)stream->abstract;
|
||||
size_t got;
|
||||
|
||||
|
||||
if (data->internal_file->is_deleted) {
|
||||
stream->eof = 1;
|
||||
return 0;
|
||||
@@ -312,7 +378,6 @@ static size_t phar_stream_read(php_stream *stream, char *buf, size_t count TSRML
|
||||
data->position = php_stream_tell(data->fp) - data->zero;
|
||||
stream->eof = (data->position == (off_t) data->internal_file->uncompressed_filesize);
|
||||
|
||||
|
||||
return got;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -402,8 +467,6 @@ static int phar_stream_flush(php_stream *stream TSRMLS_DC) /* {{{ */
|
||||
void phar_dostat(phar_archive_data *phar, phar_entry_info *data, php_stream_statbuf *ssb,
|
||||
zend_bool is_temp_dir, char *alias, int alias_len TSRMLS_DC)
|
||||
{
|
||||
char *tmp;
|
||||
int tmp_len;
|
||||
memset(ssb, 0, sizeof(php_stream_statbuf));
|
||||
|
||||
if (!is_temp_dir && !data->is_dir) {
|
||||
@@ -454,23 +517,12 @@ void phar_dostat(phar_archive_data *phar, phar_entry_info *data, php_stream_stat
|
||||
|
||||
ssb->sb.st_nlink = 1;
|
||||
ssb->sb.st_rdev = -1;
|
||||
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 */
|
||||
ssb->sb.st_ino = (unsigned short)zend_get_hash_value(tmp, tmp_len);
|
||||
efree(tmp);
|
||||
if (!is_temp_dir) {
|
||||
ssb->sb.st_ino = data->inode;
|
||||
}
|
||||
#ifndef PHP_WIN32
|
||||
ssb->sb.st_blksize = -1;
|
||||
ssb->sb.st_blocks = -1;
|
||||
@@ -502,10 +554,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags,
|
||||
php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
php_url *resource = NULL;
|
||||
phar_zstr key;
|
||||
char *internal_file, *error, *str_key;
|
||||
uint keylen;
|
||||
ulong unused;
|
||||
char *internal_file, *error;
|
||||
phar_archive_data *phar;
|
||||
phar_entry_info *entry;
|
||||
uint host_len;
|
||||
@@ -557,76 +606,62 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags,
|
||||
phar_dostat(phar, entry, ssb, 0, phar->alias, phar->alias_len TSRMLS_CC);
|
||||
php_url_free(resource);
|
||||
return SUCCESS;
|
||||
} 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)) {
|
||||
PHAR_STR(key, str_key);
|
||||
if (keylen >= (uint)internal_file_len && 0 == memcmp(internal_file, str_key, internal_file_len)) {
|
||||
/* directory found, all dirs have the same stat */
|
||||
if (str_key[internal_file_len] == '/') {
|
||||
phar_dostat(phar, NULL, ssb, 1, phar->alias, phar->alias_len TSRMLS_CC);
|
||||
php_url_free(resource);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SUCCESS != zend_hash_move_forward(&phar->manifest)) {
|
||||
}
|
||||
if (zend_hash_exists(&(phar->virtual_dirs), internal_file, internal_file_len)) {
|
||||
phar_dostat(phar, NULL, ssb, 1, phar->alias, phar->alias_len TSRMLS_CC);
|
||||
php_url_free(resource);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* check for mounted directories */
|
||||
if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) {
|
||||
phar_zstr key;
|
||||
char *str_key;
|
||||
ulong unused;
|
||||
uint keylen;
|
||||
HashPosition pos;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(&phar->mounted_dirs, &pos);
|
||||
while (FAILURE != zend_hash_has_more_elements_ex(&phar->mounted_dirs, &pos)) {
|
||||
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, &pos)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* check for mounted directories */
|
||||
if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) {
|
||||
phar_zstr key;
|
||||
char *str_key;
|
||||
ulong unused;
|
||||
uint keylen;
|
||||
|
||||
zend_hash_internal_pointer_reset(&phar->mounted_dirs);
|
||||
while (FAILURE != zend_hash_has_more_elements(&phar->mounted_dirs)) {
|
||||
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, NULL)) {
|
||||
break;
|
||||
PHAR_STR(key, str_key);
|
||||
if ((int)keylen >= internal_file_len || strncmp(str_key, internal_file, keylen)) {
|
||||
zend_hash_move_forward_ex(&phar->mounted_dirs, &pos);
|
||||
continue;
|
||||
} else {
|
||||
char *test;
|
||||
int test_len;
|
||||
phar_entry_info *entry;
|
||||
php_stream_statbuf ssbi;
|
||||
|
||||
if (SUCCESS != zend_hash_find(&phar->manifest, str_key, keylen, (void **) &entry)) {
|
||||
goto free_resource;
|
||||
}
|
||||
PHAR_STR(key, str_key);
|
||||
if ((int)keylen >= internal_file_len || strncmp(str_key, internal_file, keylen)) {
|
||||
continue;
|
||||
} else {
|
||||
char *test;
|
||||
int test_len;
|
||||
phar_entry_info *entry;
|
||||
php_stream_statbuf ssbi;
|
||||
|
||||
if (SUCCESS != zend_hash_find(&phar->manifest, str_key, keylen, (void **) &entry)) {
|
||||
goto free_resource;
|
||||
}
|
||||
if (!entry->tmp || !entry->is_mounted) {
|
||||
goto free_resource;
|
||||
}
|
||||
test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, internal_file + keylen);
|
||||
if (SUCCESS != php_stream_stat_path(test, &ssbi)) {
|
||||
efree(test);
|
||||
continue;
|
||||
}
|
||||
/* mount the file/directory just in time */
|
||||
if (SUCCESS != phar_mount_entry(phar, test, test_len, internal_file, internal_file_len TSRMLS_CC)) {
|
||||
efree(test);
|
||||
goto free_resource;
|
||||
}
|
||||
if (!entry->tmp || !entry->is_mounted) {
|
||||
goto free_resource;
|
||||
}
|
||||
test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, internal_file + keylen);
|
||||
if (SUCCESS != php_stream_stat_path(test, &ssbi)) {
|
||||
efree(test);
|
||||
if (SUCCESS != zend_hash_find(&phar->manifest, internal_file, internal_file_len, (void**)&entry)) {
|
||||
goto free_resource;
|
||||
}
|
||||
phar_dostat(phar, entry, ssb, 0, phar->alias, phar->alias_len TSRMLS_CC);
|
||||
php_url_free(resource);
|
||||
return SUCCESS;
|
||||
zend_hash_move_forward_ex(&phar->mounted_dirs, &pos);
|
||||
continue;
|
||||
}
|
||||
/* mount the file/directory just in time */
|
||||
if (SUCCESS != phar_mount_entry(phar, test, test_len, internal_file, internal_file_len TSRMLS_CC)) {
|
||||
efree(test);
|
||||
goto free_resource;
|
||||
}
|
||||
efree(test);
|
||||
if (SUCCESS != zend_hash_find(&phar->manifest, internal_file, internal_file_len, (void**)&entry)) {
|
||||
goto free_resource;
|
||||
}
|
||||
phar_dostat(phar, entry, ssb, 0, phar->alias, phar->alias_len TSRMLS_CC);
|
||||
php_url_free(resource);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_resource:
|
||||
php_url_free(resource);
|
||||
return FAILURE;
|
||||
@@ -692,7 +727,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
|
||||
efree(error);
|
||||
}
|
||||
if (idata->internal_file->fp_refcount > 1) {
|
||||
/* more than just our fp resource is open for this file */
|
||||
/* 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);
|
||||
@@ -717,6 +752,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
|
||||
phar_archive_data *phar, *pfrom, *pto;
|
||||
phar_entry_info *entry;
|
||||
uint host_len;
|
||||
int is_dir = 0;
|
||||
int is_modified = 0;
|
||||
|
||||
error = NULL;
|
||||
|
||||
@@ -767,7 +804,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid url \"%s\"", url_from, url_to, url_from);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!resource_to->scheme || !resource_to->host || !resource_to->path) {
|
||||
php_url_free(resource_from);
|
||||
php_url_free(resource_to);
|
||||
@@ -790,7 +827,6 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
|
||||
}
|
||||
|
||||
host_len = strlen(resource_from->host);
|
||||
phar_request_initialize(TSRMLS_C);
|
||||
|
||||
if (SUCCESS != phar_get_archive(&phar, resource_from->host, strlen(resource_from->host), NULL, 0, &error TSRMLS_CC)) {
|
||||
php_url_free(resource_from);
|
||||
@@ -800,6 +836,13 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
|
||||
php_url_free(resource_from);
|
||||
php_url_free(resource_to);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": could not make cached phar writeable", url_from, url_to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SUCCESS == zend_hash_find(&(phar->manifest), resource_from->path+1, strlen(resource_from->path)-1, (void **)&entry)) {
|
||||
phar_entry_info new, *source;
|
||||
|
||||
@@ -831,20 +874,122 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
|
||||
zend_hash_del(&(phar->manifest), entry->filename, strlen(entry->filename));
|
||||
return 0;
|
||||
}
|
||||
is_modified = 1;
|
||||
entry->is_modified = 1;
|
||||
entry->filename_len = strlen(entry->filename);
|
||||
is_dir = entry->is_dir;
|
||||
} else {
|
||||
is_dir = zend_hash_exists(&(phar->virtual_dirs), resource_from->path+1, strlen(resource_from->path)-1);
|
||||
}
|
||||
|
||||
/* Rename directory. Update all nested paths */
|
||||
if (is_dir) {
|
||||
int key_type;
|
||||
phar_zstr key, new_key;
|
||||
char *str_key, *new_str_key;
|
||||
uint key_len, new_key_len;
|
||||
ulong unused;
|
||||
uint from_len = strlen(resource_from->path+1);
|
||||
uint to_len = strlen(resource_to->path+1);
|
||||
|
||||
for (zend_hash_internal_pointer_reset(&phar->manifest);
|
||||
HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL)) &&
|
||||
SUCCESS == zend_hash_get_current_data(&phar->manifest, (void **) &entry);
|
||||
zend_hash_move_forward(&phar->manifest)) {
|
||||
|
||||
PHAR_STR(key, str_key);
|
||||
|
||||
if (!entry->is_deleted &&
|
||||
key_len > from_len &&
|
||||
memcmp(str_key, resource_from->path+1, from_len) == 0 &&
|
||||
IS_SLASH(str_key[from_len])) {
|
||||
|
||||
new_key_len = key_len + to_len - from_len;
|
||||
new_str_key = emalloc(new_key_len+1);
|
||||
memcpy(new_str_key, resource_to->path + 1, to_len);
|
||||
memcpy(new_str_key + to_len, str_key + from_len, key_len - from_len);
|
||||
new_str_key[new_key_len] = 0;
|
||||
is_modified = 1;
|
||||
entry->is_modified = 1;
|
||||
efree(entry->filename);
|
||||
entry->filename = new_str_key;
|
||||
entry->filename_len = new_key_len;
|
||||
|
||||
PHAR_ZSTR(new_str_key, new_key);
|
||||
zend_hash_update_current_key_ex(&phar->manifest, key_type, new_key, new_key_len, 0, NULL);
|
||||
efree(new_str_key);
|
||||
}
|
||||
}
|
||||
|
||||
for (zend_hash_internal_pointer_reset(&phar->virtual_dirs);
|
||||
HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL));
|
||||
zend_hash_move_forward(&phar->virtual_dirs)) {
|
||||
|
||||
PHAR_STR(key, str_key);
|
||||
|
||||
if (key_len >= from_len &&
|
||||
memcmp(str_key, resource_from->path+1, from_len) == 0 &&
|
||||
(key_len == from_len || IS_SLASH(str_key[from_len]))) {
|
||||
|
||||
new_key_len = key_len + to_len - from_len;
|
||||
new_str_key = emalloc(new_key_len+1);
|
||||
memcpy(new_str_key, resource_to->path + 1, to_len);
|
||||
memcpy(new_str_key + to_len, str_key + from_len, key_len - from_len);
|
||||
new_str_key[new_key_len] = 0;
|
||||
|
||||
PHAR_ZSTR(new_str_key, new_key);
|
||||
zend_hash_update_current_key_ex(&phar->virtual_dirs, key_type, new_key, new_key_len, 0, NULL);
|
||||
efree(new_str_key);
|
||||
}
|
||||
}
|
||||
|
||||
for (zend_hash_internal_pointer_reset(&phar->mounted_dirs);
|
||||
HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &key_len, &unused, 0, NULL)) &&
|
||||
SUCCESS == zend_hash_get_current_data(&phar->mounted_dirs, (void **) &entry);
|
||||
zend_hash_move_forward(&phar->mounted_dirs)) {
|
||||
|
||||
PHAR_STR(key, str_key);
|
||||
|
||||
if (key_len >= from_len &&
|
||||
memcmp(str_key, resource_from->path+1, from_len) == 0 &&
|
||||
(key_len == from_len || IS_SLASH(str_key[from_len]))) {
|
||||
|
||||
new_key_len = key_len + to_len - from_len;
|
||||
new_str_key = emalloc(new_key_len+1);
|
||||
memcpy(new_str_key, resource_to->path + 1, to_len);
|
||||
memcpy(new_str_key + to_len, str_key + from_len, key_len - from_len);
|
||||
new_str_key[new_key_len] = 0;
|
||||
|
||||
PHAR_ZSTR(new_str_key, new_key);
|
||||
zend_hash_update_current_key_ex(&phar->mounted_dirs, key_type, new_key, new_key_len, 0, NULL);
|
||||
efree(new_str_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_modified) {
|
||||
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
|
||||
if (error) {
|
||||
php_url_free(resource_from);
|
||||
php_url_free(resource_to);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error);
|
||||
efree(error);
|
||||
zend_hash_del(&(phar->manifest), entry->filename, strlen(entry->filename));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
php_url_free(resource_from);
|
||||
php_url_free(resource_to);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| phar php single-file executable PHP extension |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2006-2007 The PHP Group |
|
||||
| Copyright (c) 2006-2008 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
|
||||
371
ext/phar/tar.c
371
ext/phar/tar.c
@@ -27,19 +27,19 @@ static php_uint32 phar_tar_number(char *buf, int len) /* {{{ */
|
||||
while (i < len && buf[i] == ' ') {
|
||||
++i;
|
||||
}
|
||||
while (i < len &&
|
||||
buf[i] >= '0' &&
|
||||
buf[i] <= '7') {
|
||||
|
||||
while (i < len && buf[i] >= '0' && buf[i] <= '7') {
|
||||
num = num * 8 + (buf[i] - '0');
|
||||
++i;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* adapted from format_octal() in libarchive
|
||||
*
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2003-2008 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -97,7 +97,7 @@ static php_uint32 phar_tar_checksum(char *buf, int len) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int phar_is_tar(char *buf, char *fname)
|
||||
int phar_is_tar(char *buf, char *fname) /* {{{ */
|
||||
{
|
||||
tar_header *header = (tar_header *) buf;
|
||||
php_uint32 checksum = phar_tar_number(header->checksum, sizeof(header->checksum));
|
||||
@@ -119,6 +119,7 @@ int phar_is_tar(char *buf, char *fname)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
@@ -152,8 +153,9 @@ int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_l
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp TSRMLS_DC)
|
||||
int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *metadata;
|
||||
size_t save = php_stream_tell(fp), read;
|
||||
@@ -174,6 +176,7 @@ int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp TSRMLS_DC)
|
||||
php_stream_seek(fp, save, SEEK_SET);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (entry->filename_len == sizeof(".phar/.metadata.bin")-1 && !memcmp(entry->filename, ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1)) {
|
||||
entry->phar->metadata = entry->metadata;
|
||||
entry->metadata = NULL;
|
||||
@@ -182,10 +185,12 @@ int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp TSRMLS_DC)
|
||||
mentry->metadata = entry->metadata;
|
||||
entry->metadata = NULL;
|
||||
}
|
||||
|
||||
efree(metadata);
|
||||
php_stream_seek(fp, save, SEEK_SET);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
@@ -204,6 +209,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
totalsize = php_stream_tell(fp);
|
||||
php_stream_seek(fp, 0, SEEK_SET);
|
||||
read = php_stream_read(fp, buf, sizeof(buf));
|
||||
|
||||
if (read != sizeof(buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: \"%s\" is not a tar file or is truncated", fname);
|
||||
@@ -211,14 +217,19 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
php_stream_close(fp);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
hdr = (tar_header*)buf;
|
||||
old = (memcmp(hdr->magic, "ustar", sizeof("ustar")-1) != 0);
|
||||
|
||||
myphar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
|
||||
zend_hash_init(&myphar->manifest, sizeof(phar_entry_info),
|
||||
zend_get_hash_value, destroy_phar_manifest_entry, 0);
|
||||
zend_hash_init(&myphar->mounted_dirs, sizeof(char *),
|
||||
zend_get_hash_value, NULL, 0);
|
||||
myphar = (phar_archive_data *) pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
|
||||
myphar->is_persistent = PHAR_G(persist);
|
||||
/* estimate number of entries, can't be certain with tar files */
|
||||
zend_hash_init(&myphar->manifest, 2 + (totalsize >> 12),
|
||||
zend_get_hash_value, destroy_phar_manifest_entry, (zend_bool)myphar->is_persistent);
|
||||
zend_hash_init(&myphar->mounted_dirs, 5,
|
||||
zend_get_hash_value, NULL, (zend_bool)myphar->is_persistent);
|
||||
zend_hash_init(&myphar->virtual_dirs, 4 + (totalsize >> 11),
|
||||
zend_get_hash_value, NULL, (zend_bool)myphar->is_persistent);
|
||||
myphar->is_tar = 1;
|
||||
/* remember whether this entire phar was compressed with gz/bzip2 */
|
||||
myphar->flags = compression;
|
||||
@@ -227,6 +238,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
entry.is_crc_checked = 1;
|
||||
entry.phar = myphar;
|
||||
pos += sizeof(buf);
|
||||
|
||||
do {
|
||||
phar_entry_info *newentry;
|
||||
|
||||
@@ -242,6 +254,81 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
size = entry.uncompressed_filesize = entry.compressed_filesize =
|
||||
phar_tar_number(hdr->size, sizeof(hdr->size));
|
||||
|
||||
if (((!old && hdr->prefix[0] == 0) || old) && strlen(hdr->name) == sizeof(".phar/signature.bin")-1 && !strncmp(hdr->name, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
|
||||
size_t read;
|
||||
if (size > 511) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: tar-based phar \"%s\" has signature that is larger than 511 bytes, cannot process", fname);
|
||||
}
|
||||
bail:
|
||||
php_stream_close(fp);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
read = php_stream_read(fp, buf, size);
|
||||
if (read != size) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be read", fname);
|
||||
}
|
||||
goto bail;
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define PHAR_GET_32(buffer) \
|
||||
(((((unsigned char*)(buffer))[3]) << 24) \
|
||||
| ((((unsigned char*)(buffer))[2]) << 16) \
|
||||
| ((((unsigned char*)(buffer))[1]) << 8) \
|
||||
| (((unsigned char*)(buffer))[0]))
|
||||
#else
|
||||
# define PHAR_GET_32(buffer) (php_uint32) *(buffer)
|
||||
#endif
|
||||
if (FAILURE == phar_verify_signature(fp, php_stream_tell(fp) - size - 512, PHAR_GET_32(buf), buf + 8, PHAR_GET_32(buf + 4), fname, &myphar->signature, &myphar->sig_len, error TSRMLS_CC)) {
|
||||
if (error) {
|
||||
char *save = *error;
|
||||
spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be verified: %s", fname, save);
|
||||
efree(save);
|
||||
}
|
||||
goto bail;
|
||||
}
|
||||
/* signature checked out, let's ensure this is the last file in the phar */
|
||||
size = ((size+511)&~511) + 512;
|
||||
if (((hdr->typeflag == 0) || (hdr->typeflag == TAR_FILE)) && size > 0) {
|
||||
/* this is not good enough - seek succeeds even on truncated tars */
|
||||
php_stream_seek(fp, size, SEEK_CUR);
|
||||
if ((uint)php_stream_tell(fp) > totalsize) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
read = php_stream_read(fp, buf, sizeof(buf));
|
||||
|
||||
if (read != sizeof(buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
hdr = (tar_header*) buf;
|
||||
sum1 = phar_tar_number(hdr->checksum, sizeof(hdr->checksum));
|
||||
|
||||
if (sum1 == 0 && phar_tar_checksum(buf, sizeof(buf)) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: \"%s\" has entries after signature, invalid phar", fname);
|
||||
}
|
||||
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!old && hdr->prefix[0] != 0) {
|
||||
char name[256];
|
||||
|
||||
@@ -252,32 +339,34 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
} else {
|
||||
strcat(name, hdr->name);
|
||||
}
|
||||
|
||||
entry.filename_len = strlen(hdr->prefix) + 100;
|
||||
|
||||
if (name[entry.filename_len - 1] == '/') {
|
||||
/* some tar programs store directories with trailing slash */
|
||||
entry.filename_len--;
|
||||
}
|
||||
entry.filename = estrndup(name, entry.filename_len);
|
||||
entry.filename = pestrndup(name, entry.filename_len, myphar->is_persistent);
|
||||
} else {
|
||||
entry.filename = estrdup(hdr->name);
|
||||
entry.filename = pestrdup(hdr->name, myphar->is_persistent);
|
||||
entry.filename_len = strlen(entry.filename);
|
||||
|
||||
if (entry.filename[entry.filename_len - 1] == '/') {
|
||||
/* some tar programs store directories with trailing slash */
|
||||
entry.filename[entry.filename_len - 1] = '\0';
|
||||
entry.filename_len--;
|
||||
}
|
||||
}
|
||||
|
||||
phar_add_virtual_dirs(myphar, entry.filename, entry.filename_len TSRMLS_CC);
|
||||
|
||||
if (sum1 != sum2) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.filename);
|
||||
}
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, myphar->is_persistent);
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -286,13 +375,14 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
entry.fp_type = PHAR_FP;
|
||||
entry.flags = phar_tar_number(hdr->mode, sizeof(hdr->mode)) & PHAR_ENT_PERM_MASK;
|
||||
entry.timestamp = phar_tar_number(hdr->mtime, sizeof(hdr->mtime));
|
||||
|
||||
entry.is_persistent = myphar->is_persistent;
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry.flags)) {
|
||||
entry.tar_type = TAR_DIR;
|
||||
}
|
||||
|
||||
if (entry.tar_type == TAR_DIR) {
|
||||
entry.is_dir = 1;
|
||||
} else {
|
||||
@@ -300,39 +390,39 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
}
|
||||
|
||||
entry.link = NULL;
|
||||
|
||||
if (entry.tar_type == TAR_LINK) {
|
||||
if (!zend_hash_exists(&myphar->manifest, hdr->linkname, strlen(hdr->linkname))) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%s\"", fname, hdr->linkname);
|
||||
}
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
entry.link = estrdup(hdr->linkname);
|
||||
} else if (entry.tar_type == TAR_SYMLINK) {
|
||||
entry.link = estrdup(hdr->linkname);
|
||||
}
|
||||
phar_set_inode(&entry TSRMLS_CC);
|
||||
zend_hash_add(&myphar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), (void **) &newentry);
|
||||
|
||||
if (entry.is_persistent) {
|
||||
++entry.manifest_pos;
|
||||
}
|
||||
|
||||
if (entry.filename_len >= sizeof(".phar/.metadata")-1 && !memcmp(entry.filename, ".phar/.metadata", sizeof(".phar/.metadata")-1)) {
|
||||
if (FAILURE == phar_tar_process_metadata(newentry, fp TSRMLS_CC)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: tar-based phar \"%s\" has invalid metadata in magic file \"%s\"", fname, entry.filename);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!actual_alias && entry.filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry.filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
|
||||
size_t read;
|
||||
/* found explicit alias */
|
||||
@@ -341,14 +431,12 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
spprintf(error, 4096, "phar error: tar-based phar \"%s\" has alias that is larger than 511 bytes, cannot process", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
read = php_stream_read(fp, buf, size);
|
||||
|
||||
if (read == size) {
|
||||
buf[size] = '\0';
|
||||
if (!phar_validate_alias(buf, size)) {
|
||||
@@ -358,18 +446,17 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
buf[52] = '.';
|
||||
buf[53] = '\0';
|
||||
}
|
||||
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: invalid alias \"%s\" in tar-based phar \"%s\"", buf, fname);
|
||||
}
|
||||
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
actual_alias = estrndup(buf, size);
|
||||
|
||||
actual_alias = pestrndup(buf, size, myphar->is_persistent);
|
||||
myphar->alias = actual_alias;
|
||||
myphar->alias_len = size;
|
||||
php_stream_seek(fp, pos, SEEK_SET);
|
||||
@@ -377,16 +464,15 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: Unable to read alias from tar-based phar \"%s\"", fname);
|
||||
}
|
||||
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
size = (size+511)&~511;
|
||||
|
||||
if (((hdr->typeflag == 0) || (hdr->typeflag == TAR_FILE)) && size > 0) {
|
||||
/* this is not good enough - seek succeeds even on truncated tars */
|
||||
php_stream_seek(fp, size, SEEK_CUR);
|
||||
@@ -395,33 +481,39 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
read = php_stream_read(fp, buf, sizeof(buf));
|
||||
|
||||
if (read != sizeof(buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
} while (read != 0);
|
||||
myphar->fname = estrndup(fname, fname_len);
|
||||
|
||||
/* ensure signature set */
|
||||
if (PHAR_G(require_hash) && !myphar->signature) {
|
||||
php_stream_close(fp);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
if (error) {
|
||||
spprintf(error, 0, "tar-based phar \"%s\" does not have a signature", fname);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
myphar->fname = pestrndup(fname, fname_len, myphar->is_persistent);
|
||||
#ifdef PHP_WIN32
|
||||
phar_unixify_path_separators(myphar->fname, fname_len);
|
||||
#endif
|
||||
myphar->fname_len = fname_len;
|
||||
myphar->fp = fp;
|
||||
p = strrchr(myphar->fname, '/');
|
||||
|
||||
if (zend_hash_exists(&(myphar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
|
||||
@@ -439,25 +531,25 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
myphar->ext_len = (myphar->fname + fname_len) - myphar->ext;
|
||||
}
|
||||
}
|
||||
myphar->fp = fp;
|
||||
|
||||
phar_request_initialize(TSRMLS_C);
|
||||
|
||||
if (SUCCESS != zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len, (void*)&myphar, sizeof(phar_archive_data*), (void **)&actual)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\" to phar registry", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
zend_hash_destroy(&myphar->manifest);
|
||||
myphar->manifest.arBuckets = 0;
|
||||
zend_hash_destroy(&myphar->mounted_dirs);
|
||||
myphar->mounted_dirs.arBuckets = 0;
|
||||
efree(myphar);
|
||||
phar_destroy_phar_data(myphar TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
myphar = *actual;
|
||||
|
||||
if (actual_alias) {
|
||||
phar_archive_data **fd_ptr;
|
||||
|
||||
myphar->is_temporary_alias = 0;
|
||||
|
||||
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void **)&fd_ptr)) {
|
||||
if (SUCCESS != phar_free_alias(*fd_ptr, actual_alias, myphar->alias_len TSRMLS_CC)) {
|
||||
if (error) {
|
||||
@@ -467,6 +559,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
|
||||
} else {
|
||||
phar_archive_data **fd_ptr;
|
||||
@@ -481,18 +574,21 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
|
||||
myphar->alias = estrndup(alias, alias_len);
|
||||
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
|
||||
myphar->alias = pestrndup(alias, alias_len, myphar->is_persistent);
|
||||
myphar->alias_len = alias_len;
|
||||
} else {
|
||||
myphar->alias = estrndup(myphar->fname, fname_len);
|
||||
myphar->alias = pestrndup(myphar->fname, fname_len, myphar->is_persistent);
|
||||
myphar->alias_len = fname_len;
|
||||
}
|
||||
|
||||
myphar->is_temporary_alias = 1;
|
||||
}
|
||||
|
||||
if (pphar) {
|
||||
*pphar = myphar;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -505,7 +601,7 @@ struct _phar_pass_tar_info {
|
||||
char **error;
|
||||
};
|
||||
|
||||
int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||
int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
tar_header header;
|
||||
size_t pos;
|
||||
@@ -516,6 +612,7 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||
if (entry->is_mounted) {
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
|
||||
if (entry->is_deleted) {
|
||||
if (entry->fp_refcount <= 0) {
|
||||
return ZEND_HASH_APPLY_REMOVE;
|
||||
@@ -526,6 +623,7 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||
}
|
||||
|
||||
memset((char *) &header, 0, sizeof(header));
|
||||
|
||||
if (entry->filename_len > 100) {
|
||||
if (entry->filename_len > 255) {
|
||||
if (fp->error) {
|
||||
@@ -538,28 +636,35 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||
} else {
|
||||
memcpy(header.name, entry->filename, entry->filename_len);
|
||||
}
|
||||
|
||||
phar_tar_octal(header.mode, entry->flags & PHAR_ENT_PERM_MASK, sizeof(header.mode)-1);
|
||||
|
||||
if (FAILURE == phar_tar_octal(header.size, entry->uncompressed_filesize, sizeof(header.size)-1)) {
|
||||
if (fp->error) {
|
||||
spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too large for tar file format", entry->phar->fname, entry->filename);
|
||||
}
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (FAILURE == phar_tar_octal(header.mtime, entry->timestamp, sizeof(header.mtime)-1)) {
|
||||
if (fp->error) {
|
||||
spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, file modification time of file \"%s\" is too large for tar file format", entry->phar->fname, entry->filename);
|
||||
}
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
/* calc checksum */
|
||||
header.typeflag = entry->tar_type;
|
||||
|
||||
if (entry->link) {
|
||||
strncpy(header.linkname, entry->link, strlen(entry->link));
|
||||
}
|
||||
|
||||
strncpy(header.magic, "ustar", sizeof("ustar")-1);
|
||||
strncpy(header.version, "00", sizeof("00")-1);
|
||||
strncpy(header.checksum, " ", sizeof(" ")-1);
|
||||
entry->crc32 = phar_tar_checksum((char *)&header, sizeof(header));
|
||||
|
||||
if (FAILURE == phar_tar_octal(header.checksum, entry->crc32, sizeof(header.checksum)-1)) {
|
||||
if (fp->error) {
|
||||
spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, checksum of file \"%s\" is too large for tar file format", entry->phar->fname, entry->filename);
|
||||
@@ -569,12 +674,14 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||
|
||||
/* write header */
|
||||
entry->header_offset = php_stream_tell(fp->new);
|
||||
|
||||
if (sizeof(header) != php_stream_write(fp->new, (char *) &header, sizeof(header))) {
|
||||
if (fp->error) {
|
||||
spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, header for file \"%s\" could not be written", entry->phar->fname, entry->filename);
|
||||
}
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
pos = php_stream_tell(fp->new); /* save start of file within tar */
|
||||
|
||||
/* write contents */
|
||||
@@ -582,22 +689,25 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||
if (FAILURE == phar_open_entry_fp(entry, fp->error, 0 TSRMLS_CC)) {
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC)) {
|
||||
if (fp->error) {
|
||||
spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written, seek failed", entry->phar->fname, entry->filename);
|
||||
}
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (entry->uncompressed_filesize != php_stream_copy_to_stream(phar_get_efp(entry, 0 TSRMLS_CC), fp->new, entry->uncompressed_filesize)) {
|
||||
if (fp->error) {
|
||||
spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written", entry->phar->fname, entry->filename);
|
||||
}
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
|
||||
memset(padding, 0, 512);
|
||||
php_stream_write(fp->new, padding, ((entry->uncompressed_filesize +511)&~511) - entry->uncompressed_filesize);
|
||||
}
|
||||
|
||||
if (!entry->is_modified && entry->fp_refcount) {
|
||||
/* open file pointers refer to this fp, do not free the stream */
|
||||
switch (entry->fp_type) {
|
||||
@@ -612,48 +722,57 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||
}
|
||||
|
||||
entry->is_modified = 0;
|
||||
|
||||
if (entry->fp_type == PHAR_MOD && entry->fp != entry->phar->fp && entry->fp != entry->phar->ufp) {
|
||||
if (!entry->fp_refcount) {
|
||||
php_stream_close(entry->fp);
|
||||
}
|
||||
entry->fp = NULL;
|
||||
}
|
||||
|
||||
entry->fp_type = PHAR_FP;
|
||||
|
||||
/* note new location within tar */
|
||||
entry->offset = entry->offset_abs = pos;
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int phar_tar_setmetadata(zval *metadata, phar_entry_info *entry, char **error, php_stream *fp TSRMLS_DC)
|
||||
int phar_tar_setmetadata(zval *metadata, phar_entry_info *entry, char **error, php_stream *fp TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
php_serialize_data_t metadata_hash;
|
||||
|
||||
if (entry->metadata_str.c) {
|
||||
smart_str_free(&entry->metadata_str);
|
||||
}
|
||||
|
||||
entry->metadata_str.c = 0;
|
||||
entry->metadata_str.len = 0;
|
||||
PHP_VAR_SERIALIZE_INIT(metadata_hash);
|
||||
php_var_serialize(&entry->metadata_str, &metadata, &metadata_hash TSRMLS_CC);
|
||||
PHP_VAR_SERIALIZE_DESTROY(metadata_hash);
|
||||
entry->uncompressed_filesize = entry->compressed_filesize = entry->metadata_str.len;
|
||||
|
||||
if (entry->fp && entry->fp_type == PHAR_MOD) {
|
||||
php_stream_close(entry->fp);
|
||||
}
|
||||
|
||||
entry->fp_type = PHAR_MOD;
|
||||
entry->is_modified = 1;
|
||||
entry->fp = php_stream_fopen_tmpfile();
|
||||
entry->offset = entry->offset_abs = 0;
|
||||
|
||||
if (entry->metadata_str.len != php_stream_write(entry->fp, entry->metadata_str.c, entry->metadata_str.len)) {
|
||||
spprintf(error, 0, "phar tar error: unable to write metadata to magic metadata file \"%s\"", entry->filename);
|
||||
zend_hash_del(&(entry->phar->manifest), entry->filename, entry->filename_len);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int phar_tar_setupmetadata(void *pDest, void *argument TSRMLS_DC)
|
||||
int phar_tar_setupmetadata(void *pDest, void *argument TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int lookfor_len;
|
||||
struct _phar_pass_tar_info *i = (struct _phar_pass_tar_info *)argument;
|
||||
@@ -677,13 +796,16 @@ int phar_tar_setupmetadata(void *pDest, void *argument TSRMLS_DC)
|
||||
if (!entry->is_modified) {
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
|
||||
/* now we are dealing with regular files, so look for metadata */
|
||||
lookfor_len = spprintf(&lookfor, 0, ".phar/.metadata/%s/.metadata.bin", entry->filename);
|
||||
|
||||
if (!entry->metadata) {
|
||||
zend_hash_del(&(entry->phar->manifest), lookfor, lookfor_len);
|
||||
efree(lookfor);
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
|
||||
if (SUCCESS == zend_hash_find(&(entry->phar->manifest), lookfor, lookfor_len, (void **)&metadata)) {
|
||||
int ret;
|
||||
ret = phar_tar_setmetadata(entry->metadata, metadata, error, fp TSRMLS_CC);
|
||||
@@ -705,15 +827,16 @@ int phar_tar_setupmetadata(void *pDest, void *argument TSRMLS_DC)
|
||||
|
||||
return phar_tar_setmetadata(entry->metadata, metadata, error, fp TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defaultstub, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
phar_entry_info entry = {0};
|
||||
static const char newstub[] = "<?php // tar-based phar archive stub file\n__HALT_COMPILER();";
|
||||
php_stream *oldfile, *newfile, *stubfile;
|
||||
int closeoldfile, free_user_stub;
|
||||
int closeoldfile, free_user_stub, signature_length;
|
||||
struct _phar_pass_tar_info pass;
|
||||
char *buf;
|
||||
char *buf, *signature, sigbuf[8];
|
||||
|
||||
entry.flags = PHAR_ENT_PERM_DEF_FILE;
|
||||
entry.timestamp = time(NULL);
|
||||
@@ -724,6 +847,13 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
entry.phar = phar;
|
||||
entry.fp_type = PHAR_MOD;
|
||||
|
||||
if (phar->is_persistent) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "internal error: attempt to flush cached tar-based phar \"%s\"", phar->fname);
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (phar->is_data) {
|
||||
goto nostub;
|
||||
}
|
||||
@@ -733,14 +863,16 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1);
|
||||
entry.filename_len = sizeof(".phar/alias.txt")-1;
|
||||
entry.fp = php_stream_fopen_tmpfile();
|
||||
entry.crc32 = phar_tar_checksum(phar->alias, phar->alias_len);
|
||||
|
||||
if (phar->alias_len != (int)php_stream_write(entry.fp, phar->alias, phar->alias_len)) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname);
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
entry.uncompressed_filesize = phar->alias_len;
|
||||
|
||||
if (SUCCESS != zend_hash_update(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname);
|
||||
@@ -778,8 +910,8 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
} else {
|
||||
free_user_stub = 0;
|
||||
}
|
||||
if ((pos = strstr(user_stub, "__HALT_COMPILER();")) == NULL)
|
||||
{
|
||||
|
||||
if ((pos = strstr(user_stub, "__HALT_COMPILER();")) == NULL) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "illegal stub for tar-based phar \"%s\"", phar->fname);
|
||||
}
|
||||
@@ -788,6 +920,7 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
len = pos - user_stub + 18;
|
||||
entry.fp = php_stream_fopen_tmpfile();
|
||||
entry.uncompressed_filesize = len + 5;
|
||||
@@ -803,9 +936,11 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
php_stream_close(entry.fp);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1);
|
||||
entry.filename_len = sizeof(".phar/stub.php")-1;
|
||||
zend_hash_update(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL);
|
||||
|
||||
if (free_user_stub) {
|
||||
efree(user_stub);
|
||||
}
|
||||
@@ -850,9 +985,7 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nostub:
|
||||
|
||||
if (phar->fp && !phar->is_brandnew) {
|
||||
oldfile = phar->fp;
|
||||
closeoldfile = 0;
|
||||
@@ -861,7 +994,9 @@ nostub:
|
||||
oldfile = php_stream_open_wrapper(phar->fname, "rb", 0, NULL);
|
||||
closeoldfile = oldfile != NULL;
|
||||
}
|
||||
|
||||
newfile = php_stream_fopen_tmpfile();
|
||||
|
||||
if (!newfile) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "unable to create temporary file");
|
||||
@@ -903,6 +1038,7 @@ nostub:
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (ZEND_HASH_APPLY_KEEP != phar_tar_setmetadata(phar->metadata, mentry, error, oldfile TSRMLS_CC)) {
|
||||
zend_hash_del(&(phar->manifest), ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1);
|
||||
if (closeoldfile) {
|
||||
@@ -912,12 +1048,14 @@ nostub:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zend_hash_apply_with_argument(&phar->manifest, (apply_func_arg_t) phar_tar_setupmetadata, (void *) &pass TSRMLS_CC);
|
||||
|
||||
if (error && *error) {
|
||||
if (closeoldfile) {
|
||||
php_stream_close(oldfile);
|
||||
}
|
||||
|
||||
/* on error in the hash iterator above, error is set */
|
||||
php_stream_close(newfile);
|
||||
return EOF;
|
||||
@@ -925,6 +1063,67 @@ nostub:
|
||||
|
||||
zend_hash_apply_with_argument(&phar->manifest, (apply_func_arg_t) phar_tar_writeheaders, (void *) &pass TSRMLS_CC);
|
||||
|
||||
/* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */
|
||||
if (!phar->is_data || phar->sig_flags) {
|
||||
if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, error TSRMLS_CC)) {
|
||||
if (error) {
|
||||
char *save = *error;
|
||||
spprintf(error, 0, "phar error: unable to write signature to tar-based phar: %s", save);
|
||||
efree(save);
|
||||
}
|
||||
|
||||
if (closeoldfile) {
|
||||
php_stream_close(oldfile);
|
||||
}
|
||||
|
||||
php_stream_close(newfile);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
entry.filename = ".phar/signature.bin";
|
||||
entry.filename_len = sizeof(".phar/signature.bin")-1;
|
||||
entry.fp = php_stream_fopen_tmpfile();
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define PHAR_SET_32(var, buffer) \
|
||||
*(php_uint32 *)(var) = (((((unsigned char*)(buffer))[3]) << 24) \
|
||||
| ((((unsigned char*)(buffer))[2]) << 16) \
|
||||
| ((((unsigned char*)(buffer))[1]) << 8) \
|
||||
| (((unsigned char*)(buffer))[0]))
|
||||
#else
|
||||
# define PHAR_SET_32(var, buffer) *(php_uint32 *)(var) = (php_uint32) (buffer)
|
||||
#endif
|
||||
PHAR_SET_32(sigbuf, phar->sig_flags);
|
||||
PHAR_SET_32(sigbuf + 4, signature_length);
|
||||
|
||||
if (8 != (int)php_stream_write(entry.fp, sigbuf, 8) || signature_length != (int)php_stream_write(entry.fp, signature, signature_length)) {
|
||||
efree(signature);
|
||||
if (error) {
|
||||
spprintf(error, 0, "phar error: unable to write signature to tar-based phar %s", phar->fname);
|
||||
}
|
||||
|
||||
if (closeoldfile) {
|
||||
php_stream_close(oldfile);
|
||||
}
|
||||
php_stream_close(newfile);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
efree(signature);
|
||||
entry.uncompressed_filesize = entry.compressed_filesize = signature_length + 8;
|
||||
/* throw out return value and write the signature */
|
||||
entry.filename_len = phar_tar_writeheaders((void *)&entry, (void *)&pass TSRMLS_CC);
|
||||
|
||||
if (error && *error) {
|
||||
if (closeoldfile) {
|
||||
php_stream_close(oldfile);
|
||||
}
|
||||
/* error is set by writeheaders */
|
||||
php_stream_close(newfile);
|
||||
return EOF;
|
||||
}
|
||||
} /* signature */
|
||||
|
||||
/* add final zero blocks */
|
||||
buf = (char *) ecalloc(1024, 1);
|
||||
php_stream_write(newfile, buf, 1024);
|
||||
@@ -933,14 +1132,17 @@ nostub:
|
||||
if (closeoldfile) {
|
||||
php_stream_close(oldfile);
|
||||
}
|
||||
|
||||
/* on error in the hash iterator above, error is set */
|
||||
if (error && *error) {
|
||||
php_stream_close(newfile);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (phar->fp && pass.free_fp) {
|
||||
php_stream_close(phar->fp);
|
||||
}
|
||||
|
||||
if (phar->ufp) {
|
||||
if (pass.free_ufp) {
|
||||
php_stream_close(phar->ufp);
|
||||
@@ -949,7 +1151,6 @@ nostub:
|
||||
}
|
||||
|
||||
phar->is_brandnew = 0;
|
||||
|
||||
php_stream_rewind(newfile);
|
||||
|
||||
if (phar->donotflush) {
|
||||
@@ -964,6 +1165,7 @@ nostub:
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (phar->flags & PHAR_FILE_COMPRESSED_GZ) {
|
||||
php_stream_filter *filter;
|
||||
/* to properly compress, we have to tell zlib to add a zlib header */
|
||||
@@ -977,6 +1179,7 @@ nostub:
|
||||
add_assoc_long(&filterparams, "window", MAX_WBITS + 16);
|
||||
filter = php_stream_filter_create("zlib.deflate", &filterparams, php_stream_is_persistent(phar->fp) TSRMLS_CC);
|
||||
zval_dtor(&filterparams);
|
||||
|
||||
if (!filter) {
|
||||
/* copy contents uncompressed rather than lose them */
|
||||
php_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL);
|
||||
@@ -986,6 +1189,7 @@ nostub:
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
php_stream_filter_append(&phar->fp->writefilters, filter);
|
||||
php_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL);
|
||||
php_stream_filter_flush(filter, 1);
|
||||
@@ -1013,3 +1217,12 @@ nostub:
|
||||
return EOF;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
1237
ext/phar/util.c
1237
ext/phar/util.c
File diff suppressed because it is too large
Load Diff
314
ext/phar/zip.c
314
ext/phar/zip.c
@@ -34,7 +34,7 @@
|
||||
# define PHAR_SET_16(buffer) (buffer)
|
||||
#endif
|
||||
|
||||
static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, php_uint16 len TSRMLS_DC)
|
||||
static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, php_uint16 len TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
union {
|
||||
phar_zip_extra_field_header header;
|
||||
@@ -46,32 +46,41 @@ static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, php_ui
|
||||
if (sizeof(h.header) != php_stream_read(fp, (char *) &h.header, sizeof(h.header))) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (h.header.tag[0] != 'n' || h.header.tag[1] != 'u') {
|
||||
/* skip to next header */
|
||||
php_stream_seek(fp, PHAR_GET_16(h.header.size), SEEK_CUR);
|
||||
len -= PHAR_GET_16(h.header.size) + 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* unix3 header found */
|
||||
read = php_stream_read(fp, (char *) &(h.unix3.crc32), sizeof(h.unix3) - sizeof(h.header));
|
||||
len -= read + 4;
|
||||
|
||||
if (sizeof(h.unix3) - sizeof(h.header) != read) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (PHAR_GET_16(h.unix3.size) > sizeof(h.unix3) - 4) {
|
||||
/* skip symlink filename - we may add this support in later */
|
||||
php_stream_seek(fp, h.unix3.size - sizeof(h.unix3.size), SEEK_CUR);
|
||||
}
|
||||
|
||||
/* set permissions */
|
||||
entry->flags &= PHAR_ENT_COMPRESSION_MASK;
|
||||
|
||||
if (entry->is_dir) {
|
||||
entry->flags |= PHAR_GET_16(h.unix3.perms) & PHAR_ENT_PERM_MASK;
|
||||
} else {
|
||||
entry->flags |= PHAR_GET_16(h.unix3.perms) & PHAR_ENT_PERM_MASK;
|
||||
}
|
||||
|
||||
} while (len);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
extracted from libzip
|
||||
@@ -93,7 +102,7 @@ static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, php_ui
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@@ -106,38 +115,40 @@ static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, php_ui
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
static time_t phar_zip_d2u_time(int dtime, int ddate)
|
||||
static time_t phar_zip_d2u_time(int dtime, int ddate) /* {{{ */
|
||||
{
|
||||
struct tm *tm, tmbuf;
|
||||
time_t now;
|
||||
struct tm *tm, tmbuf;
|
||||
time_t now;
|
||||
|
||||
now = time(NULL);
|
||||
tm = php_localtime_r(&now, &tmbuf);
|
||||
|
||||
tm->tm_year = ((ddate>>9)&127) + 1980 - 1900;
|
||||
tm->tm_mon = ((ddate>>5)&15) - 1;
|
||||
tm->tm_mday = ddate&31;
|
||||
now = time(NULL);
|
||||
tm = php_localtime_r(&now, &tmbuf);
|
||||
|
||||
tm->tm_hour = (dtime>>11)&31;
|
||||
tm->tm_min = (dtime>>5)&63;
|
||||
tm->tm_sec = (dtime<<1)&62;
|
||||
tm->tm_year = ((ddate>>9)&127) + 1980 - 1900;
|
||||
tm->tm_mon = ((ddate>>5)&15) - 1;
|
||||
tm->tm_mday = ddate&31;
|
||||
|
||||
return mktime(tm);
|
||||
tm->tm_hour = (dtime>>11)&31;
|
||||
tm->tm_min = (dtime>>5)&63;
|
||||
tm->tm_sec = (dtime<<1)&62;
|
||||
|
||||
return mktime(tm);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void phar_zip_u2d_time(time_t time, php_uint16 *dtime, php_uint16 *ddate)
|
||||
static void phar_zip_u2d_time(time_t time, php_uint16 *dtime, php_uint16 *ddate) /* {{{ */
|
||||
{
|
||||
struct tm *tm, tmbuf;
|
||||
struct tm *tm, tmbuf;
|
||||
|
||||
tm = php_localtime_r(&time, &tmbuf);
|
||||
*ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday;
|
||||
*dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1);
|
||||
tm = php_localtime_r(&time, &tmbuf);
|
||||
*ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday;
|
||||
*dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* This is used by phar_open_from_fp to process a zip-based phar, but can be called
|
||||
@@ -155,6 +166,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
|
||||
char *p = buf, *ext, *actual_alias = NULL;
|
||||
|
||||
size = php_stream_tell(fp);
|
||||
|
||||
if (size > sizeof(locator) + 65536) {
|
||||
/* seek to max comment length + end of central directory record */
|
||||
size = sizeof(locator) + 65536;
|
||||
@@ -168,6 +180,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
|
||||
} else {
|
||||
php_stream_seek(fp, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
if (!(read = php_stream_read(fp, buf, size))) {
|
||||
php_stream_close(fp);
|
||||
if (error) {
|
||||
@@ -175,6 +188,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while ((p=(char *) memchr(p + 1, 'P', (size_t) (size - (p + 1 - buf)))) != NULL) {
|
||||
if (!memcmp(p + 1, "K\5\6", 3)) {
|
||||
memcpy((void *)&locator, (void *) p, sizeof(locator));
|
||||
@@ -186,6 +200,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (locator.counthere != locator.count) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname);
|
||||
@@ -193,45 +208,65 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
|
||||
php_stream_close(fp);
|
||||
return FAILURE;
|
||||
}
|
||||
mydata = ecalloc(sizeof(phar_archive_data), 1);
|
||||
|
||||
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
|
||||
mydata->is_persistent = PHAR_G(persist);
|
||||
|
||||
/* read in archive comment, if any */
|
||||
if (locator.comment_len) {
|
||||
char *metadata;
|
||||
|
||||
metadata = p + sizeof(locator);
|
||||
|
||||
if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
efree(mydata);
|
||||
pefree(mydata, mydata->is_persistent);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata->metadata_len = PHAR_GET_16(locator.comment_len);
|
||||
|
||||
if (phar_parse_metadata(&metadata, &mydata->metadata, PHAR_GET_16(locator.comment_len) TSRMLS_CC) == FAILURE) {
|
||||
mydata->metadata_len = 0;
|
||||
/* if not valid serialized data, it is a regular string */
|
||||
ALLOC_INIT_ZVAL(mydata->metadata);
|
||||
ZVAL_STRINGL(mydata->metadata, metadata, PHAR_GET_16(locator.comment_len), 1);
|
||||
|
||||
if (entry.is_persistent) {
|
||||
ALLOC_PERMANENT_ZVAL(mydata->metadata);
|
||||
} else {
|
||||
ALLOC_ZVAL(mydata->metadata);
|
||||
}
|
||||
|
||||
INIT_ZVAL(*mydata->metadata);
|
||||
metadata = pestrndup(metadata, PHAR_GET_16(locator.comment_len), mydata->is_persistent);
|
||||
ZVAL_STRINGL(mydata->metadata, metadata, PHAR_GET_16(locator.comment_len), 0);
|
||||
}
|
||||
} else {
|
||||
mydata->metadata = NULL;
|
||||
}
|
||||
|
||||
goto foundit;
|
||||
}
|
||||
}
|
||||
|
||||
php_stream_close(fp);
|
||||
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: end of central directory not found in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
foundit:
|
||||
mydata->fname = estrndup(fname, fname_len);
|
||||
mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent);
|
||||
#ifdef PHP_WIN32
|
||||
phar_unixify_path_separators(mydata->fname, fname_len);
|
||||
#endif
|
||||
mydata->is_zip = 1;
|
||||
mydata->fname_len = fname_len;
|
||||
ext = strrchr(mydata->fname, '/');
|
||||
|
||||
if (ext) {
|
||||
mydata->ext = memchr(ext, '.', (mydata->fname + fname_len) - ext);
|
||||
if (mydata->ext == ext) {
|
||||
@@ -241,22 +276,28 @@ foundit:
|
||||
mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
|
||||
}
|
||||
}
|
||||
|
||||
/* clean up on big-endian systems */
|
||||
/* seek to central directory */
|
||||
php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
|
||||
/* read in central directory */
|
||||
zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
|
||||
zend_get_hash_value, destroy_phar_manifest_entry, 0);
|
||||
zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
|
||||
zend_get_hash_value, NULL, 0);
|
||||
zend_hash_init(&mydata->manifest, PHAR_GET_16(locator.count),
|
||||
zend_get_hash_value, destroy_phar_manifest_entry, (zend_bool)mydata->is_persistent);
|
||||
zend_hash_init(&mydata->mounted_dirs, 5,
|
||||
zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
|
||||
zend_hash_init(&mydata->virtual_dirs, PHAR_GET_16(locator.count) * 2,
|
||||
zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
|
||||
entry.phar = mydata;
|
||||
entry.is_zip = 1;
|
||||
entry.fp_type = PHAR_FP;
|
||||
entry.is_persistent = mydata->is_persistent;
|
||||
#define PHAR_ZIP_FAIL(errmsg) \
|
||||
zend_hash_destroy(&mydata->manifest); \
|
||||
mydata->manifest.arBuckets = 0; \
|
||||
zend_hash_destroy(&mydata->mounted_dirs); \
|
||||
mydata->mounted_dirs.arBuckets = 0; \
|
||||
zend_hash_destroy(&mydata->virtual_dirs); \
|
||||
mydata->virtual_dirs.arBuckets = 0; \
|
||||
php_stream_close(fp); \
|
||||
if (mydata->metadata) { \
|
||||
zval_dtor(mydata->metadata); \
|
||||
@@ -264,25 +305,31 @@ foundit:
|
||||
if (error) { \
|
||||
spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \
|
||||
} \
|
||||
efree(mydata->fname); \
|
||||
pefree(mydata->fname, mydata->is_persistent); \
|
||||
if (mydata->alias) { \
|
||||
efree(mydata->alias); \
|
||||
pefree(mydata->alias, mydata->is_persistent); \
|
||||
} \
|
||||
efree(mydata); \
|
||||
pefree(mydata, mydata->is_persistent); \
|
||||
return FAILURE;
|
||||
|
||||
/* add each central directory item to the manifest */
|
||||
for (i = 0; i < locator.count; ++i) {
|
||||
for (i = 0; i < PHAR_GET_16(locator.count); ++i) {
|
||||
phar_zip_central_dir_file zipentry;
|
||||
|
||||
if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) {
|
||||
PHAR_ZIP_FAIL("unable to read central directory entry, truncated");
|
||||
}
|
||||
|
||||
/* clean up for bigendian systems */
|
||||
if (memcmp("PK\1\2", zipentry.signature, 4)) {
|
||||
/* corrupted entry */
|
||||
PHAR_ZIP_FAIL("corrupted central directory entry, no magic signature");
|
||||
}
|
||||
|
||||
if (entry.is_persistent) {
|
||||
entry.manifest_pos = i;
|
||||
}
|
||||
|
||||
entry.compressed_filesize = PHAR_GET_32(zipentry.compsize);
|
||||
entry.uncompressed_filesize = PHAR_GET_32(zipentry.uncompsize);
|
||||
entry.crc32 = PHAR_GET_32(zipentry.crc32);
|
||||
@@ -292,19 +339,25 @@ foundit:
|
||||
entry.header_offset = PHAR_GET_32(zipentry.offset);
|
||||
entry.offset = entry.offset_abs = PHAR_GET_32(zipentry.offset) + sizeof(phar_zip_file_header) + PHAR_GET_16(zipentry.filename_len) +
|
||||
PHAR_GET_16(zipentry.extra_len);
|
||||
|
||||
if (PHAR_GET_16(zipentry.flags) & PHAR_ZIP_FLAG_ENCRYPTED) {
|
||||
PHAR_ZIP_FAIL("Cannot process encrypted zip files");
|
||||
}
|
||||
|
||||
if (!PHAR_GET_16(zipentry.filename_len)) {
|
||||
PHAR_ZIP_FAIL("Cannot process zips created from stdin (zero-length filename)");
|
||||
}
|
||||
|
||||
entry.filename_len = PHAR_GET_16(zipentry.filename_len);
|
||||
entry.filename = (char *) emalloc(entry.filename_len + 1);
|
||||
entry.filename = (char *) pemalloc(entry.filename_len + 1, entry.is_persistent);
|
||||
|
||||
if (entry.filename_len != php_stream_read(fp, entry.filename, entry.filename_len)) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unable to read in filename from central directory, truncated");
|
||||
}
|
||||
|
||||
entry.filename[entry.filename_len] = '\0';
|
||||
|
||||
if (entry.filename[entry.filename_len - 1] == '/') {
|
||||
entry.is_dir = 1;
|
||||
entry.filename_len--;
|
||||
@@ -312,14 +365,18 @@ foundit:
|
||||
} else {
|
||||
entry.is_dir = 0;
|
||||
}
|
||||
|
||||
phar_add_virtual_dirs(mydata, entry.filename, entry.filename_len TSRMLS_CC);
|
||||
|
||||
if (PHAR_GET_16(zipentry.extra_len)) {
|
||||
off_t loc = php_stream_tell(fp);
|
||||
if (FAILURE == phar_zip_process_extra(fp, &entry, PHAR_GET_16(zipentry.extra_len) TSRMLS_CC)) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("Unable to process extra field header for file in central directory");
|
||||
}
|
||||
php_stream_seek(fp, loc + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
|
||||
}
|
||||
|
||||
switch (zipentry.compressed) {
|
||||
case PHAR_ZIP_COMP_NONE :
|
||||
/* compression flag already set */
|
||||
@@ -327,112 +384,134 @@ foundit:
|
||||
case PHAR_ZIP_COMP_DEFLATE :
|
||||
entry.flags |= PHAR_ENT_COMPRESSED_GZ;
|
||||
if (!PHAR_G(has_zlib)) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("zlib extension is required");
|
||||
}
|
||||
break;
|
||||
case PHAR_ZIP_COMP_BZIP2 :
|
||||
entry.flags |= PHAR_ENT_COMPRESSED_BZ2;
|
||||
if (!PHAR_G(has_bz2)) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("bzip2 extension is required");
|
||||
}
|
||||
break;
|
||||
case 1 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (Shrunk) used in this zip");
|
||||
case 2 :
|
||||
case 3 :
|
||||
case 4 :
|
||||
case 5 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (Reduce) used in this zip");
|
||||
case 6 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (Implode) used in this zip");
|
||||
case 7 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (Tokenize) used in this zip");
|
||||
case 9 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (Deflate64) used in this zip");
|
||||
case 10 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (PKWare Implode/old IBM TERSE) used in this zip");
|
||||
case 14 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (LZMA) used in this zip");
|
||||
case 18 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (IBM TERSE) used in this zip");
|
||||
case 19 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (IBM LZ77) used in this zip");
|
||||
case 97 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (WavPack) used in this zip");
|
||||
case 98 :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (PPMd) used in this zip");
|
||||
default :
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unsupported compression method (unknown) used in this zip");
|
||||
}
|
||||
|
||||
/* get file metadata */
|
||||
if (zipentry.comment_len) {
|
||||
if (PHAR_GET_16(zipentry.comment_len) != php_stream_read(fp, buf, PHAR_GET_16(zipentry.comment_len))) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unable to read in file comment, truncated");
|
||||
}
|
||||
|
||||
p = buf;
|
||||
entry.metadata_len = zipentry.comment_len;
|
||||
|
||||
if (phar_parse_metadata(&p, &(entry.metadata), PHAR_GET_16(zipentry.comment_len) TSRMLS_CC) == FAILURE) {
|
||||
entry.metadata_len = 0;
|
||||
/* if not valid serialized data, it is a regular string */
|
||||
ALLOC_INIT_ZVAL(entry.metadata);
|
||||
ZVAL_STRINGL(entry.metadata, buf, PHAR_GET_16(zipentry.comment_len), 1);
|
||||
|
||||
if (entry.is_persistent) {
|
||||
ALLOC_PERMANENT_ZVAL(entry.metadata);
|
||||
} else {
|
||||
ALLOC_ZVAL(entry.metadata);
|
||||
}
|
||||
|
||||
INIT_ZVAL(*entry.metadata);
|
||||
ZVAL_STRINGL(entry.metadata, pestrndup(buf, PHAR_GET_16(zipentry.comment_len), entry.is_persistent), PHAR_GET_16(zipentry.comment_len), 0);
|
||||
}
|
||||
} else {
|
||||
entry.metadata = NULL;
|
||||
}
|
||||
|
||||
if (!actual_alias && entry.filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry.filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
|
||||
php_stream_filter *filter;
|
||||
off_t saveloc;
|
||||
|
||||
/* archive alias found, seek to file contents, do not validate local header. Potentially risky, but
|
||||
not very. */
|
||||
/* archive alias found, seek to file contents, do not validate local header. Potentially risky, but not very. */
|
||||
saveloc = php_stream_tell(fp);
|
||||
php_stream_seek(fp, PHAR_GET_32(zipentry.offset) + sizeof(phar_zip_file_header) + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
|
||||
mydata->alias_len = entry.uncompressed_filesize;
|
||||
|
||||
if (entry.flags & PHAR_ENT_COMPRESSED_GZ) {
|
||||
filter = php_stream_filter_create("zlib.inflate", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
|
||||
|
||||
if (!filter) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unable to decompress alias, zlib filter creation failed");
|
||||
}
|
||||
|
||||
php_stream_filter_append(&fp->readfilters, filter);
|
||||
|
||||
if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unable to read in alias, truncated");
|
||||
}
|
||||
|
||||
php_stream_filter_flush(filter, 1);
|
||||
php_stream_filter_remove(filter, 1 TSRMLS_CC);
|
||||
|
||||
} else if (entry.flags & PHAR_ENT_COMPRESSED_BZ2) {
|
||||
php_stream_filter *filter;
|
||||
filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
|
||||
|
||||
if (!filter) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unable to read in alias, bzip2 filter creation failed");
|
||||
}
|
||||
|
||||
php_stream_filter_append(&fp->readfilters, filter);
|
||||
php_stream_filter_append(&fp->readfilters, filter);
|
||||
|
||||
if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unable to read in alias, truncated");
|
||||
}
|
||||
|
||||
php_stream_filter_flush(filter, 1);
|
||||
php_stream_filter_remove(filter, 1 TSRMLS_CC);
|
||||
} else {
|
||||
if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
|
||||
efree(entry.filename);
|
||||
pefree(entry.filename, entry.is_persistent);
|
||||
PHAR_ZIP_FAIL("unable to read in alias, truncated");
|
||||
}
|
||||
}
|
||||
@@ -440,8 +519,11 @@ foundit:
|
||||
/* return to central directory parsing */
|
||||
php_stream_seek(fp, saveloc, SEEK_SET);
|
||||
}
|
||||
|
||||
phar_set_inode(&entry TSRMLS_CC);
|
||||
zend_hash_add(&mydata->manifest, entry.filename, entry.filename_len, (void *)&entry,sizeof(phar_entry_info), NULL);
|
||||
}
|
||||
|
||||
mydata->fp = fp;
|
||||
|
||||
if (zend_hash_exists(&(mydata->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
|
||||
@@ -451,6 +533,7 @@ foundit:
|
||||
}
|
||||
|
||||
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
|
||||
|
||||
if (actual_alias) {
|
||||
phar_archive_data **fd_ptr;
|
||||
|
||||
@@ -462,7 +545,9 @@ foundit:
|
||||
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata->is_temporary_alias = 0;
|
||||
|
||||
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void **)&fd_ptr)) {
|
||||
if (SUCCESS != phar_free_alias(*fd_ptr, actual_alias, mydata->alias_len TSRMLS_CC)) {
|
||||
if (error) {
|
||||
@@ -473,7 +558,13 @@ foundit:
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
mydata->alias = actual_alias;
|
||||
|
||||
mydata->alias = entry.is_persistent ? pestrndup(actual_alias, mydata->alias_len, 1) : actual_alias;
|
||||
|
||||
if (entry.is_persistent) {
|
||||
efree(actual_alias);
|
||||
}
|
||||
|
||||
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
|
||||
} else {
|
||||
phar_archive_data **fd_ptr;
|
||||
@@ -488,18 +579,22 @@ foundit:
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
|
||||
mydata->alias = estrndup(alias, alias_len);
|
||||
mydata->alias = pestrndup(alias, alias_len, mydata->is_persistent);
|
||||
mydata->alias_len = alias_len;
|
||||
} else {
|
||||
mydata->alias = estrndup(mydata->fname, fname_len);
|
||||
mydata->alias = pestrndup(mydata->fname, fname_len, mydata->is_persistent);
|
||||
mydata->alias_len = fname_len;
|
||||
}
|
||||
|
||||
mydata->is_temporary_alias = 1;
|
||||
}
|
||||
|
||||
if (pphar) {
|
||||
*pphar = mydata;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -537,6 +632,7 @@ int phar_open_or_create_zip(char *fname, int fname_len, char *alias, int alias_l
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar zip error: phar \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a zip-based phar", fname);
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -562,9 +658,11 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */
|
||||
|
||||
entry = (phar_entry_info *)data;
|
||||
p = (struct _phar_zip_pass*) arg;
|
||||
|
||||
if (entry->is_mounted) {
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
|
||||
if (entry->is_deleted) {
|
||||
if (entry->fp_refcount <= 0) {
|
||||
return ZEND_HASH_APPLY_REMOVE;
|
||||
@@ -573,6 +671,7 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&local, 0, sizeof(local));
|
||||
memset(¢ral, 0, sizeof(central));
|
||||
memset(&perms, 0, sizeof(perms));
|
||||
@@ -587,18 +686,22 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */
|
||||
CRC32(perms.crc32, (char)perms.perms & 0xFF);
|
||||
CRC32(perms.crc32, (char)perms.perms & 0xFF00 >> 8);
|
||||
perms.crc32 = PHAR_SET_32(~(perms.crc32));
|
||||
|
||||
if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
|
||||
local.compressed = central.compressed = PHAR_SET_16(PHAR_ZIP_COMP_DEFLATE);
|
||||
}
|
||||
|
||||
if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
|
||||
local.compressed = central.compressed = PHAR_SET_16(PHAR_ZIP_COMP_BZIP2);
|
||||
}
|
||||
|
||||
/* do not use PHAR_SET_16 on either field of the next line */
|
||||
phar_zip_u2d_time(entry->timestamp, &local.timestamp, &local.datestamp);
|
||||
central.timestamp = local.timestamp;
|
||||
central.datestamp = local.datestamp;
|
||||
central.filename_len = local.filename_len = PHAR_SET_16(entry->filename_len + (entry->is_dir ? 1 : 0));
|
||||
central.offset = PHAR_SET_32(php_stream_tell(p->filefp));
|
||||
|
||||
/* do extra field for perms later */
|
||||
if (entry->is_modified) {
|
||||
php_uint32 loc;
|
||||
@@ -614,29 +717,36 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
goto continue_dir;
|
||||
}
|
||||
|
||||
if (FAILURE == phar_open_entry_fp(entry, p->error, 0 TSRMLS_CC)) {
|
||||
spprintf(p->error, 0, "unable to open file contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC)) {
|
||||
spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
efp = phar_get_efp(entry, 0 TSRMLS_CC);
|
||||
|
||||
efp = phar_get_efp(entry, 0 TSRMLS_CC);
|
||||
newcrc32 = ~0;
|
||||
|
||||
for (loc = 0;loc < entry->uncompressed_filesize; ++loc) {
|
||||
CRC32(newcrc32, php_stream_getc(efp));
|
||||
}
|
||||
|
||||
entry->crc32 = ~newcrc32;
|
||||
central.uncompsize = local.uncompsize = PHAR_SET_32(entry->uncompressed_filesize);
|
||||
|
||||
if (!(entry->flags & PHAR_ENT_COMPRESSION_MASK)) {
|
||||
/* not compressed */
|
||||
entry->compressed_filesize = entry->uncompressed_filesize;
|
||||
central.compsize = local.compsize = PHAR_SET_32(entry->compressed_filesize);
|
||||
goto not_compressed;
|
||||
}
|
||||
|
||||
filter = php_stream_filter_create(phar_compress_filter(entry, 0), NULL, 0 TSRMLS_CC);
|
||||
|
||||
if (!filter) {
|
||||
if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
|
||||
spprintf(p->error, 0, "unable to gzip compress file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
@@ -650,20 +760,26 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */
|
||||
/* work around inability to specify freedom in write and strictness
|
||||
in read count */
|
||||
entry->cfp = php_stream_fopen_tmpfile();
|
||||
|
||||
if (!entry->cfp) {
|
||||
spprintf(p->error, 0, "unable to create temporary file for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
php_stream_flush(efp);
|
||||
|
||||
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC)) {
|
||||
spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
php_stream_filter_append((&entry->cfp->writefilters), filter);
|
||||
|
||||
if (entry->uncompressed_filesize != php_stream_copy_to_stream(efp, entry->cfp, entry->uncompressed_filesize)) {
|
||||
spprintf(p->error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
php_stream_filter_flush(filter, 1);
|
||||
php_stream_flush(entry->cfp);
|
||||
php_stream_filter_remove(filter, 1 TSRMLS_CC);
|
||||
@@ -677,6 +793,7 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */
|
||||
} else {
|
||||
central.uncompsize = local.uncompsize = PHAR_SET_32(entry->uncompressed_filesize);
|
||||
central.compsize = local.compsize = PHAR_SET_32(entry->compressed_filesize);
|
||||
|
||||
if (-1 == php_stream_seek(p->old, entry->offset_abs, SEEK_SET)) {
|
||||
spprintf(p->error, 0, "unable to seek to start of file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
@@ -699,29 +816,36 @@ continue_dir:
|
||||
PHP_VAR_SERIALIZE_DESTROY(metadata_hash);
|
||||
central.comment_len = PHAR_SET_16(entry->metadata_str.len);
|
||||
}
|
||||
|
||||
entry->header_offset = php_stream_tell(p->filefp);
|
||||
offset = entry->header_offset + sizeof(local) + entry->filename_len + (entry->is_dir ? 1 : 0) + sizeof(perms);
|
||||
|
||||
if (sizeof(local) != php_stream_write(p->filefp, (char *)&local, sizeof(local))) {
|
||||
spprintf(p->error, 0, "unable to write local file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (sizeof(central) != php_stream_write(p->centralfp, (char *)¢ral, sizeof(central))) {
|
||||
spprintf(p->error, 0, "unable to write central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (entry->is_dir) {
|
||||
if (entry->filename_len != php_stream_write(p->filefp, entry->filename, entry->filename_len)) {
|
||||
spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (1 != php_stream_write(p->filefp, "/", 1)) {
|
||||
spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (entry->filename_len != php_stream_write(p->centralfp, entry->filename, entry->filename_len)) {
|
||||
spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (1 != php_stream_write(p->centralfp, "/", 1)) {
|
||||
spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
@@ -731,40 +855,49 @@ continue_dir:
|
||||
spprintf(p->error, 0, "unable to write filename to local directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (entry->filename_len != php_stream_write(p->centralfp, entry->filename, entry->filename_len)) {
|
||||
spprintf(p->error, 0, "unable to write filename to central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
if (sizeof(perms) != php_stream_write(p->filefp, (char *)&perms, sizeof(perms))) {
|
||||
spprintf(p->error, 0, "unable to write local extra permissions file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (sizeof(perms) != php_stream_write(p->centralfp, (char *)&perms, sizeof(perms))) {
|
||||
spprintf(p->error, 0, "unable to write central extra permissions file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
if (entry->is_modified) {
|
||||
if (entry->cfp) {
|
||||
if (entry->compressed_filesize != php_stream_copy_to_stream(entry->cfp, p->filefp, entry->compressed_filesize)) {
|
||||
spprintf(p->error, 0, "unable to write compressed contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
php_stream_close(entry->cfp);
|
||||
entry->cfp = NULL;
|
||||
} else {
|
||||
if (FAILURE == phar_open_entry_fp(entry, p->error, 0 TSRMLS_CC)) {
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC);
|
||||
|
||||
if (entry->uncompressed_filesize != php_stream_copy_to_stream(phar_get_efp(entry, 0 TSRMLS_CC), p->filefp, entry->uncompressed_filesize)) {
|
||||
spprintf(p->error, 0, "unable to write contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry->fp_type == PHAR_MOD && entry->fp != entry->phar->fp && entry->fp != entry->phar->ufp && entry->fp_refcount == 0) {
|
||||
php_stream_close(entry->fp);
|
||||
}
|
||||
|
||||
entry->is_modified = 0;
|
||||
} else {
|
||||
if (entry->fp_refcount) {
|
||||
@@ -779,22 +912,27 @@ continue_dir:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry->is_dir && entry->compressed_filesize && entry->compressed_filesize != php_stream_copy_to_stream(p->old, p->filefp, entry->compressed_filesize)) {
|
||||
spprintf(p->error, 0, "unable to copy contents of file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
entry->fp = NULL;
|
||||
entry->offset = entry->offset_abs = offset;
|
||||
entry->fp_type = PHAR_FP;
|
||||
|
||||
if (entry->metadata_str.c) {
|
||||
if (entry->metadata_str.len != php_stream_write(p->centralfp, entry->metadata_str.c, entry->metadata_str.len)) {
|
||||
spprintf(p->error, 0, "unable to write metadata as file comment for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
|
||||
smart_str_free(&entry->metadata_str);
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
}
|
||||
|
||||
smart_str_free(&entry->metadata_str);
|
||||
}
|
||||
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -820,6 +958,13 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
entry.phar = phar;
|
||||
entry.fp_type = PHAR_MOD;
|
||||
|
||||
if (phar->is_persistent) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "internal error: attempt to flush cached zip-based phar \"%s\"", phar->fname);
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (phar->is_data) {
|
||||
goto nostub;
|
||||
}
|
||||
@@ -827,15 +972,18 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
/* set alias */
|
||||
if (!phar->is_temporary_alias && phar->alias_len) {
|
||||
entry.fp = php_stream_fopen_tmpfile();
|
||||
|
||||
if (phar->alias_len != (int)php_stream_write(entry.fp, phar->alias, phar->alias_len)) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname);
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
entry.uncompressed_filesize = entry.compressed_filesize = phar->alias_len;
|
||||
entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1);
|
||||
entry.filename_len = sizeof(".phar/alias.txt")-1;
|
||||
|
||||
if (SUCCESS != zend_hash_update(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname);
|
||||
@@ -845,6 +993,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
} else {
|
||||
zend_hash_del(&phar->manifest, ".phar/alias.txt", sizeof(".phar/alias.txt")-1);
|
||||
}
|
||||
|
||||
/* register alias */
|
||||
if (phar->alias_len) {
|
||||
if (FAILURE == phar_get_archive(&phar, phar->fname, phar->fname_len, phar->alias, phar->alias_len, error TSRMLS_CC)) {
|
||||
@@ -862,12 +1011,15 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (len == -1) {
|
||||
len = PHP_STREAM_COPY_ALL;
|
||||
} else {
|
||||
len = -len;
|
||||
}
|
||||
|
||||
user_stub = 0;
|
||||
|
||||
if (!(len = php_stream_copy_to_mem(stubfile, &user_stub, len, 0)) || !user_stub) {
|
||||
if (error) {
|
||||
spprintf(error, 0, "unable to read resource to copy stub to new zip-based phar \"%s\"", phar->fname);
|
||||
@@ -878,6 +1030,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
} else {
|
||||
free_user_stub = 0;
|
||||
}
|
||||
|
||||
if ((pos = strstr(user_stub, "__HALT_COMPILER();")) == NULL)
|
||||
{
|
||||
if (error) {
|
||||
@@ -888,6 +1041,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
len = pos - user_stub + 18;
|
||||
entry.fp = php_stream_fopen_tmpfile();
|
||||
entry.uncompressed_filesize = len + 5;
|
||||
@@ -903,8 +1057,10 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
php_stream_close(entry.fp);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1);
|
||||
entry.filename_len = sizeof(".phar/stub.php")-1;
|
||||
|
||||
if (SUCCESS != zend_hash_update(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
|
||||
if (free_user_stub) {
|
||||
efree(user_stub);
|
||||
@@ -914,6 +1070,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (free_user_stub) {
|
||||
efree(user_stub);
|
||||
}
|
||||
@@ -958,9 +1115,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nostub:
|
||||
|
||||
if (phar->fp && !phar->is_brandnew) {
|
||||
oldfile = phar->fp;
|
||||
closeoldfile = 0;
|
||||
@@ -973,6 +1128,7 @@ nostub:
|
||||
/* save modified files to the zip */
|
||||
pass.old = oldfile;
|
||||
pass.filefp = php_stream_fopen_tmpfile();
|
||||
|
||||
if (!pass.filefp) {
|
||||
if (closeoldfile) {
|
||||
php_stream_close(oldfile);
|
||||
@@ -982,7 +1138,9 @@ nostub:
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
pass.centralfp = php_stream_fopen_tmpfile();
|
||||
|
||||
if (!pass.centralfp) {
|
||||
if (closeoldfile) {
|
||||
php_stream_close(oldfile);
|
||||
@@ -992,12 +1150,14 @@ nostub:
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
pass.free_fp = pass.free_ufp = 1;
|
||||
memset(&eocd, 0, sizeof(eocd));
|
||||
|
||||
strncpy(eocd.signature, "PK\5\6", 4);
|
||||
eocd.counthere = eocd.count = zend_hash_num_elements(&phar->manifest);
|
||||
zend_hash_apply_with_argument(&phar->manifest, phar_zip_changed_apply, (void *) &pass TSRMLS_CC);
|
||||
|
||||
if (temperr) {
|
||||
php_stream_close(pass.filefp);
|
||||
php_stream_close(pass.centralfp);
|
||||
@@ -1015,6 +1175,7 @@ nostub:
|
||||
eocd.cdir_size = php_stream_tell(pass.centralfp);
|
||||
eocd.cdir_offset = php_stream_tell(pass.filefp);
|
||||
php_stream_seek(pass.centralfp, 0, SEEK_SET);
|
||||
|
||||
if (eocd.cdir_size != php_stream_copy_to_stream(pass.centralfp, pass.filefp, PHP_STREAM_COPY_ALL)) {
|
||||
php_stream_close(pass.filefp);
|
||||
php_stream_close(pass.centralfp);
|
||||
@@ -1026,13 +1187,16 @@ nostub:
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
php_stream_close(pass.centralfp);
|
||||
|
||||
if (phar->metadata) {
|
||||
/* set phar metadata */
|
||||
PHP_VAR_SERIALIZE_INIT(metadata_hash);
|
||||
php_var_serialize(&main_metadata_str, &phar->metadata, &metadata_hash TSRMLS_CC);
|
||||
PHP_VAR_SERIALIZE_DESTROY(metadata_hash);
|
||||
eocd.comment_len = PHAR_SET_16(main_metadata_str.len);
|
||||
|
||||
if (sizeof(eocd) != php_stream_write(pass.filefp, (char *)&eocd, sizeof(eocd))) {
|
||||
php_stream_close(pass.filefp);
|
||||
if (error) {
|
||||
@@ -1044,6 +1208,7 @@ nostub:
|
||||
smart_str_free(&main_metadata_str);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (main_metadata_str.len != php_stream_write(pass.filefp, main_metadata_str.c, main_metadata_str.len)) {
|
||||
php_stream_close(pass.filefp);
|
||||
if (error) {
|
||||
@@ -1055,7 +1220,9 @@ nostub:
|
||||
smart_str_free(&main_metadata_str);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
smart_str_free(&main_metadata_str);
|
||||
|
||||
} else {
|
||||
if (sizeof(eocd) != php_stream_write(pass.filefp, (char *)&eocd, sizeof(eocd))) {
|
||||
php_stream_close(pass.filefp);
|
||||
@@ -1068,17 +1235,21 @@ nostub:
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
|
||||
if (phar->fp && pass.free_fp) {
|
||||
php_stream_close(phar->fp);
|
||||
}
|
||||
|
||||
if (phar->ufp) {
|
||||
if (pass.free_ufp) {
|
||||
php_stream_close(phar->ufp);
|
||||
}
|
||||
phar->ufp = NULL;
|
||||
}
|
||||
|
||||
/* re-open */
|
||||
phar->is_brandnew = 0;
|
||||
|
||||
if (phar->donotflush) {
|
||||
/* deferred flush */
|
||||
phar->fp = pass.filefp;
|
||||
@@ -1106,3 +1277,12 @@ nostub:
|
||||
return EOF;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user