complete re-factoring of front controller. Now it is done with

Phar->webPhar():
<?php
Phar::webPhar();
__HALT_COMPILER();

With the above stub, the default front controller will kick in.  An array of mime type overrides, and another
array mapping phar file entry -> redirected entry can be used to further customize
[DOC]
This commit is contained in:
Greg Beaver 2007-12-23 21:12:42 +00:00
parent d443c76bed
commit 02c7ff1343
6 changed files with 385 additions and 237 deletions

View file

@ -185,11 +185,6 @@ PHP_INI_END()
*/
static void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC) /* {{{ */
{
if (!PHAR_G(request_ends)) {
if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_web_map))) {
zend_hash_del(&(PHAR_GLOBALS->phar_web_map), data->fname, data->fname_len);
}
}
if (data->alias && data->alias != data->fname) {
efree(data->alias);
data->alias = NULL;
@ -504,7 +499,7 @@ static int phar_open_entry_file(phar_archive_data *phar, phar_entry_info *entry,
* appended, truncated, or read. For read, if the entry is marked unmodified, it is
* assumed that the file pointer, if present, is opened for reading
*/
static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */
int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */
{
phar_archive_data *phar;
phar_entry_info *entry;
@ -1334,13 +1329,6 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int
mydata->sig_len = sig_len;
mydata->signature = signature;
phar_request_initialize(TSRMLS_C);
if ((manifest_flags & PHAR_HDR_WEB) != 0) {
mydata->is_web = 1;
if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_mimes))) {
phar_init_mime_list(TSRMLS_C);
}
zend_hash_add(&(PHAR_GLOBALS->phar_web_map), mydata->fname, fname_len, (void*)&mydata, sizeof(void*), NULL);
}
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
if (register_alias) {
mydata->is_explicit_alias = 1;
@ -2780,13 +2768,8 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err
manifest_len = offset + archive->alias_len + sizeof(manifest) + main_metadata_str.len;
phar_set_32(manifest, manifest_len);
phar_set_32(manifest+4, new_manifest_count);
if (archive->is_web) {
*(manifest + 8) = (unsigned char) (((PHAR_API_VERSION_NOWEB) >> 8) & 0xFF);
*(manifest + 9) = (unsigned char) (((PHAR_API_VERSION_NOWEB) & 0xF0));
} else {
*(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF);
*(manifest + 9) = (unsigned char) (((PHAR_API_VERSION) & 0xF0));
}
*(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF);
*(manifest + 9) = (unsigned char) (((PHAR_API_VERSION) & 0xF0));
phar_set_32(manifest+10, global_flags);
phar_set_32(manifest+14, archive->alias_len);
@ -3867,159 +3850,6 @@ static void php_phar_init_globals_module(zend_phar_globals *phar_globals)
}
/* }}} */
static void phar_init_mime_list(TSRMLS_D)
{
phar_mime_type mime;
#define PHAR_SET_MIME(mimetype, ret, ...) \
mime.mime = mimetype; \
mime.len = sizeof((mimetype))+1; \
mime.type = ret; \
{ \
char mimes[][5] = {__VA_ARGS__, "\0"}; \
int i = 0; \
for (; mimes[i][0]; i++) { \
zend_hash_add(&(PHAR_GLOBALS->phar_mimes), mimes[i], strlen(mimes[i]), (void *)&mime, sizeof(phar_mime_type), NULL); \
} \
}
PHAR_SET_MIME("text/html", PHAR_MIME_PHPS, "phps")
PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "c", "cc", "cpp", "c++", "dtd", "h", "log", "rng", "txt", "xsd")
PHAR_SET_MIME("", PHAR_MIME_PHP, "php", "inc")
PHAR_SET_MIME("video/avi", PHAR_MIME_OTHER, "avi")
PHAR_SET_MIME("image/bmp", PHAR_MIME_OTHER, "bmp")
PHAR_SET_MIME("text/css", PHAR_MIME_OTHER, "css")
PHAR_SET_MIME("image/gif", PHAR_MIME_OTHER, "gif")
PHAR_SET_MIME("text/html", PHAR_MIME_OTHER, "htm", "html", "htmls")
PHAR_SET_MIME("image/x-ico", PHAR_MIME_OTHER, "ico")
PHAR_SET_MIME("image/jpeg", PHAR_MIME_OTHER, "jpe", "jpg", "jpeg")
PHAR_SET_MIME("application/x-javascript", PHAR_MIME_OTHER, "js")
PHAR_SET_MIME("audio/midi", PHAR_MIME_OTHER, "mid", "midi")
PHAR_SET_MIME("audio/mod", PHAR_MIME_OTHER, "mod")
PHAR_SET_MIME("movie/quicktime", PHAR_MIME_OTHER, "mov")
PHAR_SET_MIME("audio/mp3", PHAR_MIME_OTHER, "mp3")
PHAR_SET_MIME("video/mpeg", PHAR_MIME_OTHER, "mpg", "mpeg")
PHAR_SET_MIME("application/pdf", PHAR_MIME_OTHER, "pdf")
PHAR_SET_MIME("image/png", PHAR_MIME_OTHER, "png")
PHAR_SET_MIME("application/shockwave-flash", PHAR_MIME_OTHER, "swf")
PHAR_SET_MIME("image/tiff", PHAR_MIME_OTHER, "tif", "tiff")
PHAR_SET_MIME("audio/wav", PHAR_MIME_OTHER, "wav")
PHAR_SET_MIME("image/xbm", PHAR_MIME_OTHER, "xbm")
PHAR_SET_MIME("text/xml", PHAR_MIME_OTHER, "xml")
}
static int phar_file_type(char *file, char **mime_type TSRMLS_DC)
{
char *ext;
phar_mime_type *mime;
if (!mime_type) {
/* assume PHP */
return 0;
}
ext = strrchr(file, '.');
if (!ext) {
*mime_type = "text/plain";
/* no file extension = assume text/plain */
return PHAR_MIME_OTHER;
}
ext++;
if (SUCCESS != zend_hash_find(&(PHAR_GLOBALS->phar_mimes), ext, strlen(ext), (void **) &mime)) {
*mime_type = "application/octet-stream";
return PHAR_MIME_OTHER;
}
*mime_type = mime->mime;
return mime->type;
}
/* }}} */
static zend_op_array *phar_file_action(char *entry, int entry_len, char *arch, int arch_len, char **ourname TSRMLS_DC)
{
char *mime_type, *name = NULL, buf[8192], *error;
zend_syntax_highlighter_ini syntax_highlighter_ini;
sapi_header_line ctr = {0};
zend_op_array *nada;
zend_op *opline;
phar_entry_data *phar;
size_t got;
*ourname = name;
#define PHAR_NOP() \
nada = (zend_op_array *) emalloc(sizeof(zend_op_array)); \
init_op_array(nada, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); \
opline = get_next_op(nada TSRMLS_CC); \
opline->opcode = ZEND_RETURN; \
opline->op1.op_type = IS_CONST; \
INIT_ZVAL(opline->op1.u.constant); \
SET_UNUSED(opline->op2); \
ZEND_VM_SET_OPCODE_HANDLER(opline); \
nada->done_pass_two = 1; \
return nada;
switch (phar_file_type(entry, &mime_type TSRMLS_CC)) {
case PHAR_MIME_PHPS:
/* highlight source */
spprintf(&name, 4096, "phar://%s/%s", arch, entry);
efree(arch);
php_get_highlight_struct(&syntax_highlighter_ini);
if (highlight_file(name, &syntax_highlighter_ini TSRMLS_CC) == FAILURE) {
}
PHAR_NOP();
case PHAR_MIME_OTHER:
/* send headers, output file contents */
if (FAILURE == phar_get_entry_data(&phar, arch, arch_len, entry, entry_len, "r", &error TSRMLS_CC)) {
ctr.response_code = 404;
ctr.line_len = sizeof("HTTP/1.0 404")+1;
ctr.line = "HTTP/1.0 404";
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
PHAR_NOP();
}
ctr.line_len = spprintf(&(ctr.line), 0, "Content-type: %s", mime_type);
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
efree(ctr.line);
ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %d", phar->internal_file->uncompressed_filesize);
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
efree(ctr.line);
if (FAILURE == sapi_send_headers(TSRMLS_C)) {
phar_entry_delref(phar TSRMLS_CC);
zend_bailout();
}
/* prepare to output */
if (!phar->fp) {
phar->internal_file->fp_refcount++;
phar->fp = phar->phar->fp;
phar->zero = phar->phar->internal_file_start + phar->internal_file->offset_within_phar;
}
php_stream_seek(phar->fp, phar->position + phar->zero, SEEK_SET);
do {
if (!phar->zero) {
got = php_stream_read(phar->fp, buf, 8192);
PHPWRITE(buf, got);
if (phar->fp->eof) {
break;
}
} else {
got = php_stream_read(phar->fp, buf, MIN(8192, phar->internal_file->uncompressed_filesize - phar->position));
PHPWRITE(buf, got);
phar->position = php_stream_tell(phar->fp) - phar->zero;
if (phar->position == (off_t) phar->internal_file->uncompressed_filesize) {
break;
}
}
} while (1);
phar_entry_delref(phar TSRMLS_CC);
PHAR_NOP();
case PHAR_MIME_PHP:
/* fall through */
break;
}
return NULL;
}
static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) /* {{{ */
{
zend_op_array *res;
@ -4035,19 +3865,6 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type
int arch_len, entry_len;
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
/* check for web front controller phars */
if (zend_hash_exists(&(PHAR_GLOBALS->phar_web_map), fname, fname_len)) {
zend_op_array *retval;
if (strncasecmp(file_handle->filename, "phar://", 7)) {
goto skip_phar;
}
fname_len = strlen(file_handle->filename);
if (SUCCESS == phar_split_fname(file_handle->filename, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
if ((retval = phar_file_action(entry, entry_len, arch, arch_len, &name TSRMLS_CC))) {
return retval;
}
}
}
if (strncasecmp(fname, "phar://", 7)) {
goto skip_phar;
}
@ -4179,8 +3996,6 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */
PHAR_GLOBALS->request_done = 0;
zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_web_map), sizeof(void *), zend_get_hash_value, NULL, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_mimes), sizeof(phar_mime_type *), zend_get_hash_value, NULL, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_plain_map), sizeof(const char *), zend_get_hash_value, NULL, 0);
phar_split_extract_list(TSRMLS_C);
if (SUCCESS == zend_hash_find(CG(function_table), "fopen", 6, (void **)&orig)) {
@ -4202,8 +4017,6 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */
}
zend_hash_destroy(&(PHAR_GLOBALS->phar_alias_map));
zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map));
zend_hash_destroy(&(PHAR_GLOBALS->phar_web_map));
zend_hash_destroy(&(PHAR_GLOBALS->phar_mimes));
zend_hash_destroy(&(PHAR_GLOBALS->phar_plain_map));
PHAR_GLOBALS->request_init = 0;
}

View file

@ -36,6 +36,8 @@
#include "zend_vm.h"
#include "main/php_streams.h"
#include "main/streams/php_stream_plain_wrapper.h"
#include "main/SAPI.h"
#include "main/php_main.h"
#include "ext/standard/info.h"
#include "ext/standard/basic_functions.h"
#include "ext/standard/file.h"
@ -70,11 +72,9 @@
#endif
#define PHAR_EXT_VERSION_STR "1.3.0"
#define PHAR_API_VERSION_STR "1.2.0"
#define PHAR_API_VERSION_STR "1.1.0"
/* x.y.z maps to 0xyz0 */
#define PHAR_API_VERSION 0x1200
/* API version to use for is_web=0 in phar creation */
#define PHAR_API_VERSION_NOWEB 0x1100
#define PHAR_API_VERSION 0x1100
#define PHAR_API_MIN_READ 0x1000
#define PHAR_API_MAJORVERSION 0x1000
#define PHAR_API_MAJORVER_MASK 0xF000
@ -85,7 +85,6 @@
#define PHAR_HDR_COMPRESSED_GZ 0x00001000
#define PHAR_HDR_COMPRESSED_BZ2 0x00002000
#define PHAR_HDR_SIGNATURE 0x00010000
#define PHAR_HDR_WEB 0x00020000
#define PHAR_SIG_MD5 0x0001
#define PHAR_SIG_SHA1 0x0002
@ -113,10 +112,6 @@ ZEND_BEGIN_MODULE_GLOBALS(phar)
HashTable phar_fname_map;
HashTable phar_alias_map;
HashTable phar_plain_map;
/* phar archives that have is_web = 1, used for fast lookup in phar_compile_file */
HashTable phar_web_map;
/* mapping of file extension to MIME type */
HashTable phar_mimes;
char* extract_list;
int readonly;
zend_bool readonly_orig;
@ -210,8 +205,6 @@ struct _phar_archive_data {
int is_brandnew:1;
/* defer phar creation */
int donotflush:1;
/* this phar is intended to use a web front controller with non-CLI SAPI */
int is_web:1;
};
#define PHAR_MIME_PHP '\0'
@ -273,7 +266,6 @@ int phar_open_compiled_file(char *alias, int alias_len, char **error TSRMLS_DC);
#ifdef PHAR_MAIN
static void phar_init_mime_list(TSRMLS_D);
static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS);
static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
@ -309,6 +301,7 @@ int phar_entry_delref(phar_entry_data *idata TSRMLS_DC);
phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC);
phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error TSRMLS_DC);
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC);
int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC);
int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC);
int phar_detect_phar_fname_ext(const char *filename, int check_length, char **ext_str, int *ext_len);
int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);

View file

@ -65,6 +65,301 @@ PHP_METHOD(Phar, getExtractList)
}
/* }}} */
static int phar_file_type(HashTable *mimes, char *file, char **mime_type TSRMLS_DC)
{
char *ext;
phar_mime_type *mime;
if (!mime_type) {
/* assume PHP */
return 0;
}
ext = strrchr(file, '.');
if (!ext) {
*mime_type = "text/plain";
/* no file extension = assume text/plain */
return PHAR_MIME_OTHER;
}
ext++;
if (SUCCESS != zend_hash_find(mimes, ext, strlen(ext), (void **) &mime)) {
*mime_type = "application/octet-stream";
return PHAR_MIME_OTHER;
}
*mime_type = mime->mime;
return mime->type;
}
/* }}} */
static int phar_file_action(phar_entry_data *phar, char *mime_type, int code, char *entry, int entry_len, char *arch, int arch_len TSRMLS_DC)
{
char *name = NULL, buf[8192];
zend_syntax_highlighter_ini syntax_highlighter_ini;
sapi_header_line ctr = {0};
size_t got;
int dummy = 1, name_len, ret;
zend_file_handle file_handle;
zend_op_array *new_op_array;
zval *result = NULL;
switch (code) {
case PHAR_MIME_PHPS:
/* highlight source */
spprintf(&name, 4096, "phar://%s%s", arch, entry);
php_get_highlight_struct(&syntax_highlighter_ini);
if (highlight_file(name, &syntax_highlighter_ini TSRMLS_CC) == FAILURE) {
}
phar_entry_delref(phar TSRMLS_CC);
efree(name);
zend_bailout();
return PHAR_MIME_PHPS;
case PHAR_MIME_OTHER:
/* send headers, output file contents */
ctr.line_len = spprintf(&(ctr.line), 0, "Content-type: %s", mime_type);
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
efree(ctr.line);
ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %d", phar->internal_file->uncompressed_filesize);
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
efree(ctr.line);
if (FAILURE == sapi_send_headers(TSRMLS_C)) {
phar_entry_delref(phar TSRMLS_CC);
zend_bailout();
}
/* prepare to output */
if (!phar->fp) {
phar->internal_file->fp_refcount++;
phar->fp = phar->phar->fp;
phar->zero = phar->phar->internal_file_start + phar->internal_file->offset_within_phar;
phar->internal_file->fp = phar->phar->fp;
}
php_stream_seek(phar->fp, phar->position + phar->zero, SEEK_SET);
do {
if (!phar->zero) {
got = php_stream_read(phar->fp, buf, 8192);
PHPWRITE(buf, got);
if (phar->fp->eof) {
break;
}
} else {
got = php_stream_read(phar->fp, buf, MIN(8192, phar->internal_file->uncompressed_filesize - phar->position));
PHPWRITE(buf, got);
phar->position = php_stream_tell(phar->fp) - phar->zero;
if (phar->position == (off_t) phar->internal_file->uncompressed_filesize) {
break;
}
}
} while (1);
phar_entry_delref(phar TSRMLS_CC);
return PHAR_MIME_OTHER;
case PHAR_MIME_PHP:
phar_entry_delref(phar TSRMLS_CC);
name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
ret = php_stream_open_for_zend_ex(name, &file_handle, ENFORCE_SAFE_MODE|USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
if (ret != SUCCESS) {
efree(name);
return -1;
}
if (!file_handle.opened_path) {
file_handle.opened_path = estrndup(name, name_len);
}
if (zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) {
new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
new_op_array = NULL;
zend_file_handle_dtor(&file_handle);
}
if (new_op_array) {
EG(return_value_ptr_ptr) = &result;
EG(active_op_array) = new_op_array;
zend_execute(new_op_array TSRMLS_CC);
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
if (!EG(exception)) {
if (EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
}
efree(name);
zend_bailout();
}
return PHAR_MIME_PHP;
}
return -1;
}
/* {{{ proto void Phar::webPhar([string alias, [int dataoffset, [array mimetypes, [array redirects]]]])
* mapPhar for web-based phars. Reads the currently executed file (a phar)
* and registers its manifest.
*/
PHP_METHOD(Phar, webPhar)
{
HashTable mimetypes;
phar_mime_type mime;
zval *mimeoverride = NULL, *redirects = NULL;
char *alias = NULL, *error, *plain_map;
int alias_len = 0, ret;
long dataoffset;
char *fname, *basename, *path_info, *mime_type, *entry;
int fname_len, entry_len, code;
phar_entry_data *phar;
zval **_SERVER, **stuff;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!laa", &alias, &alias_len, &dataoffset, &mimeoverride, &redirects) == FAILURE) {
return;
}
phar_request_initialize(TSRMLS_C);
if (phar_open_compiled_file(alias, alias_len, &error TSRMLS_CC) != SUCCESS) {
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
return;
}
/* retrieve requested file within phar */
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;
}
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
basename = strrchr(fname, DEFAULT_SLASH);
if (!basename) {
basename = fname;
} else {
basename++;
}
path_info = SG(request_info).request_uri;
entry_len = strlen(path_info);
if (strstr(path_info, basename)) {
entry_len -= fname_len - (basename - fname) + 1;
entry = estrndup(path_info + (fname_len - (basename - fname) + 1), entry_len);
} else {
// error
}
/* "tweak" $_SERVER variables */
if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &_SERVER)) {
if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(_SERVER), "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &stuff)) {
zval *temp;
path_info = Z_STRVAL_PP(stuff);
code = Z_STRLEN_PP(stuff);
Z_STRVAL_PP(stuff) = entry;
Z_STRLEN_PP(stuff) = entry_len;
MAKE_STD_ZVAL(temp);
Z_TYPE_P(temp) = IS_STRING;
Z_STRVAL_P(temp) = path_info;
Z_STRLEN_P(temp) = code;
zend_hash_update(Z_ARRVAL_PP(_SERVER), "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME"), (void *) &temp, sizeof(zval **), NULL);
}
if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(_SERVER), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &stuff)) {
path_info = Z_STRVAL_PP(stuff);
Z_STRLEN_PP(stuff) = spprintf(&(Z_STRVAL_PP(stuff)), 4096, "phar://%s%s", fname, entry);
efree(path_info);
}
}
if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, entry, entry_len, "r", &error TSRMLS_CC)) {
sapi_header_line ctr = {0};
ctr.response_code = 404;
ctr.line_len = sizeof("HTTP/1.0 404")+1;
ctr.line = "HTTP/1.0 404";
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
return;
}
/* set up mime types */
zend_hash_init(&mimetypes, sizeof(phar_mime_type *), zend_get_hash_value, NULL, 0);
#define PHAR_SET_MIME(mimetype, ret, ...) \
mime.mime = mimetype; \
mime.len = sizeof((mimetype))+1; \
mime.type = ret; \
{ \
char mimes[][5] = {__VA_ARGS__, "\0"}; \
int i = 0; \
for (; mimes[i][0]; i++) { \
zend_hash_add(&mimetypes, mimes[i], strlen(mimes[i]), (void *)&mime, sizeof(phar_mime_type), NULL); \
} \
}
PHAR_SET_MIME("text/html", PHAR_MIME_PHPS, "phps")
PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "c", "cc", "cpp", "c++", "dtd", "h", "log", "rng", "txt", "xsd")
PHAR_SET_MIME("", PHAR_MIME_PHP, "php", "inc")
PHAR_SET_MIME("video/avi", PHAR_MIME_OTHER, "avi")
PHAR_SET_MIME("image/bmp", PHAR_MIME_OTHER, "bmp")
PHAR_SET_MIME("text/css", PHAR_MIME_OTHER, "css")
PHAR_SET_MIME("image/gif", PHAR_MIME_OTHER, "gif")
PHAR_SET_MIME("text/html", PHAR_MIME_OTHER, "htm", "html", "htmls")
PHAR_SET_MIME("image/x-ico", PHAR_MIME_OTHER, "ico")
PHAR_SET_MIME("image/jpeg", PHAR_MIME_OTHER, "jpe", "jpg", "jpeg")
PHAR_SET_MIME("application/x-javascript", PHAR_MIME_OTHER, "js")
PHAR_SET_MIME("audio/midi", PHAR_MIME_OTHER, "mid", "midi")
PHAR_SET_MIME("audio/mod", PHAR_MIME_OTHER, "mod")
PHAR_SET_MIME("movie/quicktime", PHAR_MIME_OTHER, "mov")
PHAR_SET_MIME("audio/mp3", PHAR_MIME_OTHER, "mp3")
PHAR_SET_MIME("video/mpeg", PHAR_MIME_OTHER, "mpg", "mpeg")
PHAR_SET_MIME("application/pdf", PHAR_MIME_OTHER, "pdf")
PHAR_SET_MIME("image/png", PHAR_MIME_OTHER, "png")
PHAR_SET_MIME("application/shockwave-flash", PHAR_MIME_OTHER, "swf")
PHAR_SET_MIME("image/tiff", PHAR_MIME_OTHER, "tif", "tiff")
PHAR_SET_MIME("audio/wav", PHAR_MIME_OTHER, "wav")
PHAR_SET_MIME("image/xbm", PHAR_MIME_OTHER, "xbm")
PHAR_SET_MIME("text/xml", PHAR_MIME_OTHER, "xml")
/* set up user overrides */
#define PHAR_SET_USER_MIME(ret) \
mime.mime = Z_STRVAL_P(val); \
mime.len = Z_STRLEN_P(val); \
mime.type = ret; \
zend_hash_update(&mimetypes, key, keylen, (void *)&mime, sizeof(phar_mime_type), NULL);
if (mimeoverride) {
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(mimeoverride)); zend_hash_has_more_elements(Z_ARRVAL_P(mimeoverride)); zend_hash_move_forward(Z_ARRVAL_P(mimeoverride))) {
zval *val;
char *key;
uint keylen;
ulong intkey;
if (HASH_KEY_IS_LONG == zend_hash_get_current_key_ex(Z_ARRVAL_P(mimeoverride), &key, &keylen, &intkey, 0, NULL)) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Key of MIME type overrides array must be a file extension, was \"%d\"", intkey);
RETURN_FALSE;
}
if (FAILURE == zend_hash_get_current_data(Z_ARRVAL_P(mimeoverride), (void **) &val)) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Failed to retrieve Mime type for extension \"%s\"", key);
RETURN_FALSE;
}
switch (Z_TYPE_P(val)) {
case IS_LONG :
if (Z_LVAL_P(val) == PHAR_MIME_PHP || Z_LVAL_P(val) == PHAR_MIME_PHPS) {
PHAR_SET_USER_MIME(Z_LVAL_P(val))
} else {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed");
RETURN_FALSE;
}
break;
case IS_STRING :
PHAR_SET_USER_MIME(PHAR_MIME_OTHER)
break;
default :
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed");
RETURN_FALSE;
}
}
}
code = phar_file_type(&mimetypes, entry, &mime_type TSRMLS_CC);
ret = phar_file_action(phar, mime_type, code, entry, entry_len, fname, fname_len TSRMLS_CC);
zend_hash_destroy(&mimetypes);
RETURN_LONG(ret);
}
/* {{{ proto mixed Phar::mapPhar([string alias, [int dataoffset]])
* Reads the currently executed file (a phar) and registers its manifest */
PHP_METHOD(Phar, mapPhar)
@ -342,31 +637,6 @@ PHP_METHOD(Phar, getSupportedCompression)
return; \
}
/* {{{ proto void Phar::useWebFrontController()
* This method is used in Phar creation to specify that this phar
* is intended to be executed as a self-contained website, and the
* built-in fast front controller should be used.
*/
PHP_METHOD(Phar, useWebFrontController)
{
char *error;
PHAR_ARCHIVE_OBJECT();
if (PHAR_G(readonly)) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Cannot specify use of default front controller, phar is read-only");
return;
}
phar_obj->arc.archive->is_web = 1;
phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC);
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
efree(error);
}
}
/* }}} */
static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC)
{
zval **value;
@ -1932,6 +2202,15 @@ ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mapPhar, 0, 0, 0)
ZEND_ARG_INFO(0, alias)
ZEND_ARG_INFO(0, offset)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_webPhar, 0, 0, 0)
ZEND_ARG_INFO(0, alias)
ZEND_ARG_INFO(0, offset)
ZEND_ARG_INFO(0, mimetypes)
ZEND_ARG_INFO(0, redirects)
ZEND_END_ARG_INFO();
static
@ -2007,7 +2286,6 @@ zend_function_entry php_archive_methods[] = {
PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
PHP_ME(Phar, uncompressAllFiles, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC)
PHP_ME(Phar, useWebFrontController, NULL, ZEND_ACC_PUBLIC)
#endif
/* static member functions */
PHP_ME(Phar, apiVersion, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
@ -2015,6 +2293,7 @@ zend_function_entry php_archive_methods[] = {
PHP_ME(Phar, canWrite, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, webPhar, arginfo_phar_webPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, getExtractList, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, getSupportedSignatures,NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, getSupportedCompression,NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
@ -2094,6 +2373,8 @@ void phar_object_init(TSRMLS_D) /* {{{ */
REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA256", PHAR_SIG_SHA256)
REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA512", PHAR_SIG_SHA512)
REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PGP", PHAR_SIG_PGP)
REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHP", PHAR_MIME_PHP)
REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHPS", PHAR_MIME_PHPS)
}
/* }}} */

View file

@ -9,20 +9,14 @@ phar.readonly=0
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
$pname = 'phar://' . $fname;
$file = '<?php echo "first stub\n"; __HALT_COMPILER(); ?>';
$files = array();
$gflags = 0x020000;
$files['a.jpg'] = 'hio';
include 'phar_test.inc';
$a = new Phar($fname);
$a['a.jpg'] = 'hio';
$a->setStub('<?php
Phar::mapPhar();
include "phar://" . __FILE__ . "/a.jpg";
Phar::webPhar();
__HALT_COMPILER();');
$_SERVER['REQUEST_URI'] = '/' . basename(__FILE__, '.php') . '.phar.php/a.jpg';
include $fname;
?>
===DONE===

View file

@ -0,0 +1,32 @@
--TEST--
Phar front controller php
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.require_hash=0
phar.readonly=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
$pname = 'phar://' . $fname;
$a = new Phar($fname);
$a['a.php'] = 'hio';
$a->setStub('<?php
Phar::webPhar();
__HALT_COMPILER();');
$_SERVER['REQUEST_URI'] = '/' . basename(__FILE__, '.php') . '.phar.php/a.php';
include $fname;
?>
===DONE===
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php');
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phartmp.php');
__HALT_COMPILER();
?>
--EXPECTHEADERS--
Content-type: text/html
--EXPECT--
hio

View file

@ -0,0 +1,35 @@
--TEST--
Phar front controller phps
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.require_hash=0
phar.readonly=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
$pname = 'phar://' . $fname;
$a = new Phar($fname);
$a['a.phps'] = '<?php function hio(){}';
$a->setStub('<?php
Phar::webPhar();
__HALT_COMPILER();');
$_SERVER['REQUEST_URI'] = '/' . basename(__FILE__, '.php') . '.phar.php/a.phps';
include $fname;
?>
===DONE===
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php');
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phartmp.php');
__HALT_COMPILER();
?>
--EXPECTHEADERS--
Content-type: text/html
--EXPECT--
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php&nbsp;</span><span style="color: #007700">function&nbsp;</span><span style="color: #0000BB">hio</span><span style="color: #007700">(){}</span>
</span>
</code>