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

Reply via email to