]> granicus.if.org Git - php/commitdiff
Add SAPI module for thttpd server. Quote from the README:
authorSascha Schumann <sas@php.net>
Mon, 20 Dec 1999 07:11:14 +0000 (07:11 +0000)
committerSascha Schumann <sas@php.net>
Mon, 20 Dec 1999 07:11:14 +0000 (07:11 +0000)
    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 [new file with mode: 0644]
sapi/thttpd/README [new file with mode: 0644]
sapi/thttpd/config.m4 [new file with mode: 0644]
sapi/thttpd/php.sym [new file with mode: 0644]
sapi/thttpd/php_thttpd.h [new file with mode: 0644]
sapi/thttpd/thttpd.c [new file with mode: 0644]
sapi/thttpd/thttpd_patch [new file with mode: 0644]

diff --git a/sapi/thttpd/Makefile.am b/sapi/thttpd/Makefile.am
new file mode 100644 (file)
index 0000000..3affcbf
--- /dev/null
@@ -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 (file)
index 0000000..7dc32d8
--- /dev/null
@@ -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 \
+                       <further PHP options>
+          $ 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 (file)
index 0000000..79ae3db
--- /dev/null
@@ -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 (file)
index 0000000..2214d39
--- /dev/null
@@ -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 (file)
index 0000000..1bd81f9
--- /dev/null
@@ -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 <sascha@schumann.cx>                         |
+   +----------------------------------------------------------------------+
+*/
+
+#ifndef PHP_THTTPD_H
+#define PHP_THTTPD_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <libhttpd.h>
+
+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 (file)
index 0000000..c3ac2c5
--- /dev/null
@@ -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 <sascha@schumann.cx>                         |
+   +----------------------------------------------------------------------+
+*/
+
+
+#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 (file)
index 0000000..fc9fb7d
--- /dev/null
@@ -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;