thetaphi Thu May 29 08:27:39 2003 EDT Modified files: (Branch: PHP_4_3) /php4/sapi/nsapi nsapi.c Log: MFH: php.ini values in magnus/obj.conf; virtual() similar to apache;...
Index: php4/sapi/nsapi/nsapi.c diff -u php4/sapi/nsapi/nsapi.c:1.28.2.7 php4/sapi/nsapi/nsapi.c:1.28.2.8 --- php4/sapi/nsapi/nsapi.c:1.28.2.7 Wed May 21 05:34:15 2003 +++ php4/sapi/nsapi/nsapi.c Thu May 29 08:27:39 2003 @@ -17,13 +17,17 @@ +----------------------------------------------------------------------+ */ -/* $Id: nsapi.c,v 1.28.2.7 2003/05/21 09:34:15 zeev Exp $ */ +/* $Id: nsapi.c,v 1.28.2.8 2003/05/29 12:27:39 thetaphi Exp $ */ /* * PHP includes */ #define NSAPI 1 +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "php.h" #include "php_variables.h" #include "ext/standard/info.h" @@ -34,6 +38,12 @@ #include "php_version.h" #include "TSRM.h" #include "ext/standard/php_standard.h" +#include <sys/types.h> +#include <sys/stat.h> + +#ifndef RTLD_DEFAULT +#define RTLD_DEFAULT NULL +#endif /* * If neither XP_UNIX not XP_WIN32 is defined use PHP_WIN32 @@ -57,11 +67,6 @@ #include "base/util.h" /* is_mozilla, getline */ #include "frame/log.h" /* log_error */ -/* - * Timeout for net_read(). This should probably go into php.ini - */ -#define NSAPI_READ_TIMEOUT 60 /* 60 seconds */ - #define NSLS_D struct nsapi_request_context *request_context #define NSLS_DC , NSLS_D #define NSLS_C request_context @@ -144,6 +149,221 @@ } } + +/*******************/ +/* PHP module part */ +/*******************/ + +PHP_MINIT_FUNCTION(nsapi); +PHP_MSHUTDOWN_FUNCTION(nsapi); +PHP_RINIT_FUNCTION(nsapi); +PHP_RSHUTDOWN_FUNCTION(nsapi); +PHP_MINFO_FUNCTION(nsapi); + +PHP_FUNCTION(virtual); + +ZEND_BEGIN_MODULE_GLOBALS(nsapi) + long read_timeout; +ZEND_END_MODULE_GLOBALS(nsapi) + +ZEND_DECLARE_MODULE_GLOBALS(nsapi) + +#define NSAPI_G(v) TSRMG(nsapi_globals_id, zend_nsapi_globals *, v) + +/* compatibility with PHP4_3 */ +#if !defined(OnUpdateLong) +#define OnUpdateLong OnUpdateInt +#endif + +/* {{{ nsapi_functions[] + * + * Every user visible function must have an entry in nsapi_functions[]. + */ +function_entry nsapi_functions[] = { + PHP_FE(virtual, NULL) /* Make subrequest */ + {NULL, NULL, NULL} /* Must be the last line in nsapi_functions[] */ +}; +/* }}} */ + +/* {{{ nsapi_module_entry + */ +zend_module_entry nsapi_module_entry = { + STANDARD_MODULE_HEADER, + "nsapi", + nsapi_functions, + PHP_MINIT(nsapi), + PHP_MSHUTDOWN(nsapi), + NULL, + NULL, + PHP_MINFO(nsapi), + NO_VERSION_YET, + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +/* {{{ PHP_INI + */ +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("nsapi.read_timeout", "60", PHP_INI_ALL, OnUpdateLong, read_timeout, zend_nsapi_globals, nsapi_globals) +PHP_INI_END() +/* }}} */ + +/* newer servers hide this functions from the programmer so redefine the functions dynamically + thanks to Chris Elving from Sun for the function declarations */ + +int (NSAPI_PUBLIC *nsapi_servact_uri2path)(Session *, Request *) = NULL; +int (NSAPI_PUBLIC *nsapi_servact_pathchecks)(Session *, Request *) = NULL; +int (NSAPI_PUBLIC *nsapi_servact_fileinfo)(Session *, Request *) = NULL; +int (NSAPI_PUBLIC *nsapi_servact_service)(Session *, Request *) = NULL; + +/* {{{ php_nsapi_init_dynamic_symbols + */ +static void php_nsapi_init_dynamic_symbols(void) +{ +#if defined(servact_uri2path) && defined(servact_pathchecks) && defined(servact_fileinfo) && defined(servact_service) + /* use functions from nsapi.h if available */ + nsapi_servact_uri2path = &servact_uri2path; + nsapi_servact_pathchecks = &servact_pathchecks; + nsapi_servact_fileinfo = &servact_fileinfo; + nsapi_servact_service = &servact_service; +#elif !defined(PHP_WIN32) + /* find address of internal NSAPI functions */ + *(void **)(&nsapi_servact_uri2path) = DL_FETCH_SYMBOL(RTLD_DEFAULT, "INTservact_uri2path"); + *(void **)(&nsapi_servact_pathchecks) = DL_FETCH_SYMBOL(RTLD_DEFAULT, "INTservact_pathchecks"); + *(void **)(&nsapi_servact_fileinfo) = DL_FETCH_SYMBOL(RTLD_DEFAULT, "INTservact_fileinfo"); + *(void **)(&nsapi_servact_service) = DL_FETCH_SYMBOL(RTLD_DEFAULT, "INTservact_service"); + if (!(nsapi_servact_uri2path && nsapi_servact_pathchecks && nsapi_servact_fileinfo && nsapi_servact_service)) { + /* not found - could be cause they are undocumented */ + nsapi_servact_uri2path = NULL; + nsapi_servact_pathchecks = NULL; + nsapi_servact_fileinfo = NULL; + nsapi_servact_service = NULL; + } +#endif +} +/* }}} */ + +/* {{{ php_nsapi_init_globals + */ +static void php_nsapi_init_globals(zend_nsapi_globals *nsapi_globals) +{ + nsapi_globals->read_timeout = 60; +} +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(nsapi) +{ + php_nsapi_init_dynamic_symbols(); + ZEND_INIT_MODULE_GLOBALS(nsapi, php_nsapi_init_globals, NULL); + REGISTER_INI_ENTRIES(); + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(nsapi) +{ + UNREGISTER_INI_ENTRIES(); + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(nsapi) +{ + php_info_print_table_start(); + php_info_print_table_row(2, "NSAPI support", "enabled"); + php_info_print_table_row(2, "Server Software", system_version()); + php_info_print_table_row(2, "Sub-requests with virtual()", (nsapi_servact_service)?"enabled":"not supported on this platform" ); + php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); +} +/* }}} */ + +/* {{{ proto bool virtual(string filename) + Perform an NSAPI sub-request */ +/* This function is equivalent to <!--#include virtual...--> + * in SSI. It does an NSAPI sub-request. It is useful + * for including CGI scripts or .shtml files, or anything else + * that you'd parse through webserver. + */ +PHP_FUNCTION(virtual) +{ + pval **uri; + int rv; + char *value; + Request *rq; + nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &uri) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(uri); + + if (!nsapi_servact_service) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests not supported on this platform", (*uri)->value.str.val); + RETURN_FALSE; + } else { + php_end_ob_buffers(1 TSRMLS_CC); + php_header(); + + /* do the sub-request */ + /* thanks to Chris Elving from Sun for this code sniplet */ + if ((rq = request_restart_internal((*uri)->value.str.val, NULL)) == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Internal request creation failed", (*uri)->value.str.val); + RETURN_FALSE; + } + + /* insert host of current request to get page from same vhost */ + param_free(pblock_remove("host", rq->headers)); + if (value = pblock_findval("host", rc->rq->headers)) { + pblock_nvinsert("host", value, rq->headers); + } + + /* go through the normal request stages as given in obj.conf, + but leave out the logging/error section */ + do { + rv = (*nsapi_servact_uri2path)(rc->sn, rq); + if (rv != REQ_PROCEED) { + continue; + } + + rv = (*nsapi_servact_pathchecks)(rc->sn, rq); + if (rv != REQ_PROCEED) { + continue; + } + + rv = (*nsapi_servact_fileinfo)(rc->sn, rq); + if (rv != REQ_PROCEED) { + continue; + } + + rv = (*nsapi_servact_service)(rc->sn, rq); + } while (rv == REQ_RESTART); + + if (rq->status_num != 200) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - HTTP status code %d during subrequest", (*uri)->value.str.val, rq->status_num); + request_free(rq); + RETURN_FALSE; + } + + request_free(rq); + + RETURN_TRUE; + } +} +/* }}} */ + + +/*************/ +/* SAPI part */ +/*************/ + static int sapi_nsapi_ub_write(const char *str, unsigned int str_length TSRMLS_DC) { int retval; @@ -228,16 +448,6 @@ count_bytes = MIN(count_bytes, SG(request_info).content_length-rc->read_post_bytes); content_length = SG(request_info).content_length; -#if 0 - /* - * Determine the content-length. This will tell us the limit we can read. - */ - content_length_str = pblock_findval("content-length", rc->rq->headers); - if (content_length_str != NULL) { - content_length = strtol(content_length_str, 0, 0); - } -#endif - if (content_length <= 0) { return 0; } @@ -265,7 +475,7 @@ bytes_to_read = content_length; } - length = net_read(rc->sn->csd, read_ptr, bytes_to_read, NSAPI_READ_TIMEOUT); + length = net_read(rc->sn->csd, read_ptr, bytes_to_read, NSAPI_G(read_timeout)); if (length == IO_ERROR || length == IO_EOF) { break; @@ -323,6 +533,7 @@ *p = '_'; } } + buf[NS_BUF_SIZE]='\0'; php_register_variable(buf, entry->param->value, track_vars_array TSRMLS_CC); entry=entry->next; } @@ -376,19 +587,22 @@ /* Create full Request-URI */ if (value = pblock_findval("uri", rc->rq->reqpb)) { - snprintf(buf,NS_BUF_SIZE, "%s", value); + strncpy(buf, value, NS_BUF_SIZE); + buf[NS_BUF_SIZE]='\0'; if (value = pblock_findval("query", rc->rq->reqpb)) { p = strchr(buf, 0); snprintf(p, NS_BUF_SIZE-(p-buf), "?%s", value); + buf[NS_BUF_SIZE]='\0'; } php_register_variable("REQUEST_URI", buf, track_vars_array TSRMLS_CC); } /* Create Script-Name */ if (value = pblock_findval("uri", rc->rq->reqpb)) { - snprintf(buf,NS_BUF_SIZE, "%s", value); + strncpy(buf, value, NS_BUF_SIZE); + buf[NS_BUF_SIZE]='\0'; if (value = pblock_findval("path-info", rc->rq->vars)) { - buf[strlen(buf) - strlen(value)] = 0; + buf[strlen(buf) - strlen(value)] = '\0'; } php_register_variable("SCRIPT_NAME", buf, track_vars_array TSRMLS_CC); } @@ -404,7 +618,7 @@ static int php_nsapi_startup(sapi_module_struct *sapi_module) { - if (php_module_startup(sapi_module, NULL, 0)==FAILURE) { + if (php_module_startup(sapi_module, &nsapi_module_entry, 1)==FAILURE) { return FAILURE; } return SUCCESS; @@ -444,78 +658,27 @@ STANDARD_SAPI_MODULE_PROPERTIES }; - -static void nsapi_request_ctor(NSLS_D TSRMLS_DC) -{ - char *query_string = pblock_findval("query", NSG(rq)->reqpb); - char *uri = pblock_findval("uri", NSG(rq)->reqpb); - char *path_info = pblock_findval("path-info", NSG(rq)->vars); - char *request_method = pblock_findval("method", NSG(rq)->reqpb); - char *content_type = pblock_findval("content-type", NSG(rq)->headers); - char *content_length = pblock_findval("content-length", NSG(rq)->headers); - char *path_translated = pblock_findval("path", NSG(rq)->vars);; - -#if defined(NSAPI_DEBUG) - log_error(LOG_INFORM, "nsapi_request_ctor", NSG(sn), NSG(rq), - "query_string = %s, " - "uri = %s, " - "path_info = %s, " - "path_translated = %s, " - "request_method = %s, " - "content_type = %s, " - "content_length = %s", - query_string, - uri, - path_info, - path_translated, - request_method, - content_type, - content_length); -#endif - - SG(request_info).query_string = nsapi_strdup(query_string); - SG(request_info).request_uri = nsapi_strdup(uri); - SG(request_info).request_method = nsapi_strdup(request_method); - SG(request_info).path_translated = nsapi_strdup(path_translated); - SG(request_info).content_type = nsapi_strdup(content_type); - SG(request_info).content_length = (content_length == NULL) ? 0 : strtoul(content_length, 0, 0); - SG(sapi_headers).http_response_code = 200; -} - -static void nsapi_request_dtor(NSLS_D TSRMLS_DC) +static void nsapi_php_ini_entries(NSLS_D TSRMLS_DC) { - nsapi_free(SG(request_info).query_string); - nsapi_free(SG(request_info).request_uri); - nsapi_free(SG(request_info).request_method); - nsapi_free(SG(request_info).path_translated); - nsapi_free(SG(request_info).content_type); -} - -int nsapi_module_main(NSLS_D TSRMLS_DC) -{ - zend_file_handle file_handle; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return FAILURE; - } - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - -#if defined(NSAPI_DEBUG) - log_error(LOG_INFORM, "nsapi_module_main", NSG(sn), NSG(rq), "Parsing [%s]", SG(request_info).path_translated); -#endif - - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); - -#if defined(NSAPI_DEBUG) - log_error(LOG_INFORM, "nsapi_module_main", NSG(sn), NSG(rq), "PHP request finished Ok"); -#endif + struct pb_entry *entry; + register int i; - return SUCCESS; + for (i=0; i < NSG(pb)->hsize; i++) { + entry=NSG(pb)->ht[i]; + while (entry) { + /* exclude standard entries given to "Service" which should not go into ini entries */ + if (strcasecmp(entry->param->name,"fn") && strcasecmp(entry->param->name,"type") + && strcasecmp(entry->param->name,"method") && strcasecmp(entry->param->name,"directive")) { + /* change the ini entry */ + if (zend_alter_ini_entry(entry->param->name, strlen(entry->param->name)+1, + entry->param->value, strlen(entry->param->value), + PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME)==FAILURE) { + log_error(LOG_WARN, "php4_execute", NSG(sn), NSG(rq), "Cannot change php.ini key \"%s\" to \"%s\"", entry->param->name, entry->param->value); + } + } + entry=entry->next; + } + } } void NSAPI_PUBLIC php4_close(void *vparam) @@ -523,20 +686,45 @@ if (nsapi_sapi_module.shutdown) { nsapi_sapi_module.shutdown(&nsapi_sapi_module); } + + if (nsapi_sapi_module.php_ini_path_override) { + free(nsapi_sapi_module.php_ini_path_override); + } + tsrm_shutdown(); + + log_error(LOG_INFORM, "php4_close", NULL, NULL, "Shutdown PHP Module"); } int NSAPI_PUBLIC php4_init(pblock *pb, Session *sn, Request *rq) { php_core_globals *core_globals; + char *ini_path; + int threads=128; /* default for server */ + + /* fetch max threads from NSAPI and initialize TSRM with it */ +#if defined(pool_maxthreads) + threads=pool_maxthreads; + if (threads<1) { + threads=128; /* default for server */ + } +#endif + tsrm_startup(threads, 1, 0, NULL); - tsrm_startup(1, 1, 0, NULL); core_globals = ts_resource(core_globals_id); + /* look if php_ini parameter is given to php4_init */ + if (ini_path = pblock_findval("php_ini", pb)) { + nsapi_sapi_module.php_ini_path_override = strdup(ini_path); + } + + /* start SAPI */ sapi_startup(&nsapi_sapi_module); nsapi_sapi_module.startup(&nsapi_sapi_module); - log_error(LOG_INFORM, "php4_init", sn, rq, "Initialized PHP Module\n"); + daemon_atrestart(&php4_close, NULL); + + log_error(LOG_INFORM, "php4_init", sn, rq, "Initialized PHP Module (%d threads exspected)", threads); return REQ_PROCEED; } @@ -544,6 +732,17 @@ { int retval; nsapi_request_context *request_context; + zend_file_handle file_handle = {0}; + struct stat fst; + + char *query_string = pblock_findval("query", rq->reqpb); + char *uri = pblock_findval("uri", rq->reqpb); + char *path_info = pblock_findval("path-info", rq->vars); + char *request_method = pblock_findval("method", rq->reqpb); + char *content_type = pblock_findval("content-type", rq->headers); + char *content_length = pblock_findval("content-length", rq->headers); + char *path_translated = pblock_findval("path", rq->vars); + TSRMLS_FETCH(); request_context = (nsapi_request_context *)MALLOC(sizeof(nsapi_request_context)); @@ -553,14 +752,48 @@ request_context->read_post_bytes = 0; SG(server_context) = request_context; + SG(request_info).query_string = nsapi_strdup(query_string); + SG(request_info).request_uri = nsapi_strdup(uri); + SG(request_info).request_method = nsapi_strdup(request_method); + SG(request_info).path_translated = nsapi_strdup(path_translated); + SG(request_info).content_type = nsapi_strdup(content_type); + SG(request_info).content_length = (content_length == NULL) ? 0 : strtoul(content_length, 0, 0); + SG(sapi_headers).http_response_code = 200; - nsapi_request_ctor(NSLS_C TSRMLS_CC); - retval = nsapi_module_main(NSLS_C TSRMLS_CC); - nsapi_request_dtor(NSLS_C TSRMLS_CC); + nsapi_php_ini_entries(NSLS_C TSRMLS_CC); + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = SG(request_info).path_translated; + file_handle.free_filename = 0; + file_handle.opened_path = NULL; + + if (stat(SG(request_info).path_translated, &fst)==0 && S_ISREG(fst.st_mode)) { + if (php_request_startup(TSRMLS_C) == SUCCESS) { + php_execute_script(&file_handle TSRMLS_CC); + php_request_shutdown(NULL); + retval=REQ_PROCEED; + } else { + /* send 500 internal server error */ + log_error(LOG_WARN, "php4_execute", sn, rq, "Cannot prepare PHP engine!"); + protocol_status(sn, rq, 500, NULL); + retval=REQ_ABORTED; + } + } else { + /* send 404 because file not found */ + log_error(LOG_WARN, "php4_execute", sn, rq, "Cannot execute PHP script: %s", SG(request_info).path_translated); + protocol_status(sn, rq, 404, NULL); + retval=REQ_ABORTED; + } + + nsapi_free(SG(request_info).query_string); + nsapi_free(SG(request_info).request_uri); + nsapi_free(SG(request_info).request_method); + nsapi_free(SG(request_info).path_translated); + nsapi_free(SG(request_info).content_type); FREE(request_context); - return (retval == SUCCESS) ? REQ_PROCEED : REQ_EXIT; + return retval; } /*********************************************************
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php