cellog Sun Dec 23 21:12:41 2007 UTC Added files: /pecl/phar/tests frontcontroller2.phpt frontcontroller3.phpt
Modified files: /pecl/phar phar.c phar_internal.h phar_object.c /pecl/phar/tests frontcontroller1.phpt Log: 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]
http://cvs.php.net/viewvc.cgi/pecl/phar/phar.c?r1=1.234&r2=1.235&diff_format=u Index: pecl/phar/phar.c diff -u pecl/phar/phar.c:1.234 pecl/phar/phar.c:1.235 --- pecl/phar/phar.c:1.234 Sat Dec 22 07:46:52 2007 +++ pecl/phar/phar.c Sun Dec 23 21:12:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar.c,v 1.234 2007/12/22 07:46:52 cellog Exp $ */ +/* $Id: phar.c,v 1.235 2007/12/23 21:12:41 cellog Exp $ */ #define PHAR_MAIN #include "phar_internal.h" @@ -185,11 +185,6 @@ */ 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 @@ * 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ } 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; } @@ -4218,7 +4031,7 @@ php_info_print_table_header(2, "Phar: PHP Archive support", "enabled"); php_info_print_table_row(2, "Phar EXT version", PHAR_EXT_VERSION_STR); php_info_print_table_row(2, "Phar API version", PHAR_API_VERSION_STR); - php_info_print_table_row(2, "CVS revision", "$Revision: 1.234 $"); + php_info_print_table_row(2, "CVS revision", "$Revision: 1.235 $"); #if HAVE_ZLIB if (phar_has_zlib) { php_info_print_table_row(2, "gzip compression", http://cvs.php.net/viewvc.cgi/pecl/phar/phar_internal.h?r1=1.47&r2=1.48&diff_format=u Index: pecl/phar/phar_internal.h diff -u pecl/phar/phar_internal.h:1.47 pecl/phar/phar_internal.h:1.48 --- pecl/phar/phar_internal.h:1.47 Sat Dec 22 07:46:52 2007 +++ pecl/phar/phar_internal.h Sun Dec 23 21:12:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar_internal.h,v 1.47 2007/12/22 07:46:52 cellog Exp $ */ +/* $Id: phar_internal.h,v 1.48 2007/12/23 21:12:41 cellog Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -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 @@ 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 @@ 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 @@ #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 @@ 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); http://cvs.php.net/viewvc.cgi/pecl/phar/phar_object.c?r1=1.82&r2=1.83&diff_format=u Index: pecl/phar/phar_object.c diff -u pecl/phar/phar_object.c:1.82 pecl/phar/phar_object.c:1.83 --- pecl/phar/phar_object.c:1.82 Sat Dec 22 07:46:52 2007 +++ pecl/phar/phar_object.c Sun Dec 23 21:12:41 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar_object.c,v 1.82 2007/12/22 07:46:52 cellog Exp $ */ +/* $Id: phar_object.c,v 1.83 2007/12/23 21:12:41 cellog Exp $ */ #include "phar_internal.h" @@ -65,6 +65,301 @@ } /* }}} */ +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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) } /* }}} */ http://cvs.php.net/viewvc.cgi/pecl/phar/tests/frontcontroller1.phpt?r1=1.1&r2=1.2&diff_format=u Index: pecl/phar/tests/frontcontroller1.phpt diff -u pecl/phar/tests/frontcontroller1.phpt:1.1 pecl/phar/tests/frontcontroller1.phpt:1.2 --- pecl/phar/tests/frontcontroller1.phpt:1.1 Sat Dec 22 07:47:14 2007 +++ pecl/phar/tests/frontcontroller1.phpt Sun Dec 23 21:12:41 2007 @@ -9,20 +9,14 @@ <?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=== http://cvs.php.net/viewvc.cgi/pecl/phar/tests/frontcontroller2.phpt?view=markup&rev=1.1 Index: pecl/phar/tests/frontcontroller2.phpt +++ pecl/phar/tests/frontcontroller2.phpt --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 http://cvs.php.net/viewvc.cgi/pecl/phar/tests/frontcontroller3.phpt?view=markup&rev=1.1 Index: pecl/phar/tests/frontcontroller3.phpt +++ pecl/phar/tests/frontcontroller3.phpt --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"><?php </span><span style="color: #007700">function </span><span style="color: #0000BB">hio</span><span style="color: #007700">(){}</span> </span> </code>