diff options
| author | Stig Bakken <ssb@php.net> | 1999-09-27 16:34:28 +0000 |
|---|---|---|
| committer | Stig Bakken <ssb@php.net> | 1999-09-27 16:34:28 +0000 |
| commit | 2a854ca8b9e94ea75e949edb1283157b0daad617 (patch) | |
| tree | 6eafc28bd9403f91354068a364254bde5d9afc7a /sapi | |
| parent | 154663e9a2ee5310172886384a7c2a8598f66bc8 (diff) | |
| download | php-git-2a854ca8b9e94ea75e949edb1283157b0daad617.tar.gz | |
Generalized server-API build process on UNIX. Each SAPI
implementation now has its own directory under sapi/, just like
extensions have theirs under ext/. To make the final targets appear
in the main dir, the top-level Makefile includes sapi/NN/Makefile.inc
from the selected sapi backend. This is a plan Makefile stub without
any autoconf substitutions. Each SAPI backend also has its own
config.m4 like extensions (read at the end of diversion 2) and
config.h.stub files.
Each SAPI backend has to contain:
config.m4: just like for extensions, this file contains
autoconf/automake directives that end up in the configure script. The
only difference is that the sapi config.m4 files are read in diversion
(output block) 2 instead of 3. The sapi config.m4 files should set
two variables: PHP_SAPI (which sapi backend to choose) and SAPI_TARGET
(the name of the resulting library or program, previously BINNAME).
If they are not specified, they will default to "cgi" and "php",
respectively.
Makefile.inc: has to exist, has to define "INSTALL_IT" to the command
used to install the final target (or ":" for no operation). It also
has to define a plain Makefile rule (without autoconf substitutions)
to build $(SAPI_TARGET)
Makefile.am: just what you think. Make sure your target is called
"libphpsapi_NNN.a", where NNN is the value of PHP_SAPI.
Some testing and fixing probably remains. To make everything hang
together, I've done some ugly tricks that I can imagine causing some
problems. I've built and run the CGI version and built the Apache
DSO.
Diffstat (limited to 'sapi')
| -rw-r--r-- | sapi/Makefile.am | 14 | ||||
| -rw-r--r-- | sapi/aolserver/Makefile.am | 5 | ||||
| -rw-r--r-- | sapi/aolserver/Makefile.inc | 6 | ||||
| -rw-r--r-- | sapi/aolserver/aolserver.c | 343 | ||||
| -rw-r--r-- | sapi/aolserver/config.m4 | 26 | ||||
| -rw-r--r-- | sapi/apache/Makefile.am | 6 | ||||
| -rw-r--r-- | sapi/apache/Makefile.inc | 23 | ||||
| -rw-r--r-- | sapi/apache/config.h.stub | 0 | ||||
| -rw-r--r-- | sapi/apache/config.m4 | 190 | ||||
| -rw-r--r-- | sapi/apache/mod_php4.c | 651 | ||||
| -rw-r--r-- | sapi/apache/mod_php4.exp | 1 | ||||
| -rw-r--r-- | sapi/apache/mod_php4.h | 49 | ||||
| -rw-r--r-- | sapi/cgi/Makefile.am | 5 | ||||
| -rw-r--r-- | sapi/cgi/Makefile.inc | 6 | ||||
| -rw-r--r-- | sapi/cgi/cgi_main.c | 501 | ||||
| -rw-r--r-- | sapi/cgi/config.h.in | 0 | ||||
| -rw-r--r-- | sapi/cgi/config.m4 | 83 | ||||
| -rw-r--r-- | sapi/isapi/Makefile.am | 5 | ||||
| -rw-r--r-- | sapi/isapi/Makefile.inc | 6 | ||||
| -rw-r--r-- | sapi/isapi/config.m4 | 31 | ||||
| -rw-r--r-- | sapi/isapi/php4isapi.c | 464 | ||||
| -rw-r--r-- | sapi/isapi/php4isapi.def | 5 | ||||
| -rw-r--r-- | sapi/isapi/php4isapi.dsp | 106 | ||||
| -rw-r--r-- | sapi/nsapi/Makefile.am | 5 | ||||
| -rw-r--r-- | sapi/nsapi/Makefile.inc | 6 | ||||
| -rw-r--r-- | sapi/nsapi/aolserver.c | 343 | ||||
| -rw-r--r-- | sapi/nsapi/config.m4 | 26 |
27 files changed, 2906 insertions, 0 deletions
diff --git a/sapi/Makefile.am b/sapi/Makefile.am new file mode 100644 index 0000000000..bc9794a370 --- /dev/null +++ b/sapi/Makefile.am @@ -0,0 +1,14 @@ +## Process this file with automake to produce Makefile.in + +PHP_SAPI=@PHP_SAPI@ +PHP_SAPI_LIB=$(PHP_SAPI)/libphpsapi_$(PHP_SAPI).a +SUBDIRS = $(PHP_SAPI) + +noinst_LIBRARIES=libphpsapi.a + +libphpsapi.a: $(PHP_SAPI_LIB) + cp $(PHP_SAPI_LIB) $@ + @test "`uname -s`" = "Rhapsody" && $(RANLIB) $@ || exit 0 + +$(PHP_SAPI_LIB): + (cd $(PHP_SAPI); $(MAKE) libphpsapi_$(PHP_SAPI).a) diff --git a/sapi/aolserver/Makefile.am b/sapi/aolserver/Makefile.am new file mode 100644 index 0000000000..4a8edf6074 --- /dev/null +++ b/sapi/aolserver/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend +noinst_LIBRARIES=libphpsapi_nsapi.a +libphpsapi_nsapi_a_SOURCES=aolserver.c diff --git a/sapi/aolserver/Makefile.inc b/sapi/aolserver/Makefile.inc new file mode 100644 index 0000000000..6c56958bc8 --- /dev/null +++ b/sapi/aolserver/Makefile.inc @@ -0,0 +1,6 @@ +# NSAPI/AOLserver module + +INSTALL_IT=: + +php4_nsapi.so: libmodphp4-so.a + g++ $(LDFLAGS) -shared sapi/nsapi/aolserver.o -o $@ libmodphp4-so.a $(LIBS) diff --git a/sapi/aolserver/aolserver.c b/sapi/aolserver/aolserver.c new file mode 100644 index 0000000000..cbc4ec0257 --- /dev/null +++ b/sapi/aolserver/aolserver.c @@ -0,0 +1,343 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 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_0.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: Sascha Schumann <sascha@schumann.cx> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* conflict between PHP and aolserver */ +#define Debug php_Debug +#include "php.h" +#undef Debug + +#ifdef HAVE_AOLSERVER + +#include "php_ini.h" +#include "php_globals.h" +#include "SAPI.h" +#include "main.h" + +#include "ns.h" + +#include "php_version.h" + +int Ns_ModuleVersion = 1; + +#define NSLS_D ns_globals_struct *ns_context +#define NSLS_DC , NSLS_D +#define NSLS_C ns_context +#define NSLS_CC , NSLS_C +#define NSG(v) (ns_context->v) +#define NSLS_FETCH() ns_globals_struct *ns_context = ts_resource(ns_globals_id) + +static int ns_globals_id; + +typedef struct { + sapi_module_struct *sapi_module; + char *ns_server; + char *ns_module; +} php_ns_context; + +typedef struct { + Ns_Conn *conn; + Ns_DString content_type; +} ns_globals_struct; + +static void php_ns_config(php_ns_context *ctx); + +static int +php_ns_sapi_ub_write(const char *str, uint str_length) +{ + int sent_bytes; + NSLS_FETCH(); + + sent_bytes = Ns_ConnWrite(NSG(conn), (void *) str, str_length); + + return sent_bytes; +} + +static int +php_ns_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers SLS_DC) +{ + char *header_name, *header_content; + char *p; + NSLS_FETCH(); + + header_name = sapi_header->header; + header_content = p = strchr(header_name, ':'); + + if(!p) return 0; + + *p = '\0'; + do { + header_content++; + } while(*header_content == ' '); + + if(!strcasecmp(header_name, "Content-type")) { + Ns_ConnSetTypeHeader(NSG(conn), header_content); + } else { + Ns_ConnSetHeaders(NSG(conn), header_name, header_content); + } + + *p = ':'; + + efree(sapi_header->header); + + return 0; +} + +static int +php_ns_sapi_send_headers(sapi_headers_struct *sapi_headers SLS_DC) +{ + NSLS_FETCH(); + + if(SG(sapi_headers).send_default_content_type) { + Ns_ConnSetRequiredHeaders(NSG(conn), "text/html", 0); + } + Ns_ConnFlushHeaders(NSG(conn), SG(sapi_headers).http_response_code); + return SAPI_HEADER_SENT_SUCCESSFULLY; +} + +static int +php_ns_sapi_read_post(char *buf, uint count_bytes SLS_DC) +{ + uint total_read = 0; + NSLS_FETCH(); + + total_read = Ns_ConnRead(NSG(conn), buf, count_bytes); + + if(total_read == NS_ERROR) { + total_read = -1; + } + + return total_read; +} + +static char * +php_ns_sapi_read_cookies(SLS_D) +{ + int i; + char *http_cookie = NULL; + NSLS_FETCH(); + + i = Ns_SetFind(NSG(conn->headers), "cookie"); + if(i != -1) { + http_cookie = Ns_SetValue(NSG(conn->headers), i); + } + + return http_cookie; +} + +static sapi_module_struct sapi_module = { + "PHP Language", + + php_module_startup, /* startup */ + php_module_shutdown_wrapper, /* shutdown */ + + php_ns_sapi_ub_write, /* unbuffered write */ + + php_error, /* error handler */ + + php_ns_sapi_header_handler, /* header handler */ + php_ns_sapi_send_headers, /* send headers handler */ + NULL, /* send header handler */ + + php_ns_sapi_read_post, /* read POST data */ + php_ns_sapi_read_cookies, /* read Cookies */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + +static void +php_ns_hash_environment(NSLS_D CLS_DC ELS_DC PLS_DC SLS_DC) +{ + int i; + + for(i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) { + char *key = Ns_SetKey(NSG(conn->headers), i); + char *value = Ns_SetValue(NSG(conn->headers), i); + char *p; + zval *pval; + char buf[512]; + int buf_len; + + buf_len = snprintf(buf, 511, "HTTP_%s", key); + for(p = buf; *p; p++) { + *p = toupper(*p); + if(*p < 'A' || *p > 'Z') { + *p = '_'; + } + } + + MAKE_STD_ZVAL(pval); + pval->type = IS_STRING; + pval->value.str.len = strlen(value); + pval->value.str.val = estrndup(value, pval->value.str.len); + + zend_hash_update(&EG(symbol_table), buf, buf_len + 1, &pval, sizeof(zval *), NULL); + } +} + +static int +php_ns_module_main(NSLS_D SLS_DC) +{ + zend_file_handle file_handle; + CLS_FETCH(); + ELS_FETCH(); + PLS_FETCH(); + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = SG(request_info).path_translated; + + php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC); + php_ns_hash_environment(NSLS_C CLS_CC ELS_CC PLS_CC SLS_CC); + php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); + php_request_shutdown(NULL); + + return NS_OK; +} + +static void +php_ns_request_ctor(NSLS_D SLS_DC) +{ + char *server; + Ns_DString ds; + char *root; + + server = Ns_ConnServer(NSG(conn)); + + SG(request_info).query_string = NSG(conn->request->query); + + Ns_DStringInit(&ds); + Ns_UrlToFile(&ds, server, NSG(conn->request->url)); + SG(request_info).path_translated = strdup(Ns_DStringValue(&ds)); + Ns_DStringFree(&ds); + root = Ns_PageRoot(server); + SG(request_info).request_uri = SG(request_info).path_translated + strlen(root); + SG(request_info).request_method = NSG(conn)->request->method; + SG(request_info).content_length = Ns_ConnContentLength(NSG(conn)); + Ns_DStringInit(&NSG(content_type)); + Ns_ConnCopyToDString(NSG(conn), SG(request_info).content_length, &NSG(content_type)); + SG(request_info).content_type = Ns_DStringValue(&NSG(content_type)); + SG(request_info).auth_user = NULL; + SG(request_info).auth_password = NULL; +} + +static void +php_ns_request_dtor(NSLS_D SLS_DC) +{ + free(SG(request_info).path_translated); + Ns_DStringFree(&NSG(content_type)); +} + +static int +php_ns_request_handler(void *context, Ns_Conn *conn) +{ + int status = NS_OK; + SLS_FETCH(); + NSLS_FETCH(); + + NSG(conn) = conn; + + php_ns_request_ctor(NSLS_C SLS_CC); + + status = php_ns_module_main(NSLS_C SLS_CC); + + php_ns_request_dtor(NSLS_C SLS_CC); + + return status; +} + +static void +php_ns_config(php_ns_context *ctx) +{ + int i; + char *path; + Ns_Set *set; + + path = Ns_ConfigPath(ctx->ns_server, ctx->ns_module, NULL); + set = Ns_ConfigGetSection(path); + + for(i = 0; set && i < Ns_SetSize(set); i++) { + char *key = Ns_SetKey(set, i); + char *value = Ns_SetValue(set, i); + + if(!strcasecmp(key, "map")) { + Ns_Log(Notice, "Registering PHP for \"%s\"", value); + Ns_RegisterRequest(ctx->ns_server, "GET", value, php_ns_request_handler, NULL, ctx, 0); + Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0); + Ns_RegisterRequest(ctx->ns_server, "HEAD", value, php_ns_request_handler, NULL, ctx, 0); + } else if(!strcasecmp(key, "php_value")) { + char *val; + + val = strchr(value, ' '); + if(val) { + char *new_key; + + new_key = estrndup(value, val - value); + + do { + val++; + } while(*val == ' '); + + Ns_Log(Debug, "PHP configuration option '%s=%s'", new_key, val); + php_alter_ini_entry(new_key, strlen(new_key) + 1, val, + strlen(val) + 1, PHP_INI_SYSTEM); + + efree(new_key); + } + } + + } +} + +static void +php_ns_server_shutdown(void *context) +{ + php_ns_context *ctx = (php_ns_context *) context; + + ctx->sapi_module->shutdown(ctx->sapi_module); + sapi_shutdown(); + tsrm_shutdown(); + + free(ctx->ns_module); + free(ctx->ns_server); + free(ctx); +} + +int Ns_ModuleInit(char *server, char *module) +{ + php_ns_context *ctx; + + tsrm_startup(1, 1, 0); + sapi_startup(&sapi_module); + sapi_module.startup(&sapi_module); + + ns_globals_id = ts_allocate_id(sizeof(ns_globals_struct), NULL, NULL); + + ctx = malloc(sizeof *ctx); + ctx->sapi_module = &sapi_module; + ctx->ns_server = strdup(server); + ctx->ns_module = strdup(module); + + php_ns_config(ctx); + + Ns_RegisterServerShutdown(server, php_ns_server_shutdown, ctx); + + return NS_OK; +} + +#endif diff --git a/sapi/aolserver/config.m4 b/sapi/aolserver/config.m4 new file mode 100644 index 0000000000..854785df04 --- /dev/null +++ b/sapi/aolserver/config.m4 @@ -0,0 +1,26 @@ +dnl ## $Id$ -*- sh -*- + +RESULT=no +AC_MSG_CHECKING(for AOLserver support) +AC_ARG_WITH(aolserver, +[ --with-aolserver=DIR], +[ + if test ! -d $withval ; then + AC_MSG_ERROR(You did not specify a directory) + fi + if test "$enable_thread_safety" != "yes"; then + AC_MSG_ERROR(AOLserver must be compiled using --enable-thread-safety) + fi + NS_DIR=$withval + AC_ADD_INCLUDE($NS_DIR/include) + AC_DEFINE(HAVE_AOLSERVER) + PHP_SAPI=nsapi + SAPI_TARGET=php4_nsapi.so + INSTALL_IT="\$(SHELL) \$(srcdir)/install-sh -m 0755 $SAPI_TARGET $NS_DIR/root/bin/$SAPI_TARGET" + RESULT=yes +]) +AC_MSG_RESULT($RESULT) + +dnl ## Local Variables: +dnl ## tab-width: 4 +dnl ## End: diff --git a/sapi/apache/Makefile.am b/sapi/apache/Makefile.am new file mode 100644 index 0000000000..8661c36f80 --- /dev/null +++ b/sapi/apache/Makefile.am @@ -0,0 +1,6 @@ +## Process this file with automake to produce Makefile.in + +APACHE_INCLUDE=@APACHE_INCLUDE@ +INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend $(APACHE_INCLUDE) +noinst_LIBRARIES=libphpsapi_apache.a +libphpsapi_apache_a_SOURCES=mod_php4.c diff --git a/sapi/apache/Makefile.inc b/sapi/apache/Makefile.inc new file mode 100644 index 0000000000..8b62c74c35 --- /dev/null +++ b/sapi/apache/Makefile.inc @@ -0,0 +1,23 @@ +# -*- makefile -*- + +INSTALL_IT=$(APACHE_INSTALL) + +# Apache modules +libphp4.a libmodphp4.a: all-recursive $(OBJS) sapi/libphpsapi.a $(REGEX_LIB) + $(AR) $@.tmp $(OBJS) + $(srcdir)/scripts/armerge $@ $@.tmp \ + ext/libphpext.a libzend/libzend.a sapi/libphpsapi.a $(TSRM_LIB) + @rm -f $@.tmp + $(RANLIB) $(SAPI_TARGET) + +# Apache modules +libmodphp4-so.a: all-recursive $(OBJS) sapi/libphpsapi.a $(REGEX_LIB) + $(AR) $@.tmp $(OBJS) + $(srcdir)/scripts/armerge $@ $@.tmp \ + ext/libphpext.a libzend/libzend.a sapi/libphpsapi.a $(TSRM_LIB) + @rm -f $@.tmp + $(RANLIB) libmodphp4-so.a + +# Apache 1.3 shared module +libphp4.so: libmodphp4-so.a $(REGEX_LIB) + $(APXS) $(INCLUDE) -c -o libphp4.so $(VERSION_SCRIPT) $(RPATHS) sapi/apache/mod_php4.c libmodphp4-so.a $(APXS_LDFLAGS) $(APXS_EXP) diff --git a/sapi/apache/config.h.stub b/sapi/apache/config.h.stub new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/sapi/apache/config.h.stub diff --git a/sapi/apache/config.m4 b/sapi/apache/config.m4 new file mode 100644 index 0000000000..b1bd590ed2 --- /dev/null +++ b/sapi/apache/config.m4 @@ -0,0 +1,190 @@ +dnl ## -*- sh -*- + +divert(1) + +if test "`uname -sv`" = "AIX 4" -a "$GCC" != "yes"; then + APXS_EXP="-bE:sapi/apache/mod_php4.exp" +fi +AC_SUBST(APXS_EXP) + +divert(2) + +AC_MSG_CHECKING(for Apache module support via DSO through APXS) +AC_ARG_WITH(apxs, +[ --with-apxs[=FILE] Build shared Apache module. FILE is the optional + pathname to the Apache apxs tool; defaults to "apxs". + (This option needs Perl installed)], +[ + if test "$withval" = "yes"; then + withval=apxs + fi + AC_EXPAND_PATH($withval, APXS) + APXS_LDFLAGS="@SYBASE_LFLAGS@ @SYBASE_LIBS@ @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@" + APXS_INCLUDEDIR=`$APXS -q INCLUDEDIR` + if test -d "$APXS_INCLUDEDIR/xml" ; then + XML_INCLUDE="$APXS_INCLUDEDIR/xml" + fi + APACHE_INCLUDE="-I$APXS_INCLUDEDIR" + PHP_SAPI=apache + SAPI_TARGET=libphp4.so + APACHE_INSTALL="\$(APXS) -i -a -n php4 $SAPI_TARGET" + CFLAGS_SHLIB=`perl -V:cccdlflags | cut -d\' -f2` + LDFLAGS_SHLIB=`perl -V:lddlflags | cut -d\' -f2` + LDFLAGS_SHLIB_EXPORT=`perl -V:ccdlflags | cut -d\' -f2` + PHP_LIBS= + STRONGHOLD= + INCLUDES="$INCLUDES $APACHE_INCLUDE" + AC_DEFINE(APACHE) + AC_DEFINE(HAVE_AP_CONFIG_H) + AC_DEFINE(HAVE_AP_COMPAT_H) + AC_MSG_RESULT(yes) +],[ + AC_MSG_RESULT(no) +]) + +APACHE_INSTALL_FILES="$srcdir/mod_php4.* libphp4.module" + +if test "$SAPI_TARGET" != "libmodphp4-so.a"; then +if test "$SAPI_TARGET" != "libphp4.so"; then +AC_MSG_CHECKING(for Apache module support) +AC_ARG_WITH(apache, +[ --with-apache[=DIR] Build Apache module. DIR is the top-level Apache + build directory, defaults to /usr/local/etc/httpd.], +[ + if test "$withval" = "yes"; then + # Apache's default directory + withval=/usr/local/apache + fi + if test "$withval" != "no"; then + AC_EXPAND_PATH($withval, withval) + # For Apache 1.2.x + if test -f $withval/src/httpd.h; then + APACHE_INCLUDE=-I$withval/src + APACHE_TARGET=$withval/src + PHP_SAPI=apache + SAPI_TARGET=libphp4.a + APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_TARGET $APACHE_INSTALL_FILES $APACHE_TARGET" + PHP_LIBS="-L. -lphp3" + AC_DEFINE(APACHE) + AC_MSG_RESULT(yes - Apache 1.2.x) + STRONGHOLD= + if test -f $withval/src/ap_config.h; then + AC_DEFINE(HAVE_AP_CONFIG_H) + fi + # For Apache 1.3.x + elif test -f $withval/src/main/httpd.h; then + APACHE_INCLUDE="-I$withval/src/main -I$withval/src/os/unix -I$withval/src/ap" + APACHE_TARGET=$withval/src/modules/php4 + if test ! -d $APACHE_TARGET; then + mkdir $APACHE_TARGET + fi + PHP_SAPI=apache + SAPI_TARGET=libmodphp4.a + APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_TARGET $APACHE_INSTALL_FILES $APACHE_TARGET; cp $srcdir/apMakefile.tmpl $APACHE_TARGET/Makefile.tmpl; cp $srcdir/apMakefile.libdir $APACHE_TARGET/Makefile.libdir" + PHP_LIBS="-Lmodules/php4 -L../modules/php4 -L../../modules/php4 -lmodphp4" + AC_DEFINE(APACHE) + AC_MSG_RESULT(yes - Apache 1.3.x) + STRONGHOLD= + if test -f $withval/src/include/ap_config.h; then + AC_DEFINE(HAVE_AP_CONFIG_H) + fi + if test -f $withval/src/include/ap_compat.h; then + AC_DEFINE(HAVE_AP_COMPAT_H) + if test ! -f $withval/src/include/ap_config_auto.h; then + AC_MSG_ERROR(Please run Apache\'s configure or src/Configure program once and try again) + fi + else + if test -f $withval/src/include/compat.h; then + AC_DEFINE(HAVE_OLD_COMPAT_H) + fi + fi + # Also for Apache 1.3.x + elif test -f $withval/src/include/httpd.h; then + APACHE_INCLUDE="-I$withval/src/include -I$withval/src/os/unix" + APACHE_TARGET=$withval/src/modules/php4 + if test -d $withval/src/lib/expat-lite ; then + XML_INCLUDE=$withval/src/lib/expat-lite + fi + if test ! -d $APACHE_TARGET; then + mkdir $APACHE_TARGET + fi + PHP_SAPI=apache + SAPI_TARGET=libmodphp4.a + PHP_LIBS="-Lmodules/php4 -L../modules/php4 -L../../modules/php4 -lmodphp4" + APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_TARGET $APACHE_INSTALL_FILES $APACHE_TARGET; cp $srcdir/apMakefile.tmpl $APACHE_TARGET/Makefile.tmpl; cp $srcdir/apMakefile.libdir $APACHE_TARGET/Makefile.libdir" + AC_DEFINE(APACHE) + AC_MSG_RESULT(yes - Apache 1.3.x) + STRONGHOLD= + if test -f $withval/src/include/ap_config.h; then + AC_DEFINE(HAVE_AP_CONFIG_H) + fi + if test -f $withval/src/include/ap_compat.h; then + AC_DEFINE(HAVE_AP_COMPAT_H) + if test ! -f $withval/src/include/ap_config_auto.h; then + AC_MSG_ERROR(Please run Apache\'s configure or src/Configure program once and try again) + fi + else + if test -f $withval/src/include/compat.h; then + AC_DEFINE(HAVE_OLD_COMPAT_H) + fi + fi + # For StrongHold 2.2 + elif test -f $withval/apache/httpd.h; then + APACHE_INCLUDE=-"I$withval/apache -I$withval/ssl/include" + APACHE_TARGET=$withval/apache + PHP_SAPI=apache + SAPI_TARGET=libmodphp4.a + PHP_LIBS="-Lmodules/php4 -L../modules/php4 -L../../modules/php4 -lmodphp4" + APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_TARGET $APACHE_INSTALL_FILES $APACHE_TARGET" + STRONGHOLD=-DSTRONGHOLD=1 + AC_DEFINE(APACHE) + AC_MSG_RESULT(yes - StrongHold) + if test -f $withval/apache/ap_config.h; then + AC_DEFINE(HAVE_AP_CONFIG_H) + fi + if test -f $withval/src/ap_compat.h; then + AC_DEFINE(HAVE_AP_COMPAT_H) + if test ! -f $withval/src/include/ap_config_auto.h; then + AC_MSG_ERROR(Please run Apache\'s configure or src/Configure program once and try again) + fi + else + if test -f $withval/src/compat.h; then + AC_DEFINE(HAVE_OLD_COMPAT_H) + fi + fi + else + AC_MSG_RESULT(no) + AC_MSG_ERROR(Invalid Apache directory - unable to find httpd.h under $withval) + fi + else + AC_MSG_RESULT(no) + fi +],[ + AC_MSG_RESULT(no) +]) + +INCLUDES="$INCLUDES $APACHE_INCLUDE" +dnl## AC_SUBST(APACHE_INCLUDE) +fi +fi + +AC_SUBST(APACHE_INCLUDE) +AC_SUBST(APACHE_TARGET) +AC_SUBST(APXS) +AC_SUBST(APXS_LDFLAGS) +AC_SUBST(APACHE_INSTALL) +AC_SUBST(STRONGHOLD) + +AC_MSG_CHECKING(for mod_charset compatibility option) +AC_ARG_WITH(mod_charset, +[ --with-mod_charset Enable transfer tables for mod_charset (Rus Apache).], +[ + AC_MSG_RESULT(yes) + AC_DEFINE(USE_TRANSFER_TABLES) +],[ + AC_MSG_RESULT(no) +]) + +dnl ## Local Variables: +dnl ## tab-width: 4 +dnl ## End: diff --git a/sapi/apache/mod_php4.c b/sapi/apache/mod_php4.c new file mode 100644 index 0000000000..2f844738f6 --- /dev/null +++ b/sapi/apache/mod_php4.c @@ -0,0 +1,651 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 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_0.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. | + +----------------------------------------------------------------------+ + | Authors: Rasmus Lerdorf <rasmus@php.net> | + | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> | + | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> | + +----------------------------------------------------------------------+ + */ +/* $Id$ */ + +#include "httpd.h" +#include "http_config.h" +#if MODULE_MAGIC_NUMBER > 19980712 +# include "ap_compat.h" +#else +# if MODULE_MAGIC_NUMBER > 19980324 +# include "compat.h" +# endif +#endif +#include "http_core.h" +#include "http_main.h" +#include "http_protocol.h" +#include "http_request.h" +#include "http_log.h" + +#include "zend.h" +#include "php.h" +#include "php_ini.h" +#include "php_globals.h" +#include "SAPI.h" +#include "main.h" + +#include "zend_compile.h" +#include "zend_execute.h" +#include "zend_highlight.h" +#include "zend_indent.h" + +#include "ext/standard/php3_standard.h" + +#include "util_script.h" + +#include "php_version.h" +#include "mod_php4.h" +#if HAVE_MOD_DAV +# include "mod_dav.h" +#endif + +PHPAPI int apache_php_module_main(request_rec *r, int fd, int display_source_mode SLS_DC); + +/* ### these should be defined in mod_php4.h or somewhere else */ +#define USE_PATH 1 +#define IGNORE_URL 2 + +module MODULE_VAR_EXPORT php4_module; + +int saved_umask; +static unsigned char apache_php_initialized=0; + +typedef struct _php_per_dir_entry { + char *key; + char *value; + uint key_length; + uint value_length; + int type; +} php_per_dir_entry; + +#if WIN32|WINNT +/* popenf isn't working on Windows, use open instead*/ +# ifdef popenf +# undef popenf +# endif +# define popenf(p,n,f,m) open((n),(f),(m)) +# ifdef pclosef +# undef pclosef +# endif +# define pclosef(p,f) close(f) +#else +# define php3i_popenf(p,n,f,m) popenf((p),(n),(f),(m)) +#endif + +php_apache_info_struct php_apache_info; /* active config */ + +/* some systems are missing these from their header files */ + +PHPAPI int apache_php_module_main(request_rec *r, int fd, int display_source_mode SLS_DC) +{ + zend_file_handle file_handle; +#ifdef ZTS + zend_compiler_globals cg; + zend_executor_globals eg; + php_core_globals pcg; + zend_compiler_globals *compiler_globals=&cg; + zend_executor_globals *executor_globals=⪚ + php_core_globals *core_globals=&pcg; +#endif + SLS_FETCH(); + + if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC) == FAILURE) { + return FAILURE; + } + file_handle.type = ZEND_HANDLE_FD; + file_handle.handle.fd = fd; + file_handle.filename = SG(request_info).path_translated; + + if (display_source_mode) { + zend_syntax_highlighter_ini syntax_highlighter_ini; + + if (open_file_for_scanning(&file_handle CLS_CC)==SUCCESS) { + php_get_highlight_struct(&syntax_highlighter_ini); + zend_highlight(&syntax_highlighter_ini); + fclose(file_handle.handle.fp); + return OK; + } else { + return NOT_FOUND; + } + } else { + (void) php_execute_script(&file_handle CLS_CC ELS_CC); + } + + php3_header(); /* Make sure headers have been sent */ + php_end_ob_buffering(1); + return (OK); +} + +void php_save_umask() +{ + saved_umask = umask(077); + umask(saved_umask); +} + + +static int zend_apache_ub_write(const char *str, uint str_length) +{ + int ret; + SLS_FETCH(); + + if (SG(server_context)) { + ret = rwrite(str, str_length, (request_rec *) SG(server_context)); + } else { + ret = fwrite(str, 1, str_length, stdout); + } + if(ret != str_length) { + PG(connection_status) = PHP_CONNECTION_ABORTED; + if(!PG(ignore_user_abort)) zend_bailout(); + } + return ret; +} + + +int sapi_apache_read_post(char *buffer, uint count_bytes SLS_DC) +{ + uint total_read_bytes=0, read_bytes; + request_rec *r = (request_rec *) SG(server_context); + void (*handler)(int); + + handler = signal(SIGPIPE, SIG_IGN); + while (total_read_bytes<count_bytes) { + hard_timeout("Read POST information", r); /* start timeout timer */ + read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes); + reset_timeout(r); + if (read_bytes<=0) { + break; + } + total_read_bytes += read_bytes; + } + signal(SIGPIPE, handler); + return total_read_bytes; +} + + +char *sapi_apache_read_cookies(SLS_D) +{ + return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE"); +} + + +int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers SLS_DC) +{ + char *header_name, *header_content, *p; + request_rec *r = (request_rec *) SG(server_context); + + header_name = sapi_header->header; + + header_content = p = strchr(header_name, ':'); + if (!p) { + return 0; + } + + *p = 0; + do { + header_content++; + } while (*header_content==' '); + + if (!strcasecmp(header_name, "Content-Type")) { + r->content_type = pstrdup(r->pool, header_content); + } else if (!strcasecmp(header_name, "Set-Cookie")) { + table_add(r->headers_out, header_name, header_content); + } else { + table_set(r->headers_out, header_name, header_content); + } + + *p = ':'; /* a well behaved header handler shouldn't change its original arguments */ + + efree(sapi_header->header); + + return 0; /* don't use the default SAPI mechanism, Apache duplicates this functionality */ +} + + +int sapi_apache_send_headers(sapi_headers_struct *sapi_headers SLS_DC) +{ + ((request_rec *) SG(server_context))->status = SG(sapi_headers).http_response_code; + send_http_header((request_rec *) SG(server_context)); + return SAPI_HEADER_SENT_SUCCESSFULLY; +} + + +sapi_module_struct sapi_module = { + "PHP Language", /* name */ + + php_module_startup, /* startup */ + php_module_shutdown_wrapper, /* shutdown */ + + zend_apache_ub_write, /* unbuffered write */ + + php_error, /* error handler */ + + sapi_apache_header_handler, /* header handler */ + sapi_apache_send_headers, /* send headers handler */ + NULL, /* send header handler */ + + sapi_apache_read_post, /* read POST data */ + sapi_apache_read_cookies, /* read Cookies */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + + +void php_restore_umask() +{ + umask(saved_umask); +} + + +static void init_request_info(SLS_D) +{ + request_rec *r = ((request_rec *) SG(server_context)); + char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH"); + const char *authorization=NULL; + char *tmp; + + SG(request_info).query_string = r->args; + SG(request_info).path_translated = r->filename; + SG(request_info).request_uri = r->uri; + SG(request_info).request_method = (char *)r->method; + SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE"); + SG(request_info).content_length = (content_length ? atoi(content_length) : 0); + + if (r->headers_in) { + authorization = table_get(r->headers_in, "Authorization"); + } + if (authorization +/* && !auth_type(r) */ + && !strcmp(getword(r->pool, &authorization, ' '), "Basic")) { + tmp = uudecode(r->pool, authorization); + SG(request_info).auth_user = getword_nulls_nc(r->pool, &tmp, ':'); + if (SG(request_info).auth_user) { + SG(request_info).auth_user = estrdup(SG(request_info).auth_user); + } + SG(request_info).auth_password = tmp; + if (SG(request_info).auth_password) { + SG(request_info).auth_password = estrdup(SG(request_info).auth_password); + } + } else { + SG(request_info).auth_user = NULL; + SG(request_info).auth_password = NULL; + } +} + + +static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry) +{ + php_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length+1, per_dir_entry->type); + return 0; +} + + +int send_php(request_rec *r, int display_source_mode, char *filename) +{ + int fd, retval; + HashTable *per_dir_conf; + SLS_FETCH(); + + if (setjmp(EG(bailout))!=0) { + return OK; + } + per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php4_module); + zend_hash_apply((HashTable *) per_dir_conf, (int (*)(void *)) php_apache_alter_ini_entries); + + /* We don't accept OPTIONS requests, but take everything else */ + if (r->method_number == M_OPTIONS) { + r->allowed |= (1 << METHODS) - 1; + return DECLINED; + } + + /* Make sure file exists */ + if (filename == NULL && r->finfo.st_mode == 0) { + return NOT_FOUND; + } + + /* If PHP parser engine has been turned off with an "engine off" + * directive, then decline to handle this request + */ + if (!php_apache_info.engine) { + r->content_type = "text/html"; + r->allowed |= (1 << METHODS) - 1; + return DECLINED; + } + if (filename == NULL) { + filename = r->filename; + } + /* Open the file */ + if ((fd = popenf(r->pool, filename, O_RDONLY, 0)) == -1) { + log_reason("file permissions deny server access", filename, r); + return FORBIDDEN; + } + + /* Apache 1.2 has a more complex mechanism for reading POST data */ +#if MODULE_MAGIC_NUMBER > 19961007 + if ((retval = setup_client_block(r, REQUEST_CHUNKED_ERROR))) + return retval; +#endif + + if (php_apache_info.last_modified) { +#if MODULE_MAGIC_NUMBER < 19970912 + if ((retval = set_last_modified(r, r->finfo.st_mtime))) { + return retval; + } +#else + update_mtime (r, r->finfo.st_mtime); + set_last_modified(r); + set_etag(r); +#endif + } + /* Assume output will be HTML. Individual scripts may change this + further down the line */ + r->content_type = "text/html"; + + /* Init timeout */ + hard_timeout("send", r); + + SG(server_context) = r; + + php_save_umask(); + chdir_file(filename); + add_common_vars(r); + add_cgi_vars(r); + + init_request_info(SLS_C); + apache_php_module_main(r, fd, display_source_mode SLS_CC); + + /* Done, restore umask, turn off timeout, close file and return */ + php_restore_umask(); + kill_timeout(r); + pclosef(r->pool, fd); + return OK; +} + + +int send_parsed_php(request_rec * r) +{ + return send_php(r, 0, NULL); +} + + +int send_parsed_php_source(request_rec * r) +{ + return send_php(r, 1, NULL); +} + + +static int destroy_per_dir_entry(php_per_dir_entry *per_dir_entry) +{ + free(per_dir_entry->key); + free(per_dir_entry->value); + return 1; +} + +static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry) +{ + php_per_dir_entry tmp = *per_dir_entry; + + per_dir_entry->key = (char *) malloc(tmp.key_length+1); + memcpy(per_dir_entry->key, tmp.key, tmp.key_length); + per_dir_entry->key[per_dir_entry->key_length] = 0; + + per_dir_entry->value = (char *) malloc(tmp.value_length+1); + memcpy(per_dir_entry->value, tmp.value, tmp.value_length); + per_dir_entry->value[per_dir_entry->value_length] = 0; +} + + +static void php_destroy_per_dir_info(HashTable *per_dir_info) +{ + zend_hash_destroy(per_dir_info); + free(per_dir_info); +} + +static void *php_create_dir(pool *p, char *dummy) +{ + HashTable *per_dir_info; + + per_dir_info = (HashTable *) malloc(sizeof(HashTable)); + zend_hash_init(per_dir_info, 5, NULL, (int (*)(void *)) destroy_per_dir_entry, 1); + register_cleanup(p, (void *) per_dir_info, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) zend_hash_destroy); + + return per_dir_info; +} + + +static void *php_merge_dir(pool *p, void *basev, void *addv) +{ + php_per_dir_entry tmp; + + zend_hash_merge((HashTable *) addv, (HashTable *) basev, (void (*)(void *)) copy_per_dir_entry, &tmp, sizeof(php_per_dir_entry), 0); + return addv; +} + + +#if MODULE_MAGIC_NUMBER > 19961007 +#define CONST_PREFIX const +#else +#define CONST_PREFIX +#endif + +CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) +{ + php_per_dir_entry per_dir_entry; + + if (!apache_php_initialized) { + sapi_startup(&sapi_module); + php_module_startup(&sapi_module); + apache_php_initialized = 1; + } + per_dir_entry.type = mode; + + per_dir_entry.key_length = strlen(arg1); + per_dir_entry.value_length = strlen(arg2); + + per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1); + memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length); + per_dir_entry.key[per_dir_entry.key_length] = 0; + + per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1); + memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length); + per_dir_entry.value[per_dir_entry.value_length] = 0; + + zend_hash_update((HashTable *) conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL); + return NULL; +} + + +CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) +{ + return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR); +} + + +CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) +{ + return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM); +} + + +CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) +{ + char bool_val[2]; + + if (!strcasecmp(arg2, "On")) { + bool_val[0] = '1'; + } else { + bool_val[0] = '0'; + } + bool_val[1] = 0; + + return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode); +} + + +CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) +{ + return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR); +} + + +CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) +{ + return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM); +} + + + + +int php_xbithack_handler(request_rec * r) +{ + php_apache_info_struct *conf; + + conf = (php_apache_info_struct *) get_module_config(r->per_dir_config, &php4_module); + if (!(r->finfo.st_mode & S_IXUSR)) { + r->allowed |= (1 << METHODS) - 1; + return DECLINED; + } + if (conf->xbithack == 0) { + r->allowed |= (1 << METHODS) - 1; + return DECLINED; + } + return send_parsed_php(r); +} + +static void apache_php_module_shutdown_wrapper(void) +{ + apache_php_initialized = 0; + sapi_module.shutdown(&sapi_module); +} + + +void php_init_handler(server_rec *s, pool *p) +{ + register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, php_module_shutdown_for_exec); + if (!apache_php_initialized) { + sapi_startup(&sapi_module); + php_module_startup(&sapi_module); + apache_php_initialized = 1; + } +#if MODULE_MAGIC_NUMBER >= 19980527 + if (PG(expose_php)) { + ap_add_version_component("PHP/" PHP_VERSION); + } +#endif +} + + +#if HAVE_MOD_DAV + +extern int phpdav_mkcol_test_handler(request_rec *r); +extern int phpdav_mkcol_create_handler(request_rec *r); + +/* conf is being read twice (both here and in send_php()) */ +int send_parsed_php_dav_script(request_rec *r) +{ + php_apache_info_struct *conf; + + conf = (php_apache_info_struct *) get_module_config(r->per_dir_config, + &php4_module); + return send_php(r, 0, 0, conf->dav_script); +} + +static int php_type_checker(request_rec *r) +{ + php_apache_info_struct *conf; + + conf = (php_apache_info_struct *)get_module_config(r->per_dir_config, + &php4_module); + + /* If DAV support is enabled, use mod_dav's type checker. */ + if (conf->dav_script) { + dav_api_set_request_handler(r, send_parsed_php_dav_script); + dav_api_set_mkcol_handlers(r, phpdav_mkcol_test_handler, + phpdav_mkcol_create_handler); + /* leave the rest of the request to mod_dav */ + return dav_api_type_checker(r); + } + + return DECLINED; +} + +#else /* HAVE_MOD_DAV */ + +# define php_type_checker NULL + +#endif /* HAVE_MOD_DAV */ + + +handler_rec php_handlers[] = +{ + {"application/x-httpd-php", send_parsed_php}, + {"application/x-httpd-php-source", send_parsed_php_source}, + {"text/html", php_xbithack_handler}, + {NULL} +}; + + +command_rec php_commands[] = +{ + {"php_value", php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"}, + {"php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"}, + {"php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"}, + {"php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"}, + {NULL} +}; + + + +module MODULE_VAR_EXPORT php4_module = +{ + STANDARD_MODULE_STUFF, + php_init_handler, /* initializer */ + php_create_dir, /* per-directory config creator */ + php_merge_dir, /* dir merger */ + NULL, /* per-server config creator */ + NULL, /* merge server config */ + php_commands, /* command table */ + php_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + php_type_checker, /* type_checker */ + NULL, /* fixups */ + NULL /* logger */ +#if MODULE_MAGIC_NUMBER >= 19970103 + ,NULL /* header parser */ +#endif +#if MODULE_MAGIC_NUMBER >= 19970719 + ,NULL /* child_init */ +#endif +#if MODULE_MAGIC_NUMBER >= 19970728 + ,NULL /* child_exit */ +#endif +#if MODULE_MAGIC_NUMBER >= 19970902 + ,NULL /* post read-request */ +#endif +}; + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/sapi/apache/mod_php4.exp b/sapi/apache/mod_php4.exp new file mode 100644 index 0000000000..2dca1256c2 --- /dev/null +++ b/sapi/apache/mod_php4.exp @@ -0,0 +1 @@ +php4_module diff --git a/sapi/apache/mod_php4.h b/sapi/apache/mod_php4.h new file mode 100644 index 0000000000..4fe749d2d6 --- /dev/null +++ b/sapi/apache/mod_php4.h @@ -0,0 +1,49 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 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_0.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. | + +----------------------------------------------------------------------+ + | Authors: Rasmus Lerdorf <rasmus@php.net> | + +----------------------------------------------------------------------+ + */ +/* $Id$ */ + +#ifndef _MOD_PHP4_H +#define _MOD_PHP4_H + +#if !defined(WIN32) && !defined(WINNT) +#ifndef MODULE_VAR_EXPORT +#define MODULE_VAR_EXPORT +#endif +#endif + +typedef struct { + long engine; + long last_modified; + char *dav_script; + long xbithack; +} php_apache_info_struct; + +extern php_apache_info_struct php_apache_info; + +#if MSVC5 +#define S_IXUSR _S_IEXEC +#endif + +#endif /* _MOD_PHP4_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/sapi/cgi/Makefile.am b/sapi/cgi/Makefile.am new file mode 100644 index 0000000000..9525e44240 --- /dev/null +++ b/sapi/cgi/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend +noinst_LIBRARIES=libphpsapi_cgi.a +libphpsapi_cgi_a_SOURCES=cgi_main.c diff --git a/sapi/cgi/Makefile.inc b/sapi/cgi/Makefile.inc new file mode 100644 index 0000000000..b48bd31b1c --- /dev/null +++ b/sapi/cgi/Makefile.inc @@ -0,0 +1,6 @@ +# CGI binary or fhttpd module + +INSTALL_IT=: + +php: all-recursive $(OBJS) $(REGEX_LIB) $(FHTTPD_LIB) + $(CC) $(CFLAGS) -o $(SAPI_TARGET) $(LDFLAGS) $(OBJS) -Lsapi -lphpsapi $(LIBS) diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c new file mode 100644 index 0000000000..4a165b80c5 --- /dev/null +++ b/sapi/cgi/cgi_main.c @@ -0,0 +1,501 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 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_0.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. | + +----------------------------------------------------------------------+ + | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | + | Stig Bakken <ssb@fast.no> | + | Zeev Suraski <zeev@zend.com> | + +----------------------------------------------------------------------+ +*/ + + +#include "php.h" +#include "php_globals.h" + +#include "SAPI.h" + +#if CGI_BINARY + +#include <stdio.h> +#include "php.h" +#ifdef MSVC5 +#include "win32/time.h" +#include "win32/signal.h" +#include <process.h> +#else +#include "build-defs.h" +#endif +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_SIGNAL_H +#include <signal.h> +#endif +#if HAVE_SETLOCALE +#include <locale.h> +#endif +#include "zend.h" +#include "php_ini.h" +#include "php_globals.h" +#include "main.h" +#include "fopen-wrappers.h" +#include "ext/standard/php3_standard.h" +#include "snprintf.h" +#if WIN32|WINNT +#include <io.h> +#include <fcntl.h> +#include "win32/syslog.h" +#include "win32/php_registry.h" +#else +#include <syslog.h> +#endif + +#include "zend_compile.h" +#include "zend_execute.h" +#include "zend_highlight.h" +#include "zend_indent.h" + + +#if USE_SAPI +#include "serverapi/sapi.h" +void *gLock; +#ifndef THREAD_SAFE +struct sapi_request_info *sapi_rqst; +#endif +#endif + +#if MSVC5 || !defined(HAVE_GETOPT) +#include "php_getopt.h" +#endif + +PHPAPI extern char *php3_ini_path; + +#define PHP_MODE_STANDARD 1 +#define PHP_MODE_HIGHLIGHT 2 +#define PHP_MODE_INDENT 3 + +PHPAPI extern char *optarg; +PHPAPI extern int optind; + + +static int zend_cgibin_ub_write(const char *str, uint str_length) +{ + return fwrite(str, 1, str_length, stdout); +} + + +static void sapi_cgi_send_header(sapi_header_struct *sapi_header, void *server_context) +{ + if (sapi_header) { + PHPWRITE_H(sapi_header->header, sapi_header->header_len); + } + PHPWRITE_H("\r\n", 2); +} + + +static int sapi_cgi_read_post(char *buffer, uint count_bytes SLS_DC) +{ + uint read_bytes=0, tmp_read_bytes; + + count_bytes = MIN(count_bytes, SG(request_info).content_length-SG(read_post_bytes)); + while (read_bytes < count_bytes) { + tmp_read_bytes = read(0, buffer+read_bytes, count_bytes-read_bytes); + if (tmp_read_bytes<=0) { + break; + } + read_bytes += tmp_read_bytes; + } + return read_bytes; +} + + +static char *sapi_cgi_read_cookies(SLS_D) +{ + return getenv("HTTP_COOKIE"); +} + + +static sapi_module_struct sapi_module = { + "PHP Language", /* name */ + + php_module_startup, /* startup */ + php_module_shutdown_wrapper, /* shutdown */ + + zend_cgibin_ub_write, /* unbuffered write */ + + php_error, /* error handler */ + + NULL, /* header handler */ + NULL, /* send headers handler */ + sapi_cgi_send_header, /* send header handler */ + + sapi_cgi_read_post, /* read POST data */ + sapi_cgi_read_cookies, /* read Cookies */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + + +static void php_cgi_usage(char *argv0) +{ + char *prog; + + prog = strrchr(argv0, '/'); + if (prog) { + prog++; + } else { + prog = "php"; + } + + php_printf("Usage: %s [-q] [-h]" + " [-s]" + " [-v] [-i] [-f <file>] | " + "{<file> [args...]}\n" + " -q Quiet-mode. Suppress HTTP Header output.\n" + " -s Display colour syntax highlighted source.\n" + " -f<file> Parse <file>. Implies `-q'\n" + " -v Version number\n" + " -c<path> Look for php.ini file in this directory\n" +#if SUPPORT_INTERACTIVE + " -a Run interactively\n" +#endif + " -d foo[=bar] Define INI entry foo with value 'bar'\n" + " -e Generate extended information for debugger/profiler\n" + " -i PHP information\n" + " -h This help\n", prog); +} + + +static void init_request_info(SLS_D) +{ + char *content_length = getenv("CONTENT_LENGTH"); + + SG(request_info).request_method = getenv("REQUEST_METHOD"); + SG(request_info).query_string = getenv("QUERY_STRING"); + SG(request_info).request_uri = getenv("PATH_INFO"); + SG(request_info).path_translated = NULL; /* we have to update it later, when we have that information */ + SG(request_info).content_type = getenv("CONTENT_TYPE"); + SG(request_info).content_length = (content_length?atoi(content_length):0); + + /* CGI does not support HTTP authentication */ + SG(request_info).auth_user = NULL; + SG(request_info).auth_password = NULL; +} + + +void define_command_line_ini_entry(char *arg) +{ + char *name, *value; + + name = arg; + value = strchr(arg, '='); + if (value) { + *value = 0; + value++; + } else { + value = "1"; + } + php_alter_ini_entry(name, strlen(name), value, strlen(value), PHP_INI_SYSTEM); +} + + +int main(int argc, char *argv[]) +{ + int cgi = 0, c, i, len; + zend_file_handle file_handle; + char *s; +/* temporary locals */ + int cgi_started=0; + int behavior=PHP_MODE_STANDARD; + int no_headers=0; +#if SUPPORT_INTERACTIVE + int interactive=0; +#endif +/* end of temporary locals */ +#ifdef ZTS + zend_compiler_globals *compiler_globals; + zend_executor_globals *executor_globals; + php_core_globals *core_globals; + sapi_globals_struct *sapi_globals; +#endif + + +#ifndef ZTS + if (setjmp(EG(bailout))!=0) { + return -1; + } +#endif + +#ifdef ZTS + tsrm_startup(1,1,0); +#endif + + sapi_startup(&sapi_module); + +#if WIN32|WINNT + _fmode = _O_BINARY; /*sets default for file streams to binary */ + setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ + setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ + setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ +#endif + + + /* Make sure we detect we are a cgi - a bit redundancy here, + but the default case is that we have to check only the first one. */ + if (getenv("SERVER_SOFTWARE") + || getenv("SERVER_NAME") + || getenv("GATEWAY_INTERFACE") + || getenv("REQUEST_METHOD")) { + cgi = 1; + if (argc > 1) + request_info.php_argv0 = strdup(argv[1]); + else request_info.php_argv0 = NULL; +#if FORCE_CGI_REDIRECT + if (!getenv("REDIRECT_STATUS")) { + PUTS("<b>Security Alert!</b> PHP CGI cannot be accessed directly.\n\ +\n\ +<P>This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\ +means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\ +set. This variable is set, for example, by Apache's Action directive redirect.\n\ +<P>You may disable this restriction by recompiling the PHP binary with the\n\ +--disable-force-cgi-redirect switch. If you do this and you have your PHP CGI\n\ +binary accessible somewhere in your web tree, people will be able to circumvent\n\ +.htaccess security by loading files through the PHP parser. A good way around\n\ +this is to define doc_root in your php.ini file to something other than your\n\ +top-level DOCUMENT_ROOT. This way you can separate the part of your web space\n\n\ +which uses PHP from the normal part using .htaccess security. If you do not have\n\ +any .htaccess restrictions anywhere on your site you can leave doc_root undefined.\n\ +\n"); + + /* remove that detailed explanation some time */ + + return FAILURE; + } +#endif /* FORCE_CGI_REDIRECT */ + } + + if (php_module_startup(&sapi_module)==FAILURE) { + return FAILURE; + } +#ifdef ZTS + compiler_globals = ts_resource(compiler_globals_id); + executor_globals = ts_resource(executor_globals_id); + core_globals = ts_resource(core_globals_id); + sapi_globals = ts_resource(sapi_globals_id); + if (setjmp(EG(bailout))!=0) { + return -1; + } +#endif + + SG(request_info).path_translated = NULL; + init_request_info(SLS_C); + SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */ + CG(extended_info) = 0; + + if (!cgi) { /* never execute the arguments if you are a CGI */ + request_info.php_argv0 = NULL; + while ((c = getopt(argc, argv, "c:d:qvisnaeh?vf:")) != -1) { + switch (c) { + case 'f': + if (!cgi_started){ + if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC)==FAILURE) { + php_module_shutdown(); + return FAILURE; + } + } + if (no_headers) { + SG(headers_sent) = 1; + } + cgi_started=1; + SG(request_info).path_translated = estrdup(optarg); + /* break missing intentionally */ + case 'q': + no_headers = 1; + break; + case 'v': + if (!cgi_started) { + if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC)==FAILURE) { + php_module_shutdown(); + return FAILURE; + } + } + if (no_headers) { + SG(headers_sent) = 1; + } + php_printf("%s\n", PHP_VERSION); + exit(1); + break; + case 'i': + if (!cgi_started) { + if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC)==FAILURE) { + php_module_shutdown(); + return FAILURE; + } + } + if (no_headers) { + SG(headers_sent) = 1; + } + cgi_started=1; + php_print_info(0xFFFFFFFF); + exit(1); + break; + case 's': + behavior=PHP_MODE_HIGHLIGHT; + break; + case 'n': + behavior=PHP_MODE_INDENT; + break; + case 'c': + php3_ini_path = strdup(optarg); /* intentional leak */ + break; + case 'a': +#if SUPPORT_INTERACTIVE + printf("Interactive mode enabled\n\n"); + interactive=1; +#else + printf("Interactive mode not supported!\n\n"); +#endif + break; + case 'e': + CG(extended_info) = 1; + break; + case 'h': + case '?': + php_output_startup(); + SG(headers_sent) = 1; + php_cgi_usage(argv[0]); + exit(1); + break; + case 'd': + define_command_line_ini_entry(optarg); + break; + default: + break; + } + } + } /* not cgi */ + +#if SUPPORT_INTERACTIVE + EG(interactive) = interactive; +#endif + + if (!cgi_started) { + if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC)==FAILURE) { + php_module_shutdown(); + return FAILURE; + } + } + if (no_headers) { + SG(headers_sent) = 1; + } + file_handle.filename = "-"; + file_handle.type = ZEND_HANDLE_FP; + file_handle.handle.fp = stdin; + + + if (!cgi) { + if (!SG(request_info).query_string) { + for (i = optind, len = 0; i < argc; i++) + len += strlen(argv[i]) + 1; + + s = malloc(len + 1); /* leak - but only for command line version, so ok */ + *s = '\0'; /* we are pretending it came from the environment */ + for (i = optind, len = 0; i < argc; i++) { + strcat(s, argv[i]); + if (i < (argc - 1)) + strcat(s, "+"); + } + SG(request_info).query_string = s; + } + if (!SG(request_info).path_translated && argc > optind) + SG(request_info).path_translated = argv[optind]; + } + /* If for some reason the CGI interface is not setting the + PATH_TRANSLATED correctly, SG(request_info).path_translated is NULL. + We still call php3_fopen_for_parser, because if you set doc_root + or user_dir configuration directives, PATH_INFO is used to construct + the filename as a side effect of php3_fopen_for_parser. + */ + if(cgi) { + SG(request_info).path_translated = getenv("PATH_TRANSLATED"); + } + if (cgi || SG(request_info).path_translated) { + file_handle.handle.fp = php3_fopen_for_parser(); + file_handle.filename = SG(request_info).path_translated; + } + + if (cgi && !file_handle.handle.fp) { + PUTS("No input file specified.\n"); +#if 0 /* this is here for debuging under windows */ + if (argc) { + i = 0; + php_printf("\nargc %d\n",argc); + while (i <= argc) { + php_printf("%s\n",argv[i]); + i++; + } + } +#endif + php_request_shutdown((void *) 0); + php_module_shutdown(); + return FAILURE; + } else if (file_handle.handle.fp && file_handle.handle.fp!=stdin) { + /* #!php support */ + c = fgetc(file_handle.handle.fp); + if (c == '#') { + while (c != 10 && c != 13) { + c = fgetc(file_handle.handle.fp); /* skip to end of line */ + } + CG(zend_lineno)++; + } else { + rewind(file_handle.handle.fp); + } + } + + switch (behavior) { + case PHP_MODE_STANDARD: + php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); + break; + case PHP_MODE_HIGHLIGHT: { + zend_syntax_highlighter_ini syntax_highlighter_ini; + + if (open_file_for_scanning(&file_handle CLS_CC)==SUCCESS) { + php_get_highlight_struct(&syntax_highlighter_ini); + zend_highlight(&syntax_highlighter_ini); + fclose(file_handle.handle.fp); + } + return 0; + } + break; + case PHP_MODE_INDENT: + open_file_for_scanning(&file_handle CLS_CC); + zend_indent(); + fclose(file_handle.handle.fp); + return 0; + break; + } + + php3_header(); /* Make sure headers have been sent */ + php_request_shutdown((void *) 0); + php_module_shutdown(); +#ifdef ZTS + tsrm_shutdown(); +#endif + return SUCCESS; +} + + +#endif diff --git a/sapi/cgi/config.h.in b/sapi/cgi/config.h.in new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/sapi/cgi/config.h.in diff --git a/sapi/cgi/config.m4 b/sapi/cgi/config.m4 new file mode 100644 index 0000000000..4722f33b16 --- /dev/null +++ b/sapi/cgi/config.m4 @@ -0,0 +1,83 @@ + +if test "$SAPI_TARGET" = "php"; then +AC_MSG_CHECKING(whether to force Apache CGI redirect) +AC_ARG_ENABLE(force-cgi-redirect, +[ --enable-force-cgi-redirect + Enable the security check for internal server + redirects. You should use this if you are + running the CGI version with Apache. ], +[ + if test "$enableval" = "yes"; then + AC_DEFINE(FORCE_CGI_REDIRECT, 1) + AC_MSG_RESULT(yes) + REDIRECT=1 + else + AC_DEFINE(FORCE_CGI_REDIRECT, 0) + AC_MSG_RESULT(no) + REDIRECT=0 + fi +],[ + AC_DEFINE(FORCE_CGI_REDIRECT, 0) + AC_MSG_RESULT(no) + REDIRECT=0 +]) + +AC_MSG_CHECKING(whether to discard path_info + path_translated) +AC_ARG_ENABLE(discard_path, +[ --enable-discard-path If this is enabled, the PHP CGI binary + can safely be placed outside of the + web tree and people will not be able + to circumvent .htaccess security. ], +[ + if test "$enableval" = "yes"; then + AC_DEFINE(DISCARD_PATH, 1) + AC_MSG_RESULT(yes) + DISCARD_PATH=1 + else + AC_DEFINE(DISCARD_PATH, 0) + AC_MSG_RESULT(no) + DISCARD_PATH=0 + fi +],[ + AC_DEFINE(DISCARD_PATH, 0) + AC_MSG_RESULT(no) + DISCARD_PATH=0 +]) +fi + +if test "$SAPI_TARGET" = "php" ; then + INSTALL_IT="\$(SHELL) \$(srcdir)/install-sh -m 0755 $SAPI_TARGET \$(bindir)/$SAPI_TARGET" +fi + +AC_MSG_CHECKING(for fhttpd module support) +AC_ARG_WITH(fhttpd, +[ --with-fhttpd[=DIR] Build fhttpd module. DIR is the fhttpd sources + directory, defaults to /usr/local/src/fhttpd.], +[ + if test "$withval" = "yes"; then + # fhttpd source directory + withval=/usr/local/src/fhttpd + fi + if test "$withval" != "no"; then +# For fhttpd 0.3.x + if test -f $withval/servproc.h; then + FHTTPD_INCLUDE=-I$withval/ + FHTTPD_LIB=$withval/servproc.o + FHTTPD_TARGET=$withval/ + SAPI_TARGET=php + AC_DEFINE(FHTTPD) + AC_MSG_RESULT(yes - fhttpd 0.3.x) + else + AC_MSG_RESULT(no) + AC_MSG_ERROR(Invalid fhttpd directory - unable to find servproc.h under $withval) + fi + else + AC_MSG_RESULT(no) + fi +],[ + AC_MSG_RESULT(no) +]) +INCLUDES="$INCLUDES $FHTTPD_INCLUDE" +dnl## AC_SUBST(FHTTPD_INCLUDE) +AC_SUBST(FHTTPD_LIB) +AC_SUBST(FHTTPD_TARGET) diff --git a/sapi/isapi/Makefile.am b/sapi/isapi/Makefile.am new file mode 100644 index 0000000000..682eebc468 --- /dev/null +++ b/sapi/isapi/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend +noinst_LIBRARIES=libphpsapi_isapi.a +libphpsapi_isapi_a_SOURCES=php4isapi.c diff --git a/sapi/isapi/Makefile.inc b/sapi/isapi/Makefile.inc new file mode 100644 index 0000000000..d64acf40eb --- /dev/null +++ b/sapi/isapi/Makefile.inc @@ -0,0 +1,6 @@ +# ISAPI/Zeus module + +INSTALL_IT=: + +php4isapi.so: libmodphp4-so.a + g++ $(LDFLAGS) -shared sapi/isapi/php4isapi.o -o $@ libmodphp4-so.a $(LIBS) diff --git a/sapi/isapi/config.m4 b/sapi/isapi/config.m4 new file mode 100644 index 0000000000..777ec8de65 --- /dev/null +++ b/sapi/isapi/config.m4 @@ -0,0 +1,31 @@ +dnl ## $Id$ -*- sh -*- + +AC_MSG_CHECKING(for Zeus ISAPI support) +AC_ARG_WITH(zeus, +[ --with-zeus=DIR Build PHP as an ISAPI module for use with Zeus.], +[ + if test "$withval" != "no"; then + SAPI_TARGET=libphp4_isapi.so + AC_MSG_RESULT(yes) + if test "${enable_thread_safety}" != "yes"; then + AC_MSG_ERROR(You must specify --enable-thread-safety to build as an ISAPI module) + fi + if test "$withval" = "yes"; then + zeuspath=/usr/local/zeus # the default + fi + if ! test -f "$zeuspath/web/include/httpext.h"; then + AC_MSG_ERROR(Unable to find httpext.h in $zeuspath/web/include) + fi + AC_ADD_INCLUDE($zeuspath/web/include) + PHP_SAPI=isapi + SAPI_TARGET=php4isapi.so + else + AC_MSG_RESULT(no) + fi +],[ + AC_MSG_RESULT(no) +]) + +dnl ## Local Variables: +dnl ## tab-width: 4 +dnl ## End: diff --git a/sapi/isapi/php4isapi.c b/sapi/isapi/php4isapi.c new file mode 100644 index 0000000000..ee3f1f2179 --- /dev/null +++ b/sapi/isapi/php4isapi.c @@ -0,0 +1,464 @@ +#include <windows.h> +#include <httpext.h> +#include <httpfilt.h> +#include <httpext.h> +#include "php.h" +#include "main.h" +#include "SAPI.h" +#include "php_globals.h" +#include "ext/standard/info.h" + +#define MAX_STATUS_LENGTH sizeof("xxxx LONGEST STATUS DESCRIPTION") +#define ISAPI_SERVER_VAR_BUF_SIZE 1024 +#define ISAPI_POST_DATA_BUF 1024 + +int IWasLoaded=0; + +static char *isapi_server_variables[] = { + "ALL_HTTP", + "APPL_MD_PATH", + "APPL_PHYSICAL_PATH", + "AUTH_PASSWORD", + "AUTH_TYPE", + "AUTH_USER", + "CERT_COOKIE", + "CERT_FLAGS", + "CERT_ISSUER", + "CERT_KEYSIZE", + "CERT_SECRETKEYSIZE", + "CERT_SERIALNUMBER", + "CERT_SERVER_ISSUER", + "CERT_SERVER_SUBJECT", + "CERT_SUBJECT", + "CONTENT_LENGTH", + "CONTENT_TYPE", + "LOGON_USER", + "HTTP_COOKIE", + "HTTPS", + "HTTPS_KEYSIZE", + "HTTPS_SECRETKEYSIZE", + "HTTPS_SERVER_ISSUER", + "HTTPS_SERVER_SUBJECT", + "INSTANCE_ID", + "INSTANCE_META_PATH", + "PATH_INFO", + "PATH_TRANSLATED", + "QUERY_STRING", + "REMOTE_ADDR", + "REMOTE_HOST", + "REMOTE_USER", + "REQUEST_METHOD", + "SCRIPT_NAME", + "SERVER_NAME", + "SERVER_PORT", + "SERVER_PORT_SECURE", + "SERVER_PROTOCOL", + "SERVER_SOFTWARE", + "URL", + NULL +}; + + +static void php_info_isapi(ZEND_MODULE_INFO_FUNC_ARGS) +{ + char **p = isapi_server_variables; + char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; + DWORD variable_len; + LPEXTENSION_CONTROL_BLOCK lpECB; + SLS_FETCH(); + + lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); + + PUTS("<table border=5 width=\"600\">\n"); + php_info_print_table_header(2, "Server Variable", "Value"); + while (*p) { + variable_len = ISAPI_SERVER_VAR_BUF_SIZE; + if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len) + && variable_buf[0]) { + php_info_print_table_row(2, *p, variable_buf); + } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + char *tmp_variable_buf; + + tmp_variable_buf = (char *) emalloc(variable_len); + if (lpECB->GetServerVariable(lpECB->ConnID, *p, tmp_variable_buf, &variable_len) + && variable_buf[0]) { + php_info_print_table_row(2, *p, tmp_variable_buf); + } + efree(tmp_variable_buf); + } + p++; + } + + PUTS("</table>"); +} + + +static zend_module_entry php_isapi_module = { + "ISAPI", + NULL, + NULL, + NULL, + NULL, + NULL, + php_info_isapi, + STANDARD_MODULE_PROPERTIES +}; + + +static int zend_isapi_ub_write(const char *str, uint str_length) +{ + DWORD num_bytes = str_length; + LPEXTENSION_CONTROL_BLOCK ecb; + SLS_FETCH(); + + ecb = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); + ecb->WriteClient(ecb->ConnID, (char *) str, &num_bytes, HSE_IO_SYNC ); + return num_bytes; +} + + +static int sapi_isapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers SLS_DC) +{ + return SAPI_HEADER_ADD; +} + + + +static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length) +{ + *total_length += sapi_header->header_len+2; +} + + +static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr) +{ + memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len); + *combined_headers_ptr += sapi_header->header_len; + **combined_headers_ptr = '\r'; + (*combined_headers_ptr)++; + **combined_headers_ptr = '\n'; + (*combined_headers_ptr)++; +} + + +static int sapi_isapi_send_headers(sapi_headers_struct *sapi_headers SLS_DC) +{ + uint total_length = 2; /* account for the trailing \r\n */ + char *combined_headers, *combined_headers_ptr; + LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); + HSE_SEND_HEADER_EX_INFO header_info; + char status_buf[MAX_STATUS_LENGTH]; + sapi_header_struct default_content_type = { SAPI_DEFAULT_CONTENT_TYPE, sizeof(SAPI_DEFAULT_CONTENT_TYPE)-1 }; + sapi_header_struct php_version_header = { SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1 }; + PLS_FETCH(); + + /* Obtain headers length */ + if (SG(sapi_headers).send_default_content_type) { + accumulate_header_length(&default_content_type, (void *) &total_length); + } + if (PG(expose_php)) { + accumulate_header_length(&php_version_header, (void *) &total_length); + } + zend_llist_apply_with_argument(&SG(sapi_headers).headers, (void (*)(void *, void *)) accumulate_header_length, (void *) &total_length); + + /* Generate headers */ + combined_headers = (char *) emalloc(total_length+1); + combined_headers_ptr = combined_headers; + if (SG(sapi_headers).send_default_content_type) { + concat_header(&default_content_type, (void *) &combined_headers_ptr); + } + if (PG(expose_php)) { + concat_header(&php_version_header, (void *) &combined_headers_ptr); + } + zend_llist_apply_with_argument(&SG(sapi_headers).headers, (void (*)(void *, void *)) concat_header, (void *) &combined_headers_ptr); + *combined_headers_ptr++ = '\r'; + *combined_headers_ptr++ = '\n'; + *combined_headers_ptr = 0; + + switch (SG(sapi_headers).http_response_code) { + case 200: + header_info.pszStatus = "200 OK"; + break; + case 302: + header_info.pszStatus = "302 Moved Temporarily"; + break; + case 401: + header_info.pszStatus = "401 Authorization Required"; + break; + default: + snprintf(status_buf, MAX_STATUS_LENGTH, "%d Undescribed", SG(sapi_headers).http_response_code); + header_info.pszStatus = status_buf; + break; + } + header_info.cchStatus = strlen(header_info.pszStatus); + header_info.pszHeader = combined_headers; + header_info.cchHeader = total_length; + lpECB->dwHttpStatusCode = SG(sapi_headers).http_response_code; + + lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL); + + efree(combined_headers); + if (SG(sapi_headers).http_status_line) { + efree(SG(sapi_headers).http_status_line); + } + return SAPI_HEADER_SENT_SUCCESSFULLY; +} + + +static int php_isapi_startup(sapi_module_struct *sapi_module) +{ + if (php_module_startup(sapi_module)==FAILURE + || zend_register_module(&php_isapi_module)==FAILURE) { + return FAILURE; + } else { + return SUCCESS; + } +} + + + +static int sapi_isapi_read_post(char *buffer, uint count_bytes SLS_DC) +{ + LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); + DWORD read_from_buf=0; + DWORD read_from_input=0; + DWORD total_read=0; + + if (SG(read_post_bytes) < lpECB->cbAvailable) { + read_from_buf = MIN(lpECB->cbAvailable-SG(read_post_bytes), count_bytes); + memcpy(buffer, lpECB->lpbData+SG(read_post_bytes), read_from_buf); + total_read += read_from_buf; + } + if (read_from_buf<count_bytes + && (SG(read_post_bytes)+read_from_buf) < lpECB->cbTotalBytes) { + DWORD cbRead=0, cbSize; + + read_from_input = MIN(count_bytes-read_from_buf, lpECB->cbTotalBytes-SG(read_post_bytes)-read_from_buf); + while (cbRead < read_from_input) { + cbSize = read_from_input - cbRead; + if (!lpECB->ReadClient(lpECB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) { + break; + } + cbRead += cbSize; + } + total_read += cbRead; + } + SG(read_post_bytes) += total_read; + return total_read; +} + + +static char *sapi_isapi_read_cookies(SLS_D) +{ + LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); + char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; + DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; + + if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) { + return estrndup(variable_buf, variable_len); + } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) { + char *tmp_variable_buf = (char *) emalloc(variable_len+1); + + if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) { + tmp_variable_buf[variable_len] = 0; + return tmp_variable_buf; + } else { + efree(tmp_variable_buf); + } + } + return NULL; +} + + +static sapi_module_struct sapi_module = { + "PHP Language", /* name */ + + php_isapi_startup, /* startup */ + php_module_shutdown_wrapper, /* shutdown */ + + zend_isapi_ub_write, /* unbuffered write */ + + php_error, /* error handler */ + + sapi_isapi_header_handler, /* header handler */ + sapi_isapi_send_headers, /* send headers handler */ + NULL, /* send header handler */ + + sapi_isapi_read_post, /* read POST data */ + sapi_isapi_read_cookies, /* read Cookies */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + + +BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pFilterVersion) +{ + pFilterVersion->dwFilterVersion = HTTP_FILTER_REVISION; + strcpy(pFilterVersion->lpszFilterDesc, sapi_module.name); + pFilterVersion->dwFlags= (SF_NOTIFY_AUTHENTICATION | SF_NOTIFY_PREPROC_HEADERS); + return TRUE; +} + + +DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification) +{ + SLS_FETCH(); + + switch (notificationType) { + case SF_NOTIFY_PREPROC_HEADERS: + SG(request_info).auth_user = NULL; + SG(request_info).auth_password = NULL; + break; + case SF_NOTIFY_AUTHENTICATION: { + char *auth_user = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszUser; + char *auth_password = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszPassword; + + if (auth_user && auth_user[0]) { + SG(request_info).auth_user = estrdup(auth_user); + } + if (auth_password && auth_password[0]) { + SG(request_info).auth_password = estrdup(auth_password); + } + auth_user[0] = 0; + auth_password[0] = 0; + return SF_STATUS_REQ_HANDLED_NOTIFICATION; + } + break; + } + return SF_STATUS_REQ_NEXT_NOTIFICATION; +} + + +static void init_request_info(sapi_globals_struct *sapi_globals, LPEXTENSION_CONTROL_BLOCK lpECB) +{ + SG(request_info).request_method = lpECB->lpszMethod; + SG(request_info).query_string = lpECB->lpszQueryString; + SG(request_info).path_translated = lpECB->lpszPathTranslated; + SG(request_info).request_uri = lpECB->lpszPathInfo; + SG(request_info).content_type = lpECB->lpszContentType; + SG(request_info).content_length = lpECB->cbTotalBytes; + { + char *path_end = strrchr(SG(request_info).path_translated, '\\'); + + if (path_end) { + *path_end = 0; + chdir(SG(request_info).path_translated); + *path_end = '\\'; + } + } +} + + +BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) +{ + pVer->dwExtensionVersion = HSE_VERSION; + lstrcpyn(pVer->lpszExtensionDesc, sapi_module.name, HSE_MAX_EXT_DLL_NAME_LEN); + return TRUE; +} + + +static void hash_isapi_variables(ELS_D SLS_DC) +{ + char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; + char *variable_buf; + DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; + char *variable; + LPEXTENSION_CONTROL_BLOCK lpECB; + + lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); + + if (lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", static_variable_buf, &variable_len)) { + variable_buf = static_variable_buf; + } else { + if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) { + variable_buf = (char *) emalloc(variable_len); + if (!lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", variable_buf, &variable_len)) { + efree(variable_buf); + return; + } + } else { + return; + } + } + variable = strtok(variable_buf, "\r\n"); + while (variable) { + char *colon = strchr(variable, ':'); + + if (colon) { + char *value = colon+1; + zval *entry = (zval *) emalloc(sizeof(zval)); + + while (*value==' ') { + value++; + } + *colon = 0; + INIT_PZVAL(entry); + entry->value.str.len = strlen(value); + entry->value.str.val = estrndup(value, entry->value.str.len); + entry->type = IS_STRING; + zend_hash_add(&EG(symbol_table), variable, strlen(variable)+1, &entry, sizeof(zval *), NULL); + *colon = ':'; + } + variable = strtok(NULL, "\r\n"); + } + if (variable_buf!=static_variable_buf) { + efree(variable_buf); + } +} + + +DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) +{ + zend_file_handle file_handle; + SLS_FETCH(); + CLS_FETCH(); + ELS_FETCH(); + PLS_FETCH(); + + if (setjmp(EG(bailout))!=0) { + return HSE_STATUS_ERROR; + } + + init_request_info(sapi_globals, lpECB); + SG(server_context) = lpECB; + + file_handle.filename = sapi_globals->request_info.path_translated; + file_handle.type = ZEND_HANDLE_FILENAME; + + php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC); + hash_isapi_variables(ELS_C SLS_CC); + php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); + if (SG(request_info).cookie_data) { + efree(SG(request_info).cookie_data); + } + php_request_shutdown(NULL); + return HSE_STATUS_SUCCESS; +} + + + +__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + tsrm_startup(1, 1, 0); + sapi_startup(&sapi_module); + if (sapi_module.startup) { + sapi_module.startup(&sapi_module); + } + IWasLoaded = 1; + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + ts_free_thread(); + break; + case DLL_PROCESS_DETACH: + if (sapi_module.shutdown) { + sapi_module.shutdown(&sapi_module); + } + tsrm_shutdown(); + break; + } + return TRUE; +}
\ No newline at end of file diff --git a/sapi/isapi/php4isapi.def b/sapi/isapi/php4isapi.def new file mode 100644 index 0000000000..596023ef55 --- /dev/null +++ b/sapi/isapi/php4isapi.def @@ -0,0 +1,5 @@ +EXPORTS +HttpFilterProc +GetFilterVersion +HttpExtensionProc +GetExtensionVersion diff --git a/sapi/isapi/php4isapi.dsp b/sapi/isapi/php4isapi.dsp new file mode 100644 index 0000000000..3facc5baca --- /dev/null +++ b/sapi/isapi/php4isapi.dsp @@ -0,0 +1,106 @@ +# Microsoft Developer Studio Project File - Name="php4isapi" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=php4isapi - Win32 Debug_TS
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "php4isapi.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "php4isapi.mak" CFG="php4isapi - Win32 Debug_TS"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "php4isapi - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "php4isapi - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "php4isapi - Win32 Debug_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PHP4ISAPI_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\win32" /I "..\libzend" /I ".." /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "PHP4ISAPI_EXPORTS" /D "MSVC5" /D "COMPILE_LIBZEND" /D "WIN32" /D "_MBCS" /D "ZTS" /D ZEND_DEBUG=1 /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x40d /d "_DEBUG"
+# ADD RSC /l 0x40d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"libcmt" /pdbtype:sept /libpath:"..\Debug_TS"
+
+!ELSEIF "$(CFG)" == "php4isapi - Win32 Release_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PHP4ISAPI_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\include" /I "..\win32" /I "..\libzend" /I ".." /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "PHP4ISAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "WIN32" /D "_MBCS" /D ZEND_DEBUG=0 /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x40d /d "NDEBUG"
+# ADD RSC /l 0x40d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 /libpath:"..\Release_TS"
+
+!ENDIF
+
+# Begin Target
+
+# Name "php4isapi - Win32 Debug_TS"
+# Name "php4isapi - Win32 Release_TS"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\php4isapi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\php4isapi.def
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/sapi/nsapi/Makefile.am b/sapi/nsapi/Makefile.am new file mode 100644 index 0000000000..4a8edf6074 --- /dev/null +++ b/sapi/nsapi/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend +noinst_LIBRARIES=libphpsapi_nsapi.a +libphpsapi_nsapi_a_SOURCES=aolserver.c diff --git a/sapi/nsapi/Makefile.inc b/sapi/nsapi/Makefile.inc new file mode 100644 index 0000000000..6c56958bc8 --- /dev/null +++ b/sapi/nsapi/Makefile.inc @@ -0,0 +1,6 @@ +# NSAPI/AOLserver module + +INSTALL_IT=: + +php4_nsapi.so: libmodphp4-so.a + g++ $(LDFLAGS) -shared sapi/nsapi/aolserver.o -o $@ libmodphp4-so.a $(LIBS) diff --git a/sapi/nsapi/aolserver.c b/sapi/nsapi/aolserver.c new file mode 100644 index 0000000000..cbc4ec0257 --- /dev/null +++ b/sapi/nsapi/aolserver.c @@ -0,0 +1,343 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 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_0.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: Sascha Schumann <sascha@schumann.cx> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* conflict between PHP and aolserver */ +#define Debug php_Debug +#include "php.h" +#undef Debug + +#ifdef HAVE_AOLSERVER + +#include "php_ini.h" +#include "php_globals.h" +#include "SAPI.h" +#include "main.h" + +#include "ns.h" + +#include "php_version.h" + +int Ns_ModuleVersion = 1; + +#define NSLS_D ns_globals_struct *ns_context +#define NSLS_DC , NSLS_D +#define NSLS_C ns_context +#define NSLS_CC , NSLS_C +#define NSG(v) (ns_context->v) +#define NSLS_FETCH() ns_globals_struct *ns_context = ts_resource(ns_globals_id) + +static int ns_globals_id; + +typedef struct { + sapi_module_struct *sapi_module; + char *ns_server; + char *ns_module; +} php_ns_context; + +typedef struct { + Ns_Conn *conn; + Ns_DString content_type; +} ns_globals_struct; + +static void php_ns_config(php_ns_context *ctx); + +static int +php_ns_sapi_ub_write(const char *str, uint str_length) +{ + int sent_bytes; + NSLS_FETCH(); + + sent_bytes = Ns_ConnWrite(NSG(conn), (void *) str, str_length); + + return sent_bytes; +} + +static int +php_ns_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers SLS_DC) +{ + char *header_name, *header_content; + char *p; + NSLS_FETCH(); + + header_name = sapi_header->header; + header_content = p = strchr(header_name, ':'); + + if(!p) return 0; + + *p = '\0'; + do { + header_content++; + } while(*header_content == ' '); + + if(!strcasecmp(header_name, "Content-type")) { + Ns_ConnSetTypeHeader(NSG(conn), header_content); + } else { + Ns_ConnSetHeaders(NSG(conn), header_name, header_content); + } + + *p = ':'; + + efree(sapi_header->header); + + return 0; +} + +static int +php_ns_sapi_send_headers(sapi_headers_struct *sapi_headers SLS_DC) +{ + NSLS_FETCH(); + + if(SG(sapi_headers).send_default_content_type) { + Ns_ConnSetRequiredHeaders(NSG(conn), "text/html", 0); + } + Ns_ConnFlushHeaders(NSG(conn), SG(sapi_headers).http_response_code); + return SAPI_HEADER_SENT_SUCCESSFULLY; +} + +static int +php_ns_sapi_read_post(char *buf, uint count_bytes SLS_DC) +{ + uint total_read = 0; + NSLS_FETCH(); + + total_read = Ns_ConnRead(NSG(conn), buf, count_bytes); + + if(total_read == NS_ERROR) { + total_read = -1; + } + + return total_read; +} + +static char * +php_ns_sapi_read_cookies(SLS_D) +{ + int i; + char *http_cookie = NULL; + NSLS_FETCH(); + + i = Ns_SetFind(NSG(conn->headers), "cookie"); + if(i != -1) { + http_cookie = Ns_SetValue(NSG(conn->headers), i); + } + + return http_cookie; +} + +static sapi_module_struct sapi_module = { + "PHP Language", + + php_module_startup, /* startup */ + php_module_shutdown_wrapper, /* shutdown */ + + php_ns_sapi_ub_write, /* unbuffered write */ + + php_error, /* error handler */ + + php_ns_sapi_header_handler, /* header handler */ + php_ns_sapi_send_headers, /* send headers handler */ + NULL, /* send header handler */ + + php_ns_sapi_read_post, /* read POST data */ + php_ns_sapi_read_cookies, /* read Cookies */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + +static void +php_ns_hash_environment(NSLS_D CLS_DC ELS_DC PLS_DC SLS_DC) +{ + int i; + + for(i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) { + char *key = Ns_SetKey(NSG(conn->headers), i); + char *value = Ns_SetValue(NSG(conn->headers), i); + char *p; + zval *pval; + char buf[512]; + int buf_len; + + buf_len = snprintf(buf, 511, "HTTP_%s", key); + for(p = buf; *p; p++) { + *p = toupper(*p); + if(*p < 'A' || *p > 'Z') { + *p = '_'; + } + } + + MAKE_STD_ZVAL(pval); + pval->type = IS_STRING; + pval->value.str.len = strlen(value); + pval->value.str.val = estrndup(value, pval->value.str.len); + + zend_hash_update(&EG(symbol_table), buf, buf_len + 1, &pval, sizeof(zval *), NULL); + } +} + +static int +php_ns_module_main(NSLS_D SLS_DC) +{ + zend_file_handle file_handle; + CLS_FETCH(); + ELS_FETCH(); + PLS_FETCH(); + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = SG(request_info).path_translated; + + php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC); + php_ns_hash_environment(NSLS_C CLS_CC ELS_CC PLS_CC SLS_CC); + php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); + php_request_shutdown(NULL); + + return NS_OK; +} + +static void +php_ns_request_ctor(NSLS_D SLS_DC) +{ + char *server; + Ns_DString ds; + char *root; + + server = Ns_ConnServer(NSG(conn)); + + SG(request_info).query_string = NSG(conn->request->query); + + Ns_DStringInit(&ds); + Ns_UrlToFile(&ds, server, NSG(conn->request->url)); + SG(request_info).path_translated = strdup(Ns_DStringValue(&ds)); + Ns_DStringFree(&ds); + root = Ns_PageRoot(server); + SG(request_info).request_uri = SG(request_info).path_translated + strlen(root); + SG(request_info).request_method = NSG(conn)->request->method; + SG(request_info).content_length = Ns_ConnContentLength(NSG(conn)); + Ns_DStringInit(&NSG(content_type)); + Ns_ConnCopyToDString(NSG(conn), SG(request_info).content_length, &NSG(content_type)); + SG(request_info).content_type = Ns_DStringValue(&NSG(content_type)); + SG(request_info).auth_user = NULL; + SG(request_info).auth_password = NULL; +} + +static void +php_ns_request_dtor(NSLS_D SLS_DC) +{ + free(SG(request_info).path_translated); + Ns_DStringFree(&NSG(content_type)); +} + +static int +php_ns_request_handler(void *context, Ns_Conn *conn) +{ + int status = NS_OK; + SLS_FETCH(); + NSLS_FETCH(); + + NSG(conn) = conn; + + php_ns_request_ctor(NSLS_C SLS_CC); + + status = php_ns_module_main(NSLS_C SLS_CC); + + php_ns_request_dtor(NSLS_C SLS_CC); + + return status; +} + +static void +php_ns_config(php_ns_context *ctx) +{ + int i; + char *path; + Ns_Set *set; + + path = Ns_ConfigPath(ctx->ns_server, ctx->ns_module, NULL); + set = Ns_ConfigGetSection(path); + + for(i = 0; set && i < Ns_SetSize(set); i++) { + char *key = Ns_SetKey(set, i); + char *value = Ns_SetValue(set, i); + + if(!strcasecmp(key, "map")) { + Ns_Log(Notice, "Registering PHP for \"%s\"", value); + Ns_RegisterRequest(ctx->ns_server, "GET", value, php_ns_request_handler, NULL, ctx, 0); + Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0); + Ns_RegisterRequest(ctx->ns_server, "HEAD", value, php_ns_request_handler, NULL, ctx, 0); + } else if(!strcasecmp(key, "php_value")) { + char *val; + + val = strchr(value, ' '); + if(val) { + char *new_key; + + new_key = estrndup(value, val - value); + + do { + val++; + } while(*val == ' '); + + Ns_Log(Debug, "PHP configuration option '%s=%s'", new_key, val); + php_alter_ini_entry(new_key, strlen(new_key) + 1, val, + strlen(val) + 1, PHP_INI_SYSTEM); + + efree(new_key); + } + } + + } +} + +static void +php_ns_server_shutdown(void *context) +{ + php_ns_context *ctx = (php_ns_context *) context; + + ctx->sapi_module->shutdown(ctx->sapi_module); + sapi_shutdown(); + tsrm_shutdown(); + + free(ctx->ns_module); + free(ctx->ns_server); + free(ctx); +} + +int Ns_ModuleInit(char *server, char *module) +{ + php_ns_context *ctx; + + tsrm_startup(1, 1, 0); + sapi_startup(&sapi_module); + sapi_module.startup(&sapi_module); + + ns_globals_id = ts_allocate_id(sizeof(ns_globals_struct), NULL, NULL); + + ctx = malloc(sizeof *ctx); + ctx->sapi_module = &sapi_module; + ctx->ns_server = strdup(server); + ctx->ns_module = strdup(module); + + php_ns_config(ctx); + + Ns_RegisterServerShutdown(server, php_ns_server_shutdown, ctx); + + return NS_OK; +} + +#endif diff --git a/sapi/nsapi/config.m4 b/sapi/nsapi/config.m4 new file mode 100644 index 0000000000..854785df04 --- /dev/null +++ b/sapi/nsapi/config.m4 @@ -0,0 +1,26 @@ +dnl ## $Id$ -*- sh -*- + +RESULT=no +AC_MSG_CHECKING(for AOLserver support) +AC_ARG_WITH(aolserver, +[ --with-aolserver=DIR], +[ + if test ! -d $withval ; then + AC_MSG_ERROR(You did not specify a directory) + fi + if test "$enable_thread_safety" != "yes"; then + AC_MSG_ERROR(AOLserver must be compiled using --enable-thread-safety) + fi + NS_DIR=$withval + AC_ADD_INCLUDE($NS_DIR/include) + AC_DEFINE(HAVE_AOLSERVER) + PHP_SAPI=nsapi + SAPI_TARGET=php4_nsapi.so + INSTALL_IT="\$(SHELL) \$(srcdir)/install-sh -m 0755 $SAPI_TARGET $NS_DIR/root/bin/$SAPI_TARGET" + RESULT=yes +]) +AC_MSG_RESULT($RESULT) + +dnl ## Local Variables: +dnl ## tab-width: 4 +dnl ## End: |
