*/
#define NSAPI 1
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "php.h"
#include "php_variables.h"
#include "ext/standard/info.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
*/
#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
}
}
+
+/*******************/
+/* 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;
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;
}
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;
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;
/* 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 */
+ if (threads<1) {
+ threads=128; /* default for server */
+ }
#endif
tsrm_startup(threads, 1, 0, NULL);