summaryrefslogtreecommitdiff
path: root/sapi
diff options
context:
space:
mode:
authorAlex Leigh <aleigh@php.net>2003-12-08 16:54:18 +0000
committerAlex Leigh <aleigh@php.net>2003-12-08 16:54:18 +0000
commit862a7e589d9b4297ee7dd8d181749357b741daff (patch)
tree1e774c925d5d59be9714ae1a137beec68ae48cad /sapi
parent03f8baa87ed334e0b30d826e4643338f3b754e7f (diff)
downloadphp-git-862a7e589d9b4297ee7dd8d181749357b741daff.tar.gz
New SAPI module for Continuity HTTP server (ashpool.com)
Diffstat (limited to 'sapi')
-rw-r--r--sapi/continuity/CREDITS2
-rw-r--r--sapi/continuity/capi.c527
-rw-r--r--sapi/continuity/config.m435
3 files changed, 564 insertions, 0 deletions
diff --git a/sapi/continuity/CREDITS b/sapi/continuity/CREDITS
new file mode 100644
index 0000000000..12cab239c7
--- /dev/null
+++ b/sapi/continuity/CREDITS
@@ -0,0 +1,2 @@
+CAPI
+Alex Leigh
diff --git a/sapi/continuity/capi.c b/sapi/continuity/capi.c
new file mode 100644
index 0000000000..078ffc5d7b
--- /dev/null
+++ b/sapi/continuity/capi.c
@@ -0,0 +1,527 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2003 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Alex Leigh <aleigh at tessier dot com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* For more information on Continuity: http://www.ashpool.com/ */
+
+/*
+ * This code is based on the PHP4 SAPI module for NSAPI by Jayakumar
+ * Muthukumarasamy
+ */
+
+/* PHP includes */
+#define CONTINUITY 1
+#define CAPI_DEBUG
+
+/* Define for CDP specific extensions */
+#undef CONTINUITY_CDPEXT
+
+#include "php.h"
+#include "php_variables.h"
+#include "ext/standard/info.h"
+#include "php_ini.h"
+#include "php_globals.h"
+#include "SAPI.h"
+#include "php_main.h"
+#include "php_version.h"
+#include "TSRM.h"
+#include "ext/standard/php_standard.h"
+
+/*
+ * If neither XP_UNIX not XP_WIN32 is defined, try to guess which one.
+ * Ideally, this should be done by the configure script.
+ */
+#if !defined(XP_UNIX) && !defined(XP_WIN32)
+#if defined(WIN32)
+#define XP_WIN32
+#else
+#define XP_UNIX
+#endif
+#endif
+
+/*
+ * CAPI includes
+ */
+#include <continuity.h>
+#include <http.h>
+
+#define NSLS_D struct capi_request_context *request_context
+#define NSLS_DC , NSLS_D
+#define NSLS_C request_context
+#define NSLS_CC , NSLS_C
+#define NSG(v) (request_context->v)
+
+/*
+ * ZTS needs to be defined for CAPI to work
+ */
+#if !defined(ZTS)
+#error "CAPI module needs ZTS to be defined"
+#endif
+
+/*
+ * Structure to encapsulate the CAPI request in SAPI
+ */
+typedef struct capi_request_context {
+ httpTtrans *t;
+ int read_post_bytes;
+} capi_request_context;
+
+/**************/
+
+PHP_MINIT_FUNCTION(continuity);
+PHP_MSHUTDOWN_FUNCTION(continuity);
+PHP_RINIT_FUNCTION(continuity);
+PHP_RSHUTDOWN_FUNCTION(continuity);
+PHP_MINFO_FUNCTION(continuity);
+
+PHP_FUNCTION(continuity_virtual);
+PHP_FUNCTION(continuity_request_headers);
+PHP_FUNCTION(continuity_response_headers);
+
+function_entry continuity_functions[] = {
+ {NULL, NULL, NULL}
+};
+
+zend_module_entry continuity_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "continuity",
+ continuity_functions,
+ PHP_MINIT(continuity),
+ PHP_MSHUTDOWN(continuity),
+ NULL,
+ NULL,
+ PHP_MINFO(continuity),
+ "$Revision$",
+ STANDARD_MODULE_PROPERTIES
+};
+
+PHP_MINIT_FUNCTION(continuity)
+{
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(continuity)
+{
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(continuity)
+{
+ php_info_print_table_start();
+ php_info_print_table_row(2, "Continuity Module Version", continuity_module_entry.version);
+ php_info_print_table_row(2, "Server Version", conFget_build());
+#ifdef CONTINUITY_CDPEXT
+ php_info_print_table_row(2,"CDP Extensions", "enabled");
+#else
+ php_info_print_table_row(2,"CDP Extensions", "disabled");
+#endif
+ php_info_print_table_end();
+
+/* DISPLAY_INI_ENTRIES(); */
+}
+
+/**************/
+
+/*
+ * sapi_capi_ub_write: Write len bytes to the connection output.
+ */
+static int sapi_capi_ub_write(const char *str, unsigned int str_length TSRMLS_DC)
+{
+ int retval;
+ capi_request_context *rc;
+
+ rc = (capi_request_context *) SG(server_context);
+ retval = httpFwrite(rc->t, (char *) str, str_length);
+ if (retval == -1 || retval == 0)
+ php_handle_aborted_connection();
+ return retval;
+}
+
+/*
+ * sapi_capi_header_handler: Add/update response headers with those provided
+ * by the PHP engine.
+ */
+static int sapi_capi_header_handler(sapi_header_struct * sapi_header, sapi_headers_struct * sapi_headers TSRMLS_DC)
+{
+ char *header_name, *header_content, *p;
+ capi_request_context *rc = (capi_request_context *) SG(server_context);
+
+ lstFset_delete_key(rc->t->res_hdrs, "content-type");
+
+ header_name = sapi_header->header;
+ header_content = p = strchr(header_name, ':');
+ if (p == NULL) {
+ return 0;
+ }
+ *p = 0;
+ do {
+ header_content++;
+ } while (*header_content == ' ');
+
+ lstFset_add(rc->t->res_hdrs, header_name, header_content);
+
+ *p = ':'; /* restore '*p' */
+
+ efree(sapi_header->header);
+
+ return 0; /* don't use the default SAPI mechanism, CAPI
+ * duplicates this functionality */
+}
+
+/*
+ * sapi_capi_send_headers: Transmit the headers to the client. This has the
+ * effect of starting the response under Continuity.
+ */
+static int sapi_capi_send_headers(sapi_headers_struct * sapi_headers TSRMLS_DC)
+{
+ int retval;
+ capi_request_context *rc = (capi_request_context *) SG(server_context);
+
+ /*
+ * We could probably just do this in the header_handler. But, I don't know
+ * what the implication of doing it there is.
+ */
+
+ if (SG(sapi_headers).send_default_content_type) {
+ /* lstFset_delete_key(rc->t->res_hdrs, "content-type"); */
+ lstFset_update(rc->t->res_hdrs, "content-type", "text/html");
+ }
+ httpFset_status(rc->t, SG(sapi_headers).http_response_code, NULL);
+ httpFstart_response(rc->t);
+
+ return SAPI_HEADER_SENT_SUCCESSFULLY;
+
+}
+
+static int sapi_capi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
+{
+ unsigned int max_read, total_read = 0;
+ capi_request_context *rc = (capi_request_context *) SG(server_context);
+
+ if (rc->read_post_bytes == -1) {
+ max_read = MIN(count_bytes, SG(request_info).content_length);
+ } else {
+ if (rc->read_post_bytes == 0)
+ return 0;
+ max_read = MIN(count_bytes, (SG(request_info).content_length - rc->read_post_bytes));
+ }
+
+ total_read = httpFread(rc->t, buffer, max_read);
+
+ if (total_read < 0)
+ total_read = -1;
+ else
+ rc->read_post_bytes = total_read;
+
+ return total_read;
+}
+
+/*
+ * sapi_capi_read_cookies: Return cookie information into PHP.
+ */
+static char *sapi_capi_read_cookies(TSRMLS_D)
+{
+ char *cookie_string;
+ capi_request_context *rc = (capi_request_context *) SG(server_context);
+
+ cookie_string = lstFset_get(rc->t->req_hdrs, "cookie");
+ return cookie_string;
+}
+
+static void sapi_capi_register_server_variables(zval * track_vars_array TSRMLS_DC)
+{
+ capi_request_context *rc = (capi_request_context *) SG(server_context);
+ size_t i;
+ char *value;
+ char buf[128];
+
+ /* PHP_SELF and REQUEST_URI */
+ value = lstFset_get(rc->t->vars, "uri");
+ if (value != NULL) {
+ php_register_variable("PHP_SELF", value, track_vars_array TSRMLS_CC);
+ php_register_variable("REQUEST_URI", value, track_vars_array TSRMLS_CC);
+ }
+
+/* COUNTRY CODE */
+ value = lstFset_get(rc->t->vars, "ccode");
+ if(value!=NULL)
+ php_register_variable("COUNTRY_CODE", value, track_vars_array TSRMLS_CC);
+
+ /* argv */
+ value = lstFset_get(rc->t->vars, "query");
+ if (value != NULL)
+ php_register_variable("argv", value, track_vars_array TSRMLS_CC);
+
+ /* GATEWAY_INTERFACE */
+ php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC);
+
+ /* SERVER_NAME and HTTP_HOST */
+ value = lstFset_get(rc->t->req_hdrs, "host");
+ if (value != NULL) {
+ php_register_variable("HTTP_HOST", value, track_vars_array TSRMLS_CC);
+ /* TODO: This should probably scrub the port value if one is present. */
+ php_register_variable("SERVER_NAME", value, track_vars_array TSRMLS_CC);
+ }
+ /* SERVER_SOFTWARE */
+ value = lstFset_get(rc->t->res_hdrs, "server");
+ if (value != NULL)
+ php_register_variable("SERVER_SOFTWARE", value, track_vars_array TSRMLS_CC);
+
+ /* SERVER_PROTOCOL */
+ value = lstFset_get(rc->t->vars, "protocol");
+ if (value != NULL)
+ php_register_variable("SERVER_PROTOCOL", value, track_vars_array TSRMLS_CC);
+
+ /* REQUEST_METHOD */
+ value = lstFset_get(rc->t->vars, "method");
+ if (value != NULL)
+ php_register_variable("REQUEST_METHOD", value, track_vars_array TSRMLS_CC);
+
+ /* QUERY_STRING */
+ value = lstFset_get(rc->t->vars, "query");
+ if (value != NULL)
+ php_register_variable("QUERY_STRING", value, track_vars_array TSRMLS_CC);
+
+ /* DOCUMENT_ROOT */
+ value = lstFset_get(rc->t->vars, "docroot");
+ if (value != NULL)
+ php_register_variable("DOCUMENT_ROOT", value, track_vars_array TSRMLS_CC);
+
+ /* HTTP_ACCEPT */
+ value = lstFset_get(rc->t->req_hdrs, "accept");
+ if (value != NULL)
+ php_register_variable("HTTP_ACCEPT", value, track_vars_array TSRMLS_CC);
+
+ /* HTTP_ACCEPT_CHARSET */
+ value = lstFset_get(rc->t->req_hdrs, "accept-charset");
+ if (value != NULL)
+ php_register_variable("HTTP_ACCEPT_CHARSET", value, track_vars_array TSRMLS_CC);
+
+ /* HTTP_ACCEPT_ENCODING */
+ value = lstFset_get(rc->t->req_hdrs, "accept-encoding");
+ if (value != NULL)
+ php_register_variable("HTTP_ACCEPT_ENCODING", value, track_vars_array TSRMLS_CC);
+
+ /* HTTP_ACCEPT_LANGUAGE */
+ value = lstFset_get(rc->t->req_hdrs, "accept-language");
+ if (value != NULL)
+ php_register_variable("HTTP_ACCEPT_LANGUAGE", value, track_vars_array TSRMLS_CC);
+
+ /* HTTP_CONNECTION */
+ value = lstFset_get(rc->t->req_hdrs, "connection");
+ if (value != NULL)
+ php_register_variable("HTTP_CONNECTION", value, track_vars_array TSRMLS_CC);
+
+ /* HTTP_REFERER */
+ value = lstFset_get(rc->t->req_hdrs, "referer");
+ if (value != NULL)
+ php_register_variable("HTTP_REFERER", value, track_vars_array TSRMLS_CC);
+
+ /* HTTP_USER_AGENT */
+ value = lstFset_get(rc->t->req_hdrs, "user-agent");
+ if (value != NULL)
+ php_register_variable("HTTP_USER_AGENT", value, track_vars_array TSRMLS_CC);
+
+ /* REMOTE_ADDR */
+ utlFip_to_str(rc->t->cli_ipv4_addr, buf, sizeof(buf));
+ php_register_variable("REMOTE_ADDR", buf, track_vars_array TSRMLS_CC);
+
+ /* REMOTE_PORT */
+
+ /* SCRIPT_FILENAME and PATH_TRANSLATED */
+ value = lstFset_get(rc->t->vars, "path");
+ if (value != NULL) {
+ php_register_variable("SCRIPT_FILENAME", value, track_vars_array TSRMLS_CC);
+ php_register_variable("PATH_TRANSLATED", value, track_vars_array TSRMLS_CC);
+ }
+ /* SERVER_ADMIN */
+ /* Not applicable */
+
+ /* SERVER_PORT */
+
+}
+
+static void capi_log_message(char *message)
+{
+ TSRMLS_FETCH();
+ capi_request_context *rc = (capi_request_context *) SG(server_context);
+ logFmsg(0, "mod/php: %s", message);
+}
+
+static int php_capi_startup(sapi_module_struct *sapi_module);
+
+sapi_module_struct capi_sapi_module = {
+ "Continuity", /* name */
+ "Continuity Server Enterprise Edition", /* pretty name */
+
+ php_capi_startup, /* startup */
+ php_module_shutdown_wrapper, /* shutdown */
+
+ NULL, /* activate */
+ NULL, /* deactivate */
+
+ sapi_capi_ub_write, /* unbuffered write */
+ NULL, /* flush */
+ NULL, /* get uid */
+ NULL, /* getenv */
+
+ php_error, /* error handler */
+
+ sapi_capi_header_handler, /* header handler */
+ sapi_capi_send_headers, /* send headers handler */
+ NULL, /* send header handler */
+
+ sapi_capi_read_post, /* read POST data */
+ sapi_capi_read_cookies, /* read Cookies */
+
+ sapi_capi_register_server_variables, /* register server variables */
+ capi_log_message, /* Log message */
+
+ NULL, /* Block interruptions */
+ NULL, /* Unblock interruptions */
+
+ STANDARD_SAPI_MODULE_PROPERTIES
+};
+
+static int php_capi_startup(sapi_module_struct *sapi_module) {
+ if(php_module_startup(sapi_module,&continuity_module_entry,1)==FAILURE) {
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+
+static char *
+ capi_strdup(char *str)
+{
+ if (str != NULL)
+ return strFcopy(str);
+ return NULL;
+}
+
+static void capi_free(void *addr)
+{
+ if (addr != NULL)
+ free(addr);
+}
+
+static void capi_request_ctor(NSLS_D TSRMLS_DC)
+{
+ char *query_string = lstFset_get(NSG(t->vars), "query");
+ char *uri = lstFset_get(NSG(t->vars), "uri");
+ char *path_info = lstFset_get(NSG(t->vars), "path-info");
+ char *path_translated = lstFset_get(NSG(t->vars), "path");
+ char *request_method = lstFset_get(NSG(t->vars), "method");
+ char *content_type = lstFset_get(NSG(t->req_hdrs), "content-type");
+ char *content_length = lstFset_get(NSG(t->req_hdrs), "content-length");
+
+ SG(request_info).query_string = capi_strdup(query_string);
+ SG(request_info).request_uri = capi_strdup(uri);
+ SG(request_info).request_method = capi_strdup(request_method);
+ SG(request_info).path_translated = capi_strdup(path_translated);
+ SG(request_info).content_type = capi_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 capi_request_dtor(NSLS_D TSRMLS_DC)
+{
+ capi_free(SG(request_info).query_string);
+ capi_free(SG(request_info).request_uri);
+ capi_free(SG(request_info).request_method);
+ capi_free(SG(request_info).path_translated);
+ capi_free(SG(request_info).content_type);
+}
+
+int capi_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;
+
+ php_execute_script(&file_handle TSRMLS_CC);
+ php_request_shutdown(NULL);
+
+ return SUCCESS;
+}
+
+void php4_close(void *vparam)
+{
+ if (capi_sapi_module.shutdown) {
+ capi_sapi_module.shutdown(&capi_sapi_module);
+ }
+ tsrm_shutdown();
+}
+
+int phpFinit(lstTset * opt)
+{
+ php_core_globals *core_globals;
+
+ tsrm_startup(128, 1, 0, NULL);
+ core_globals = ts_resource(core_globals_id);
+
+ logFmsg(0, "mod/php: PHP Interface v3 (module)");
+ logFmsg(0, "mod/php: Copyright (c) 1999, 2000 The PHP Group. All rights reserved.");
+
+ sapi_startup(&capi_sapi_module);
+ capi_sapi_module.startup(&capi_sapi_module);
+
+ return STATUS_PROCEED;
+}
+
+int phpFservice(httpTtrans * t, lstTset * opts)
+{
+ int retval;
+ capi_request_context *request_context;
+
+ TSRMLS_FETCH();
+
+ request_context = (capi_request_context *) malloc(sizeof(capi_request_context));
+ request_context->t = t;
+ request_context->read_post_bytes = -1;
+
+ SG(server_context) = request_context;
+
+ capi_request_ctor(NSLS_C TSRMLS_CC);
+ retval = capi_module_main(NSLS_C TSRMLS_CC);
+ capi_request_dtor(NSLS_C TSRMLS_CC);
+
+ free(request_context);
+
+ /*
+ * This call is ostensibly provided to free the memory from PHP/TSRM when
+ * the thread terminated, but, it leaks a structure in some hash list
+ * according to the developers. Not calling this will leak the entire
+ * interpreter, around 100k, but calling it and then terminating the
+ * thread will leak the struct (around a k). The only answer with the
+ * current TSRM implementation is to reuse the threads that allocate TSRM
+ * resources.
+ */
+ /* ts_free_thread(); */
+
+ if (retval == SUCCESS) {
+ return STATUS_EXIT;
+ } else {
+ return STATUS_ERROR;
+ }
+}
diff --git a/sapi/continuity/config.m4 b/sapi/continuity/config.m4
new file mode 100644
index 0000000000..e95f2b4b22
--- /dev/null
+++ b/sapi/continuity/config.m4
@@ -0,0 +1,35 @@
+dnl ## $Id$ -*- sh -*-
+
+AC_MSG_CHECKING(for Continuity support)
+AC_ARG_WITH(continuity,
+[ --with-continuity=DIR Specify path to the installed Continuity Server],[
+ PHP_CONTINUITY=$withval
+],[
+ PHP_CONTINUITY=no
+])
+AC_MSG_RESULT($PHP_CONTINUITY)
+
+if test "$PHP_CONTINUITY" != "no"; then
+
+ if test ! -d $PHP_CONTINUITY; then
+ AC_MSG_ERROR(Please specify the path to the root of your Continuity server using --with-continuity=DIR)
+ fi
+ AC_MSG_CHECKING(for Continuity include files)
+ if test -d $PHP_CONTINUITY/include ; then
+ CAPI_INCLUDE=$PHP_CONTINUITY/include
+ AC_MSG_RESULT(Continuity Binary Distribution)
+ else
+ AC_MSG_ERROR(Cannot find your CAPI include files in either DIR/src or DIR/include)
+ fi
+
+ PHP_SELECT_SAPI(continuity,shared,capi.c)
+ PHP_ADD_INCLUDE($CAPI_INCLUDE)
+ PHP_BUILD_THREAD_SAFE
+ AC_DEFINE(HAVE_CONTINUITY,1,[Whether you have a Continuity Server])
+ INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$PHP_CONTINUITY/lib/"
+fi
+
+
+dnl ## Local Variables:
+dnl ## tab-width: 4
+dnl ## End: