- some unsynced changes need valgrind testing before they can go into this branch, see PECL/HEAD
* @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);
}
'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") {
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);
{
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;
}
/* }}} */
{
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);
}
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';
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
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)) {
continue;
}
}
+
if (*dir == '/') {
/* root directory */
if (keylen >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
}
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);
memcpy(entry, str_key, keylen);
entry[keylen] = '\0';
}
+
goto PHAR_ADD_ENTRY;
} else {
if (0 != memcmp(str_key, dir, dirlen)) {
}
}
}
+
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;
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) {
/**
* 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;
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);
php_url_free(resource);
return NULL;
}
+
if (error) {
efree(error);
}
+
if (*internal_file == '\0') {
/* root directory requested */
internal_file = estrndup(internal_file - 1, 1);
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;
return phar_make_dirstream(internal_file, &phar->manifest TSRMLS_CC);
}
}
+
if (SUCCESS != zend_hash_move_forward(&phar->manifest)) {
break;
}
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;
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);
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;
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;
}
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;
}
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);
}
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);
}
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);
+----------------------------------------------------------------------+
| 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 |
&& !cached_phars.arBuckets) {
goto skip_phar;
}
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &zcontext) == FAILURE) {
return;
}
&& !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;
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! */
+----------------------------------------------------------------------+
| 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 |
+----------------------------------------------------------------------+
| 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 |
if (!phar->is_data) {
phar->is_writeable = !keep;
}
+
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
-/* if the original value is 0 (disabled), then allow setting/unsetting at will
- otherwise, only allow 1 (enabled), and error on disabling */
+/* if the original value is 0 (disabled), then allow setting/unsetting at will. Otherwise only allow 1 (enabled), and error on disabling */
ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */
{
zend_bool old, ini;
old = PHAR_G(readonly_orig);
} else {
old = PHAR_G(require_hash_orig);
- }
+ }
if (new_value_length == 2 && !strcasecmp("on", new_value)) {
ini = (zend_bool) 1;
/* do not allow unsetting in runtime */
if (stage == ZEND_INI_STAGE_STARTUP) {
if (entry->name_length == 14) {
- PHAR_G(readonly_orig) = ini;
+ PHAR_G(readonly_orig) = ini;
} else {
PHAR_G(require_hash_orig) = ini;
- }
+ }
} else if (old && !ini) {
return FAILURE;
}
}
} else {
PHAR_G(require_hash) = ini;
- }
+ }
+
return SUCCESS;
}
/* }}}*/
if (zend_hash_init(&EG(regular_list), 0, NULL, NULL, 0) == SUCCESS) {
EG(regular_list).nNextFreeElement=1; /* we don't want resource id 0 */
}
+
PHAR_G(has_bz2) = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
PHAR_G(has_zlib) = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
/* these two are dummies and will be destroyed later */
for (key = php_strtok_r(tmp, ds, &lasts);
key;
- key = php_strtok_r(NULL, ds, &lasts))
- {
+ key = php_strtok_r(NULL, ds, &lasts)) {
end = strchr(key, DEFAULT_DIR_SEPARATOR);
+
if (end) {
if (SUCCESS == phar_open_from_filename(key, end - key, NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
finish_up:
}
}
}
+
PHAR_GLOBALS->persist = 0;
PHAR_GLOBALS->request_init = 0;
/* destroy dummy values from before */
/* }}} */
PHP_INI_BEGIN()
- STD_PHP_INI_BOOLEAN( "phar.readonly", "1", PHP_INI_ALL, phar_ini_modify_handler, readonly, zend_phar_globals, phar_globals)
+ STD_PHP_INI_BOOLEAN( "phar.readonly", "1", PHP_INI_ALL, phar_ini_modify_handler, readonly, zend_phar_globals, phar_globals)
STD_PHP_INI_BOOLEAN( "phar.require_hash", "1", PHP_INI_ALL, phar_ini_modify_handler, require_hash, zend_phar_globals, phar_globals)
- STD_PHP_INI_ENTRY("phar.cache_list", "", PHP_INI_SYSTEM, phar_ini_cache_list, cache_list, zend_phar_globals, phar_globals)
+ STD_PHP_INI_ENTRY("phar.cache_list", "", PHP_INI_SYSTEM, phar_ini_cache_list, cache_list, zend_phar_globals, phar_globals)
PHP_INI_END()
/**
pefree(phar->alias, phar->is_persistent);
phar->alias = NULL;
}
+
if (phar->fname) {
pefree(phar->fname, phar->is_persistent);
phar->fname = NULL;
}
+
if (phar->signature) {
pefree(phar->signature, phar->is_persistent);
phar->signature = NULL;
}
+
if (phar->manifest.arBuckets) {
zend_hash_destroy(&phar->manifest);
phar->manifest.arBuckets = NULL;
}
+
if (phar->mounted_dirs.arBuckets) {
zend_hash_destroy(&phar->mounted_dirs);
phar->mounted_dirs.arBuckets = NULL;
}
+
if (phar->virtual_dirs.arBuckets) {
zend_hash_destroy(&phar->virtual_dirs);
phar->virtual_dirs.arBuckets = NULL;
}
+
if (phar->metadata) {
if (phar->is_persistent) {
if (phar->metadata_len) {
phar->metadata_len = 0;
phar->metadata = 0;
}
+
if (phar->fp) {
php_stream_close(phar->fp);
phar->fp = 0;
}
+
if (phar->ufp) {
php_stream_close(phar->ufp);
phar->ufp = 0;
}
+
pefree(phar, phar->is_persistent);
}
/* }}}*/
*/
int phar_archive_delref(phar_archive_data *phar TSRMLS_DC) /* {{{ */
{
- if (phar->is_persistent) return 0;
+ if (phar->is_persistent) {
+ return 0;
+ }
+
if (--phar->refcount < 0) {
if (PHAR_GLOBALS->request_done
|| zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), phar->fname, phar->fname_len) != SUCCESS) {
/* invalidate phar cache */
PHAR_G(last_phar) = NULL;
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
+
if (phar->fp && !(phar->flags & PHAR_FILE_COMPRESSION_MASK)) {
/* close open file handle - allows removal or rename of
the file on windows, which has greedy locking
php_stream_close(phar->fp);
phar->fp = NULL;
}
+
if (!zend_hash_num_elements(&phar->manifest)) {
/* this is a new phar that has perhaps had an alias/metadata set, but has never
been flushed */
if (entry->fp_type != PHAR_TMP) {
return ZEND_HASH_APPLY_KEEP;
}
+
if (entry->fp && !entry->fp_refcount) {
php_stream_close(entry->fp);
entry->fp = NULL;
}
+
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
destroy_phar_data_only(pDest);
return;
}
+
zend_hash_apply_with_argument(&(PHAR_GLOBALS->phar_alias_map), phar_unalias_apply, phar_data TSRMLS_CC);
+
if (--phar_data->refcount < 0) {
phar_destroy_phar_data(phar_data TSRMLS_CC);
}
php_stream_close(entry->cfp);
entry->cfp = 0;
}
+
if (entry->fp) {
php_stream_close(entry->fp);
entry->fp = 0;
}
+
if (entry->metadata) {
if (entry->is_persistent) {
if (entry->metadata_len) {
entry->metadata_len = 0;
entry->metadata = 0;
}
+
if (entry->metadata_str.c) {
smart_str_free(&entry->metadata_str);
entry->metadata_str.c = 0;
}
+
pefree(entry->filename, entry->is_persistent);
+
if (entry->link) {
pefree(entry->link, entry->is_persistent);
entry->link = 0;
}
+
if (entry->tmp) {
pefree(entry->tmp, entry->is_persistent);
entry->tmp = 0;
if (--idata->internal_file->fp_refcount < 0) {
idata->internal_file->fp_refcount = 0;
}
+
if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
php_stream_close(idata->fp);
}
}
+
phar_archive_delref(idata->phar TSRMLS_CC);
efree(idata);
return ret;
phar_archive_data *phar;
phar = idata->phar;
+
if (idata->internal_file->fp_refcount < 2) {
if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
php_stream_close(idata->fp);
#ifdef PHP_WIN32
unixfname = estrndup(fname, fname_len);
phar_unixify_path_separators(unixfname, fname_len);
+
if (SUCCESS == phar_get_archive(&phar, unixfname, fname_len, alias, alias_len, error TSRMLS_CC)
&& ((alias && fname_len == phar->fname_len
&& !strncmp(unixfname, phar->fname, fname_len)) || !alias)
}
}
}
+
if (pphar) {
*pphar = phar;
}
+
return SUCCESS;
} else {
#ifdef PHP_WIN32
if (pphar) {
*pphar = NULL;
}
+
if (phar && error && !(options & REPORT_ERRORS)) {
efree(error);
}
+
return FAILURE;
}
}
INIT_ZVAL(**metadata);
p = (const unsigned char*) *buffer;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(metadata, &p, p + buf_len, &var_hash TSRMLS_CC)) {
+
+ if (!php_var_unserialize(metadata, &p, p + buf_len, &var_hash TSRMLS_CC)) {
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
zval_ptr_dtor(metadata);
*metadata = NULL;
return FAILURE;
}
+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
if (PHAR_G(persist)) {
/* lazy init metadata */
zval_ptr_dtor(metadata);
} else {
*metadata = NULL;
}
+
if (!zip_metadata_len) {
*buffer += buf_len;
}
+
return SUCCESS;
}
/* }}}*/
/**
* 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_filename to process the manifest, but can be called
if (pphar) {
*pphar = NULL;
}
+
if (error) {
*error = NULL;
}
}
buffer = b32;
+
if (3 != php_stream_read(fp, buffer, 3)) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at stub end)")
}
+
if ((*buffer == ' ' || *buffer == '\n') && *(buffer + 1) == '?' && *(buffer + 2) == '>') {
int nextchar;
halt_offset += 3;
if (EOF == (nextchar = php_stream_getc(fp))) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at stub end)")
}
+
if ((char) nextchar == '\r') {
/* if we have an \r we require an \n as well */
if (EOF == (nextchar = php_stream_getc(fp)) || (char)nextchar != '\n') {
}
++halt_offset;
}
+
if ((char) nextchar == '\n') {
++halt_offset;
}
}
+
/* make sure we are at the right location to read the manifest */
if (-1 == php_stream_seek(fp, halt_offset, SEEK_SET)) {
MAPPHAR_ALLOC_FAIL("cannot seek to __HALT_COMPILER(); location in phar \"%s\"")
/* read in manifest */
buffer = b32;
+
if (4 != php_stream_read(fp, buffer, 4)) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at manifest length)")
}
+
PHAR_GET_32(buffer, manifest_len);
+
if (manifest_len > 1048576 * 100) {
/* prevent serious memory issues by limiting manifest to at most 100 MB in length */
MAPPHAR_ALLOC_FAIL("manifest cannot be larger than 100 MB in phar \"%s\"")
}
+
buffer = (char *)emalloc(manifest_len);
savebuf = buffer;
endbuffer = buffer + manifest_len;
+
if (manifest_len < 10 || manifest_len != php_stream_read(fp, buffer, manifest_len)) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
}
/* extract the number of entries */
PHAR_GET_32(buffer, manifest_count);
+
if (manifest_count == 0) {
MAPPHAR_FAIL("in phar \"%s\", manifest claims to have zero entries. Phars must have at least 1 entry");
}
/* extract API version, lowest nibble currently unused */
- manifest_ver = (((unsigned char)buffer[0]) << 8)
- + ((unsigned char)buffer[1]);
+ manifest_ver = (((unsigned char)buffer[0]) << 8)
+ + ((unsigned char)buffer[1]);
buffer += 2;
+
if ((manifest_ver & PHAR_API_VER_MASK) < PHAR_API_MIN_READ) {
efree(savebuf);
php_stream_close(fp);
PHAR_GET_32(buffer, manifest_flags);
manifest_flags &= ~PHAR_HDR_COMPRESSION_MASK;
-
manifest_flags &= ~PHAR_FILE_COMPRESSION_MASK;
/* remember whether this entire phar was compressed with gz/bzip2 */
manifest_flags |= compression;
if (-1 == php_stream_seek(fp, -8, SEEK_END)
|| (read_len = php_stream_tell(fp)) < 20
- || 8 != php_stream_read(fp, sig_buf, 8)
+ || 8 != php_stream_read(fp, sig_buf, 8)
|| memcmp(sig_buf+4, "GBMB", 4)) {
efree(savebuf);
php_stream_close(fp);
}
return FAILURE;
}
+
PHAR_GET_32(sig_ptr, sig_flags);
+
switch(sig_flags) {
- case PHAR_SIG_OPENSSL: {
- php_uint32 signature_len;
- char *sig;
- off_t whence;
-
- /* we store the signature followed by the signature length */
- if (-1 == php_stream_seek(fp, -12, SEEK_CUR)
- || 4 != php_stream_read(fp, sig_buf, 4)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" openssl signature length could not be read", fname);
+ case PHAR_SIG_OPENSSL: {
+ php_uint32 signature_len;
+ char *sig;
+ off_t whence;
+
+ /* we store the signature followed by the signature length */
+ if (-1 == php_stream_seek(fp, -12, SEEK_CUR)
+ || 4 != php_stream_read(fp, sig_buf, 4)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" openssl signature length could not be read", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
-
- sig_ptr = sig_buf;
- PHAR_GET_32(sig_ptr, signature_len);
- sig = (char *) emalloc(signature_len);
+ sig_ptr = sig_buf;
+ PHAR_GET_32(sig_ptr, signature_len);
+ sig = (char *) emalloc(signature_len);
+ whence = signature_len + 4;
+ whence = -whence;
+
+ if (-1 == php_stream_seek(fp, whence, SEEK_CUR)
+ || !(end_of_phar = php_stream_tell(fp))
+ || signature_len != php_stream_read(fp, sig, signature_len)) {
+ efree(savebuf);
+ efree(sig);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" openssl signature could not be read", fname);
+ }
+ return FAILURE;
+ }
- whence = signature_len + 4;
- whence = -whence;
- if (-1 == php_stream_seek(fp, whence, SEEK_CUR)
- || !(end_of_phar = php_stream_tell(fp))
- || signature_len != php_stream_read(fp, sig, signature_len)) {
- efree(savebuf);
- efree(sig);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" openssl signature could not be read", fname);
+ if (FAILURE == phar_verify_signature(fp, end_of_phar, PHAR_SIG_OPENSSL, sig, signature_len, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ efree(sig);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" openssl signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- if (FAILURE == phar_verify_signature(fp, end_of_phar, PHAR_SIG_OPENSSL, sig, signature_len, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
efree(sig);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" openssl signature could not be verified: %s", fname, *error);
- efree(save);
- }
- return FAILURE;
}
- efree(sig);
- }
- break;
+ break;
#if HAVE_HASH_EXT
- case PHAR_SIG_SHA512: {
- unsigned char digest[64];
+ case PHAR_SIG_SHA512: {
+ unsigned char digest[64];
- php_stream_seek(fp, -(8 + 64), SEEK_END);
- read_len = php_stream_tell(fp);
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ php_stream_seek(fp, -(8 + 64), SEEK_END);
+ read_len = php_stream_tell(fp);
+
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA512, (char *)digest, 64, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" SHA512 signature could not be verified: %s", fname, *error);
- efree(save);
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA512, (char *)digest, 64, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA512 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
}
- return FAILURE;
+ break;
}
- break;
- }
- case PHAR_SIG_SHA256: {
- unsigned char digest[32];
+ case PHAR_SIG_SHA256: {
+ unsigned char digest[32];
- php_stream_seek(fp, -(8 + 32), SEEK_END);
- read_len = php_stream_tell(fp);
+ php_stream_seek(fp, -(8 + 32), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA256, (char *)digest, 32, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA256, (char *)digest, 32, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA256 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
+ }
+ break;
+ }
+#else
+ case PHAR_SIG_SHA512:
+ case PHAR_SIG_SHA256:
efree(savebuf);
php_stream_close(fp);
+
if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" SHA256 signature could not be verified: %s", fname, *error);
- efree(save);
+ spprintf(error, 0, "phar \"%s\" has a unsupported signature", fname);
}
return FAILURE;
- }
- break;
- }
-#else
- case PHAR_SIG_SHA512:
- case PHAR_SIG_SHA256:
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a unsupported signature", fname);
- }
- return FAILURE;
#endif
- case PHAR_SIG_SHA1: {
- unsigned char digest[20];
+ case PHAR_SIG_SHA1: {
+ unsigned char digest[20];
- php_stream_seek(fp, -(8 + 20), SEEK_END);
- read_len = php_stream_tell(fp);
+ php_stream_seek(fp, -(8 + 20), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA1, (char *)digest, 20, fname, &signature, &sig_len, error TSRMLS_CC)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" SHA1 signature could not be verified: %s", fname, *error);
- efree(save);
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA1, (char *)digest, 20, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA1 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
}
- return FAILURE;
+ break;
}
- break;
- }
- case PHAR_SIG_MD5: {
- unsigned char digest[16];
+ case PHAR_SIG_MD5: {
+ unsigned char digest[16];
- php_stream_seek(fp, -(8 + 16), SEEK_END);
- read_len = php_stream_tell(fp);
+ php_stream_seek(fp, -(8 + 16), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_MD5, (char *)digest, 16, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_MD5, (char *)digest, 16, fname, &signature, &sig_len, error TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" MD5 signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
+ }
+ break;
+ }
+ default:
efree(savebuf);
php_stream_close(fp);
+
if (error) {
- char *save = *error;
- spprintf(error, 0, "phar \"%s\" MD5 signature could not be verified: %s", fname, *error);
- efree(save);
+ spprintf(error, 0, "phar \"%s\" has a broken or unsupported signature", fname);
}
return FAILURE;
- }
- break;
- }
- default:
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" has a broken or unsupported signature", fname);
- }
- return FAILURE;
}
} else if (PHAR_G(require_hash)) {
efree(savebuf);
php_stream_close(fp);
+
if (error) {
spprintf(error, 0, "phar \"%s\" does not have a signature", fname);
}
/* extract alias */
PHAR_GET_32(buffer, tmp_len);
+
if (buffer + tmp_len > endbuffer) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (buffer overrun)");
}
+
if (manifest_len < 10 + tmp_len) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
}
+
/* tmp_len = 0 says alias length is 0, which means the alias is not stored in the phar */
if (tmp_len) {
/* if the alias is stored we enforce it (implicit overrides explicit) */
{
buffer[tmp_len] = '\0';
php_stream_close(fp);
+
if (signature) {
efree(signature);
}
+
if (error) {
spprintf(error, 0, "cannot load phar \"%s\" with implicit alias \"%s\" under different alias \"%s\"", fname, buffer, alias);
}
+
efree(savebuf);
return FAILURE;
}
+
alias_len = tmp_len;
alias = buffer;
buffer += tmp_len;
if (buffer + 4 > endbuffer) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)")
}
+
PHAR_GET_32(buffer, entry.filename_len);
+
if (entry.filename_len == 0) {
MAPPHAR_FAIL("zero-length filename encountered in phar \"%s\"");
}
- if (entry.is_persistent) entry.manifest_pos = manifest_index;
+
+ if (entry.is_persistent) {
+ entry.manifest_pos = manifest_index;
+ }
+
if (buffer + entry.filename_len + 20 > endbuffer) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)");
}
+
if ((manifest_ver & PHAR_API_VER_MASK) >= PHAR_API_MIN_DIR && buffer[entry.filename_len - 1] == '/') {
entry.is_dir = 1;
} else {
entry.is_dir = 0;
}
+
phar_add_virtual_dirs(mydata, buffer, entry.filename_len TSRMLS_CC);
entry.filename = pestrndup(buffer, entry.filename_len, entry.is_persistent);
buffer += entry.filename_len;
PHAR_GET_32(buffer, entry.uncompressed_filesize);
PHAR_GET_32(buffer, entry.timestamp);
+
if (offset == halt_offset + (int)manifest_len + 4) {
mydata->min_timestamp = entry.timestamp;
mydata->max_timestamp = entry.timestamp;
mydata->max_timestamp = entry.timestamp;
}
}
+
PHAR_GET_32(buffer, entry.compressed_filesize);
PHAR_GET_32(buffer, entry.crc32);
PHAR_GET_32(buffer, entry.flags);
+
if (entry.is_dir) {
entry.filename_len--;
entry.flags |= PHAR_ENT_PERM_DEF_DIR;
}
+
if (entry.is_persistent) {
if (phar_parse_metadata(&buffer, &entry.metadata, 0 TSRMLS_CC) == FAILURE) {
pefree(entry.filename, entry.is_persistent);
MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
}
}
+
entry.offset = entry.offset_abs = offset;
offset += entry.compressed_filesize;
+
switch (entry.flags & PHAR_ENT_COMPRESSION_MASK) {
- case PHAR_ENT_COMPRESSED_GZ:
- if (!PHAR_G(has_zlib)) {
- if (entry.metadata) {
- if (entry.is_persistent) {
- free(entry.metadata);
- } else {
- zval_ptr_dtor(&entry.metadata);
+ case PHAR_ENT_COMPRESSED_GZ:
+ if (!PHAR_G(has_zlib)) {
+ if (entry.metadata) {
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
}
- pefree(entry.filename, entry.is_persistent);
- MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
- }
- break;
- case PHAR_ENT_COMPRESSED_BZ2:
- if (!PHAR_G(has_bz2)) {
- if (entry.metadata) {
- if (entry.is_persistent) {
- free(entry.metadata);
- } else {
- zval_ptr_dtor(&entry.metadata);
+ break;
+ case PHAR_ENT_COMPRESSED_BZ2:
+ if (!PHAR_G(has_bz2)) {
+ if (entry.metadata) {
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
}
- pefree(entry.filename, entry.is_persistent);
- MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
- }
- break;
- default:
- if (entry.uncompressed_filesize != entry.compressed_filesize) {
- if (entry.metadata) {
- if (entry.is_persistent) {
- free(entry.metadata);
- } else {
- zval_ptr_dtor(&entry.metadata);
+ break;
+ default:
+ if (entry.uncompressed_filesize != entry.compressed_filesize) {
+ if (entry.metadata) {
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)");
}
- pefree(entry.filename, entry.is_persistent);
- MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)");
- }
- break;
+ break;
}
+
manifest_flags |= (entry.flags & PHAR_ENT_COMPRESSION_MASK);
/* if signature matched, no need to check CRC32 for each file */
entry.is_crc_checked = (manifest_flags & PHAR_HDR_SIGNATURE ? 1 : 0);
mydata->halt_offset = halt_offset;
mydata->flags = manifest_flags;
endbuffer = strrchr(mydata->fname, '/');
+
if (endbuffer) {
mydata->ext = memchr(endbuffer, '.', (mydata->fname + fname_len) - endbuffer);
if (mydata->ext == endbuffer) {
mydata->ext_len = (mydata->fname + mydata->fname_len) - mydata->ext;
}
}
+
mydata->alias = alias ?
pestrndup(alias, alias_len, mydata->is_persistent) :
pestrndup(mydata->fname, fname_len, mydata->is_persistent);
mydata->sig_len = sig_len;
mydata->signature = signature;
phar_request_initialize(TSRMLS_C);
+
if (register_alias) {
phar_archive_data **fd_ptr;
mydata->is_temporary_alias = temp_alias;
+
if (!phar_validate_alias(mydata->alias, mydata->alias_len)) {
signature = NULL;
fp = NULL;
MAPPHAR_FAIL("Cannot open archive \"%s\", invalid alias");
}
+
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
signature = NULL;
MAPPHAR_FAIL("Cannot open archive \"%s\", alias is already in use by existing archive");
}
}
+
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
} else {
mydata->is_temporary_alias = 1;
}
+
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
efree(savebuf);
phar_archive_data **test, *unused = NULL;
test = &unused;
+
if (error) {
*error = NULL;
}
if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, 1 TSRMLS_CC) == SUCCESS) {
goto check_file;
}
+
/* next try to create a new file */
if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, 1 TSRMLS_CC)) {
if (error) {
}
return FAILURE;
}
-
check_file:
if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, test, &my_error TSRMLS_CC) == SUCCESS) {
if (pphar) {
*pphar = *test;
}
+
if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) {
if (error) {
spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname);
}
return FAILURE;
}
+
if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) {
phar_entry_info *stub;
if (FAILURE == zend_hash_find(&((*test)->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
return FAILURE;
}
}
+
if (!PHAR_G(readonly) || (*test)->is_data) {
(*test)->is_writeable = 1;
}
}
return phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC);
-
}
/* }}} */
return FAILURE;
}
#endif
-
if (php_check_open_basedir(fname TSRMLS_CC)) {
return FAILURE;
}
/* first open readonly so it won't be created if not present */
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual);
+
if (actual) {
fname = actual;
fname_len = strlen(actual);
return FAILURE;
}
}
+
if (actual) {
efree(actual);
}
/* set up our manifest */
mydata = ecalloc(1, sizeof(phar_archive_data));
-
mydata->fname = expand_filepath(fname, NULL TSRMLS_CC);
fname_len = strlen(mydata->fname);
#ifdef PHP_WIN32
phar_unixify_path_separators(mydata->fname, fname_len);
#endif
p = strrchr(mydata->fname, '/');
+
if (p) {
mydata->ext = memchr(p, '.', (mydata->fname + fname_len) - p);
if (mydata->ext == p) {
if (pphar) {
*pphar = mydata;
}
+
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 *),
mydata->is_brandnew = 1;
phar_request_initialize(TSRMLS_C);
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
+
if (is_data) {
alias = NULL;
alias_len = 0;
if (error) {
spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias);
}
+
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
+
if (pphar) {
*pphar = NULL;
}
+
return FAILURE;
}
}
+
mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
mydata->alias_len = alias ? alias_len : fname_len;
}
+
if (alias_len && alias) {
if (FAILURE == zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL)) {
if (options & REPORT_ERRORS) {
spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias);
}
}
+
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
+
if (pphar) {
*pphar = NULL;
}
+
return FAILURE;
}
}
+
return SUCCESS;
}
/* }}}*/
} else if (error && *error) {
return FAILURE;
}
-
#if PHP_MAJOR_VERSION < 6
if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
return FAILURE;
}
#endif
-
if (php_check_open_basedir(fname TSRMLS_CC)) {
return FAILURE;
}
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);
+
if (!fp) {
if (options & REPORT_ERRORS) {
if (error) {
}
ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
+
if (actual) {
efree(actual);
}
+
return ret;
}
/* }}}*/
if (buf_len < search_len) {
return NULL;
}
+
c = buf - 1;
+
do {
if (!(c = memchr(c + 1, search[0], buf_len - search_len - so_far))) {
return (char *) NULL;
}
+
so_far = c - buf;
+
if (so_far >= (buf_len - search_len)) {
return (char *) NULL;
}
+
if (!memcmp(c, search, search_len)) {
return (char *) c;
}
if (error) {
*error = NULL;
}
+
if (-1 == php_stream_rewind(fp)) {
MAPPHAR_ALLOC_FAIL("cannot rewind phar \"%s\"")
}
if ((got = php_stream_read(fp, buffer+tokenlen, readsize)) < (size_t) tokenlen) {
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)")
}
+
if (!test) {
test = '\1';
pos = buffer+tokenlen;
MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file, enable zlib extension in php.ini")
}
array_init(&filterparams);
-
/* this is defined in zlib's zconf.h */
#ifndef MAX_WBITS
#define MAX_WBITS 15
#endif
add_assoc_long(&filterparams, "window", MAX_WBITS + 32);
+
/* entire file is gzip-compressed, uncompress to temporary file */
if (!(temp = php_stream_fopen_tmpfile())) {
MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"")
}
+
php_stream_rewind(fp);
filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp) TSRMLS_CC);
+
if (!filter) {
err = 1;
add_assoc_long(&filterparams, "window", MAX_WBITS);
filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp) TSRMLS_CC);
zval_dtor(&filterparams);
+
if (!filter) {
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\", ext/zlib is buggy in PHP versions older than 5.2.6")
} else {
zval_dtor(&filterparams);
}
+
php_stream_filter_append(&temp->writefilters, filter);
+
if (0 == php_stream_copy_to_stream(fp, temp, PHP_STREAM_COPY_ALL)) {
if (err) {
php_stream_close(temp);
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file")
}
+
php_stream_filter_flush(filter, 1);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
php_stream_close(fp);
if (!PHAR_G(has_bz2)) {
MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file, enable bz2 extension in php.ini")
}
+
/* entire file is bzip-compressed, uncompress to temporary file */
if (!(temp = php_stream_fopen_tmpfile())) {
MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of bzipped phar archive \"%s\"")
}
+
php_stream_rewind(fp);
filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
+
if (!filter) {
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\", filter creation failed")
}
+
php_stream_filter_append(&temp->writefilters, filter);
+
if (0 == php_stream_copy_to_stream(fp, temp, PHP_STREAM_COPY_ALL)) {
php_stream_close(temp);
MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file")
}
+
php_stream_filter_flush(filter, 1);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
php_stream_close(fp);
test = '\0';
continue;
}
+
if (!memcmp(pos, zip_magic, 4)) {
php_stream_seek(fp, 0, SEEK_END);
return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error TSRMLS_CC);
}
+
if (got > 512) {
if (phar_is_tar(pos, fname)) {
php_stream_rewind(fp);
}
}
}
+
if (got > 0 && (pos = phar_strnstr(buffer, got + sizeof(token), token, sizeof(token)-1)) != NULL) {
halt_offset += (pos - buffer); /* no -tokenlen+tokenlen here */
return phar_parse_pharfile(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, compression, error TSRMLS_CC);
halt_offset += got;
memmove(buffer, buffer + tokenlen, got + 1);
}
-
+
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (__HALT_COMPILER(); not found)")
}
/* }}} */
old = *a;
*a = '\0';
+
if ((realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
#ifdef PHP_WIN32
phar_unixify_path_separators(realpath, strlen(realpath));
efree(realpath);
return SUCCESS;
}
+
if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_phars, realpath, strlen(realpath))) {
*a = old;
efree(realpath);
}
efree(realpath);
}
+
if (SUCCESS == php_stream_stat_path((char *) fname, &ssb)) {
*a = old;
+
if (ssb.sb.st_mode & S_IFDIR) {
return FAILURE;
}
+
if (for_create == 1) {
return FAILURE;
}
+
return SUCCESS;
} else {
char *slash;
*a = old;
return FAILURE;
}
+
slash = (char *) strrchr(fname, '/');
*a = old;
+
if (slash) {
old = *slash;
*slash = '\0';
}
+
if (SUCCESS != php_stream_stat_path((char *) fname, &ssb)) {
if (slash) {
*slash = old;
a = strstr(realpath, fname) + ((ext - fname) + ext_len);
*a = '\0';
slash = strrchr(realpath, '/');
+
if (slash) {
*slash = '\0';
} else {
efree(realpath);
return FAILURE;
}
+
if (SUCCESS != php_stream_stat_path(realpath, &ssb)) {
efree(realpath);
return FAILURE;
}
+
efree(realpath);
+
if (ssb.sb.st_mode & S_IFDIR) {
return SUCCESS;
}
}
+
return FAILURE;
}
+
if (slash) {
*slash = old;
}
+
if (ssb.sb.st_mode & S_IFDIR) {
return SUCCESS;
}
+
return FAILURE;
}
}
if (ext_len >= 50) {
return FAILURE;
}
+
if (executable == 1) {
/* copy "." as well */
memcpy(test, ext_str - 1, ext_len + 1);
/* executable phars must contain ".phar" as a valid extension (phar://.pharmy/oops is invalid) */
/* (phar://hi/there/.phar/oops is also invalid) */
pos = strstr(test, ".phar");
+
if (pos && (*(pos - 1) != '/')
&& (pos += 5) && (*pos == '\0' || *pos == '/' || *pos == '.')) {
return phar_analyze_path(fname, ext_str, ext_len, for_create TSRMLS_CC);
return FAILURE;
}
}
+
/* data phars need only contain a single non-"." to be valid */
if (!executable) {
pos = strstr(ext_str, ".phar");
return phar_analyze_path(fname, ext_str, ext_len, for_create TSRMLS_CC);
}
}
+
return FAILURE;
}
/* }}} */
if (!filename_len || filename_len == 1) {
return FAILURE;
}
+
phar_request_initialize(TSRMLS_C);
/* first check for alias in first segment */
pos = memchr(filename, '/', filename_len);
+
if (pos && pos != filename) {
if (zend_hash_exists(&(PHAR_GLOBALS->phar_alias_map), (char *) filename, pos - filename)) {
*ext_str = pos;
*ext_len = -1;
return FAILURE;
}
+
if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_alias, (char *) filename, pos - filename)) {
*ext_str = pos;
*ext_len = -1;
*ext_str = filename + (filename_len - (*pphar)->ext_len);
woohoo:
*ext_len = (*pphar)->ext_len;
+
if (executable == 2) {
return SUCCESS;
}
+
if (executable == 1 && !(*pphar)->is_data) {
return SUCCESS;
}
+
if (!executable && (*pphar)->is_data) {
return SUCCESS;
}
+
return FAILURE;
}
+
if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_find(&cached_phars, (char *) filename, filename_len, (void **)&pphar)) {
*ext_str = filename + (filename_len - (*pphar)->ext_len);
goto woohoo;
ulong unused;
zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_fname_map));
+
while (FAILURE != zend_hash_has_more_elements(&(PHAR_GLOBALS->phar_fname_map))) {
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_fname_map), &key, &keylen, &unused, 0, NULL)) {
break;
zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
continue;
}
+
if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen
|| filename[keylen] == '/' || filename[keylen] == '\0')) {
if (FAILURE == zend_hash_get_current_data(&(PHAR_GLOBALS->phar_fname_map), (void **) &pphar)) {
*ext_str = filename + (keylen - (*pphar)->ext_len);
goto woohoo;
}
+
zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
}
+
if (PHAR_G(manifest_cached)) {
zend_hash_internal_pointer_reset(&cached_phars);
+
while (FAILURE != zend_hash_has_more_elements(&cached_phars)) {
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&cached_phars, &key, &keylen, &unused, 0, NULL)) {
break;
zend_hash_move_forward(&cached_phars);
continue;
}
+
if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen
|| filename[keylen] == '/' || filename[keylen] == '\0')) {
if (FAILURE == zend_hash_get_current_data(&cached_phars, (void **) &pphar)) {
if (!pos) {
return FAILURE;
}
+
while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) {
pos = memchr(pos + 1, '.', filename_len - (pos - filename) + 1);
if (!pos) {
}
slash = memchr(pos, '/', filename_len - (pos - filename));
+
if (!slash) {
/* this is a url like "phar://blah.phar" with no directory */
*ext_str = pos;
*ext_len = strlen(pos);
+
/* file extension must contain "phar" */
switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
- case SUCCESS :
+ case SUCCESS:
return SUCCESS;
- case FAILURE :
+ case FAILURE:
/* we are at the end of the string, so we fail */
return FAILURE;
}
}
+
/* we've found an extension that ends at a directory separator */
*ext_str = pos;
*ext_len = slash - pos;
+
switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
- case SUCCESS :
+ case SUCCESS:
return SUCCESS;
- case FAILURE :
+ case FAILURE:
/* look for more extensions */
pos = strchr(pos + 1, '.');
if (pos) {
}
goto next_extension;
}
+
return FAILURE;
}
/* }}} */
-static int php_check_dots(const char *element, int n) /* {{{ */
+static int php_check_dots(const char *element, int n) /* {{{ */
{
for(n--; n >= 0; --n) {
if (element[n] != '.') {
#define IS_DIRECTORY_CURRENT(element, len) \
(len == 1 && element[0] == '.')
-#define IS_BACKSLASH(c) ((c) == '/')
+#define IS_BACKSLASH(c) ((c) == '/')
#ifdef COMPILE_DL_PHAR
/* stupid-ass non-extern declaration in tsrm_strtok.h breaks dumbass MS compiler */
while (*s && in_character_class(*s, delim)) {
++s;
}
+
if (!*s) {
return NULL;
}
while (*s && !in_character_class(*s, delim)) {
++s;
}
+
if (!*s) {
*last = s;
} else {
*s = '\0';
*last = s + 1;
}
+
return token;
}
/* }}} */
newpath[0] = '/';
newpath_len = 1;
}
+
ptr = path;
- if (*ptr == '/') ++ptr;
+
+ if (*ptr == '/') {
+ ++ptr;
+ }
+
tok = ptr;
+
do {
ptr = memchr(ptr, '/', path_length - (ptr - path));
} while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);
+
if (!ptr && (path_length - (tok - path))) {
switch (path_length - (tok - path)) {
- case 1 :
+ case 1:
if (*tok == '.') {
efree(path);
*new_len = 1;
return estrndup("/", 1);
}
break;
- case 2 :
+ case 2:
if (tok[0] == '.' && tok[1] == '.') {
efree(path);
*new_len = 1;
}
return path;
}
+
while (ptr) {
ptr_length = ptr - tok;
last_time:
newpath_len += ptr_length;
}
+
if (ptr == path + path_length) {
break;
}
+
tok = ++ptr;
+
do {
ptr = memchr(ptr, '/', path_length - (ptr - path));
} while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);
+
if (!ptr && (path_length - (tok - path))) {
ptr_length = path_length - (tok - path);
ptr = path + path_length;
goto last_time;
}
}
+
efree(path);
*new_len = newpath_len;
return estrndup(newpath, newpath_len);
*arch = filename;
#endif
}
+
if (free_filename) {
efree(filename);
}
+
return FAILURE;
}
+
ext_len = 0;
/* no extension detected - instead we are dealing with an alias */
}
*arch_len = ext_str - filename + ext_len;
*arch = estrndup(filename, *arch_len);
+
if (ext_str[ext_len]) {
*entry_len = filename_len - *arch_len;
*entry = estrndup(ext_str+ext_len, *entry_len);
*entry_len = 1;
*entry = estrndup("/", 1);
}
+
if (free_filename) {
efree(filename);
}
+
return SUCCESS;
}
/* }}} */
if (error) {
*error = NULL;
}
+
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
}
MAKE_STD_ZVAL(halt_constant);
+
if (0 == zend_get_constant("__COMPILER_HALT_OFFSET__", 24, halt_constant TSRMLS_CC)) {
FREE_ZVAL(halt_constant);
if (error) {
}
return FAILURE;
}
+
halt_offset = Z_LVAL(*halt_constant);
FREE_ZVAL(halt_constant);
}
fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, &actual);
+
if (!fp) {
if (error) {
spprintf(error, 0, "unable to open phar for reading \"%s\"", fname);
}
ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, error TSRMLS_CC);
+
if (actual) {
efree(actual);
}
+
return ret;
}
/* }}} */
if (error) {
*error = NULL;
}
+
if (entry->is_zip) {
/* verify local file header */
phar_zip_file_header local;
spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", idata->phar->fname, entry->filename);
return FAILURE;
}
+
/* verify local header */
if (entry->filename_len != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) {
spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local head of file \"%s\" does not match central directory)", idata->phar->fname, entry->filename);
return FAILURE;
}
+
/* construct actual offset to file start - local extra_len can be different from central extra_len */
entry->offset = entry->offset_abs =
sizeof(local) + entry->header_offset + PHAR_ZIP_16(local.filename_len) + PHAR_ZIP_16(local.extra_len);
+
if (idata->zero && idata->zero != entry->offset_abs) {
idata->zero = entry->offset_abs;
}
}
- php_stream_seek(fp, idata->zero, SEEK_SET);
+
+ php_stream_seek(fp, idata->zero, SEEK_SET);
+
while (len--) {
CRC32(crc, php_stream_getc(fp));
}
+
php_stream_seek(fp, idata->zero, SEEK_SET);
+
if (~crc == crc32) {
entry->is_crc_checked = 1;
return SUCCESS;
zval_dtor(openssl);
return FAILURE;
}
+
zval_dtor(openssl);
efree(openssl);
++(zkey->refcount);
#else
Z_ADDREF_P(zdata);
+
if (is_sign) {
Z_SET_ISREF_P(zsig);
} else {
Z_ADDREF_P(zsig);
}
+
Z_ADDREF_P(zkey);
#endif
fci.retval_ptr_ptr = &retval_ptr;
--(zkey->refcount);
#else
Z_DELREF_P(zdata);
+
if (is_sign) {
Z_UNSET_ISREF_P(zsig);
} else {
Z_DELREF_P(zsig);
}
+
Z_DELREF_P(zkey);
#endif
zval_dtor(zdata);
efree(zdata);
zval_dtor(zkey);
efree(zkey);
+
switch (Z_TYPE_P(retval_ptr)) {
default:
- case IS_LONG :
+ case IS_LONG:
zval_dtor(zsig);
efree(zsig);
if (1 == Z_LVAL_P(retval_ptr)) {
}
efree(retval_ptr);
return FAILURE;
- case IS_BOOL :
+ case IS_BOOL:
efree(retval_ptr);
if (Z_BVAL_P(retval_ptr)) {
*signature = estrndup(Z_STRVAL_P(zsig), Z_STRLEN_P(zsig));
}
len = pos - user_stub + 18;
if ((size_t)len != php_stream_write(newfile, user_stub, len)
- || 5 != php_stream_write(newfile, " ?>\r\n", 5)) {
+ || 5 != php_stream_write(newfile, " ?>\r\n", 5)) {
if (closeoldfile) {
php_stream_close(oldfile);
}
new_manifest_count = 0;
offset = 0;
for (zend_hash_internal_pointer_reset(&phar->manifest);
- zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
- zend_hash_move_forward(&phar->manifest)) {
+ zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
+ zend_hash_move_forward(&phar->manifest)) {
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
/* write the manifest header */
if (sizeof(manifest) != php_stream_write(newfile, manifest, sizeof(manifest))
|| (size_t)phar->alias_len != php_stream_write(newfile, phar->alias, phar->alias_len)) {
+
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
phar->alias_len = restore_alias_len;
+
if (error) {
spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname);
}
+
return EOF;
}
-
+
phar->alias_len = restore_alias_len;
-
+
phar_set_32(manifest, main_metadata_str.len);
if (4 != php_stream_write(newfile, manifest, 4) || (main_metadata_str.len
&& main_metadata_str.len != php_stream_write(newfile, main_metadata_str.c, main_metadata_str.len))) {
smart_str_free(&main_metadata_str);
+
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
phar->alias_len = restore_alias_len;
+
if (error) {
spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname);
}
+
return EOF;
- }
+ }
smart_str_free(&main_metadata_str);
-
+
/* re-calculate the manifest location to simplify later code */
manifest_ftell = php_stream_tell(newfile);
-
+
/* now write the manifest */
for (zend_hash_internal_pointer_reset(&phar->manifest);
- zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
- zend_hash_move_forward(&phar->manifest)) {
+ zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
+ zend_hash_move_forward(&phar->manifest)) {
+
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
+
if (entry->is_deleted || entry->is_mounted) {
/* remove this from the new phar if deleted, ignore if mounted */
continue;
}
+
if (entry->is_dir) {
/* add 1 for trailing slash */
phar_set_32(entry_buffer, entry->filename_len + 1);
} else {
phar_set_32(entry_buffer, entry->filename_len);
}
+
if (4 != php_stream_write(newfile, entry_buffer, 4)
|| entry->filename_len != php_stream_write(newfile, entry->filename, entry->filename_len)
|| (entry->is_dir && 1 != php_stream_write(newfile, "/", 1))) {
}
return EOF;
}
+
/* set the manifest meta-data:
4: uncompressed filesize
4: creation timestamp
phar_set_32(entry_buffer+12, entry->crc32);
phar_set_32(entry_buffer+16, entry->flags);
phar_set_32(entry_buffer+20, entry->metadata_str.len);
+
if (sizeof(entry_buffer) != php_stream_write(newfile, entry_buffer, sizeof(entry_buffer))
|| entry->metadata_str.len != php_stream_write(newfile, entry->metadata_str.c, entry->metadata_str.len)) {
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
+
if (error) {
spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
}
+
return EOF;
}
}
-
+
/* now copy the actual file data to the new phar */
offset = php_stream_tell(newfile);
for (zend_hash_internal_pointer_reset(&phar->manifest);
- zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
- zend_hash_move_forward(&phar->manifest)) {
+ zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
+ zend_hash_move_forward(&phar->manifest)) {
+
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
+
if (entry->is_deleted || entry->is_dir || entry->is_mounted) {
continue;
}
+
if (entry->cfp) {
file = entry->cfp;
php_stream_rewind(file);
return EOF;
}
}
+
if (!file) {
if (closeoldfile) {
php_stream_close(oldfile);
}
return EOF;
}
- /* this will have changed for all files that have either
- changed compression or been modified */
+
+ /* this will have changed for all files that have either changed compression or been modified */
entry->offset = entry->offset_abs = offset;
offset += entry->compressed_filesize;
wrote = php_stream_copy_to_stream(file, newfile, entry->compressed_filesize);
+
if (entry->compressed_filesize != wrote) {
if (closeoldfile) {
php_stream_close(oldfile);
}
+
php_stream_close(newfile);
+
if (error) {
spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
}
+
return EOF;
}
+
entry->is_modified = 0;
+
if (entry->cfp) {
php_stream_close(entry->cfp);
entry->cfp = NULL;
}
+
if (entry->fp_type == PHAR_MOD) {
- /* this fp is in use by a phar_entry_data returned by phar_get_entry_data, it will be closed
- when the phar_entry_data is phar_entry_delref'ed */
+ /* this fp is in use by a phar_entry_data returned by phar_get_entry_data, it will be closed when the phar_entry_data is phar_entry_delref'ed */
if (entry->fp_refcount == 0 && entry->fp != phar->fp && entry->fp != phar->ufp) {
php_stream_close(entry->fp);
}
+
entry->fp = NULL;
entry->fp_type = PHAR_FP;
} else if (entry->fp_type == PHAR_UFP) {
if (phar->fp && free_fp) {
php_stream_close(phar->fp);
}
+
if (phar->ufp) {
if (free_ufp) {
php_stream_close(phar->ufp);
}
phar->ufp = NULL;
}
+
if (closeoldfile) {
php_stream_close(oldfile);
}
}
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 */
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) {
if (error) {
spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname);
}
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);
* Every user visible function must have an entry in phar_functions[].
*/
function_entry phar_functions[] = {
- {NULL, NULL, NULL} /* Must be the last line in phar_functions[] */
+ {NULL, NULL, NULL} /* Must be the last line in phar_functions[] */
};
/* }}}*/
}
}
}
+
zend_try {
failed = 0;
res = phar_orig_compile_file(file_handle, type TSRMLS_CC);
} zend_catch {
failed = 1;
} zend_end_try();
+
if (name) {
efree(name);
}
+
if (failed) {
zend_bailout();
}
+
return res;
}
/* }}} */
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
+
if (fname_len > 7 && !strncasecmp(fname, "phar://", 7)) {
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);
efree(entry);
}
}
+
/* retrieving an include within the current directory, so use this if possible */
if (!(entry = phar_find_in_include_path((char *) filename, strlen(filename), NULL TSRMLS_CC))) {
/* this file is not in the phar, use the original path */
goto skip_phar;
}
+
if (SUCCESS == phar_orig_zend_open(entry, handle TSRMLS_CC)) {
if (!handle->opened_path) {
handle->opened_path = entry;
}
return SUCCESS;
}
+
if (entry != filename) {
efree(entry);
}
+
return FAILURE;
}
skip_phar:
PHAR_GLOBALS->request_done = 0;
zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), 5, zend_get_hash_value, destroy_phar_data, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), 5, zend_get_hash_value, NULL, 0);
+
if (PHAR_G(manifest_cached)) {
phar_archive_data **pphar;
phar_entry_fp *stuff = (phar_entry_fp *) ecalloc(zend_hash_num_elements(&cached_phars), sizeof(phar_entry_fp));
zend_hash_move_forward(&cached_phars)) {
stuff[pphar[0]->phar_pos].manifest = (phar_entry_fp_info *) ecalloc( zend_hash_num_elements(&(pphar[0]->manifest)), sizeof(phar_entry_fp_info));
}
+
PHAR_GLOBALS->cached_fp = stuff;
}
+
PHAR_GLOBALS->phar_SERVER_mung_list = 0;
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
int i;
PHAR_GLOBALS->request_ends = 1;
+
if (PHAR_GLOBALS->request_init)
{
phar_release_functions(TSRMLS_C);
zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map));
PHAR_GLOBALS->phar_fname_map.arBuckets = NULL;
PHAR_GLOBALS->phar_SERVER_mung_list = 0;
+
if (PHAR_GLOBALS->cached_fp) {
for (i = 0; i < zend_hash_num_elements(&cached_phars); ++i) {
if (PHAR_GLOBALS->cached_fp[i].fp) {
efree(PHAR_GLOBALS->cached_fp);
PHAR_GLOBALS->cached_fp = 0;
}
+
PHAR_GLOBALS->request_init = 0;
+
if (PHAR_G(cwd)) {
efree(PHAR_G(cwd));
}
+
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
PHAR_G(cwd_init) = 0;
}
+
PHAR_GLOBALS->request_done = 1;
return SUCCESS;
}
php_info_print_table_row(2, "Phar-based phar archives", "enabled");
php_info_print_table_row(2, "Tar-based phar archives", "enabled");
php_info_print_table_row(2, "ZIP-based phar archives", "enabled");
+
if (PHAR_G(has_zlib)) {
php_info_print_table_row(2, "gzip compression", "enabled");
} else {
php_info_print_table_row(2, "gzip compression", "disabled (install ext/zlib)");
}
+
if (PHAR_G(has_bz2)) {
php_info_print_table_row(2, "bzip2 compression", "enabled");
} else {
php_info_print_box_start(0);
PUTS("Phar based on pear/PHP_Archive, original concept by Davey Shafik.");
- PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
+ PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
PUTS("Phar fully realized by Gregory Beaver and Marcus Boerger.");
- PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
- PUTS("Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.");
+ PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
+ PUTS("Portions of tar implementation Copyright (c) 2003-2008 Tim Kientzle.");
php_info_print_box_end();
DISPLAY_INI_ENTRIES();
+----------------------------------------------------------------------+
| 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 |
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;
zend_object std;
spl_filesystem_object spl;
struct {
- zend_object std;
- phar_archive_data *archive;
+ zend_object std;
+ phar_archive_data *archive;
} arc;
};
#endif
zend_object std;
spl_filesystem_object spl;
struct {
- zend_object std;
- phar_entry_info *entry;
+ zend_object std;
+ phar_entry_info *entry;
} ent;
};
#endif
#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()
+----------------------------------------------------------------------+
| phar php single-file executable PHP extension |
+----------------------------------------------------------------------+
- | Copyright (c) 2005-2007 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 |
_SERVER = Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]);
/* PATH_INFO and PATH_TRANSLATED should always be munged */
- if (SUCCESS == zend_hash_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO"), (void **) &stuff)) {
- int code;
- zval *temp;
+ if (SUCCESS == zend_hash_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO"), (void **) &stuff)) {
+ int code;
+ zval *temp;
path_info = Z_STRVAL_PP(stuff);
code = Z_STRLEN_PP(stuff);
+
if (Z_STRLEN_PP(stuff) > entry_len && !memcmp(Z_STRVAL_PP(stuff), entry, entry_len)) {
ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + entry_len, request_uri_len, 1);
- MAKE_STD_ZVAL(temp);
+ MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
zend_hash_update(_SERVER, "PHAR_PATH_INFO", sizeof("PHAR_PATH_INFO"), (void *) &temp, sizeof(zval **), NULL);
}
}
- if (SUCCESS == zend_hash_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"), (void **) &stuff)) {
- int code;
- zval *temp;
- path_info = Z_STRVAL_PP(stuff);
- code = Z_STRLEN_PP(stuff);
+ if (SUCCESS == zend_hash_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"), (void **) &stuff)) {
+ int code;
+ zval *temp;
+
+ path_info = Z_STRVAL_PP(stuff);
+ code = Z_STRLEN_PP(stuff);
Z_STRLEN_PP(stuff) = spprintf(&(Z_STRVAL_PP(stuff)), 4096, "phar://%s%s", fname, entry);
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
- zend_hash_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED"), (void *) &temp, sizeof(zval **), NULL);
+ zend_hash_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED"), (void *) &temp, sizeof(zval **), NULL);
}
+
if (!PHAR_GLOBALS->phar_SERVER_mung_list) {
return;
}
+
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_REQUEST_URI) {
- if (SUCCESS == zend_hash_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &stuff)) {
+ if (SUCCESS == zend_hash_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &stuff)) {
int code;
zval *temp;
path_info = Z_STRVAL_PP(stuff);
code = Z_STRLEN_PP(stuff);
+
if (Z_STRLEN_PP(stuff) > basename_len && !memcmp(Z_STRVAL_PP(stuff), basename, basename_len)) {
ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + basename_len, Z_STRLEN_PP(stuff) - basename_len, 1);
}
}
}
+
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_PHP_SELF) {
- if (SUCCESS == zend_hash_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF"), (void **) &stuff)) {
+ if (SUCCESS == zend_hash_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF"), (void **) &stuff)) {
int code;
zval *temp;
path_info = Z_STRVAL_PP(stuff);
code = Z_STRLEN_PP(stuff);
+
if (Z_STRLEN_PP(stuff) > basename_len && !memcmp(Z_STRVAL_PP(stuff), basename, basename_len)) {
ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + basename_len, Z_STRLEN_PP(stuff) - basename_len, 1);
}
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_SCRIPT_NAME) {
- if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void **) &stuff)) {
- int code;
- zval *temp;
-
- path_info = Z_STRVAL_PP(stuff);
- code = Z_STRLEN_PP(stuff);
+ if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void **) &stuff)) {
+ int code;
+ zval *temp;
+
+ path_info = Z_STRVAL_PP(stuff);
+ code = Z_STRLEN_PP(stuff);
ZVAL_STRINGL(*stuff, entry, entry_len, 1);
-
+
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
- zend_hash_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME"), (void *) &temp, sizeof(zval **), NULL);
- }
+ zend_hash_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME"), (void *) &temp, sizeof(zval **), NULL);
+ }
}
if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_SCRIPT_FILENAME) {
if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &stuff)) {
- int code;
- zval *temp;
+ int code;
+ zval *temp;
- path_info = Z_STRVAL_PP(stuff);
- code = Z_STRLEN_PP(stuff);
+ path_info = Z_STRVAL_PP(stuff);
+ code = Z_STRLEN_PP(stuff);
Z_STRLEN_PP(stuff) = spprintf(&(Z_STRVAL_PP(stuff)), 4096, "phar://%s%s", fname, entry);
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, path_info, code, 0);
- zend_hash_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME"), (void *) &temp, sizeof(zval **), NULL);
+ zend_hash_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME"), (void *) &temp, sizeof(zval **), NULL);
}
}
}
ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %d", info->uncompressed_filesize);
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
efree(ctr.line);
+
if (FAILURE == sapi_send_headers(TSRMLS_C)) {
zend_bailout();
}
/* prepare to output */
fp = phar_get_efp(info, 1 TSRMLS_CC);
+
if (!fp) {
char *error;
if (!phar_open_jit(phar, info, phar_get_pharfp(phar TSRMLS_CC), &error, 0 TSRMLS_CC)) {
}
position = 0;
phar_seek_efp(info, 0, SEEK_SET, 0, 1 TSRMLS_CC);
+
do {
got = php_stream_read(fp, buf, MIN(8192, info->uncompressed_filesize - position));
if (got > 0) {
phar_mung_server_vars(arch, entry, entry_len, basename, ru, ru_len TSRMLS_CC);
efree(basename);
}
+
if (entry[0] == '/') {
name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
} else {
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
+
if (zend_hash_add(&EG(included_files), name, name_len+1, (void *)&dummy, sizeof(int), NULL) == SUCCESS) {
if ((cwd = zend_memrchr(entry, '/', entry_len))) {
PHAR_G(cwd_init) = 1;
PHAR_G(cwd) = estrndup(entry, PHAR_G(cwd_len));
}
}
+
new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
+
if (!new_op_array) {
zend_hash_del(&EG(included_files), name, name_len+1);
}
+
zend_destroy_file_handle(&file_handle TSRMLS_CC);
+
} else {
efree(name);
new_op_array = NULL;
} zend_end_try();
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
+
if (PHAR_G(cwd)) {
efree(PHAR_G(cwd));
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
}
+
PHAR_G(cwd_init) = 0;
efree(name);
+
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
+
zend_bailout();
}
+
return PHAR_MIME_PHP;
}
return -1;
/* we already know we can retrieve the phar if we reach here */
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void **) &pphar);
+
if (!pphar && PHAR_G(manifest_cached)) {
zend_hash_find(&cached_phars, fname, fname_len, (void **) &pphar);
}
*entry_len = e_len + 1;
return;
}
+
if (u) {
u1 = strrchr(e, '/');
u[0] = '/';
return;
}
}
+
u[0] = '\0';
u_len = strlen(u + 1);
e_len -= u_len + 1;
+
if (e_len < 0) {
if (saveu) {
saveu[0] = '/';
RETURN_STRINGL(arch, arch_len, 0);
}
}
+
RETURN_STRINGL("", 0, 1);
}
/* }}} */
if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
efree(entry);
entry = NULL;
+
if (path_len > 7 && !memcmp(path, "phar://", 7)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path);
efree(arch);
goto carry_on;
}
}
+
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s is not a phar archive, cannot mount", arch);
+
if (arch) {
efree(arch);
}
if (path && path == entry) {
efree(entry);
}
+
if (arch) {
efree(arch);
}
+
return;
}
+
if (entry && path && path == entry) {
efree(entry);
}
+
if (arch) {
efree(arch);
}
+
return;
} else if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void **)&pphar)) {
goto carry_on;
if (SUCCESS == phar_copy_on_write(pphar TSRMLS_CC)) {
goto carry_on;
}
+
goto carry_on;
} else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
path = entry;
path_len = entry_len;
goto carry_on2;
}
+
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Mounting of %s to %s failed", path, actual);
}
/* }}} */
phar_request_initialize(TSRMLS_C);
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
+
if (phar_open_executed_filename(alias, alias_len, &error TSRMLS_CC) != SUCCESS) {
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
if (!(SG(request_info).request_method && SG(request_info).request_uri && (!strcmp(SG(request_info).request_method, "GET") || !strcmp(SG(request_info).request_method, "POST")))) {
return;
}
+
#ifdef PHP_WIN32
fname = estrndup(fname, fname_len);
phar_unixify_path_separators(fname, fname_len);
#endif
basename = zend_memrchr(fname, '/', fname_len);
+
if (!basename) {
basename = fname;
} else {
zval **z_script_name, **z_path_info;
if (SUCCESS != zend_hash_find(ht, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void**)&z_script_name) ||
- IS_STRING != Z_TYPE_PP(z_script_name) ||
- !strstr(Z_STRVAL_PP(z_script_name), basename)) {
+ IS_STRING != Z_TYPE_PP(z_script_name) ||
+ !strstr(Z_STRVAL_PP(z_script_name), basename)) {
return;
}
+
if (SUCCESS == zend_hash_find(ht, "PATH_INFO", sizeof("PATH_INFO"), (void**)&z_path_info) &&
- IS_STRING == Z_TYPE_PP(z_path_info)) {
+ IS_STRING == Z_TYPE_PP(z_path_info)) {
entry_len = Z_STRLEN_PP(z_path_info);
entry = estrndup(Z_STRVAL_PP(z_path_info), entry_len);
path_info = emalloc(Z_STRLEN_PP(z_script_name) + entry_len + 1);
entry = estrndup("", 0);
path_info = Z_STRVAL_PP(z_script_name);
}
+
pt = estrndup(Z_STRVAL_PP(z_script_name), Z_STRLEN_PP(z_script_name));
+
} else {
char *testit;
efree(testit);
return;
}
+
path_info = sapi_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
+
if (path_info) {
entry = path_info;
entry_len = strlen(entry);
entry = estrndup("", 0);
entry_len = 0;
}
+
pt = estrndup(testit, (pt - testit) + (fname_len - (basename - fname)));
}
not_cgi = 0;
/* this can happen with rewrite rules - and we have no idea what to do then, so return */
return;
}
- entry_len = strlen(path_info);
+ entry_len = strlen(path_info);
entry_len -= (pt - path_info) + (fname_len - (basename - fname));
entry = estrndup(pt + (fname_len - (basename - fname)), entry_len);
if (FAILURE == zend_fcall_info_init(rewrite, 0, &fci, &fcc, NULL, NULL TSRMLS_CC)) {
#endif
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: invalid rewrite callback");
+
if (free_pathinfo) {
efree(path_info);
}
+
return;
}
if (!EG(exception)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: failed to call rewrite callback");
}
+
if (free_pathinfo) {
efree(path_info);
}
+
return;
}
+
if (!fci.retval_ptr_ptr || !retval_ptr) {
if (free_pathinfo) {
efree(path_info);
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: rewrite callback must return a string or false");
return;
}
+
switch (Z_TYPE_P(retval_ptr)) {
- case IS_STRING :
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(retval_ptr TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
+ case IS_STRING:
efree(entry);
+
if (fci.retval_ptr_ptr != &retval_ptr) {
entry = estrndup(Z_STRVAL_PP(fci.retval_ptr_ptr), Z_STRLEN_PP(fci.retval_ptr_ptr));
entry_len = Z_STRLEN_PP(fci.retval_ptr_ptr);
entry = Z_STRVAL_P(retval_ptr);
entry_len = Z_STRLEN_P(retval_ptr);
}
+
break;
- case IS_BOOL :
+ case IS_BOOL:
phar_do_403(entry, entry_len TSRMLS_CC);
+
if (free_pathinfo) {
efree(path_info);
}
+
zend_bailout();
return;
default:
efree(retval_ptr);
+
if (free_pathinfo) {
efree(path_info);
}
+
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: rewrite callback must return a string or false");
return;
}
if (entry_len) {
phar_postprocess_ru_web(fname, fname_len, &entry, &entry_len, &ru, &ru_len TSRMLS_CC);
}
+
if (!entry_len || (entry_len == 1 && entry[0] == '/')) {
efree(entry);
/* direct request */
if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL TSRMLS_CC) ||
(info = phar_get_entry_info(phar, entry, entry_len, NULL, 0 TSRMLS_CC)) == NULL) {
phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len TSRMLS_CC);
+
if (free_pathinfo) {
efree(path_info);
}
+
zend_bailout();
} else {
char *tmp, sa;
sa = *tmp;
*tmp = '\0';
}
+
ctr.response_code = 0;
+
if (path_info[strlen(path_info)-1] == '/') {
ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry + 1);
} else {
ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry);
}
+
if (not_cgi) {
*tmp = sa;
}
+
if (free_pathinfo) {
efree(path_info);
}
+
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
sapi_send_headers(TSRMLS_C);
efree(ctr.line);
if (SUCCESS == zend_hash_find(Z_ARRVAL_P(mimeoverride), ext, strlen(ext)+1, (void **) &val)) {
switch (Z_TYPE_PP(val)) {
- case IS_LONG :
+ case IS_LONG:
if (Z_LVAL_PP(val) == PHAR_MIME_PHP || Z_LVAL_PP(val) == PHAR_MIME_PHPS) {
mime_type = "";
code = Z_LVAL_PP(val);
RETURN_FALSE;
}
break;
- case IS_STRING :
+ case IS_STRING:
mime_type = Z_STRVAL_PP(val);
code = PHAR_MIME_OTHER;
break;
- default :
+ default:
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed");
#ifdef PHP_WIN32
efree(fname);
PHP_METHOD(Phar, mungServer)
{
zval *mungvalues;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &mungvalues) == FAILURE) {
return;
}
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
return;
}
+
if (zend_hash_num_elements(Z_ARRVAL_P(mungvalues)) > 4) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
return;
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "unable to retrieve array value in Phar::mungServer()");
return;
}
+
if (Z_TYPE_PP(data) != IS_STRING) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
return;
}
+
if (Z_STRLEN_PP(data) == sizeof("PHP_SELF")-1 && !strncmp(Z_STRVAL_PP(data), "PHP_SELF", sizeof("PHP_SELF")-1)) {
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_PHP_SELF;
}
+
if (Z_STRLEN_PP(data) == sizeof("REQUEST_URI")-1) {
if (!strncmp(Z_STRVAL_PP(data), "REQUEST_URI", sizeof("REQUEST_URI")-1)) {
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_REQUEST_URI;
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_SCRIPT_NAME;
}
}
+
if (Z_STRLEN_PP(data) == sizeof("SCRIPT_FILENAME")-1 && !strncmp(Z_STRVAL_PP(data), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1)) {
PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_SCRIPT_FILENAME;
}
char *alias = NULL, *error;
int alias_len = 0;
long dataoffset = 0;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) {
return;
}
phar_request_initialize(TSRMLS_C);
RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error TSRMLS_CC) == SUCCESS);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
phar_request_initialize(TSRMLS_C);
RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error TSRMLS_CC) == SUCCESS);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
} else {
RETURN_FALSE;
}
-
case PHAR_ENT_COMPRESSED_BZ2:
if (PHAR_G(has_bz2)) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
-
default:
if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) {
RETURN_TRUE;
static void phar_spl_foreign_dtor(spl_filesystem_object *object TSRMLS_DC) /* {{{ */
{
phar_archive_data *phar = (phar_archive_data *) object->oth;
+
if (!phar->is_persistent) {
phar_archive_delref(phar TSRMLS_CC);
}
+
object->oth = NULL;
}
/* }}} */
/* }}} */
static spl_other_handler phar_spl_foreign_handler = {
- phar_spl_foreign_dtor,
- phar_spl_foreign_clone
+ phar_spl_foreign_dtor,
+ phar_spl_foreign_clone
};
#endif /* HAVE_SPL */
#else
char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname;
int fname_len, alias_len = 0, arch_len, entry_len, is_data;
- long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS, format = 0;
+#if PHP_VERSION_ID < 50300
+ long flags = 0;
+#else
+ long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
+#endif
+ long format = 0;
phar_archive_object *phar_obj;
phar_archive_data *phar_data;
zval *zobj = getThis(), arg1, arg2;
phar_data->is_zip = 1;
phar_data->is_tar = 0;
}
+
if (fname == arch) {
efree(arch);
fname = save_fname;
efree(entry);
return;
}
+
is_data = phar_data->is_data;
+
if (!phar_data->is_persistent) {
++(phar_data->refcount);
}
+
phar_obj->arc.archive = phar_data;
phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
INIT_PZVAL(&arg1);
ZVAL_STRINGL(&arg1, fname, fname_len, 0);
-
INIT_PZVAL(&arg2);
ZVAL_LONG(&arg2, flags);
+
zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj),
&spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
if (!phar_data->is_persistent) {
phar_obj->arc.archive->is_data = is_data;
}
- phar_obj->spl.info_class = phar_ce_entry;
+ phar_obj->spl.info_class = phar_ce_entry;
efree(fname);
#endif /* HAVE_SPL */
}
/* }}} */
-/* }}} */
/* {{{ proto array Phar::getSupportedSignatures()
* Return array of supported signature types
add_next_index_stringl(return_value, "MD5", 3, 1);
add_next_index_stringl(return_value, "SHA-1", 5, 1);
-
#if HAVE_HASH_EXT
add_next_index_stringl(return_value, "SHA-256", 7, 1);
add_next_index_stringl(return_value, "SHA-512", 7, 1);
#endif
-
#if PHAR_HAVE_OPENSSL
add_next_index_stringl(return_value, "OpenSSL", 7, 1);
#else
PHP_METHOD(Phar, getSupportedCompression)
{
array_init(return_value);
-
phar_request_initialize(TSRMLS_C);
+
if (PHAR_G(has_zlib)) {
add_next_index_stringl(return_value, "GZ", 2, 1);
}
+
if (PHAR_G(has_bz2)) {
add_next_index_stringl(return_value, "BZIP2", 5, 1);
}
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" is in phar.cache_list, cannot unlinkArchive()", fname);
return;
}
+
if (phar->refcount) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname);
return;
}
+
fname = estrndup(phar->fname, phar->fname_len);
+
/* invalidate phar cache */
PHAR_G(last_phar) = NULL;
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
char *str = "[stream]";
iter->funcs->get_current_data(iter, &value TSRMLS_CC);
+
if (EG(exception)) {
return ZEND_HASH_APPLY_STOP;
}
+
if (!value) {
/* failure in get_current_data */
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned no value", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned no value", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
switch (Z_TYPE_PP(value)) {
- case IS_STRING :
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(*(value) TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
+ case IS_STRING:
break;
- case IS_RESOURCE :
+ case IS_RESOURCE:
php_stream_from_zval_no_verify(fp, value);
+
if (!fp) {
- zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %s returned an invalid stream handle", ce->name);
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %v returned an invalid stream handle", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
if (iter->funcs->get_current_key) {
key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC);
return ZEND_HASH_APPLY_STOP;
}
- PHAR_STR(key, str_key);
-
if (key_type == HASH_KEY_IS_LONG) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
+ if (key_type > 9) { /* IS_UNICODE == 10 */
+ spprintf(&str_key, 0, "%v", key);
+ } else {
+ PHAR_STR(key, str_key);
+ }
+
save = str_key;
- if (str_key[str_key_len - 1] == '\0') str_key_len--;
+
+ if (str_key[str_key_len - 1] == '\0') {
+ str_key_len--;
+ }
+
} else {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
close_fp = 0;
opened = (char *) estrndup(str, sizeof("[stream]") + 1);
goto after_open_fp;
- case IS_OBJECT :
+ case IS_OBJECT:
if (instanceof_function(Z_OBJCE_PP(value), spl_ce_SplFileInfo TSRMLS_CC)) {
char *test = NULL;
zval dummy;
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(*value TSRMLS_CC);
if (!base_len) {
- zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %s returns an SplFileInfo object, so base directory must be specified", ce->name);
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %v returns an SplFileInfo object, so base directory must be specified", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
switch (intern->type) {
case SPL_FS_DIR:
#if PHP_VERSION_ID >= 60000
#endif
fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
php_stat(fname, fname_len, FS_IS_DIR, &dummy TSRMLS_CC);
+
if (Z_BVAL(dummy)) {
/* ignore directories */
efree(fname);
return ZEND_HASH_APPLY_KEEP;
}
+
test = expand_filepath(fname, NULL TSRMLS_CC);
+
if (test) {
efree(fname);
fname = test;
fname_len = strlen(fname);
}
+
save = fname;
is_splfileinfo = 1;
goto phar_spl_fileinfo;
case SPL_FS_INFO:
case SPL_FS_FILE:
+#if PHP_VERSION_ID >= 60000
+ fname = expand_filepath(intern->file_name.s, NULL TSRMLS_CC);
+#else
fname = expand_filepath(intern->file_name, NULL TSRMLS_CC);
+#endif
fname_len = strlen(fname);
save = fname;
is_splfileinfo = 1;
}
}
/* fall-through */
- default :
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid value (must return a string)", ce->name);
+ default:
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid value (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
temp = expand_filepath(base, NULL TSRMLS_CC);
base = temp;
base_len = strlen(base);
+
if (strstr(fname, base)) {
str_key_len = fname_len - base_len;
+
if (str_key_len <= 0) {
if (save) {
efree(save);
}
return ZEND_HASH_APPLY_KEEP;
}
+
str_key = fname + base_len;
+
if (*str_key == '/' || *str_key == '\\') {
str_key++;
str_key_len--;
}
+
} else {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that is not in the base directory \"%s\"", ce->name, fname, base);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that is not in the base directory \"%s\"", ce->name, fname, base);
+
if (save) {
efree(save);
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
} else {
return ZEND_HASH_APPLY_STOP;
}
- PHAR_STR(key, str_key);
-
if (key_type == HASH_KEY_IS_LONG) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
+
+ if (key_type > 9) { /* IS_UNICODE == 10 */
+ spprintf(&str_key, 0, "%v", key);
+ } else {
+ PHAR_STR(key, str_key);
+ }
+
save = str_key;
+
if (str_key[str_key_len - 1] == '\0') str_key_len--;
} else {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
}
#if PHP_MAJOR_VERSION < 6
if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that safe mode prevents opening", ce->name, fname);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that safe mode prevents opening", ce->name, fname);
+
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
#endif
if (php_check_open_basedir(fname TSRMLS_CC)) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that open_basedir prevents opening", ce->name, fname);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that open_basedir prevents opening", ce->name, fname);
+
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
/* try to open source file, then create internal phar file and copy contents */
fp = php_stream_open_wrapper(fname, "rb", STREAM_MUST_SEEK|0, &opened);
+
if (!fp) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a file that could not be opened \"%s\"", ce->name, fname);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a file that could not be opened \"%s\"", ce->name, fname);
+
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
return ZEND_HASH_APPLY_STOP;
}
-
after_open_fp:
if (str_key_len >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
/* silently skip any files that would be added to the magic .phar directory */
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
+
if (opened) {
efree(opened);
}
+
if (close_fp) {
php_stream_close(fp);
}
+
return ZEND_HASH_APPLY_KEEP;
}
+
if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, str_key, str_key_len, "w+b", 0, &error, 1 TSRMLS_CC))) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s cannot be created: %s", str_key, error);
efree(error);
+
if (save) {
efree(save);
}
+
if (opened) {
efree(opened);
}
+
if (temp) {
efree(temp);
}
+
if (close_fp) {
php_stream_close(fp);
}
+
return ZEND_HASH_APPLY_STOP;
+
} else {
if (error) {
efree(error);
if (data->internal_file->fp_type == PHAR_MOD) {
php_stream_close(data->internal_file->fp);
}
+
data->internal_file->fp = NULL;
data->internal_file->fp_type = PHAR_UFP;
data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp);
data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
php_stream_tell(p_obj->fp) - data->internal_file->offset;
}
+
if (close_fp) {
php_stream_close(fp);
}
if (save) {
efree(save);
}
+
if (temp) {
efree(temp);
}
INIT_PZVAL(&arg);
ZVAL_STRINGL(&arg, dir, dir_len, 0);
INIT_PZVAL(&arg2);
+#if PHP_VERSION_ID < 50300
+ ZVAL_LONG(&arg2, 0);
+#else
ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
+#endif
zend_call_method_with_2_params(&iter, spl_ce_RecursiveDirectoryIterator,
&spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2);
if (SUCCESS == spl_iterator_apply((apply_reg ? regexiter : iteriter), (spl_iterator_apply_func_t) phar_build, (void *) &pass TSRMLS_CC)) {
zval_ptr_dtor(&iteriter);
+
if (apply_reg) {
zval_ptr_dtor(®exiter);
}
+
phar_obj->arc.archive->ufp = pass.fp;
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
} else {
zval_ptr_dtor(&iteriter);
php_stream_close(pass.fp);
} else {
php_stream_close(pass.fp);
}
-
}
/* }}} */
PHP_METHOD(Phar, count)
{
PHAR_ARCHIVE_OBJECT();
-
+
RETURN_LONG(zend_hash_num_elements(&phar_obj->arc.archive->manifest));
}
/* }}} */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) {
RETURN_FALSE;
}
+
switch (type) {
case PHAR_FORMAT_TAR:
RETURN_BOOL(phar_obj->arc.archive->is_tar);
}
return FAILURE;
}
+
/* copy old contents in entirety */
phar_seek_efp(entry, 0, SEEK_SET, 0, 1 TSRMLS_CC);
offset = php_stream_tell(fp);
link = phar_get_link_source(entry TSRMLS_CC);
+
if (!link) {
link = entry;
}
+
if (link->uncompressed_filesize != php_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize)) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename);
return FAILURE;
}
+
if (entry->fp_type == PHAR_MOD) {
/* save for potential restore on error */
entry->cfp = entry->fp;
entry->fp = NULL;
}
+
/* set new location of file contents */
entry->fp_type = PHAR_FP;
entry->offset = offset;
if (!ext) {
if (phar->is_zip) {
+
if (phar->is_data) {
ext = "zip";
} else {
ext = "phar.zip";
}
+
} else if (phar->is_tar) {
+
switch (phar->flags) {
case PHAR_FILE_COMPRESSED_GZ:
if (phar->is_data) {
}
}
} else {
+
switch (phar->flags) {
case PHAR_FILE_COMPRESSED_GZ:
ext = "phar.gz";
}
}
} else if (phar_path_check(&ext, &ext_len, &pcr_error) > pcr_is_ok) {
+
if (phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
} else {
goto its_ok;
}
}
+
efree(oldpath);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to add newly converted phar \"%s\" to the list of phars, a phar with that name already exists", phar->fname);
return NULL;
}
-
its_ok:
if (!phar->is_data) {
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 1, 1, 1 TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar \"%s\" has invalid extension %s", phar->fname, ext);
return NULL;
}
+
if (phar->alias) {
if (phar->is_temporary_alias) {
phar->alias = NULL;
zend_hash_update(&(PHAR_GLOBALS->phar_alias_map), newpath, phar->fname_len, (void*)&phar, sizeof(phar_archive_data*), NULL);
}
}
+
} else {
+
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 0, 1, 1 TSRMLS_CC)) {
efree(oldpath);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
return NULL;
}
+
phar->alias = NULL;
phar->alias_len = 0;
}
}
phar_flush(phar, 0, 0, 1, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, error);
efree(error);
}
MAKE_STD_ZVAL(ret);
+
if (SUCCESS != object_init_ex(ret, ce)) {
zval_dtor(ret);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname);
return NULL;
}
+
INIT_PZVAL(&arg1);
ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len, 0);
zend_call_method_with_1_params(&ret, ce, &ce->constructor, "__construct", NULL, &arg1);
-
return ret;
}
/* }}} */
phar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
/* set whole-archive compression and type from parameter */
phar->flags = flags;
-
phar->is_data = source->is_data;
+
switch (convert) {
- case PHAR_FORMAT_TAR :
+ case PHAR_FORMAT_TAR:
phar->is_tar = 1;
break;
- case PHAR_FORMAT_ZIP :
+ case PHAR_FORMAT_ZIP:
phar->is_zip = 1;
break;
- default :
+ default:
phar->is_data = 0;
break;
}
phar->fname_len = source->fname_len;
phar->is_temporary_alias = source->is_temporary_alias;
phar->alias = source->alias;
+
/* first copy each file's uncompressed contents to a temporary file and set per-file flags */
for (zend_hash_internal_pointer_reset(&source->manifest); SUCCESS == zend_hash_has_more_elements(&source->manifest); zend_hash_move_forward(&source->manifest)) {
"Cannot convert phar archive \"%s\"", source->fname);
return NULL;
}
+
newentry = *entry;
+
if (newentry.link) {
newentry.link = estrdup(newentry.link);
goto no_copy;
}
+
if (newentry.tmp) {
newentry.tmp = estrdup(newentry.tmp);
goto no_copy;
}
+
newentry.metadata_str.c = 0;
+
if (FAILURE == phar_copy_file_contents(&newentry, phar->fp TSRMLS_CC)) {
zend_hash_destroy(&(phar->manifest));
php_stream_close(phar->fp);
}
no_copy:
newentry.filename = estrndup(newentry.filename, newentry.filename_len);
+
if (newentry.metadata) {
zval *t;
newentry.metadata_str.c = NULL;
newentry.metadata_str.len = 0;
}
+
newentry.is_zip = phar->is_zip;
newentry.is_tar = phar->is_tar;
+
if (newentry.is_tar) {
newentry.tar_type = (entry->is_dir ? TAR_DIR : TAR_FILE);
}
+
newentry.is_modified = 1;
newentry.phar = phar;
newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */
/* }}} */
/* {{{ proto object Phar::convertToExecutable([int format[, int compression [, string file_ext]]])
- * Convert a phar.tar or phar.zip archive to the phar file format. The
+ * Convert a phar.tar or phar.zip archive to the phar file format. The
* optional parameter allows the user to determine the new
* filename extension (default is phar).
*/
"Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_GZ;
break;
-
case PHAR_ENT_COMPRESSED_BZ2:
if (format == PHAR_FORMAT_ZIP) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_BZ2;
break;
default:
phar_obj->arc.archive->is_data = 0;
ret = phar_convert_to_other(phar_obj->arc.archive, format, ext, flags TSRMLS_CC);
phar_obj->arc.archive->is_data = is_data;
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
"Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_GZ;
break;
-
case PHAR_ENT_COMPRESSED_BZ2:
if (format == PHAR_FORMAT_ZIP) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
return;
}
+
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
return;
}
+
flags = PHAR_FILE_COMPRESSED_BZ2;
break;
default:
phar_obj->arc.archive->is_data = 1;
ret = phar_convert_to_other(phar_obj->arc.archive, format, ext, flags TSRMLS_CC);
phar_obj->arc.archive->is_data = is_data;
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
PHP_METHOD(Phar, isCompressed)
{
PHAR_ARCHIVE_OBJECT();
-
+
if (phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSED_GZ) {
RETURN_LONG(PHAR_ENT_COMPRESSED_GZ);
}
+
if (phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSED_BZ2) {
RETURN_LONG(PHAR_ENT_COMPRESSED_BZ2);
}
+
RETURN_FALSE;
}
/* }}} */
{
php_stream_statbuf ssb;
PHAR_ARCHIVE_OBJECT();
-
+
if (!phar_obj->arc.archive->is_writeable) {
RETURN_FALSE;
}
+
if (SUCCESS != php_stream_stat_path(phar_obj->arc.archive->fname, &ssb)) {
if (phar_obj->arc.archive->is_brandnew) {
/* assume it works if the file doesn't exist yet */
}
RETURN_FALSE;
}
+
RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0);
}
/* }}} */
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
-
+
RETURN_TRUE;
}
/* }}} */
char *alias, *error, *oldalias;
phar_archive_data **fd_ptr;
int alias_len, oldalias_len, old_temp, readd = 0;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
if (phar_obj->arc.archive->is_data) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "A Phar alias cannot be set in a plain %s archive", phar_obj->arc.archive->is_tar ? "tar" : "zip");
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar alias cannot be set in a plain tar archive");
+ } else {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar alias cannot be set in a plain zip archive");
+ }
RETURN_FALSE;
}
oldalias = phar_obj->arc.archive->alias;
oldalias_len = phar_obj->arc.archive->alias_len;
old_temp = phar_obj->arc.archive->is_temporary_alias;
+
if (alias_len) {
phar_obj->arc.archive->alias = estrndup(alias, alias_len);
} else {
phar_obj->arc.archive->alias = NULL;
}
+
phar_obj->arc.archive->alias_len = alias_len;
phar_obj->arc.archive->is_temporary_alias = 0;
-
phar_flush(phar_obj->arc.archive, NULL, 0, 0, &error TSRMLS_CC);
+
if (error) {
phar_obj->arc.archive->alias = oldalias;
phar_obj->arc.archive->alias_len = oldalias_len;
efree(error);
RETURN_FALSE;
}
+
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&(phar_obj->arc.archive), sizeof(phar_archive_data*), NULL);
+
if (oldalias) {
efree(oldalias);
}
+
RETURN_TRUE;
}
PHP_METHOD(Phar, getVersion)
{
PHAR_ARCHIVE_OBJECT();
-
+
RETURN_STRING(phar_obj->arc.archive->version, 1);
}
/* }}} */
PHP_METHOD(Phar, startBuffering)
{
PHAR_ARCHIVE_OBJECT();
-
+
phar_obj->arc.archive->donotflush = 1;
}
/* }}} */
PHP_METHOD(Phar, isBuffering)
{
PHAR_ARCHIVE_OBJECT();
-
+
RETURN_BOOL(!phar_obj->arc.archive->donotflush);
}
/* }}} */
PHP_METHOD(Phar, stopBuffering)
{
char *error;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
}
phar_obj->arc.archive->donotflush = 0;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
if (phar_obj->arc.archive->is_data) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "A Phar stub cannot be set in a plain %s archive", phar_obj->arc.archive->is_tar ? "tar" : "zip");
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain tar archive");
+ } else {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain zip archive");
+ }
return;
}
}
} else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &stub, &stub_len) == SUCCESS) {
phar_flush(phar_obj->arc.archive, stub, stub_len, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
* files cannot be loaded via this kind of stub, no parameters are accepted
* when the Phar object is zip- or tar-based.
*/
- PHP_METHOD(Phar, setDefaultStub)
+PHP_METHOD(Phar, setDefaultStub)
{
char *index = NULL, *webindex = NULL, *error = NULL, *stub = NULL;
int index_len = 0, webindex_len = 0, created_stub = 0;
PHAR_ARCHIVE_OBJECT();
if (phar_obj->arc.archive->is_data) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "A Phar stub cannot be set in a plain %s archive", phar_obj->arc.archive->is_tar ? "tar" : "zip");
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain tar archive");
+ } else {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
+ "A Phar stub cannot be set in a plain zip archive");
+ }
return;
}
}
if (!phar_obj->arc.archive->is_tar && !phar_obj->arc.archive->is_zip) {
-
stub = phar_create_default_stub(index, webindex, &stub_len, &error TSRMLS_CC);
if (error) {
}
RETURN_FALSE;
}
+
created_stub = 1;
}
long algo;
char *error, *key = NULL;
int key_len = 0;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
}
switch (algo) {
- case PHAR_SIG_SHA256 :
- case PHAR_SIG_SHA512 :
+ case PHAR_SIG_SHA256:
+ case PHAR_SIG_SHA512:
#if !HAVE_HASH_EXT
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"SHA-256 and SHA-512 signatures are only supported if the hash extension is enabled");
return;
#endif
- case PHAR_SIG_MD5 :
- case PHAR_SIG_SHA1 :
- case PHAR_SIG_OPENSSL :
+ case PHAR_SIG_MD5:
+ case PHAR_SIG_SHA1:
+ case PHAR_SIG_OPENSSL:
phar_obj->arc.archive->sig_flags = algo;
phar_obj->arc.archive->is_modified = 1;
PHAR_G(openssl_privatekey) = key;
efree(error);
}
break;
- default :
+ default:
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Unknown signature algorithm specified");
}
array_init(return_value);
add_assoc_stringl(return_value, "hash", phar_obj->arc.archive->signature, phar_obj->arc.archive->sig_len, 1);
switch(phar_obj->arc.archive->sig_flags) {
- case PHAR_SIG_MD5:
- add_assoc_stringl(return_value, "hash_type", "MD5", 3, 1);
- break;
- case PHAR_SIG_SHA1:
- add_assoc_stringl(return_value, "hash_type", "SHA-1", 5, 1);
- break;
- case PHAR_SIG_SHA256:
- add_assoc_stringl(return_value, "hash_type", "SHA-256", 7, 1);
- break;
- case PHAR_SIG_SHA512:
- add_assoc_stringl(return_value, "hash_type", "SHA-512", 7, 1);
- break;
- case PHAR_SIG_OPENSSL:
- add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7, 1);
- break;
- default:
- unknown_len = spprintf(&unknown, 0, "Unknown (%d)", phar_obj->arc.archive->sig_flags);
- add_assoc_stringl(return_value, "hash_type", unknown, unknown_len, 0);
- break;
+ case PHAR_SIG_MD5:
+ add_assoc_stringl(return_value, "hash_type", "MD5", 3, 1);
+ break;
+ case PHAR_SIG_SHA1:
+ add_assoc_stringl(return_value, "hash_type", "SHA-1", 5, 1);
+ break;
+ case PHAR_SIG_SHA256:
+ add_assoc_stringl(return_value, "hash_type", "SHA-256", 7, 1);
+ break;
+ case PHAR_SIG_SHA512:
+ add_assoc_stringl(return_value, "hash_type", "SHA-512", 7, 1);
+ break;
+ case PHAR_SIG_OPENSSL:
+ add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7, 1);
+ break;
+ default:
+ unknown_len = spprintf(&unknown, 0, "Unknown (%d)", phar_obj->arc.archive->sig_flags);
+ add_assoc_stringl(return_value, "hash_type", unknown, unknown_len, 0);
+ break;
}
} else {
RETURN_FALSE;
if (entry->is_deleted) {
return ZEND_HASH_APPLY_KEEP;
}
+
entry->old_flags = entry->flags;
entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
entry->flags |= compress;
if (entry->is_deleted) {
return ZEND_HASH_APPLY_KEEP;
}
+
if (!PHAR_G(has_bz2)) {
if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
*(int *) argument = 0;
}
}
+
if (!PHAR_G(has_zlib)) {
if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
*(int *) argument = 0;
}
}
+
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
static int pharobj_cancompress(HashTable *manifest TSRMLS_DC) /* {{{ */
{
int test;
+
test = 1;
zend_hash_apply_with_argument(manifest, phar_test_compression, &test TSRMLS_CC);
return test;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &method, &ext, &ext_len) == FAILURE) {
return;
}
-
+
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Cannot compress phar archive, phar is read-only");
}
flags = PHAR_FILE_COMPRESSED_GZ;
break;
-
+
case PHAR_ENT_COMPRESSED_BZ2:
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
} else {
ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_PHAR, ext, flags TSRMLS_CC);
}
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
} else {
ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_PHAR, ext, PHAR_FILE_COMPRESSED_NONE TSRMLS_CC);
}
+
if (ret) {
RETURN_ZVAL(ret, 1, 1);
} else {
"Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
return;
}
+
if (phar_obj->arc.archive->is_tar) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with Gzip compression, tar archives cannot compress individual files, use compress() to compress the whole archive");
return;
}
+
if (!pharobj_cancompress(&phar_obj->arc.archive->manifest TSRMLS_CC)) {
if (flags == PHAR_FILE_COMPRESSED_GZ) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
}
return;
}
- pharobj_set_compression(&phar_obj->arc.archive->manifest, flags TSRMLS_CC);
+ pharobj_set_compression(&phar_obj->arc.archive->manifest, flags TSRMLS_CC);
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, error);
efree(error);
"Phar is readonly, cannot change compression");
return;
}
+
if (!pharobj_cancompress(&phar_obj->arc.archive->manifest TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot decompress all files, some are compressed as bzip2 or gzip and cannot be decompressed");
return;
}
+
if (phar_obj->arc.archive->is_tar) {
RETURN_TRUE;
} else {
}
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
/* }}} */
const char *pcr_error;
int oldfile_len, newfile_len;
phar_entry_info *oldentry, newentry = {0}, *temp;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &oldfile, &oldfile_len, &newfile, &newfile_len) == FAILURE) {
}
memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info));
+
if (newentry.metadata) {
zval *t;
newentry.metadata_str.c = NULL;
newentry.metadata_str.len = 0;
}
+
newentry.filename = estrndup(newfile, newfile_len);
newentry.filename_len = newfile_len;
newentry.fp_refcount = 0;
zend_hash_add(&oldentry->phar->manifest, newfile, newfile_len, (void*)&newentry, sizeof(phar_entry_info), NULL);
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
char *fname;
int fname_len;
phar_entry_info *entry;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use getStub", phar_obj->arc.archive->fname);
return;
}
-
+
if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use getAlias", phar_obj->arc.archive->fname);
return;
}
-
+
if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot directly get any files or directories in magic \".phar\" directory", phar_obj->arc.archive->fname);
return;
efree(entry->filename);
efree(entry);
}
+
fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
MAKE_STD_ZVAL(zfname);
ZVAL_STRINGL(zfname, fname, fname_len, 0);
spl_instantiate_arg_ex1(phar_obj->spl.info_class, &return_value, 0, zfname TSRMLS_CC);
zval_ptr_dtor(&zfname);
}
-
}
/* }}} */
if (error) {
efree(error);
}
+
if (!data->internal_file->is_dir) {
if (cont_str) {
contents_len = php_stream_write(data->fp, cont_str, cont_len);
}
contents_len = php_stream_copy_to_stream(contents_file, data->fp, PHP_STREAM_COPY_ALL);
}
+
data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
}
+
phar_entry_delref(data TSRMLS_CC);
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
} else {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Directory %s does not exist and cannot be created", dirname);
}
+
return;
} else {
if (error) {
efree(error);
}
+
phar_entry_delref(data TSRMLS_CC);
phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
/* }}} */
-
/* {{{ proto int Phar::offsetSet(string entry, string value)
* set the contents of an internal file to those of an external file
*/
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by INI setting");
return;
}
-
+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sr", &fname, &fname_len, &zresource) == FAILURE
&& zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fname, &fname_len, &cont_str, &cont_len) == FAILURE) {
return;
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot set any files or directories in magic \".phar\" directory", phar_obj->arc.archive->fname);
return;
}
+
phar_add_file(phar_obj->arc.archive, fname, fname_len, cont_str, cont_len, zresource TSRMLS_CC);
}
/* }}} */
/* entry is deleted, but has not been flushed to disk yet */
return;
}
+
entry->is_modified = 0;
entry->is_deleted = 1;
/* we need to "flush" the stream to save the newly deleted file on disk */
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
} else {
{
char *dirname;
int dirname_len;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &dirname, &dirname_len) == FAILURE) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot create a directory in magic \".phar\" directory");
return;
}
+
phar_mkdir(phar_obj->arc.archive, dirname, dirname_len TSRMLS_CC);
}
/* }}} */
int fname_len, localname_len = 0;
php_stream *resource;
zval *zresource;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &fname, &fname_len, &localname, &localname_len) == FAILURE) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "phar error: unable to open file \"%s\" to add to phar archive", fname);
return;
}
+
if (localname) {
fname = localname;
fname_len = localname_len;
{
char *localname, *cont_str;
int localname_len, cont_len;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &localname, &localname_len, &cont_str, &cont_len) == FAILURE) {
php_stream *fp;
php_stream_filter *filter = NULL;
phar_entry_info *stub;
+
PHAR_ARCHIVE_OBJECT();
if (phar_obj->arc.archive->is_tar || phar_obj->arc.archive->is_zip) {
php_stream_rewind(fp);
carry_on:
buf = safe_emalloc(len, 1, 1);
+
if (len != php_stream_read(fp, buf, len)) {
if (fp != phar_obj->arc.archive->fp) {
php_stream_close(fp);
efree(buf);
return;
}
+
if (filter) {
php_stream_filter_flush(filter, 1);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
}
+
if (fp != phar_obj->arc.archive->fp) {
php_stream_close(fp);
}
- buf[len] = '\0';
+ buf[len] = '\0';
RETURN_STRINGL(buf, len, 0);
}
/* }}}*/
{
char *error;
zval *metadata;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
MAKE_STD_ZVAL(phar_obj->arc.archive->metadata);
ZVAL_ZVAL(phar_obj->arc.archive->metadata, metadata, 1, 0);
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
PHP_METHOD(Phar, delMetadata)
{
char *error;
+
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
zval_ptr_dtor(&phar_obj->arc.archive->metadata);
phar_obj->arc.archive->metadata = NULL;
phar_obj->arc.archive->is_modified = 1;
-
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
} else {
RETURN_TRUE;
}
+
} else {
RETURN_TRUE;
}
#if (PHP_MAJOR_VERSION < 6)
#define OPENBASEDIR_CHECKPATH(filename) \
(PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)
-#else
+#else
#define OPENBASEDIR_CHECKPATH(filename) \
php_check_open_basedir(filename TSRMLS_CC)
#endif
/* silently ignore mounted entries */
return SUCCESS;
}
+
if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
return SUCCESS;
}
+
len = spprintf(&fullpath, 0, "%s/%s", dest, entry->filename);
+
if (len >= MAXPATHLEN) {
char *tmp;
/* truncate for error message */
efree(fullpath);
return FAILURE;
}
+
if (!len) {
spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
efree(fullpath);
efree(fullpath);
return FAILURE;
}
+
/* perform dirname */
slash = zend_memrchr(entry->filename, '/', entry->filename_len);
+
if (slash) {
fullpath[dest_len + (slash - entry->filename) + 1] = '\0';
} else {
fullpath[dest_len] = '\0';
}
+
if (FAILURE == php_stream_stat_path(fullpath, &ssb)) {
if (entry->is_dir) {
if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
}
}
}
+
if (slash) {
fullpath[dest_len + (slash - entry->filename) + 1] = '/';
} else {
int nelems;
zval *zval_files = NULL;
zend_bool overwrite = 0;
+
PHAR_ARCHIVE_OBJECT();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z!b", &pathto, &pathto_len, &zval_files, &overwrite) == FAILURE) {
}
fp = php_stream_open_wrapper(phar_obj->arc.archive->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);
+
if (!fp) {
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC,
"Invalid argument, %s cannot be found", phar_obj->arc.archive->fname);
return;
}
+
efree(actual);
php_stream_close(fp);
"Invalid argument, extraction path must be non-zero length");
return;
}
+
if (pathto_len >= MAXPATHLEN) {
char *tmp = estrndup(pathto, 50);
/* truncate for error message */
switch (Z_TYPE_P(zval_files)) {
case IS_NULL:
goto all_files;
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(zval_files TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
case IS_STRING:
filename = Z_STRVAL_P(zval_files);
filename_len = Z_STRLEN_P(zval_files);
zval **zval_file;
if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
switch (Z_TYPE_PP(zval_file)) {
+#if PHP_VERSION_ID >= 60000
+ case IS_UNICODE:
+ zval_unicode_to_string(*(zval_file) TSRMLS_CC);
+ /* break intentionally omitted */
+#endif
case IS_STRING:
break;
default:
"Invalid argument, expected a filename (string) or array of filenames");
return;
}
+
if (FAILURE == zend_hash_find(&phar_obj->arc.archive->manifest, filename, filename_len, (void **)&entry)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
"Phar Error: attempted to extract non-existent file \"%s\" from phar \"%s\"", filename, phar_obj->arc.archive->fname);
return;
}
+
if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error TSRMLS_CC)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
"Extraction from phar \"%s\" failed: %s", phar_obj->arc.archive->fname, error);
}
} else {
phar_archive_data *phar = phar_obj->arc.archive;
-
all_files:
/* Extract all files */
if (!zend_hash_num_elements(&(phar->manifest))) {
zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
zend_hash_move_forward(&phar->manifest)) {
phar_entry_info *entry;
+
if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
continue;
}
+
if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error TSRMLS_CC)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
"Extraction from phar \"%s\" failed: %s", phar->fname, error);
{
char *fname, *arch, *entry, *error;
int fname_len, arch_len, entry_len;
- phar_entry_object *entry_obj;
- phar_entry_info *entry_info;
+ phar_entry_object *entry_obj;
+ phar_entry_info *entry_info;
phar_archive_data *phar_data;
zval *zobj = getThis(), arg1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
return;
}
-
+
entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
if (entry_obj->ent.entry) {
if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, 1 TSRMLS_CC)) == NULL) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
- "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error?", ":"", error?error:"");
+ "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : "");
efree(arch);
efree(entry);
return;
efree(entry_obj->ent.entry->filename);
entry_obj->ent.entry->filename = NULL;
}
+
efree(entry_obj->ent.entry);
entry_obj->ent.entry = NULL;
}
"Phar entry is a directory, does not have a CRC"); \
return;
}
+
if (entry_obj->ent.entry->is_crc_checked) {
RETURN_LONG(entry_obj->ent.entry->crc32);
} else {
PHP_METHOD(PharFileInfo, isCRCChecked)
{
PHAR_ENTRY_OBJECT();
-
+
RETURN_BOOL(entry_obj->ent.entry->is_crc_checked);
}
/* }}} */
PHP_METHOD(PharFileInfo, getPharFlags)
{
PHAR_ENTRY_OBJECT();
-
+
RETURN_LONG(entry_obj->ent.entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
}
/* }}} */
"Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", entry_obj->ent.entry->filename); \
return;
}
+
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
return;
}
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &perms) == FAILURE) {
return;
- }
- /* clear permissions */
+ }
+
+ /* clear permissions */
entry_obj->ent.entry->flags &= ~PHAR_ENT_PERM_MASK;
perms &= 0777;
entry_obj->ent.entry->flags |= perms;
entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
entry_obj->ent.entry->phar->is_modified = 1;
entry_obj->ent.entry->is_modified = 1;
+
/* hackish cache in php_stat needs to be cleared */
/* if this code fails to work, check main/streams/streams.c, _php_stream_stat_path */
if (BG(CurrentLStatFile)) {
efree(BG(CurrentLStatFile));
}
+
if (BG(CurrentStatFile)) {
efree(BG(CurrentStatFile));
}
+
BG(CurrentLStatFile) = NULL;
BG(CurrentStatFile) = NULL;
-
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
PHP_METHOD(PharFileInfo, hasMetadata)
{
PHAR_ENTRY_OBJECT();
-
+
RETURN_BOOL(entry_obj->ent.entry->metadata != NULL);
}
/* }}} */
PHP_METHOD(PharFileInfo, getMetadata)
{
PHAR_ENTRY_OBJECT();
-
+
if (entry_obj->ent.entry->metadata) {
RETURN_ZVAL(entry_obj->ent.entry->metadata, 1, 0);
}
{
char *error;
zval *metadata;
+
PHAR_ENTRY_OBJECT();
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by phar.readonly INI setting");
return;
}
+
if (entry_obj->ent.entry->is_temp_dir) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
"Phar entry is a temporary directory (not an actual entry in the archive), cannot set metadata"); \
return;
}
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &metadata) == FAILURE) {
return;
}
entry_obj->ent.entry->is_modified = 1;
entry_obj->ent.entry->phar->is_modified = 1;
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
PHP_METHOD(PharFileInfo, delMetadata)
{
char *error;
+
PHAR_ENTRY_OBJECT();
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by phar.readonly INI setting");
return;
}
+
if (entry_obj->ent.entry->is_temp_dir) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
"Phar entry is a temporary directory (not an actual entry in the archive), cannot delete metadata"); \
return;
}
+
if (entry_obj->ent.entry->metadata) {
zval_ptr_dtor(&entry_obj->ent.entry->metadata);
entry_obj->ent.entry->metadata = NULL;
entry_obj->ent.entry->phar->is_modified = 1;
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
} else {
RETURN_TRUE;
}
+
} else {
RETURN_TRUE;
}
char *error;
php_stream *fp;
phar_entry_info *link;
+
PHAR_ENTRY_OBJECT();
if (entry_obj->ent.entry->is_dir) {
"Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
return;
}
+
link = phar_get_link_source(entry_obj->ent.entry TSRMLS_CC);
+
if (!link) {
link = entry_obj->ent.entry;
}
+
if (SUCCESS != phar_open_entry_fp(link, &error, 0 TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname, error);
efree(error);
return;
}
+
if (!(fp = phar_get_efp(link, 0 TSRMLS_CC))) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
return;
}
+
phar_seek_efp(link, 0, SEEK_SET, 0, 0 TSRMLS_CC);
Z_TYPE_P(return_value) = IS_STRING;
Z_STRLEN_P(return_value) = php_stream_copy_to_mem(fp, &(Z_STRVAL_P(return_value)), link->uncompressed_filesize, 0);
+
if (!Z_STRVAL_P(return_value)) {
Z_STRVAL_P(return_value) = estrndup("", 0);
}
"Cannot compress with Gzip compression, not possible with tar-based phar archives");
return;
}
+
if (entry_obj->ent.entry->is_dir) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
"Phar entry is a directory, cannot set compression"); \
return;
}
+
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar is readonly, cannot change compression");
return;
}
+
if (entry_obj->ent.entry->is_deleted) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress deleted file");
RETURN_TRUE;
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0) {
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with gzip compression, file is already compressed with bzip2 compression and bz2 extension is not enabled, cannot decompress");
return;
}
+
/* decompress this file indirectly */
if (SUCCESS != phar_open_entry_fp(entry_obj->ent.entry, &error, 1 TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
return;
}
}
+
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with gzip compression, zlib extension is not enabled");
return;
}
+
entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
entry_obj->ent.entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
entry_obj->ent.entry->flags |= PHAR_ENT_COMPRESSED_GZ;
RETURN_TRUE;
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0) {
if (!PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with bzip2 compression, file is already compressed with gzip compression and zlib extension is not enabled, cannot decompress");
return;
}
+
/* decompress this file indirectly */
if (SUCCESS != phar_open_entry_fp(entry_obj->ent.entry, &error, 1 TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
return;
}
}
+
if (!PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with bzip2 compression, bz2 extension is not enabled");
entry_obj->ent.entry->phar->is_modified = 1;
entry_obj->ent.entry->is_modified = 1;
-
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
+
RETURN_TRUE;
}
/* }}} */
"Phar entry is a directory, cannot set compression"); \
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) {
RETURN_TRUE;
return;
}
+
if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar is readonly, cannot decompress");
return;
}
+
if (entry_obj->ent.entry->is_deleted) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress deleted file");
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0 && !PHAR_G(has_zlib)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot decompress Gzip-compressed file, zlib extension is not enabled");
return;
}
+
if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0 && !PHAR_G(has_bz2)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot decompress Bzip2-compressed file, bz2 extension is not enabled");
return;
}
+
if (!entry_obj->ent.entry->fp) {
if (FAILURE == phar_open_archive_fp(entry_obj->ent.entry->phar TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot decompress entry \"%s\", phar error: Cannot open phar archive \"%s\" for reading", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
}
entry_obj->ent.entry->fp_type = PHAR_FP;
}
+
entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
entry_obj->ent.entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
entry_obj->ent.entry->phar->is_modified = 1;
entry_obj->ent.entry->is_modified = 1;
-
phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
+
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
+----------------------------------------------------------------------+
| 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 |
+----------------------------------------------------------------------+
| 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 |
+----------------------------------------------------------------------+
| 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 |
#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;
#define PHP_PHAR_API
#endif
-#endif /* PHP_PHAR_H */
+#endif /* PHP_PHAR_H */
/*
$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',
- );
-
- 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;
- }
+ 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");
+
+ $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 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]);
-
- if (strlen($m) < $L[1]) {
- die('ERROR: manifest length read was "' .
- strlen($m) .'" should be "' .
- $L[1] . '"');
- }
-
- $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::BZ2) {
- if (!function_exists('bzdecompress')) {
- die('Error: bzip2 extension is not enabled -' .
- ' bzdecompress() function needed for bz2-compressed .phars');
- }
- }
-
- $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;
- }
-
- $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__), '');
-
- 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);
- }
- }
- }
-
- chdir($temp);
-
- 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 _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;
- }
-
- 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);
- }
- }
-
- 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 ($entry[3] != sprintf("%u", crc32((binary)$data) & 0xffffffff)) {
- die("Invalid internal .phar file (checksum error)");
- }
-
- return $data;
- }
-
- 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());
- }
- }
- }
-
- @rmdir($temp);
- clearstatcache();
- chdir($origdir);
- }
+ 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)'';
+
+ 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] . '"');
+ }
+
+ $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::BZ2) {
+ if (!function_exists('bzdecompress')) {
+ die('Error: bzip2 extension is not enabled -' .
+ ' bzdecompress() function needed for bz2-compressed .phars');
+ }
+ }
+
+ $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;
+ }
+
+ $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__), '');
+
+ 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);
+ }
+ }
+ }
+
+ chdir($temp);
+
+ 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 _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;
+ }
+
+ 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);
+ }
+ }
+
+ 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 ($entry[3] != sprintf("%u", crc32((binary)$data) & 0xffffffff)) {
+ die("Invalid internal .phar file (checksum error)");
+ }
+
+ return $data;
+ }
+
+ 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());
+ }
+ }
+ }
+
+ @rmdir($temp);
+ clearstatcache();
+ chdir($origdir);
+ }
}
};
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 */
};
/**
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) {
php_url_free(resource);
return NULL;
}
- }
+ }
return resource;
}
/* }}} */
}
}
php_url_free(resource);
-
#if MBO_0
fprintf(stderr, "Pharname: %s\n", idata->phar->filename);
fprintf(stderr, "Filename: %s\n", internal_file);
{
phar_entry_data *data = (phar_entry_data *)stream->abstract;
size_t got;
-
+
if (data->internal_file->is_deleted) {
stream->eof = 1;
return 0;
data->position = php_stream_tell(data->fp) - data->zero;
stream->eof = (data->position == (off_t) data->internal_file->uncompressed_filesize);
-
return got;
}
/* }}} */
}
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;
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 */
}
}
}
-
free_resource:
php_url_free(resource);
return FAILURE;
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);
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);
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);
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);
}
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);
php_url_free(resource_from);
php_url_free(resource_to);
+
return 1;
}
/* }}} */
+----------------------------------------------------------------------+
| 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 |
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
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;
mentry->metadata = entry->metadata;
entry->metadata = NULL;
}
+
efree(metadata);
php_stream_seek(fp, save, SEEK_SET);
return SUCCESS;
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);
php_stream_close(fp);
return FAILURE;
}
+
hdr = (tar_header*)buf;
old = (memcmp(hdr->magic, "ustar", sizeof("ustar")-1) != 0);
entry.is_crc_checked = 1;
entry.phar = myphar;
pos += sizeof(buf);
+
do {
phar_entry_info *newentry;
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);
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];
} 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--;
} 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);
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 {
}
entry.link = NULL;
+
if (entry.tar_type == TAR_LINK) {
if (!zend_hash_exists(&myphar->manifest, hdr->linkname, strlen(hdr->linkname))) {
if (error) {
}
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) {
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 */
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)) {
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;
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);
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);
} else {
myphar->is_data = 1;
}
+
if (p) {
myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p);
if (myphar->ext == p) {
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);
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) {
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;
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;
}
/* }}} */
if (entry->is_mounted) {
return ZEND_HASH_APPLY_KEEP;
}
+
if (entry->is_deleted) {
if (entry->fp_refcount <= 0) {
return ZEND_HASH_APPLY_REMOVE;
}
memset((char *) &header, 0, sizeof(header));
+
if (entry->filename_len > 100) {
if (entry->filename_len > 255) {
if (fp->error) {
} 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);
/* 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 */
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) {
}
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 */
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;
}
/* }}} */
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);
}
return EOF;
}
+
if (phar->is_data) {
goto nostub;
}
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);
} 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);
}
}
return EOF;
}
+
len = pos - user_stub + 18;
entry.fp = php_stream_fopen_tmpfile();
entry.uncompressed_filesize = len + 5;
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);
}
}
}
}
-
nostub:
-
if (phar->fp && !phar->is_brandnew) {
oldfile = phar->fp;
closeoldfile = 0;
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");
}
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) {
}
}
}
+
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;
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();
# 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);
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);
}
phar->is_brandnew = 0;
-
php_stream_rewind(newfile);
if (phar->donotflush) {
}
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 */
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);
}
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);
return phar_get_efp(link_entry, 1 TSRMLS_CC);
}
}
+
if (phar_get_fp_type(entry TSRMLS_CC) == PHAR_FP) {
if (!phar_get_entrypfp(entry TSRMLS_CC)) {
/* re-open just in time for cases where our refcount reached 0 on the phar archive */
if (!fp) {
return -1;
}
+
if (follow_links) {
phar_entry_info *t;
t = phar_get_link_source(entry TSRMLS_CC);
entry = t;
}
}
+
if (entry->is_dir) {
return 0;
}
+
eoffset = phar_get_fp_offset(entry TSRMLS_CC);
+
switch (whence) {
- case SEEK_END :
+ case SEEK_END:
temp = eoffset + entry->uncompressed_filesize + offset;
break;
- case SEEK_CUR :
+ case SEEK_CUR:
temp = eoffset + position + offset;
break;
- case SEEK_SET :
+ case SEEK_SET:
temp = eoffset + offset;
break;
}
+
if (temp > eoffset + (off_t) entry->uncompressed_filesize) {
return -1;
}
+
if (temp < eoffset) {
return -1;
}
+
return php_stream_seek(fp, temp, SEEK_SET);
}
/* }}} */
filename_len = strlen(entry.tmp);
filename = entry.tmp;
+
/* only check openbasedir for files, not for phar streams */
if (!is_phar && php_check_open_basedir(filename TSRMLS_CC)) {
efree(entry.tmp);
efree(entry.filename);
return FAILURE;
}
+
entry.is_mounted = 1;
entry.is_crc_checked = 1;
entry.fp_type = PHAR_TMP;
efree(entry.filename);
return FAILURE;
}
+
if (ssb.sb.st_mode & S_IFDIR) {
entry.is_dir = 1;
if (SUCCESS != zend_hash_add(&phar->mounted_dirs, entry.filename, path_len, (void *)&(entry.filename), sizeof(char *), NULL)) {
entry.is_dir = 0;
entry.uncompressed_filesize = entry.compressed_filesize = ssb.sb.st_size;
}
+
entry.flags = ssb.sb.st_mode;
+
if (SUCCESS == zend_hash_add(&phar->manifest, entry.filename, path_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
return SUCCESS;
}
+
efree(entry.tmp);
efree(entry.filename);
return FAILURE;
if (!zend_is_executing(TSRMLS_C) || !PHAR_G(cwd)) {
return phar_save_resolve_path(filename, filename_len TSRMLS_CC);
}
+
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
if (pphar) {
*pphar = phar;
}
+
try_len = filename_len;
test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC);
+
if (*test == '/') {
if (zend_hash_exists(&(phar->manifest), test + 1, try_len - 1)) {
spprintf(&ret, 0, "phar://%s%s", arch, test);
}
efree(test);
}
+
spprintf(&path, MAXPATHLEN, "phar://%s/%s%c%s", arch, PHAR_G(cwd), DEFAULT_DIR_SEPARATOR, PG(include_path));
efree(arch);
ret = php_resolve_path(filename, filename_len, path TSRMLS_CC);
efree(path);
+
if (ret && strlen(ret) > 8 && !strncmp(ret, "phar://", 7)) {
char *arch;
int arch_len, ret_len;
if (SUCCESS != phar_split_fname(ret, ret_len, &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
return ret;
}
+
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);
+
if (!pphar && PHAR_G(manifest_cached)) {
zend_hash_find(&cached_phars, arch, arch_len, (void **) &pphar);
}
+
efree(arch);
efree(entry);
}
+
return ret;
#else /* PHP 5.2 */
char resolved_path[MAXPATHLEN];
if (!zend_is_executing(TSRMLS_C) || !PHAR_G(cwd)) {
goto doit;
}
+
fname = zend_get_executed_filename(TSRMLS_C);
+
if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
goto doit;
}
efree(entry);
+
if (*filename == '.') {
int try_len;
efree(arch);
goto doit;
}
+
try_len = filename_len;
test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC);
+
if (*test == '/') {
if (zend_hash_exists(&(phar->manifest), test + 1, try_len - 1)) {
spprintf(&ret, 0, "phar://%s%s", arch, test);
return ret;
}
}
+
efree(test);
}
- efree(arch);
+ efree(arch);
doit:
- if (*filename == '.' ||
- IS_ABSOLUTE_PATH(filename, filename_len) ||
- !path ||
- !*path) {
+ if (*filename == '.' || IS_ABSOLUTE_PATH(filename, filename_len) || !path || !*path) {
if (tsrm_realpath(filename, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
} else {
return NULL;
}
}
+
/* test for stream wrappers and return */
for (p = filename; p - filename < filename_len && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); ++p, ++n);
+
if (n < filename_len - 3 && (*p == ':') && (!strncmp("//", p+1, 2) || ( filename_len > 4 && !memcmp("data", filename, 4)))) {
/* found stream wrapper, this is an absolute path until stream wrappers implement realpath */
return estrndup(filename, filename_len);
maybe_stream = 0;
goto not_stream;
}
+
for (p = ptr, n = 0; p < end && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); ++p, ++n);
if (n == end - ptr && *p && !strncmp("//", p+1, 2)) {
ptr = end + 1;
continue;
}
+
memcpy(trypath, ptr, end-ptr);
len = end-ptr;
trypath[end-ptr] = '/';
if (len + 1 + filename_len + 1 >= MAXPATHLEN) {
break;
}
+
memcpy(trypath, ptr, len);
trypath[len] = '/';
memcpy(trypath+len+1, filename, filename_len+1);
if (wrapper == &php_stream_phar_wrapper) {
char *arch, *entry;
int arch_len, entry_len, ret_len;
-
+
ret_len = strlen(trypath);
/* found phar:// */
if (SUCCESS != phar_split_fname(trypath, ret_len, &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
return estrndup(trypath, ret_len);
}
+
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);
+
if (!pphar && PHAR_G(manifest_cached)) {
zend_hash_find(&cached_phars, arch, arch_len, (void **) &pphar);
}
+
efree(arch);
efree(entry);
+
return estrndup(trypath, ret_len);
}
return estrdup(trypath);
}
} /* end provided path */
- /* check in calling scripts' current working directory as a fall back case
- */
+ /* check in calling scripts' current working directory as a fall back case */
if (zend_is_executing(TSRMLS_C)) {
char *exec_fname = zend_get_executed_filename(TSRMLS_C);
int exec_fname_length = strlen(exec_fname);
int n = 0;
while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
- if (exec_fname && exec_fname[0] != '[' &&
- exec_fname_length > 0 &&
- exec_fname_length + 1 + filename_len + 1 < MAXPATHLEN) {
+ if (exec_fname && exec_fname[0] != '[' &&
+ exec_fname_length > 0 &&
+ exec_fname_length + 1 + filename_len + 1 < MAXPATHLEN) {
memcpy(trypath, exec_fname, exec_fname_length + 1);
memcpy(trypath+exec_fname_length + 1, filename, filename_len+1);
/* search for stream wrapper */
for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; ++p, ++n);
+
if (n < exec_fname_length - 3 && (*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4))) {
char *actual;
-
+
wrapper = php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
+
if (wrapper == &php_plain_files_wrapper) {
/* this should never technically happen, but we'll leave it here for completeness */
strncpy(trypath, actual, MAXPATHLEN);
} else if (!wrapper) {
- /* if wrapper is NULL, there was a mal-formed include_path stream wrapper
+ /* if wrapper is NULL, there was a malformed include_path stream wrapper
this also should be impossible */
return NULL;
} else {
return estrdup(trypath);
}
}
+
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
}
if (!ret) {
return FAILURE;
}
+
*ret = NULL;
+
if (error) {
*error = NULL;
}
+
if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) {
return FAILURE;
}
+
if (for_write && PHAR_G(readonly) && !phar->is_data) {
if (error) {
spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, fname);
}
return FAILURE;
}
+
if (!path_len) {
if (error) {
spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" cannot be empty", fname);
return FAILURE;
}
}
+
if (for_write && phar->is_persistent) {
if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
if (error) {
goto really_get_entry;
}
}
+
if (entry->is_modified && !for_write) {
if (error) {
spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, fname);
}
return FAILURE;
}
+
if (entry->fp_refcount && for_write) {
if (error) {
spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, fname);
}
return FAILURE;
}
+
if (entry->is_deleted) {
if (!for_create) {
return FAILURE;
}
entry->is_deleted = 0;
}
+
if (entry->is_dir) {
*ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
(*ret)->position = 0;
(*ret)->internal_file = entry;
(*ret)->is_zip = entry->is_zip;
(*ret)->is_tar = entry->is_tar;
+
if (!phar->is_persistent) {
++(entry->phar->refcount);
++(entry->fp_refcount);
}
+
return SUCCESS;
}
+
if (entry->fp_type == PHAR_MOD) {
if (for_trunc) {
if (FAILURE == phar_create_writeable_entry(phar, entry, error TSRMLS_CC)) {
entry->link = NULL;
entry->tar_type = (entry->tar_type ? TAR_FILE : 0);
}
+
if (for_write) {
if (for_trunc) {
if (FAILURE == phar_create_writeable_entry(phar, entry, error TSRMLS_CC)) {
}
}
}
+
*ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
(*ret)->position = 0;
(*ret)->phar = phar;
(*ret)->is_tar = entry->is_tar;
(*ret)->fp = phar_get_efp(entry, 1 TSRMLS_CC);
(*ret)->zero = phar_get_fp_offset(entry TSRMLS_CC);
+
if (!phar->is_persistent) {
++(entry->fp_refcount);
++(entry->phar->refcount);
}
+
return SUCCESS;
}
/* }}} */
etemp.filename_len = path_len;
etemp.fp_type = PHAR_MOD;
etemp.fp = php_stream_fopen_tmpfile();
+
if (!etemp.fp) {
if (error) {
spprintf(error, 0, "phar error: unable to create temporary file");
efree(ret);
return NULL;
}
+
etemp.fp_refcount = 1;
if (allow_dir == 2) {
} else {
etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_FILE;
}
+
phar_add_virtual_dirs(phar, path, path_len TSRMLS_CC);
etemp.is_modified = 1;
etemp.timestamp = time(0);
etemp.phar = phar;
etemp.filename = estrndup(path, path_len);
etemp.is_zip = phar->is_zip;
+
if (phar->is_tar) {
etemp.is_tar = phar->is_tar;
etemp.tar_type = TAR_FILE;
}
+
if (FAILURE == zend_hash_add(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info), (void **) &entry)) {
php_stream_close(etemp.fp);
if (error) {
efree(etemp.filename);
return NULL;
}
-
+
if (!entry) {
php_stream_close(etemp.fp);
efree(etemp.filename);
ret->is_zip = entry->is_zip;
ret->is_tar = entry->is_tar;
ret->internal_file = entry;
+
return ret;
}
/* }}} */
/* initialize a phar_archive_data's read-only fp for existing phar data */
-int phar_open_archive_fp(phar_archive_data *phar TSRMLS_DC) /* {{{ */
+int phar_open_archive_fp(phar_archive_data *phar TSRMLS_DC) /* {{{ */
{
if (phar_get_pharfp(phar TSRMLS_CC)) {
return SUCCESS;
}
-
#if PHP_MAJOR_VERSION < 6
if (PG(safe_mode) && (!php_checkuid(phar->fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
return FAILURE;
}
#endif
-
+
if (php_check_open_basedir(phar->fname TSRMLS_CC)) {
return FAILURE;
}
if (!phar_get_pharfp(phar TSRMLS_CC)) {
return FAILURE;
}
+
return SUCCESS;
}
/* }}} */
if (FAILURE == phar_open_entry_fp(source, error, 1 TSRMLS_CC)) {
return FAILURE;
}
+
if (dest->link) {
efree(dest->link);
dest->link = NULL;
dest->tar_type = (dest->tar_type ? TAR_FILE : 0);
}
+
dest->fp_type = PHAR_MOD;
dest->offset = 0;
dest->is_modified = 1;
dest->fp = php_stream_fopen_tmpfile();
-
phar_seek_efp(source, 0, SEEK_SET, 0, 1 TSRMLS_CC);
link = phar_get_link_source(source TSRMLS_CC);
+
if (!link) {
link = source;
}
+
if (link->uncompressed_filesize != php_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), dest->fp, link->uncompressed_filesize)) {
php_stream_close(dest->fp);
dest->fp_type = PHAR_FP;
}
return FAILURE;
}
+
return SUCCESS;
}
/* }}} */
/* open and decompress a compressed phar entry
*/
-int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links TSRMLS_DC) /* {{{ */
+int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links TSRMLS_DC) /* {{{ */
{
php_stream_filter *filter;
phar_archive_data *phar = entry->phar;
if (follow_links && entry->link) {
phar_entry_info *link_entry = phar_get_link_source(entry TSRMLS_CC);
-
if (link_entry && link_entry != entry) {
return phar_open_entry_fp(link_entry, error, 1 TSRMLS_CC);
}
}
+
if (entry->fp_type == PHAR_TMP) {
if (!entry->fp) {
entry->fp = php_stream_open_wrapper(entry->tmp, "rb", STREAM_MUST_SEEK|0, NULL);
}
return SUCCESS;
}
+
if (entry->fp_type != PHAR_FP) {
/* either newly created or already modified */
return SUCCESS;
}
+
if (!phar_get_pharfp(phar TSRMLS_CC)) {
if (FAILURE == phar_open_archive_fp(phar TSRMLS_CC)) {
spprintf(error, 4096, "phar error: Cannot open phar archive \"%s\" for reading", phar->fname);
return FAILURE;
}
}
+
if ((entry->old_flags && !(entry->old_flags & PHAR_ENT_COMPRESSION_MASK)) || !(entry->flags & PHAR_ENT_COMPRESSION_MASK)) {
return SUCCESS;
}
+
if (!phar_get_entrypufp(entry TSRMLS_CC)) {
phar_set_entrypufp(entry, php_stream_fopen_tmpfile() TSRMLS_CC);
if (!phar_get_entrypufp(entry TSRMLS_CC)) {
}
ufp = phar_get_entrypufp(entry TSRMLS_CC);
+
if ((filtername = phar_decompress_filter(entry, 0)) != NULL) {
filter = php_stream_filter_create(filtername, NULL, 0 TSRMLS_CC);
} else {
filter = NULL;
}
+
if (!filter) {
spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry->filename);
return FAILURE;
}
+
/* now we can safely use proper decompression */
/* save the new offset location within ufp */
php_stream_seek(ufp, 0, SEEK_END);
loc = php_stream_tell(ufp);
php_stream_filter_append(&ufp->writefilters, filter);
php_stream_seek(phar_get_entrypfp(entry TSRMLS_CC), phar_get_fp_offset(entry TSRMLS_CC), SEEK_SET);
+
if (php_stream_copy_to_stream(phar_get_entrypfp(entry TSRMLS_CC), ufp, entry->compressed_filesize) != entry->compressed_filesize) {
spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
return FAILURE;
}
+
php_stream_filter_flush(filter, 1);
php_stream_flush(ufp);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
+
if (php_stream_tell(ufp) - loc != (off_t) entry->uncompressed_filesize) {
spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
return FAILURE;
}
entry->old_flags = entry->flags;
+
/* this is now the new location of the file contents within this fp */
phar_set_fp_type(entry, PHAR_UFP, loc TSRMLS_CC);
-
return SUCCESS;
}
/* }}} */
entry->offset = 0;
return SUCCESS;
}
+
if (error) {
*error = NULL;
}
+
/* open a new temp file for writing */
if (entry->link) {
efree(entry->link);
entry->link = NULL;
entry->tar_type = (entry->tar_type ? TAR_FILE : 0);
}
+
entry->fp = php_stream_fopen_tmpfile();
+
if (!entry->fp) {
if (error) {
spprintf(error, 0, "phar error: unable to create temporary file");
}
return FAILURE;
}
+
entry->old_flags = entry->flags;
entry->is_modified = 1;
phar->is_modified = 1;
fp = php_stream_fopen_tmpfile();
phar_seek_efp(entry, 0, SEEK_SET, 0, 1 TSRMLS_CC);
link = phar_get_link_source(entry TSRMLS_CC);
+
if (!link) {
link = entry;
}
+
if (link->uncompressed_filesize != php_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize)) {
if (error) {
spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname);
if (phar->refcount || phar->is_persistent) {
return FAILURE;
}
+
/* this archive has no open references, so emit an E_STRICT and remove it */
if (zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), phar->fname, phar->fname_len) != SUCCESS) {
return FAILURE;
}
+
/* invalidate phar cache */
PHAR_G(last_phar) = NULL;
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
+
return SUCCESS;
}
/* }}} */
if (error) {
*error = NULL;
}
+
*archive = NULL;
+
if (PHAR_G(last_phar) && fname_len == PHAR_G(last_phar_name_len) && !memcmp(fname, PHAR_G(last_phar_name), fname_len)) {
*archive = PHAR_G(last_phar);
if (alias && alias_len) {
+
if (!PHAR_G(last_phar)->is_temporary_alias && (alias_len != PHAR_G(last_phar)->alias_len || memcmp(PHAR_G(last_phar)->alias, alias, alias_len))) {
if (error) {
spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, PHAR_G(last_phar)->fname, fname);
*archive = NULL;
return FAILURE;
}
+
if (PHAR_G(last_phar)->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len, (void**)&fd_ptr)) {
zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len);
}
- zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&(*archive), sizeof(phar_archive_data*), NULL);
+
+ zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&(*archive), sizeof(phar_archive_data*), NULL);
PHAR_G(last_alias) = alias;
PHAR_G(last_alias_len) = alias_len;
}
+
return SUCCESS;
}
+
if (alias && alias_len && PHAR_G(last_phar) && alias_len == PHAR_G(last_alias_len) && !memcmp(alias, PHAR_G(last_alias), alias_len)) {
fd = PHAR_G(last_phar);
fd_ptr = &fd;
goto alias_success;
}
+
if (alias && alias_len) {
ahash = zend_inline_hash_func(alias, alias_len);
if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void**)&fd_ptr)) {
}
return FAILURE;
}
+
*archive = *fd_ptr;
fd = *fd_ptr;
PHAR_G(last_phar) = fd;
PHAR_G(last_phar_name_len) = fd->fname_len;
PHAR_G(last_alias) = alias;
PHAR_G(last_alias_len) = alias_len;
+
return SUCCESS;
}
+
if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_alias, alias, alias_len, ahash, (void **)&fd_ptr)) {
goto alias_success;
}
}
+
fhash = zend_inline_hash_func(fname, fname_len);
my_realpath = NULL;
save = fname;
save_len = fname_len;
+
if (fname && fname_len) {
if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, fhash, (void**)&fd_ptr)) {
*archive = *fd_ptr;
fd = *fd_ptr;
+
if (alias && alias_len) {
if (!fd->is_temporary_alias && (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len))) {
if (error) {
}
return FAILURE;
}
+
if (fd->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), fd->alias, fd->alias_len, (void**)&fd_ptr)) {
zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), fd->alias, fd->alias_len);
}
- zend_hash_quick_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void*)&fd, sizeof(phar_archive_data*), NULL);
+
+ zend_hash_quick_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void*)&fd, sizeof(phar_archive_data*), NULL);
}
+
PHAR_G(last_phar) = fd;
PHAR_G(last_phar_name) = fd->fname;
PHAR_G(last_phar_name_len) = fd->fname_len;
PHAR_G(last_alias) = fd->alias;
PHAR_G(last_alias_len) = fd->alias_len;
+
return SUCCESS;
}
+
if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_phars, fname, fname_len, fhash, (void**)&fd_ptr)) {
*archive = *fd_ptr;
fd = *fd_ptr;
+
/* this could be problematic - alias should never be different from manifest alias
for cached phars */
if (!fd->is_temporary_alias && alias && alias_len) {
return FAILURE;
}
}
+
PHAR_G(last_phar) = fd;
PHAR_G(last_phar_name) = fd->fname;
PHAR_G(last_phar_name_len) = fd->fname_len;
PHAR_G(last_alias) = fd->alias;
PHAR_G(last_alias_len) = fd->alias_len;
+
return SUCCESS;
}
+
if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_alias_map), save, save_len, fhash, (void**)&fd_ptr)) {
fd = *archive = *fd_ptr;
+
PHAR_G(last_phar) = fd;
PHAR_G(last_phar_name) = fd->fname;
PHAR_G(last_phar_name_len) = fd->fname_len;
PHAR_G(last_alias) = fd->alias;
PHAR_G(last_alias_len) = fd->alias_len;
+
return SUCCESS;
}
+
if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_alias, save, save_len, fhash, (void**)&fd_ptr)) {
fd = *archive = *fd_ptr;
+
PHAR_G(last_phar) = fd;
PHAR_G(last_phar_name) = fd->fname;
PHAR_G(last_phar_name_len) = fd->fname_len;
PHAR_G(last_alias) = fd->alias;
PHAR_G(last_alias_len) = fd->alias_len;
+
return SUCCESS;
}
/* not found, try converting \ to / */
my_realpath = expand_filepath(fname, my_realpath TSRMLS_CC);
+
if (my_realpath) {
fname_len = strlen(my_realpath);
fname = my_realpath;
phar_unixify_path_separators(fname, fname_len);
#endif
fhash = zend_inline_hash_func(fname, fname_len);
+
if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, fhash, (void**)&fd_ptr)) {
realpath_success:
*archive = *fd_ptr;
fd = *fd_ptr;
+
if (alias && alias_len) {
- zend_hash_quick_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void*)&fd, sizeof(phar_archive_data*), NULL);
+ zend_hash_quick_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void*)&fd, sizeof(phar_archive_data*), NULL);
}
+
efree(my_realpath);
+
PHAR_G(last_phar) = fd;
PHAR_G(last_phar_name) = fd->fname;
PHAR_G(last_phar_name_len) = fd->fname_len;
PHAR_G(last_alias) = fd->alias;
PHAR_G(last_alias_len) = fd->alias_len;
+
return SUCCESS;
}
+
if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_phars, fname, fname_len, fhash, (void**)&fd_ptr)) {
goto realpath_success;
}
+
efree(my_realpath);
}
+
return FAILURE;
}
/* }}} */
} else {
flags = entry->flags;
}
+
switch (flags & PHAR_ENT_COMPRESSION_MASK) {
- case PHAR_ENT_COMPRESSED_GZ:
- return "zlib.inflate";
- case PHAR_ENT_COMPRESSED_BZ2:
- return "bzip2.decompress";
- default:
- return return_unknown ? "unknown" : NULL;
+ case PHAR_ENT_COMPRESSED_GZ:
+ return "zlib.inflate";
+ case PHAR_ENT_COMPRESSED_BZ2:
+ return "bzip2.decompress";
+ default:
+ return return_unknown ? "unknown" : NULL;
}
}
/* }}} */
}
return NULL;
}
+
if (!path_len && !dir) {
if (error) {
spprintf(error, 4096, "phar error: invalid path \"%s\" must not be empty", path);
}
return NULL;
}
+
if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
if (error) {
spprintf(error, 4096, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
if (!phar->manifest.arBuckets) {
return NULL;
}
+
if (is_dir) {
if (!path_len || path_len == 1) {
return NULL;
}
path_len--;
}
+
if (SUCCESS == zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) {
if (entry->is_deleted) {
/* entry is deleted, but has not been flushed to disk yet */
}
return entry;
}
+
if (dir) {
if (zend_hash_exists(&phar->virtual_dirs, path, path_len)) {
/* a file or directory exists in a sub-directory of this path */
return entry;
}
}
+
if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) {
phar_zstr key;
char *str_key;
}
return NULL;
}
+
if (!entry->tmp || !entry->is_mounted) {
if (error) {
spprintf(error, 4096, "phar internal error: mounted path \"%s\" is not properly initialized as a mounted path", str_key);
}
return NULL;
}
+
test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, path + keylen);
+
if (SUCCESS != php_stream_stat_path(test, &ssb)) {
efree(test);
return NULL;
}
+
if (ssb.sb.st_mode & S_IFDIR && !dir) {
efree(test);
if (error) {
}
return NULL;
}
+
if ((ssb.sb.st_mode & S_IFDIR) == 0 && dir) {
efree(test);
/* user requested a directory, we must return one */
}
return NULL;
}
+
/* mount the file just in time */
if (SUCCESS != phar_mount_entry(phar, test, test_len, path, path_len TSRMLS_CC)) {
efree(test);
}
return NULL;
}
+
efree(test);
+
if (SUCCESS != zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) {
if (error) {
spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be retrieved after being mounted", path, test);
}
}
}
+
return NULL;
}
/* }}} */
php_stream_rewind(fp);
Z_TYPE_P(zdata) = IS_STRING;
Z_STRLEN_P(zdata) = end;
+
if (end != (off_t) php_stream_copy_to_mem(fp, &(Z_STRVAL_P(zdata)), (size_t) end, 0)) {
zval_dtor(zdata);
zval_dtor(zsig);
zval_dtor(zkey);
return FAILURE;
}
-
#if PHP_VERSION_ID < 50300
if (FAILURE == zend_fcall_info_init(openssl, &fci, &fcc TSRMLS_CC)) {
#else
efree(zsig);
return FAILURE;
}
+
zval_dtor(openssl);
efree(openssl);
-
#if PHP_VERSION_ID < 50300
--(zdata->refcount);
--(zsig->refcount);
efree(zdata);
zval_dtor(zkey);
efree(zkey);
+
switch (Z_TYPE_P(retval_ptr)) {
default:
- case IS_LONG :
+ case IS_LONG:
zval_dtor(zsig);
efree(zsig);
if (1 == Z_LVAL_P(retval_ptr)) {
}
efree(retval_ptr);
return FAILURE;
- case IS_BOOL :
+ case IS_BOOL:
efree(retval_ptr);
if (Z_BVAL_P(retval_ptr)) {
*signature = estrndup(Z_STRVAL_P(zsig), Z_STRLEN_P(zsig));
php_uint32 pubkey_len;
char *pubkey = NULL, *pfile;
php_stream *pfp;
-
#ifndef PHAR_HAVE_OPENSSL
if (!zend_hash_exists(&module_registry, "openssl", sizeof("openssl"))) {
if (error) {
spprintf(&pfile, 0, "%s.pubkey", fname);
pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
efree(pfile);
+
if (!pfp || !(pubkey_len = php_stream_copy_to_mem(pfp, &pubkey, PHP_STREAM_COPY_ALL, 0)) || !pubkey) {
if (error) {
spprintf(error, 0, "openssl public key could not be read");
}
return FAILURE;
}
+
php_stream_close(pfp);
#ifndef PHAR_HAVE_OPENSSL
tempsig = sig_len;
+
if (FAILURE == phar_call_openssl_signverify(0, fp, end_of_phar, pubkey, pubkey_len, &sig, &tempsig TSRMLS_CC)) {
if (pubkey) {
efree(pubkey);
}
+
if (error) {
spprintf(error, 0, "openssl signature could not be verified");
}
+
return FAILURE;
}
+
if (pubkey) {
efree(pubkey);
}
+
sig_len = tempsig;
#else
in = BIO_new_mem_buf(pubkey, pubkey_len);
+
if (NULL == in) {
efree(pubkey);
if (error) {
}
return FAILURE;
}
+
key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
BIO_free(in);
efree(pubkey);
+
if (NULL == key) {
if (error) {
spprintf(error, 0, "openssl signature could not be processed");
}
EVP_VerifyInit(&md_ctx, mdtype);
-
read_len = end_of_phar;
+
if (read_len > sizeof(buf)) {
read_size = sizeof(buf);
} else {
read_size = (int)read_len;
}
+
php_stream_seek(fp, 0, SEEK_SET);
+
while (read_size && (len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
EVP_VerifyUpdate (&md_ctx, buf, len);
read_len -= (off_t)len;
+
if (read_len < read_size) {
read_size = (int)read_len;
}
}
+
if (EVP_VerifyFinal(&md_ctx, (unsigned char *)sig, sig_len, key) != 1) {
/* 1: signature verified, 0: signature does not match, -1: failed signature operation */
EVP_MD_CTX_cleanup(&md_ctx);
+
if (error) {
spprintf(error, 0, "broken openssl signature");
}
+
return FAILURE;
}
+
EVP_MD_CTX_cleanup(&md_ctx);
#endif
-
+
*signature_len = phar_hex_str((const char*)sig, sig_len, signature TSRMLS_CC);
}
break;
#if HAVE_HASH_EXT
case PHAR_SIG_SHA512: {
unsigned char digest[64];
- PHP_SHA512_CTX context;
+ PHP_SHA512_CTX context;
PHP_SHA512Init(&context);
read_len = end_of_phar;
+
if (read_len > sizeof(buf)) {
read_size = sizeof(buf);
} else {
read_size = (int)read_len;
}
+
while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
PHP_SHA512Update(&context, buf, len);
read_len -= (off_t)len;
read_size = (int)read_len;
}
}
+
PHP_SHA512Final(digest, &context);
if (memcmp(digest, sig, sizeof(digest))) {
}
case PHAR_SIG_SHA256: {
unsigned char digest[32];
- PHP_SHA256_CTX context;
+ PHP_SHA256_CTX context;
PHP_SHA256Init(&context);
read_len = end_of_phar;
+
if (read_len > sizeof(buf)) {
read_size = sizeof(buf);
} else {
read_size = (int)read_len;
}
+
while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
PHP_SHA256Update(&context, buf, len);
read_len -= (off_t)len;
read_size = (int)read_len;
}
}
+
PHP_SHA256Final(digest, &context);
if (memcmp(digest, sig, sizeof(digest))) {
PHP_SHA1Init(&context);
read_len = end_of_phar;
+
if (read_len > sizeof(buf)) {
read_size = sizeof(buf);
} else {
read_size = (int)read_len;
}
+
while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
PHP_SHA1Update(&context, buf, len);
read_len -= (off_t)len;
read_size = (int)read_len;
}
}
+
PHP_SHA1Final(digest, &context);
if (memcmp(digest, sig, sizeof(digest))) {
PHP_MD5Init(&context);
read_len = end_of_phar;
+
if (read_len > sizeof(buf)) {
read_size = sizeof(buf);
} else {
read_size = (int)read_len;
}
+
while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
PHP_MD5Update(&context, buf, len);
read_len -= (off_t)len;
read_size = (int)read_len;
}
}
+
PHP_MD5Final(digest, &context);
if (memcmp(digest, sig, sizeof(digest))) {
#if HAVE_HASH_EXT
case PHAR_SIG_SHA512: {
unsigned char digest[64];
- PHP_SHA512_CTX context;
+ PHP_SHA512_CTX context;
PHP_SHA512Init(&context);
+
while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
PHP_SHA512Update(&context, buf, sig_len);
}
+
PHP_SHA512Final(digest, &context);
*signature = estrndup((char *) digest, 64);
*signature_length = 64;
case PHAR_SIG_SHA256: {
unsigned char digest[32];
PHP_SHA256_CTX context;
-
+
PHP_SHA256Init(&context);
+
while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
PHP_SHA256Update(&context, buf, sig_len);
}
+
PHP_SHA256Final(digest, &context);
*signature = estrndup((char *) digest, 32);
*signature_length = 32;
if (error) {
spprintf(error, 0, "unable to write to phar \"%s\" with requested hash type", phar->fname);
}
+
return FAILURE;
#endif
case PHAR_SIG_OPENSSL: {
}
return FAILURE;
}
- key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
+ key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
BIO_free(in);
+
if (!key) {
if (error) {
spprintf(error, 0, "unable to process private key");
siglen = EVP_PKEY_size(key);
sigbuf = emalloc(siglen + 1);
-
EVP_SignInit(&md_ctx, mdtype);
+
while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
EVP_SignUpdate(&md_ctx, buf, sig_len);
}
+
if (!EVP_SignFinal (&md_ctx, sigbuf,(unsigned int *)&siglen, key)) {
efree(sigbuf);
if (error) {
}
return FAILURE;
}
+
sigbuf[siglen] = '\0';
EVP_MD_CTX_cleanup(&md_ctx);
#else
sigbuf = NULL;
siglen = 0;
php_stream_seek(fp, 0, SEEK_END);
+
if (FAILURE == phar_call_openssl_signverify(1, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen TSRMLS_CC)) {
if (error) {
spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
PHP_SHA1_CTX context;
PHP_SHA1Init(&context);
+
while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
PHP_SHA1Update(&context, buf, sig_len);
}
+
PHP_SHA1Final(digest, &context);
*signature = estrndup((char *) digest, 20);
*signature_length = 20;
PHP_MD5_CTX context;
PHP_MD5Init(&context);
+
while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
PHP_MD5Update(&context, buf, sig_len);
}
+
PHP_MD5Final(digest, &context);
*signature = estrndup((char *) digest, 16);
*signature_length = 16;
break;
}
}
+
phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature TSRMLS_CC);
return SUCCESS;
}
TSRMLS_FETCH();
entry->phar = (phar_archive_data *)argument;
+
if (entry->link) {
entry->link = estrdup(entry->link);
}
+
if (entry->tmp) {
entry->tmp = estrdup(entry->tmp);
}
+
entry->metadata_str.c = 0;
entry->filename = estrndup(entry->filename, entry->filename_len);
entry->is_persistent = 0;
+
if (entry->metadata) {
if (entry->metadata_len) {
/* assume success, we would have failed before */
#else
Z_SET_REFCOUNT_P(entry->metadata, 1);
#endif
-
entry->metadata_str.c = NULL;
entry->metadata_str.len = 0;
}
fname = phar->fname;
phar->fname = estrndup(phar->fname, phar->fname_len);
phar->ext = phar->fname + (phar->ext - fname);
+
if (phar->alias) {
phar->alias = estrndup(phar->alias, phar->alias_len);
}
+
if (phar->signature) {
phar->signature = estrdup(phar->signature);
}
+
if (phar->metadata) {
/* assume success, we would have failed before */
if (phar->metadata_len) {
#endif
}
}
+
zend_hash_init(&newmanifest, sizeof(phar_entry_info),
zend_get_hash_value, destroy_phar_manifest_entry, 0);
zend_hash_copy(&newmanifest, &(*pphar)->manifest, NULL, NULL, sizeof(phar_entry_info));
/* invalidate phar cache */
PHAR_G(last_phar) = NULL;
PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
+
if (newpphar[0]->alias_len && FAILURE == zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), newpphar[0]->alias, newpphar[0]->alias_len, (void*)newpphar, sizeof(phar_archive_data*), NULL)) {
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), (*pphar)->fname, (*pphar)->fname_len);
return FAILURE;
}
+
*pphar = *newpphar;
return SUCCESS;
}
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;
}
/* }}} */
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
*/
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
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;
} else {
php_stream_seek(fp, 0, SEEK_SET);
}
+
if (!(read = php_stream_read(fp, buf, size))) {
php_stream_close(fp);
if (error) {
}
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));
}
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);
php_stream_close(fp);
return FAILURE;
}
+
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
mydata->is_persistent = PHAR_G(persist);
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);
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 */
} 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);
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) {
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);
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);
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--;
} 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)) {
}
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 */
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 */
} 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 {
/* 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;
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) {
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;
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;
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;
}
/* }}} */
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;
}
/* }}} */
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;
return ZEND_HASH_APPLY_KEEP;
}
}
+
memset(&local, 0, sizeof(local));
memset(¢ral, 0, sizeof(central));
memset(&perms, 0, sizeof(perms));
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;
}
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);
/* 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);
} 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;
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;
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) {
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;
}
/* }}} */
}
return EOF;
}
+
if (phar->is_data) {
goto nostub;
}
/* 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);
} 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)) {
}
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);
} else {
free_user_stub = 0;
}
+
if ((pos = strstr(user_stub, "__HALT_COMPILER();")) == NULL)
{
if (error) {
}
return EOF;
}
+
len = pos - user_stub + 18;
entry.fp = php_stream_fopen_tmpfile();
entry.uncompressed_filesize = len + 5;
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);
}
return EOF;
}
+
if (free_user_stub) {
efree(user_stub);
}
}
}
}
-
nostub:
-
if (phar->fp && !phar->is_brandnew) {
oldfile = phar->fp;
closeoldfile = 0;
/* save modified files to the zip */
pass.old = oldfile;
pass.filefp = php_stream_fopen_tmpfile();
+
if (!pass.filefp) {
if (closeoldfile) {
php_stream_close(oldfile);
}
return EOF;
}
+
pass.centralfp = php_stream_fopen_tmpfile();
+
if (!pass.centralfp) {
if (closeoldfile) {
php_stream_close(oldfile);
}
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);
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);
}
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) {
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) {
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);
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;