else
AC_MSG_RESULT([no])
fi
- PHP_NEW_EXTENSION(phar, phar.c phar_object.c phar_path_check.c $PHP_PHAR_SOURCES, $ext_shared)
+ PHP_NEW_EXTENSION(phar, tar.c phar.c phar_object.c phar_path_check.c $PHP_PHAR_SOURCES, $ext_shared)
PHP_ADD_BUILD_DIR($ext_builddir/lib, 1)
PHP_SUBST(PHAR_SHARED_LIBADD)
PHP_ADD_EXTENSION_DEP(phar, zlib, true)
/**
* destructor for the manifest hash, frees each file's entry
*/
-static void destroy_phar_manifest(void *pDest) /* {{{ */
+void destroy_phar_manifest(void *pDest) /* {{{ */
{
phar_entry_info *entry = (phar_entry_info *)pDest;
TSRMLS_FETCH();
entry->zip = 0;
}
#endif
+ if (entry->linkname) {
+ efree(entry->linkname);
+ entry->linkname = 0;
+ }
}
/* }}} */
entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info));
entry->is_dir = 1;
/* this next line tells PharFileInfo->__destruct() to efree the filename */
- entry->is_zip = 0;
+ entry->is_zip = entry->is_tar = 0;
entry->filename = (char *) estrndup(path, path_len + 1);
entry->filename_len = path_len;
return entry;
(*ret)->for_write = for_write;
(*ret)->internal_file = entry;
(*ret)->is_zip = entry->is_zip;
+ (*ret)->is_tar = entry->is_tar;
if (entry->fp) {
/* make a copy */
if (for_trunc) {
}
/* }}} */
-/* forward declaration */
-static int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
-
/**
* Create or open a phar for writing
*/
}
if (phar_open_loaded(fname, fname_len, alias, alias_len, options, pphar, 0 TSRMLS_CC) == SUCCESS) {
- if (!PHAR_G(readonly)) {
+ if (pphar && !PHAR_G(readonly)) {
(*pphar)->is_writeable = 1;
}
return SUCCESS;
/* assume zip-based phar */
return phar_open_or_create_zip(fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
}
+ if (ext_len >= sizeof(".phar.tar")-1 && !memcmp((void *) ext_str, (void *) ".phar.tar", sizeof(".phar.tar")-1)) {
+ /* assume tar-based phar */
+ return phar_open_or_create_tar(fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
+ }
}
return phar_create_or_parse_filename(fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
}
-static int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
+int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
{
phar_archive_data *mydata;
char *my_realpath;
php_stream_close(fp);
return phar_open_zipfile(fname, fname_len, alias, alias_len, pphar, error TSRMLS_CC);
}
+ if (got > 512) {
+ if (phar_is_tar(pos)) {
+ return phar_open_tarfile(fp, fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
+ }
+ }
}
if ((pos = strstr(buffer, token)) != NULL) {
halt_offset += (pos - buffer); /* no -tokenlen+tokenlen here */
char *pos_p = strstr(filename, ".phar.php");
char *pos_zi = strstr(filename, ".phar.zip");
char *pos_zi2 = strstr(filename, ".phar.zip.php");
+ char *pos_t = strstr(filename, ".phar.tar");
+ char *pos_t2 = strstr(filename, ".phar.tar.php");
char *pos_z = strstr(filename, ".phar.gz");
char *pos_b = strstr(filename, ".phar.bz2");
} else if (pos_zi) {
*ext_str = pos_zi;
*ext_len = 9;
+ } else if (pos_t2) {
+ *ext_str = pos_t2;
+ *ext_len = 13;
+ } else if (pos_t) {
+ *ext_str = pos_t;
+ *ext_len = 9;
} else if ((pos_p = strstr(filename, ".phar")) != NULL) {
*ext_str = pos_p;
*ext_len = 5;
entry = fname;
fname = arch;
fname_len = arch_len;
- if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &phar, 0 TSRMLS_CC) && phar && phar->is_zip) {
+ if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &phar, 0 TSRMLS_CC) && phar && (phar->is_zip || phar->is_tar)) {
efree(arch);
return SUCCESS;
}
return phar_zip_flush(archive, user_stub, len, error TSRMLS_CC);
}
#endif
+ if (archive->is_tar) {
+ return phar_tar_flush(archive, user_stub, len, error TSRMLS_CC);
+ }
if (archive->fp && !archive->is_brandnew) {
oldfile = archive->fp;
closeoldfile = 0;
}
goto skip_phar;
}
+ if (strstr(file_handle->filename, ".phar.tar") && !strstr(file_handle->filename, ":\\")) {
+ /* zip-based phar */
+ spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
+ file_handle->type = ZEND_HANDLE_FILENAME;
+ file_handle->free_filename = 1;
+ file_handle->filename = name;
+ if (file_handle->opened_path) {
+ efree(file_handle->opened_path);
+ }
+ goto skip_phar;
+ }
if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
char *arch, *entry;
int arch_len, entry_len;
php_info_print_table_row(2, "CVS revision", "$Revision$");
php_info_print_table_row(2, "Phar-based phar archives",
"enabled");
+ php_info_print_table_row(2, "Tar-based phar archives",
+ "enabled");
#if HAVE_PHAR_ZIP
php_info_print_table_row(2, "ZIP-based phar archives",
"enabled");
#include <time.h>
#include "php.h"
+#include "tar.h"
#include "php_ini.h"
#include "zend_constants.h"
#include "zend_execute.h"
int is_dir:1;
phar_archive_data *phar;
smart_str metadata_str;
+ /* tar-based phar file stuff */
+ int is_tar:1;
+ char *link; /* symbolic link to another file */
+ char tar_type;
/* zip-based phar file stuff */
int is_zip:1;
#if HAVE_PHAR_ZIP
int donotflush:1;
/* zip-based phar variables */
int is_zip:1;
+ /* tar-based phar variables */
+ int is_tar:1;
#if HAVE_PHAR_ZIP
struct zip *zip;
#endif
off_t zero;
int for_write:1;
int is_zip:1;
+ int is_tar:1;
phar_entry_info *internal_file;
} phar_entry_data;
int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
+int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
int phar_open_compiled_file(char *alias, int alias_len, char **error TSRMLS_DC);
phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, php_stream *fp,
char **error, int for_write TSRMLS_DC);
int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
+void destroy_phar_manifest(void *pDest);
+/* tar functions */
+int phar_is_tar(char *buf);
+int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
+int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC);
+int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
+int phar_tar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC);
#ifdef PHAR_MAIN
static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS);
entry = fname;
fname = arch;
fname_len = arch_len;
- if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &phar, 0 TSRMLS_CC) && phar && phar->is_zip) {
+ if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &phar, 0 TSRMLS_CC) && phar && (phar->is_zip || phar->is_tar)) {
efree(arch);
fname = phar->fname;
fname_len = phar->fname_len;
if (PHAR_G(readonly)) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "Cannot change stub, phar is read-only");
+ "Cannot set signature algorithm, phar is read-only");
+ }
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot set signature algorithm, not possible with tar-based phar archives");
}
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "l", &algo) != SUCCESS) {
#endif
PHAR_ARCHIVE_OBJECT();
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot compress all files as Gzip, not possible with tar-based phar archives");
+ }
if (PHAR_G(readonly)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar is readonly, cannot change compression");
#endif
PHAR_ARCHIVE_OBJECT();
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot compress all files as Bzip2, not possible with tar-based phar archives");
+ }
+ if (phar_obj->arc.archive->is_zip) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot compress all files as Bzip2, not possible with zip-based phar archives");
+ }
+
if (PHAR_G(readonly)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Phar is readonly, cannot change compression");
newentry.fp = fp;
newentry.filename = estrndup(newfile, newfile_len);
newentry.filename_len = newfile_len;
+ if (oldentry->is_tar) {
+ newentry.tar_type = oldentry->tar_type;
+ }
phar_obj->arc.archive->is_modified = 1;
zend_hash_add(&phar_obj->arc.archive->manifest, newfile, newfile_len, (void*)&newentry, sizeof(phar_entry_info), NULL);
RETURN_STRINGL(buf, len, 0);
}
#endif
+ if (phar_obj->arc.archive->is_tar) {
+ phar_entry_info *stub;
+
+ if (SUCCESS == zend_hash_find(&(phar_obj->arc.archive->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
+ if (phar_obj->arc.archive->fp && !phar_obj->arc.archive->is_brandnew) {
+ fp = phar_obj->arc.archive->fp;
+ } else {
+ fp = php_stream_open_wrapper(phar_obj->arc.archive->fname, "rb", 0, NULL);
+ }
+
+ if (!fp) {
+ zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
+ "Unable to read stub");
+ return;
+ }
+
+ php_stream_seek(fp, stub->offset_within_phar, SEEK_SET);
+ len = stub->uncompressed_filesize;
+ goto carry_on;
+ } else {
+ RETURN_STRINGL("", 0, 0);
+ }
+ }
len = phar_obj->arc.archive->halt_offset;
if (phar_obj->arc.archive->fp && !phar_obj->arc.archive->is_brandnew) {
return;
}
- buf = safe_emalloc(len, 1, 1);
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);
zval *metadata;
PHAR_ARCHIVE_OBJECT();
+ if (phar_obj->arc.archive->is_tar) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot set metadata, not possible with tar-based phar archives");
+ }
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &metadata) == FAILURE) {
return;
}
PHAR_ENTRY_OBJECT();
if (entry_obj->ent.entry->is_dir) {
- if (!entry_obj->ent.entry->is_zip && entry_obj->ent.entry->filename) {
+ if (!entry_obj->ent.entry->is_zip && !entry_obj->ent.entry->is_tar && entry_obj->ent.entry->filename) {
efree(entry_obj->ent.entry->filename);
entry_obj->ent.entry->filename = NULL;
}
zval *metadata;
PHAR_ENTRY_OBJECT();
+ if (entry_obj->ent.entry->is_tar) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot set metadata, not possible with tar-based phar archives");
+ }
if (entry_obj->ent.entry->is_dir) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
"Phar entry is a directory, cannot set metadata"); \
char *error;
PHAR_ENTRY_OBJECT();
+ if (entry_obj->ent.entry->is_tar) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot compress with Gzip compression, not possible with tar-based phar archives");
+ }
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"); \
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with Bzip2 compression, not possible with zip-based phar archives");
}
+ if (entry_obj->ent.entry->is_tar) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
+ "Cannot compress with Bzip2 compression, not possible with tar-based phar archives");
+ }
if (!phar_has_bz2) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
"Cannot compress with Bzip2 compression, bz2 extension is not enabled");