From 56a5e84f9ddbf2d63e34c797746124c5385306d4 Mon Sep 17 00:00:00 2001 From: Sascha Schumann Date: Mon, 20 Dec 1999 07:11:14 +0000 Subject: [PATCH] Add SAPI module for thttpd server. Quote from the README: This is a SAPI module for PHP 4.0 supporting thttpd, the tiny, turbo, throttling HTTP server by Jef Poskanzer. The module contains a patch against version 2.10 of thttpd. The patch adds hooks to thttpd to call PHP, if a filename matches *.php. This patch will be applied when you install PHP. While functional, this module exists primarily to demonstrate the ability of PHP to work in almost every web server environment. --- sapi/thttpd/Makefile.am | 2 + sapi/thttpd/README | 53 ++++++++ sapi/thttpd/config.m4 | 16 +++ sapi/thttpd/php.sym | 3 + sapi/thttpd/php_thttpd.h | 30 +++++ sapi/thttpd/thttpd.c | 285 +++++++++++++++++++++++++++++++++++++++ sapi/thttpd/thttpd_patch | 85 ++++++++++++ 7 files changed, 474 insertions(+) create mode 100644 sapi/thttpd/Makefile.am create mode 100644 sapi/thttpd/README create mode 100644 sapi/thttpd/config.m4 create mode 100644 sapi/thttpd/php.sym create mode 100644 sapi/thttpd/php_thttpd.h create mode 100644 sapi/thttpd/thttpd.c create mode 100644 sapi/thttpd/thttpd_patch diff --git a/sapi/thttpd/Makefile.am b/sapi/thttpd/Makefile.am new file mode 100644 index 0000000000..3affcbf4ff --- /dev/null +++ b/sapi/thttpd/Makefile.am @@ -0,0 +1,2 @@ +noinst_LTLIBRARIES = libphpsapi_thttpd.la +libphpsapi_thttpd_la_SOURCES = thttpd.c diff --git a/sapi/thttpd/README b/sapi/thttpd/README new file mode 100644 index 0000000000..7dc32d8a64 --- /dev/null +++ b/sapi/thttpd/README @@ -0,0 +1,53 @@ +README FOR THTTPD MODULE (by Sascha Schumann) ($Date$) + + This is a SAPI module for PHP 4.0 supporting thttpd, the tiny, + turbo, throttling HTTP server by Jef Poskanzer. + + The module contains a patch against version 2.10 of thttpd. The patch + adds hooks to thttpd to call PHP, if a filename matches *.php. This + patch will be applied when you install PHP. + + While functional, this module exists primarily to demonstrate the ability + of PHP to work in almost every web server environment. + +REQUIRED DOWNLOADS + + 1. thttpd 2.xx + + Full Distribution: + http://www.acme.com/software/thttpd/ + + 2. PHP 4.0.x + + Beta Versions: + http://www.php.net/version4/ + + Snapshots: + http://va.php.net/~sas/snapshots/ + + +BUILD INSTRUCTIONS + + 1. Extract software packages + + $ gunzip -c thttpd-2.xx.tar.gz | tar xf - + $ gunzip -c php-*.tar.gz | tar xf - + + 2. Prepare PHP + + $ cd php-* + $ ./configure \ + --with-thttpd=../thttpd-2.xx \ + + $ make install + $ cd .. + + You can see the list of valid PHP options by executing + + $ ./configure --help + + 3. Configure, compile, install thttpd + + Now follow the thttpd instructions. The Makefile template of + thttpd was changed to automatically use the components + required by PHP. diff --git a/sapi/thttpd/config.m4 b/sapi/thttpd/config.m4 new file mode 100644 index 0000000000..79ae3dbde1 --- /dev/null +++ b/sapi/thttpd/config.m4 @@ -0,0 +1,16 @@ +AC_ARG_WITH(thttpd, +[ --with-thttpd=SRCDIR],[ + test -d $withval || AC_MSG_RESULT(thttpd directory does not exist ($withval)) + AC_EXPAND_PATH($withval, THTTPD) + INSTALL_IT="\ + echo 'PHP_LIBS = -L. -lphp4 \$(PHP_LIBS) \$(EXTRA_LIBS)' > $THTTPD/php_makefile; \ + echo 'PHP_LDFLAGS = \$(NATIVE_RPATHS) \$(PHP_LDFLAGS)' >> $THTTPD/php_makefile; \ + cp $abs_srcdir/sapi/thttpd/php_thttpd.h $SAPI_STATIC $THTTPD;\ + test -f $THTTPD/php_patched || \ + (cd $THTTPD && patch < $abs_srcdir/sapi/thttpd/thttpd_patch && touch php_patched)" + AC_MSG_CHECKING(for thttpd) + AC_MSG_RESULT(yes - $THTTPD) + AC_ADD_INCLUDE($THTTPD) + PHP_BUILD_STATIC + PHP_SAPI=thttpd +]) diff --git a/sapi/thttpd/php.sym b/sapi/thttpd/php.sym new file mode 100644 index 0000000000..2214d3964d --- /dev/null +++ b/sapi/thttpd/php.sym @@ -0,0 +1,3 @@ +thttpd_php_request +thttpd_php_init +thttpd_php_shutdown diff --git a/sapi/thttpd/php_thttpd.h b/sapi/thttpd/php_thttpd.h new file mode 100644 index 0000000000..1bd81f969f --- /dev/null +++ b/sapi/thttpd/php_thttpd.h @@ -0,0 +1,30 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_THTTPD_H +#define PHP_THTTPD_H + +#include +#include +#include + +void thttpd_php_shutdown(void); +void thttpd_php_init(void); +off_t thttpd_php_request(httpd_conn *hc); + +#endif diff --git a/sapi/thttpd/thttpd.c b/sapi/thttpd/thttpd.c new file mode 100644 index 0000000000..c3ac2c5e7f --- /dev/null +++ b/sapi/thttpd/thttpd.c @@ -0,0 +1,285 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ +*/ + + +#include "php.h" +#include "SAPI.h" +#include "main.h" +#include "php_thttpd.h" +#include "version.h" + +typedef struct { + httpd_conn *hc; + int post_off; +} php_thttpd_globals; + +static php_thttpd_globals thttpd_globals; + +#define TLS_D +#define TLS_DC +#define TLS_C +#define TLS_CC +#define TG(v) (thttpd_globals.v) +#define TLS_FETCH() + +static int sapi_thttpd_ub_write(const char *str, uint str_length) +{ + TLS_FETCH(); + + return send(TG(hc)->conn_fd, str, str_length, 0); +} + +static int sapi_thttpd_send_headers(sapi_headers_struct *sapi_headers SLS_DC) +{ + char buf[1024]; + + if (!SG(sapi_headers).http_status_line) { + snprintf(buf, 1023, "HTTP/1.0 %d Something\r\n", SG(sapi_headers).http_response_code); + send(TG(hc)->conn_fd, buf, strlen(buf), 0); + } + + return SAPI_HEADER_DO_SEND; +} + +static void sapi_thttpd_send_header(sapi_header_struct *sapi_header, void *server_context) +{ + TLS_FETCH(); + + if (sapi_header) + send(TG(hc)->conn_fd, sapi_header->header, sapi_header->header_len, 0); + send(TG(hc)->conn_fd, "\r\n", sizeof("\r\n") - 1, 0); +} + +static int sapi_thttpd_read_post(char *buffer, uint count_bytes SLS_DC) +{ + size_t read_bytes = 0, tmp; + int c; + TLS_FETCH(); + + /* to understand this, read cgi_interpose_input() in libhttpd.c */ + c = TG(hc)->read_idx - TG(hc)->checked_idx; + if (c > 0) { + read_bytes = MIN(c, count_bytes); + memcpy(buffer, TG(hc)->read_buf + TG(hc)->checked_idx, read_bytes); + TG(hc)->checked_idx += read_bytes; + count_bytes -= read_bytes; + } + + count_bytes = MIN(count_bytes, + SG(request_info).content_length - SG(read_post_bytes) - TG(post_off)); + + while (read_bytes < count_bytes) { + tmp = recv(TG(hc)->conn_fd, buffer + read_bytes, + count_bytes - read_bytes, 0); + if (tmp <= 0) + break; + read_bytes += tmp; + } + + return read_bytes; +} + +static char *sapi_thttpd_read_cookies(SLS_D) +{ + TLS_FETCH(); + + return TG(hc)->cookie; +} + +static sapi_module_struct sapi_module = { + "PHP Language", + + php_module_startup, + php_module_shutdown_wrapper, + + sapi_thttpd_ub_write, + php_error, + + NULL, + sapi_thttpd_send_headers, + sapi_thttpd_send_header, + sapi_thttpd_read_post, + sapi_thttpd_read_cookies, + + STANDARD_SAPI_MODULE_PROPERTIES +}; + +#define BUF_SIZE 512 +#define ADD_STRING(name) \ + MAKE_STD_ZVAL(pval); \ + pval->type = IS_STRING; \ + pval->value.str.len = strlen(buf); \ + pval->value.str.val = estrndup(buf, pval->value.str.len); \ + zend_hash_update(&EG(symbol_table), name, sizeof(name), \ + &pval, sizeof(zval *), NULL) + +static void thttpd_hash_environment(void) +{ + char buf[BUF_SIZE + 1]; + zval *pval; + + buf[BUF_SIZE] = '\0'; + + strncpy(buf, SERVER_SOFTWARE, BUF_SIZE); + ADD_STRING("SERVER_SOFTWARE"); + + strncpy(buf, "CGI/1.1", BUF_SIZE); + ADD_STRING("GATEWAY_INTERFACE"); + + snprintf(buf, BUF_SIZE, "%d", TG(hc)->hs->port); + ADD_STRING("SERVER_PORT"); + + strncpy(buf, SG(request_info).request_method, BUF_SIZE); + ADD_STRING("REQUEST_METHOD"); + + strncpy(buf, SG(request_info).request_uri, BUF_SIZE); + ADD_STRING("REQUEST_URI"); + + snprintf(buf, BUF_SIZE, "/%s", TG(hc)->pathinfo); + ADD_STRING("PATH_INFO"); + + strncpy(buf, SG(request_info).path_translated, BUF_SIZE); + ADD_STRING("PATH_TRANSLATED"); + + snprintf(buf, BUF_SIZE, "/%s", TG(hc)->origfilename); + ADD_STRING("SCRIPT_NAME"); + + strncpy(buf, inet_ntoa(TG(hc)->client_addr), BUF_SIZE); + ADD_STRING("REMOTE_ADDR"); + ADD_STRING("REMOTE_HOST"); + +#define CONDADD(name, field) \ + if (TG(hc)->field[0]) { \ + strncpy(buf, TG(hc)->field, BUF_SIZE); \ + ADD_STRING(#name); \ + } + + CONDADD(HTTP_REFERER, referer); + CONDADD(HTTP_USER_AGENT, useragent); + CONDADD(HTTP_ACCEPT, accept); + CONDADD(HTTP_ACCEPT_ENCODING, accepte); + CONDADD(HTTP_COOKIE, cookie); + CONDADD(CONTENT_TYPE, contenttype); + CONDADD(REMOTE_USER, remoteuser); + CONDADD(SERVER_PROTOCOL, protocol); + + if (TG(hc)->contentlength != -1) { + sprintf(buf, "%ld", (long) TG(hc)->contentlength); + ADD_STRING("CONTENT_LENGTH"); + } + + if (TG(hc)->authorization[0]) { + strcpy(buf, "Basic"); + ADD_STRING("AUTH_TYPE"); + } +} + +static void thttpd_module_main(TLS_D SLS_DC) +{ + zend_file_handle file_handle; + CLS_FETCH(); + ELS_FETCH(); + PLS_FETCH(); + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = TG(hc)->expnfilename; + file_handle.free_filename = 0; + + if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC) == FAILURE) { + return; + } + + thttpd_hash_environment(); + php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); + php_request_shutdown(NULL); +} + +static void thttpd_request_ctor(TLS_D SLS_DC) +{ + char *cp2; + int l; + char buf[1024]; + int offset; + size_t pathinfo_len; + size_t cwd_len; + + pathinfo_len = strlen(TG(hc)->pathinfo); + cwd_len = strlen(TG(hc)->hs->cwd); + + SG(request_info).query_string = TG(hc)->query; + + l = cwd_len + pathinfo_len + 1; + cp2 = (char *) malloc(l); + sprintf(cp2, "%s%s", TG(hc)->hs->cwd, TG(hc)->pathinfo); + SG(request_info).path_translated = cp2; + + snprintf(buf, 1023, "/%s", TG(hc)->origfilename); + SG(request_info).request_uri = strdup(buf); + SG(request_info).request_method = httpd_method_str(TG(hc)->method); + + SG(request_info).content_type = TG(hc)->contenttype; + SG(request_info).content_length = TG(hc)->contentlength; + + SG(request_info).auth_user = NULL; + SG(request_info).auth_password = NULL; + + TG(post_off) = TG(hc)->read_idx - TG(hc)->checked_idx; + + /* avoid feeding \r\n from POST data to SAPI */ + offset = TG(post_off) - SG(request_info).content_length; + + if (offset > 0) { + TG(post_off) -= offset; + TG(hc)->read_idx -= offset; + } +} + +static void thttpd_request_dtor(TLS_D SLS_DC) +{ + free(SG(request_info).request_uri); + free(SG(request_info).path_translated); +} + +off_t thttpd_php_request(httpd_conn *hc) +{ + SLS_FETCH(); + TLS_FETCH(); + + TG(hc) = hc; + + thttpd_request_ctor(TLS_C SLS_CC); + + thttpd_module_main(TLS_C SLS_CC); + + thttpd_request_dtor(TLS_C SLS_CC); + + return 0; +} + +void thttpd_php_init(void) +{ + sapi_startup(&sapi_module); + sapi_module.startup(&sapi_module); + SG(server_context) = (void *) 1; +} + +void thttpd_php_shutdown(void) +{ + sapi_module.shutdown(&sapi_module); + sapi_shutdown(); +} diff --git a/sapi/thttpd/thttpd_patch b/sapi/thttpd/thttpd_patch new file mode 100644 index 0000000000..fc9fb7d47c --- /dev/null +++ b/sapi/thttpd/thttpd_patch @@ -0,0 +1,85 @@ +diff -ur thttpd-2.10/Makefile.in thttpd-2.10-php/Makefile.in +--- thttpd-2.10/Makefile.in Mon Oct 11 20:45:38 1999 ++++ thttpd-2.10-php/Makefile.in Mon Dec 20 01:37:49 1999 +@@ -46,13 +46,15 @@ + + # You shouldn't need to edit anything below here. + ++include php_makefile ++ + CC = @CC@ + CCOPT = @V_CCOPT@ + DEFS = @DEFS@ + INCLS = -I. + CFLAGS = $(CCOPT) $(DEFS) $(INCLS) +-LDFLAGS = @LDFLAGS@ +-LIBS = @LIBS@ ++LDFLAGS = @LDFLAGS@ $(PHP_LDFLAGS) ++LIBS = @LIBS@ $(PHP_LIBS) + NETLIBS = @V_NETLIBS@ + INSTALL = @INSTALL@ + +diff -ur thttpd-2.10/libhttpd.c thttpd-2.10-php/libhttpd.c +--- thttpd-2.10/libhttpd.c Wed Dec 15 23:22:50 1999 ++++ thttpd-2.10-php/libhttpd.c Mon Dec 20 01:05:47 1999 +@@ -75,6 +75,8 @@ + #include "match.h" + #include "tdate_parse.h" + ++#include "php_thttpd.h" ++ + #ifndef STDIN_FILENO + #define STDIN_FILENO 0 + #endif +@@ -211,7 +213,11 @@ + free( (void*) hs->cwd ); + if ( hs->cgi_pattern != (char*) 0 ) + free( (void*) hs->cgi_pattern ); ++ if ( hs->php_pattern != (char*) 0 ) ++ free( (void *) hs->php_pattern ); + free( (void*) hs ); ++ ++ thttpd_php_shutdown(); + } + + +@@ -244,6 +250,7 @@ + else + hs->hostname = strdup( hostname ); + hs->port = port; ++ hs->php_pattern = strdup("*.php"); + if ( cgi_pattern == (char*) 0 ) + hs->cgi_pattern = (char*) 0; + else +@@ -272,6 +279,8 @@ + hs->no_symlinks = no_symlinks; + hs->vhost = vhost; + ++ thttpd_php_init(); ++ + /* Create socket. */ + hs->listen_fd = socket( AF_INET, SOCK_STREAM, 0 ); + if ( hs->listen_fd < 0 ) +@@ -3129,6 +3138,11 @@ + ( hc->sb.st_mode & S_IXOTH ) && + match( hc->hs->cgi_pattern, hc->expnfilename ) ) + return cgi( hc ); ++ ++ if ( hc->hs->php_pattern != (char*) 0 && ++ match( hc->hs->php_pattern, hc->expnfilename)) { ++ return thttpd_php_request( hc ); ++ } + + /* It's not CGI. If it's executable or there's pathinfo, someone's + ** trying to either serve or run a non-CGI file as CGI. Either case +diff -ur thttpd-2.10/libhttpd.h thttpd-2.10-php/libhttpd.h +--- thttpd-2.10/libhttpd.h Wed Dec 8 19:53:34 1999 ++++ thttpd-2.10-php/libhttpd.h Mon Dec 20 01:06:09 1999 +@@ -57,6 +57,7 @@ + struct in_addr host_addr; + int port; + char* cgi_pattern; ++ char* php_pattern; + char* cwd; + int listen_fd; + FILE* logfp; -- 2.40.0