- ws/cs, macros, code that only affects other branches

- some unsynced changes need valgrind testing before they can go into this branch, see PECL/HEAD
This commit is contained in:
Steph Fox 2008-08-01 13:48:45 +00:00
parent 821bab83a3
commit 4e5280a7a2
18 changed files with 1852 additions and 817 deletions

View File

@ -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);

View File

@ -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';
@ -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;
}
@ -417,11 +437,14 @@ 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\", no phar archive specified", url_from);
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 0;
@ -463,18 +486,21 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
php_url_free(resource);
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 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 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);
@ -494,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;
@ -507,19 +536,23 @@ 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 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 0;
}
phar_add_virtual_dirs(phar, entry.filename, entry.filename_len TSRMLS_CC);
return 1;
}
@ -547,11 +580,14 @@ 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\", no phar archive specified, or phar archive does not exist", url);
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 0;
@ -584,7 +620,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
}
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);
@ -604,13 +640,13 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
}
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)) {
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)) {
if (!entry->is_deleted &&
key_len > path_len &&
memcmp(key, resource->path+1, path_len) == 0 &&
IS_SLASH(key[path_len])) {
if (!entry->is_deleted &&
key_len > path_len &&
memcmp(key, resource->path+1, path_len) == 0 &&
IS_SLASH(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);
@ -622,13 +658,13 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
}
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)) {
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)) {
if (!entry->is_deleted &&
key_len > path_len &&
memcmp(key, resource->path+1, path_len) == 0 &&
IS_SLASH(key[path_len])) {
if (!entry->is_deleted &&
key_len > path_len &&
memcmp(key, resource->path+1, path_len) == 0 &&
IS_SLASH(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);

View File

@ -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 |

View File

@ -37,6 +37,7 @@ PHAR_FUNC(phar_opendir) /* {{{ */
&& !cached_phars.arBuckets) {
goto skip_phar;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &zcontext) == FAILURE) {
return;
}
@ -110,10 +111,12 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
&& !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) {
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;
@ -783,7 +786,7 @@ statme_baby:
if (!phar->is_writeable) {
sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
}
sb.st_nlink = 1;
sb.st_rdev = -1;
/* this is only for APC, so use /dev/null device - no chance of conflict there! */

View File

@ -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 |

View File

@ -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 |

File diff suppressed because it is too large Load Diff

View File

@ -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 |
@ -163,7 +163,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phar)
int has_bz2;
zend_bool readonly_orig;
zend_bool require_hash_orig;
zend_bool intercepted;
zend_bool intercepted;
int request_init;
int require_hash;
int request_done;
@ -493,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
@ -505,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
@ -520,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()

File diff suppressed because it is too large Load Diff

View File

@ -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 |

View File

@ -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 |

View File

@ -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 */
/*

View File

@ -3,293 +3,293 @@
$web = '000';
if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
Phar::interceptFileFuncs();
set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());
Phar::webPhar(null, $web);
include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
return;
Phar::interceptFileFuncs();
set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());
Phar::webPhar(null, $web);
include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
return;
}
if (@(isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'POST'))) {
Extract_Phar::go(true);
$mimes = array(
'phps' => 2,
'c' => 'text/plain',
'cc' => 'text/plain',
'cpp' => 'text/plain',
'c++' => 'text/plain',
'dtd' => 'text/plain',
'h' => 'text/plain',
'log' => 'text/plain',
'rng' => 'text/plain',
'txt' => 'text/plain',
'xsd' => 'text/plain',
'php' => 1,
'inc' => 1,
'avi' => 'video/avi',
'bmp' => 'image/bmp',
'css' => 'text/css',
'gif' => 'image/gif',
'htm' => 'text/html',
'html' => 'text/html',
'htmls' => 'text/html',
'ico' => 'image/x-ico',
'jpe' => 'image/jpeg',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'js' => 'application/x-javascript',
'midi' => 'audio/midi',
'mid' => 'audio/midi',
'mod' => 'audio/mod',
'mov' => 'movie/quicktime',
'mp3' => 'audio/mp3',
'mpg' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'pdf' => 'application/pdf',
'png' => 'image/png',
'swf' => 'application/shockwave-flash',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'wav' => 'audio/wav',
'xbm' => 'image/xbm',
'xml' => 'text/xml',
);
Extract_Phar::go(true);
$mimes = array(
'phps' => 2,
'c' => 'text/plain',
'cc' => 'text/plain',
'cpp' => 'text/plain',
'c++' => 'text/plain',
'dtd' => 'text/plain',
'h' => 'text/plain',
'log' => 'text/plain',
'rng' => 'text/plain',
'txt' => 'text/plain',
'xsd' => 'text/plain',
'php' => 1,
'inc' => 1,
'avi' => 'video/avi',
'bmp' => 'image/bmp',
'css' => 'text/css',
'gif' => 'image/gif',
'htm' => 'text/html',
'html' => 'text/html',
'htmls' => 'text/html',
'ico' => 'image/x-ico',
'jpe' => 'image/jpeg',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'js' => 'application/x-javascript',
'midi' => 'audio/midi',
'mid' => 'audio/midi',
'mod' => 'audio/mod',
'mov' => 'movie/quicktime',
'mp3' => 'audio/mp3',
'mpg' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'pdf' => 'application/pdf',
'png' => 'image/png',
'swf' => 'application/shockwave-flash',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'wav' => 'audio/wav',
'xbm' => 'image/xbm',
'xml' => 'text/xml',
);
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
$basename = basename(__FILE__);
if (!strpos($_SERVER['REQUEST_URI'], $basename)) {
chdir(Extract_Phar::$temp);
include $web;
return;
}
$pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename));
if (!$pt || $pt == '/') {
$pt = $web;
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt);
exit;
}
$a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt);
if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) {
header('HTTP/1.0 404 Not Found');
echo "<html>\n <head>\n <title>File Not Found<title>\n </head>\n <body>\n <h1>404 - File ", $pt, " Not Found</h1>\n </body>\n</html>";
exit;
}
$b = pathinfo($a);
if (!isset($b['extension'])) {
header('Content-Type: text/plain');
header('Content-Length: ' . filesize($a));
readfile($a);
exit;
}
if (isset($mimes[$b['extension']])) {
if ($mimes[$b['extension']] === 1) {
include $a;
exit;
}
if ($mimes[$b['extension']] === 2) {
highlight_file($a);
exit;
}
header('Content-Type: ' .$mimes[$b['extension']]);
header('Content-Length: ' . filesize($a));
readfile($a);
exit;
}
$basename = basename(__FILE__);
if (!strpos($_SERVER['REQUEST_URI'], $basename)) {
chdir(Extract_Phar::$temp);
include $web;
return;
}
$pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename));
if (!$pt || $pt == '/') {
$pt = $web;
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt);
exit;
}
$a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt);
if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) {
header('HTTP/1.0 404 Not Found');
echo "<html>\n <head>\n <title>File Not Found<title>\n </head>\n <body>\n <h1>404 - File ", $pt, " Not Found</h1>\n </body>\n</html>";
exit;
}
$b = pathinfo($a);
if (!isset($b['extension'])) {
header('Content-Type: text/plain');
header('Content-Length: ' . filesize($a));
readfile($a);
exit;
}
if (isset($mimes[$b['extension']])) {
if ($mimes[$b['extension']] === 1) {
include $a;
exit;
}
if ($mimes[$b['extension']] === 2) {
highlight_file($a);
exit;
}
header('Content-Type: ' .$mimes[$b['extension']]);
header('Content-Length: ' . filesize($a));
readfile($a);
exit;
}
}
class Extract_Phar
{
static $temp;
static $origdir;
const GZ = 0x1000;
const BZ2 = 0x2000;
const MASK = 0x3000;
const START = 'index.php';
const LEN = XXXX;
static $temp;
static $origdir;
const GZ = 0x1000;
const BZ2 = 0x2000;
const MASK = 0x3000;
const START = 'index.php';
const LEN = XXXX;
static function go($return = false)
{
$fp = fopen(__FILE__, 'rb');
fseek($fp, self::LEN);
$L = unpack('V', $a = (binary)fread($fp, 4));
$m = (binary)'';
static function go($return = false)
{
$fp = fopen(__FILE__, 'rb');
fseek($fp, self::LEN);
$L = unpack('V', $a = (binary)fread($fp, 4));
$m = (binary)'';
do {
$read = 8192;
if ($L[1] - strlen($m) < 8192) {
$read = $L[1] - strlen($m);
}
$last = (binary)fread($fp, $read);
$m .= $last;
} while (strlen($last) && strlen($m) < $L[1]);
do {
$read = 8192;
if ($L[1] - strlen($m) < 8192) {
$read = $L[1] - strlen($m);
}
$last = (binary)fread($fp, $read);
$m .= $last;
} while (strlen($last) && strlen($m) < $L[1]);
if (strlen($m) < $L[1]) {
die('ERROR: manifest length read was "' .
strlen($m) .'" should be "' .
$L[1] . '"');
}
if (strlen($m) < $L[1]) {
die('ERROR: manifest length read was "' .
strlen($m) .'" should be "' .
$L[1] . '"');
}
$info = self::_unpack($m);
$f = $info['c'];
$info = self::_unpack($m);
$f = $info['c'];
if ($f & self::GZ) {
if (!function_exists('gzinflate')) {
die('Error: zlib extension is not enabled -' .
' gzinflate() function needed for zlib-compressed .phars');
}
}
if ($f & self::GZ) {
if (!function_exists('gzinflate')) {
die('Error: zlib extension is not enabled -' .
' gzinflate() function needed for zlib-compressed .phars');
}
}
if ($f & self::BZ2) {
if (!function_exists('bzdecompress')) {
die('Error: bzip2 extension is not enabled -' .
' bzdecompress() function needed for bz2-compressed .phars');
}
}
if ($f & self::BZ2) {
if (!function_exists('bzdecompress')) {
die('Error: bzip2 extension is not enabled -' .
' bzdecompress() function needed for bz2-compressed .phars');
}
}
$temp = self::tmpdir();
$temp = self::tmpdir();
if (!$temp || !is_writable($temp)) {
$sessionpath = session_save_path();
if (strpos ($sessionpath, ";") !== false)
$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
if (!file_exists($sessionpath) || !is_dir($sessionpath)) {
die('Could not locate temporary directory to extract phar');
}
$temp = $sessionpath;
}
if (!$temp || !is_writable($temp)) {
$sessionpath = session_save_path();
if (strpos ($sessionpath, ";") !== false)
$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
if (!file_exists($sessionpath) || !is_dir($sessionpath)) {
die('Could not locate temporary directory to extract phar');
}
$temp = $sessionpath;
}
$temp .= '/pharextract/'.basename(__FILE__, '.phar');
self::$temp = $temp;
self::$origdir = getcwd();
@mkdir($temp, 0777, true);
$temp = realpath($temp);
$temp .= '/pharextract/'.basename(__FILE__, '.phar');
self::$temp = $temp;
self::$origdir = getcwd();
@mkdir($temp, 0777, true);
$temp = realpath($temp);
if (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) {
self::_removeTmpFiles($temp, getcwd());
@mkdir($temp, 0777, true);
@file_put_contents($temp . '/' . md5_file(__FILE__), '');
if (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) {
self::_removeTmpFiles($temp, getcwd());
@mkdir($temp, 0777, true);
@file_put_contents($temp . '/' . md5_file(__FILE__), '');
foreach ($info['m'] as $path => $file) {
$a = !file_exists(dirname($temp . '/' . $path));
@mkdir(dirname($temp . '/' . $path), 0777, true);
clearstatcache();
foreach ($info['m'] as $path => $file) {
$a = !file_exists(dirname($temp . '/' . $path));
@mkdir(dirname($temp . '/' . $path), 0777, true);
clearstatcache();
if ($path[strlen($path) - 1] == '/') {
@mkdir($temp . '/' . $path, 0777);
} else {
file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
@chmod($temp . '/' . $path, 0666);
}
}
}
if ($path[strlen($path) - 1] == '/') {
@mkdir($temp . '/' . $path, 0777);
} else {
file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
@chmod($temp . '/' . $path, 0666);
}
}
}
chdir($temp);
chdir($temp);
if (!$return) {
include self::START;
}
}
if (!$return) {
include self::START;
}
}
static function tmpdir()
{
if (strpos(PHP_OS, 'WIN') !== false) {
if ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) {
return $var;
}
if (is_dir('/temp') || mkdir('/temp')) {
return realpath('/temp');
}
return false;
}
if ($var = getenv('TMPDIR')) {
return $var;
}
return realpath('/tmp');
}
static function tmpdir()
{
if (strpos(PHP_OS, 'WIN') !== false) {
if ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) {
return $var;
}
if (is_dir('/temp') || mkdir('/temp')) {
return realpath('/temp');
}
return false;
}
if ($var = getenv('TMPDIR')) {
return $var;
}
return realpath('/tmp');
}
static function _unpack($m)
{
$info = unpack('V', substr($m, 0, 4));
// skip API version, phar flags, alias, metadata
$l = unpack('V', substr($m, 10, 4));
$m = substr($m, 14 + $l[1]);
$s = unpack('V', substr($m, 0, 4));
$o = 0;
$start = 4 + $s[1];
$ret['c'] = 0;
static function _unpack($m)
{
$info = unpack('V', substr($m, 0, 4));
// skip API version, phar flags, alias, metadata
$l = unpack('V', substr($m, 10, 4));
$m = substr($m, 14 + $l[1]);
$s = unpack('V', substr($m, 0, 4));
$o = 0;
$start = 4 + $s[1];
$ret['c'] = 0;
for ($i = 0; $i < $info[1]; $i++) {
// length of the file name
$len = unpack('V', substr($m, $start, 4));
$start += 4;
// file name
$savepath = substr($m, $start, $len[1]);
$start += $len[1];
// retrieve manifest data:
// 0 = size, 1 = timestamp, 2 = compressed size, 3 = crc32, 4 = flags
// 5 = metadata length
$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));
$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]
& 0xffffffff);
$ret['m'][$savepath][7] = $o;
$o += $ret['m'][$savepath][2];
$start += 24 + $ret['m'][$savepath][5];
$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;
}
return $ret;
}
for ($i = 0; $i < $info[1]; $i++) {
// length of the file name
$len = unpack('V', substr($m, $start, 4));
$start += 4;
// file name
$savepath = substr($m, $start, $len[1]);
$start += $len[1];
// retrieve manifest data:
// 0 = size, 1 = timestamp, 2 = compressed size, 3 = crc32, 4 = flags
// 5 = metadata length
$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));
$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]
& 0xffffffff);
$ret['m'][$savepath][7] = $o;
$o += $ret['m'][$savepath][2];
$start += 24 + $ret['m'][$savepath][5];
$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;
}
return $ret;
}
static function extractFile($path, $entry, $fp)
{
$data = '';
$c = $entry[2];
static function extractFile($path, $entry, $fp)
{
$data = '';
$c = $entry[2];
while ($c) {
if ($c < 8192) {
$data .= @fread($fp, $c);
$c = 0;
} else {
$c -= 8192;
$data .= @fread($fp, 8192);
}
}
while ($c) {
if ($c < 8192) {
$data .= @fread($fp, $c);
$c = 0;
} else {
$c -= 8192;
$data .= @fread($fp, 8192);
}
}
if ($entry[4] & self::GZ) {
$data = gzinflate($data);
} elseif ($entry[4] & self::BZ2) {
$data = bzdecompress($data);
}
if ($entry[4] & self::GZ) {
$data = gzinflate($data);
} elseif ($entry[4] & self::BZ2) {
$data = bzdecompress($data);
}
if (strlen($data) != $entry[0]) {
die("Invalid internal .phar file (size error " . strlen($data) . " != " .
$stat[7] . ")");
}
if (strlen($data) != $entry[0]) {
die("Invalid internal .phar file (size error " . strlen($data) . " != " .
$stat[7] . ")");
}
if ($entry[3] != sprintf("%u", crc32((binary)$data) & 0xffffffff)) {
die("Invalid internal .phar file (checksum error)");
}
if ($entry[3] != sprintf("%u", crc32((binary)$data) & 0xffffffff)) {
die("Invalid internal .phar file (checksum error)");
}
return $data;
}
return $data;
}
static function _removeTmpFiles($temp, $origdir)
{
chdir($temp);
static function _removeTmpFiles($temp, $origdir)
{
chdir($temp);
foreach (glob('*') as $f) {
if (file_exists($f)) {
is_dir($f) ? @rmdir($f) : @unlink($f);
if (file_exists($f) && is_dir($f)) {
self::_removeTmpFiles($f, getcwd());
}
}
}
foreach (glob('*') as $f) {
if (file_exists($f)) {
is_dir($f) ? @rmdir($f) : @unlink($f);
if (file_exists($f) && is_dir($f)) {
self::_removeTmpFiles($f, getcwd());
}
}
}
@rmdir($temp);
clearstatcache();
chdir($origdir);
}
@rmdir($temp);
clearstatcache();
chdir($origdir);
}
}

View File

@ -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) {
@ -147,7 +147,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode,
php_url_free(resource);
return NULL;
}
}
}
return resource;
}
/* }}} */
@ -296,7 +296,6 @@ idata_error:
}
}
php_url_free(resource);
#if MBO_0
fprintf(stderr, "Pharname: %s\n", idata->phar->filename);
fprintf(stderr, "Filename: %s\n", internal_file);
@ -366,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;
@ -379,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;
}
/* }}} */
@ -629,7 +627,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags,
}
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);
zend_hash_move_forward_ex(&phar->mounted_dirs, &pos);
continue;
} else {
char *test;
@ -646,7 +644,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags,
test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, internal_file + keylen);
if (SUCCESS != php_stream_stat_path(test, &ssbi)) {
efree(test);
zend_hash_move_forward_ex(&phar->mounted_dirs, &pos);
zend_hash_move_forward_ex(&phar->mounted_dirs, &pos);
continue;
}
/* mount the file/directory just in time */
@ -664,7 +662,6 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags,
}
}
}
free_resource:
php_url_free(resource);
return FAILURE;
@ -730,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);
@ -807,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);
@ -895,14 +892,14 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
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)) {
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)) {
if (!entry->is_deleted &&
key_len > from_len &&
memcmp(key, resource_from->path+1, from_len) == 0 &&
IS_SLASH(key[from_len])) {
key_len > from_len &&
memcmp(key, resource_from->path+1, from_len) == 0 &&
IS_SLASH(key[from_len])) {
new_key_len = key_len + to_len - from_len;
new_key = emalloc(new_key_len+1);
@ -916,15 +913,15 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
entry->filename_len = new_key_len;
zend_hash_update_current_key_ex(&phar->manifest, key_type, new_key, new_key_len, 0, NULL);
}
}
}
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)) {
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)) {
if (key_len >= from_len &&
memcmp(key, resource_from->path+1, from_len) == 0 &&
(key_len == from_len || IS_SLASH(key[from_len]))) {
memcmp(key, resource_from->path+1, from_len) == 0 &&
(key_len == from_len || IS_SLASH(key[from_len]))) {
new_key_len = key_len + to_len - from_len;
new_key = emalloc(new_key_len+1);
@ -937,13 +934,13 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
}
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)) {
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)) {
if (key_len >= from_len &&
memcmp(key, resource_from->path+1, from_len) == 0 &&
(key_len == from_len || IS_SLASH(key[from_len]))) {
memcmp(key, resource_from->path+1, from_len) == 0 &&
(key_len == from_len || IS_SLASH(key[from_len]))) {
new_key_len = key_len + to_len - from_len;
new_key = emalloc(new_key_len+1);
@ -969,6 +966,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
php_url_free(resource_from);
php_url_free(resource_to);
return 1;
}
/* }}} */

View File

@ -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 |

View File

@ -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
@ -176,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;
@ -184,6 +185,7 @@ 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;
@ -207,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);
@ -214,6 +217,7 @@ 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);
@ -234,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;
@ -298,7 +303,9 @@ bail:
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);
@ -307,16 +314,21 @@ bail:
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];
@ -327,7 +339,9 @@ bail:
} 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--;
@ -336,13 +350,16 @@ bail:
} else {
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);
@ -359,13 +376,13 @@ bail:
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 {
@ -373,6 +390,7 @@ bail:
}
entry.link = NULL;
if (entry.tar_type == TAR_LINK) {
if (!zend_hash_exists(&myphar->manifest, hdr->linkname, strlen(hdr->linkname))) {
if (error) {
@ -389,7 +407,11 @@ bail:
}
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.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) {
@ -400,6 +422,7 @@ bail:
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 */
@ -411,7 +434,9 @@ bail:
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)) {
@ -421,13 +446,16 @@ bail:
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);
phar_destroy_phar_data(myphar TSRMLS_CC);
return FAILURE;
}
actual_alias = pestrndup(buf, size, myphar->is_persistent);
myphar->alias = actual_alias;
myphar->alias_len = size;
@ -436,12 +464,15 @@ bail:
if (error) {
spprintf(error, 4096, "phar error: Unable to read alias from tar-based phar \"%s\"", fname);
}
php_stream_close(fp);
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);
@ -454,7 +485,9 @@ bail:
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);
@ -488,6 +521,7 @@ bail:
} else {
myphar->is_data = 1;
}
if (p) {
myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p);
if (myphar->ext == p) {
@ -497,7 +531,9 @@ bail:
myphar->ext_len = (myphar->fname + fname_len) - myphar->ext;
}
}
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);
@ -506,11 +542,14 @@ bail:
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) {
@ -520,6 +559,7 @@ bail:
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;
@ -541,11 +581,14 @@ bail:
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;
}
/* }}} */
@ -569,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;
@ -579,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) {
@ -591,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);
@ -622,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 */
@ -635,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) {
@ -665,12 +722,14 @@ 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 */
@ -686,24 +745,29 @@ int phar_tar_setmetadata(zval *metadata, phar_entry_info *entry, char **error, p
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;
}
/* }}} */
@ -732,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);
@ -786,6 +853,7 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, long len, int defau
}
return EOF;
}
if (phar->is_data) {
goto nostub;
}
@ -795,13 +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();
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);
@ -839,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);
}
@ -849,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;
@ -864,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);
}
@ -911,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;
@ -922,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");
@ -964,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) {
@ -973,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;
@ -994,12 +1071,15 @@ nostub:
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();
@ -1008,26 +1088,28 @@ nostub:
# 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))[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);
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);
@ -1050,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);
@ -1066,7 +1151,6 @@ nostub:
}
phar->is_brandnew = 0;
php_stream_rewind(newfile);
if (phar->donotflush) {
@ -1081,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 */
@ -1094,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);
@ -1103,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);

File diff suppressed because it is too large Load Diff

View File

@ -46,30 +46,38 @@ 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;
}
/* }}} */
@ -94,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
@ -109,38 +117,38 @@ static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, php_ui
*/
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) /* {{{ */
{
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
@ -158,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;
@ -171,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) {
@ -178,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));
@ -189,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);
@ -196,6 +208,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
php_stream_close(fp);
return FAILURE;
}
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
mydata->is_persistent = PHAR_G(persist);
@ -204,6 +217,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
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);
@ -212,7 +226,9 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
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 */
@ -230,13 +246,17 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
} 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 = pestrndup(fname, fname_len, mydata->is_persistent);
@ -246,6 +266,7 @@ foundit:
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) {
@ -255,6 +276,7 @@ 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);
@ -297,12 +319,17 @@ foundit:
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;
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);
@ -312,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 *) pemalloc(entry.filename_len + 1, entry.is_persistent);
if (entry.filename_len != php_stream_read(fp, entry.filename, entry.filename_len)) {
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--;
@ -332,7 +365,9 @@ 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)) {
@ -341,6 +376,7 @@ foundit:
}
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 */
@ -399,14 +435,17 @@ foundit:
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))) {
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 */
@ -423,41 +462,51 @@ foundit:
} 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) {
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) {
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) {
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) {
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 {
@ -470,16 +519,21 @@ 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)) {
mydata->is_data = 0;
} else {
mydata->is_data = 1;
}
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;
@ -491,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) {
@ -502,10 +558,13 @@ foundit:
return FAILURE;
}
}
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;
@ -520,6 +579,7 @@ 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 = pestrndup(alias, alias_len, mydata->is_persistent);
mydata->alias_len = alias_len;
@ -527,12 +587,14 @@ foundit:
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;
}
/* }}} */
@ -570,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;
}
/* }}} */
@ -595,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;
@ -606,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(&central, 0, sizeof(central));
memset(&perms, 0, sizeof(perms));
@ -620,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;
@ -647,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);
@ -683,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);
@ -710,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;
@ -732,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 *)&central, 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;
@ -764,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) {
@ -812,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;
}
/* }}} */
@ -859,6 +964,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
}
return EOF;
}
if (phar->is_data) {
goto nostub;
}
@ -866,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);
@ -884,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)) {
@ -901,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);
@ -917,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) {
@ -927,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;
@ -942,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);
@ -953,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);
}
@ -997,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;
@ -1012,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);
@ -1021,7 +1138,9 @@ nostub:
}
return EOF;
}
pass.centralfp = php_stream_fopen_tmpfile();
if (!pass.centralfp) {
if (closeoldfile) {
php_stream_close(oldfile);
@ -1031,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);
@ -1054,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);
@ -1065,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) {
@ -1083,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) {
@ -1094,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);
@ -1107,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;