Skip to content

Commit 56a5e84

Browse files
author
Sascha Schumann
committed
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.
1 parent f5d5637 commit 56a5e84

File tree

7 files changed

+474
-0
lines changed

7 files changed

+474
-0
lines changed

sapi/thttpd/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
noinst_LTLIBRARIES = libphpsapi_thttpd.la
2+
libphpsapi_thttpd_la_SOURCES = thttpd.c

sapi/thttpd/README

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
README FOR THTTPD MODULE (by Sascha Schumann) ($Date$)
2+
3+
This is a SAPI module for PHP 4.0 supporting thttpd, the tiny,
4+
turbo, throttling HTTP server by Jef Poskanzer.
5+
6+
The module contains a patch against version 2.10 of thttpd. The patch
7+
adds hooks to thttpd to call PHP, if a filename matches *.php. This
8+
patch will be applied when you install PHP.
9+
10+
While functional, this module exists primarily to demonstrate the ability
11+
of PHP to work in almost every web server environment.
12+
13+
REQUIRED DOWNLOADS
14+
15+
1. thttpd 2.xx
16+
17+
Full Distribution:
18+
http://www.acme.com/software/thttpd/
19+
20+
2. PHP 4.0.x
21+
22+
Beta Versions:
23+
http://www.php.net/version4/
24+
25+
Snapshots:
26+
http://va.php.net/~sas/snapshots/
27+
28+
29+
BUILD INSTRUCTIONS
30+
31+
1. Extract software packages
32+
33+
$ gunzip -c thttpd-2.xx.tar.gz | tar xf -
34+
$ gunzip -c php-*.tar.gz | tar xf -
35+
36+
2. Prepare PHP
37+
38+
$ cd php-*
39+
$ ./configure \
40+
--with-thttpd=../thttpd-2.xx \
41+
<further PHP options>
42+
$ make install
43+
$ cd ..
44+
45+
You can see the list of valid PHP options by executing
46+
47+
$ ./configure --help
48+
49+
3. Configure, compile, install thttpd
50+
51+
Now follow the thttpd instructions. The Makefile template of
52+
thttpd was changed to automatically use the components
53+
required by PHP.

sapi/thttpd/config.m4

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
AC_ARG_WITH(thttpd,
2+
[ --with-thttpd=SRCDIR],[
3+
test -d $withval || AC_MSG_RESULT(thttpd directory does not exist ($withval))
4+
AC_EXPAND_PATH($withval, THTTPD)
5+
INSTALL_IT="\
6+
echo 'PHP_LIBS = -L. -lphp4 \$(PHP_LIBS) \$(EXTRA_LIBS)' > $THTTPD/php_makefile; \
7+
echo 'PHP_LDFLAGS = \$(NATIVE_RPATHS) \$(PHP_LDFLAGS)' >> $THTTPD/php_makefile; \
8+
cp $abs_srcdir/sapi/thttpd/php_thttpd.h $SAPI_STATIC $THTTPD;\
9+
test -f $THTTPD/php_patched || \
10+
(cd $THTTPD && patch < $abs_srcdir/sapi/thttpd/thttpd_patch && touch php_patched)"
11+
AC_MSG_CHECKING(for thttpd)
12+
AC_MSG_RESULT(yes - $THTTPD)
13+
AC_ADD_INCLUDE($THTTPD)
14+
PHP_BUILD_STATIC
15+
PHP_SAPI=thttpd
16+
])

sapi/thttpd/php.sym

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
thttpd_php_request
2+
thttpd_php_init
3+
thttpd_php_shutdown

sapi/thttpd/php_thttpd.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP version 4.0 |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 1997, 1998, 1999 The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 2.0 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available at through the world-wide-web at |
10+
| http://www.php.net/license/2_0.txt. |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| [email protected] so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Author: Sascha Schumann <[email protected]> |
16+
+----------------------------------------------------------------------+
17+
*/
18+
19+
#ifndef PHP_THTTPD_H
20+
#define PHP_THTTPD_H
21+
22+
#include <sys/types.h>
23+
#include <sys/stat.h>
24+
#include <libhttpd.h>
25+
26+
void thttpd_php_shutdown(void);
27+
void thttpd_php_init(void);
28+
off_t thttpd_php_request(httpd_conn *hc);
29+
30+
#endif

sapi/thttpd/thttpd.c

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP version 4.0 |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 1997, 1998, 1999 The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 2.0 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available at through the world-wide-web at |
10+
| http://www.php.net/license/2_0.txt. |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| [email protected] so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Author: Sascha Schumann <[email protected]> |
16+
+----------------------------------------------------------------------+
17+
*/
18+
19+
20+
#include "php.h"
21+
#include "SAPI.h"
22+
#include "main.h"
23+
#include "php_thttpd.h"
24+
#include "version.h"
25+
26+
typedef struct {
27+
httpd_conn *hc;
28+
int post_off;
29+
} php_thttpd_globals;
30+
31+
static php_thttpd_globals thttpd_globals;
32+
33+
#define TLS_D
34+
#define TLS_DC
35+
#define TLS_C
36+
#define TLS_CC
37+
#define TG(v) (thttpd_globals.v)
38+
#define TLS_FETCH()
39+
40+
static int sapi_thttpd_ub_write(const char *str, uint str_length)
41+
{
42+
TLS_FETCH();
43+
44+
return send(TG(hc)->conn_fd, str, str_length, 0);
45+
}
46+
47+
static int sapi_thttpd_send_headers(sapi_headers_struct *sapi_headers SLS_DC)
48+
{
49+
char buf[1024];
50+
51+
if (!SG(sapi_headers).http_status_line) {
52+
snprintf(buf, 1023, "HTTP/1.0 %d Something\r\n", SG(sapi_headers).http_response_code);
53+
send(TG(hc)->conn_fd, buf, strlen(buf), 0);
54+
}
55+
56+
return SAPI_HEADER_DO_SEND;
57+
}
58+
59+
static void sapi_thttpd_send_header(sapi_header_struct *sapi_header, void *server_context)
60+
{
61+
TLS_FETCH();
62+
63+
if (sapi_header)
64+
send(TG(hc)->conn_fd, sapi_header->header, sapi_header->header_len, 0);
65+
send(TG(hc)->conn_fd, "\r\n", sizeof("\r\n") - 1, 0);
66+
}
67+
68+
static int sapi_thttpd_read_post(char *buffer, uint count_bytes SLS_DC)
69+
{
70+
size_t read_bytes = 0, tmp;
71+
int c;
72+
TLS_FETCH();
73+
74+
/* to understand this, read cgi_interpose_input() in libhttpd.c */
75+
c = TG(hc)->read_idx - TG(hc)->checked_idx;
76+
if (c > 0) {
77+
read_bytes = MIN(c, count_bytes);
78+
memcpy(buffer, TG(hc)->read_buf + TG(hc)->checked_idx, read_bytes);
79+
TG(hc)->checked_idx += read_bytes;
80+
count_bytes -= read_bytes;
81+
}
82+
83+
count_bytes = MIN(count_bytes,
84+
SG(request_info).content_length - SG(read_post_bytes) - TG(post_off));
85+
86+
while (read_bytes < count_bytes) {
87+
tmp = recv(TG(hc)->conn_fd, buffer + read_bytes,
88+
count_bytes - read_bytes, 0);
89+
if (tmp <= 0)
90+
break;
91+
read_bytes += tmp;
92+
}
93+
94+
return read_bytes;
95+
}
96+
97+
static char *sapi_thttpd_read_cookies(SLS_D)
98+
{
99+
TLS_FETCH();
100+
101+
return TG(hc)->cookie;
102+
}
103+
104+
static sapi_module_struct sapi_module = {
105+
"PHP Language",
106+
107+
php_module_startup,
108+
php_module_shutdown_wrapper,
109+
110+
sapi_thttpd_ub_write,
111+
php_error,
112+
113+
NULL,
114+
sapi_thttpd_send_headers,
115+
sapi_thttpd_send_header,
116+
sapi_thttpd_read_post,
117+
sapi_thttpd_read_cookies,
118+
119+
STANDARD_SAPI_MODULE_PROPERTIES
120+
};
121+
122+
#define BUF_SIZE 512
123+
#define ADD_STRING(name) \
124+
MAKE_STD_ZVAL(pval); \
125+
pval->type = IS_STRING; \
126+
pval->value.str.len = strlen(buf); \
127+
pval->value.str.val = estrndup(buf, pval->value.str.len); \
128+
zend_hash_update(&EG(symbol_table), name, sizeof(name), \
129+
&pval, sizeof(zval *), NULL)
130+
131+
static void thttpd_hash_environment(void)
132+
{
133+
char buf[BUF_SIZE + 1];
134+
zval *pval;
135+
136+
buf[BUF_SIZE] = '\0';
137+
138+
strncpy(buf, SERVER_SOFTWARE, BUF_SIZE);
139+
ADD_STRING("SERVER_SOFTWARE");
140+
141+
strncpy(buf, "CGI/1.1", BUF_SIZE);
142+
ADD_STRING("GATEWAY_INTERFACE");
143+
144+
snprintf(buf, BUF_SIZE, "%d", TG(hc)->hs->port);
145+
ADD_STRING("SERVER_PORT");
146+
147+
strncpy(buf, SG(request_info).request_method, BUF_SIZE);
148+
ADD_STRING("REQUEST_METHOD");
149+
150+
strncpy(buf, SG(request_info).request_uri, BUF_SIZE);
151+
ADD_STRING("REQUEST_URI");
152+
153+
snprintf(buf, BUF_SIZE, "/%s", TG(hc)->pathinfo);
154+
ADD_STRING("PATH_INFO");
155+
156+
strncpy(buf, SG(request_info).path_translated, BUF_SIZE);
157+
ADD_STRING("PATH_TRANSLATED");
158+
159+
snprintf(buf, BUF_SIZE, "/%s", TG(hc)->origfilename);
160+
ADD_STRING("SCRIPT_NAME");
161+
162+
strncpy(buf, inet_ntoa(TG(hc)->client_addr), BUF_SIZE);
163+
ADD_STRING("REMOTE_ADDR");
164+
ADD_STRING("REMOTE_HOST");
165+
166+
#define CONDADD(name, field) \
167+
if (TG(hc)->field[0]) { \
168+
strncpy(buf, TG(hc)->field, BUF_SIZE); \
169+
ADD_STRING(#name); \
170+
}
171+
172+
CONDADD(HTTP_REFERER, referer);
173+
CONDADD(HTTP_USER_AGENT, useragent);
174+
CONDADD(HTTP_ACCEPT, accept);
175+
CONDADD(HTTP_ACCEPT_ENCODING, accepte);
176+
CONDADD(HTTP_COOKIE, cookie);
177+
CONDADD(CONTENT_TYPE, contenttype);
178+
CONDADD(REMOTE_USER, remoteuser);
179+
CONDADD(SERVER_PROTOCOL, protocol);
180+
181+
if (TG(hc)->contentlength != -1) {
182+
sprintf(buf, "%ld", (long) TG(hc)->contentlength);
183+
ADD_STRING("CONTENT_LENGTH");
184+
}
185+
186+
if (TG(hc)->authorization[0]) {
187+
strcpy(buf, "Basic");
188+
ADD_STRING("AUTH_TYPE");
189+
}
190+
}
191+
192+
static void thttpd_module_main(TLS_D SLS_DC)
193+
{
194+
zend_file_handle file_handle;
195+
CLS_FETCH();
196+
ELS_FETCH();
197+
PLS_FETCH();
198+
199+
file_handle.type = ZEND_HANDLE_FILENAME;
200+
file_handle.filename = TG(hc)->expnfilename;
201+
file_handle.free_filename = 0;
202+
203+
if (php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC) == FAILURE) {
204+
return;
205+
}
206+
207+
thttpd_hash_environment();
208+
php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC);
209+
php_request_shutdown(NULL);
210+
}
211+
212+
static void thttpd_request_ctor(TLS_D SLS_DC)
213+
{
214+
char *cp2;
215+
int l;
216+
char buf[1024];
217+
int offset;
218+
size_t pathinfo_len;
219+
size_t cwd_len;
220+
221+
pathinfo_len = strlen(TG(hc)->pathinfo);
222+
cwd_len = strlen(TG(hc)->hs->cwd);
223+
224+
SG(request_info).query_string = TG(hc)->query;
225+
226+
l = cwd_len + pathinfo_len + 1;
227+
cp2 = (char *) malloc(l);
228+
sprintf(cp2, "%s%s", TG(hc)->hs->cwd, TG(hc)->pathinfo);
229+
SG(request_info).path_translated = cp2;
230+
231+
snprintf(buf, 1023, "/%s", TG(hc)->origfilename);
232+
SG(request_info).request_uri = strdup(buf);
233+
SG(request_info).request_method = httpd_method_str(TG(hc)->method);
234+
235+
SG(request_info).content_type = TG(hc)->contenttype;
236+
SG(request_info).content_length = TG(hc)->contentlength;
237+
238+
SG(request_info).auth_user = NULL;
239+
SG(request_info).auth_password = NULL;
240+
241+
TG(post_off) = TG(hc)->read_idx - TG(hc)->checked_idx;
242+
243+
/* avoid feeding \r\n from POST data to SAPI */
244+
offset = TG(post_off) - SG(request_info).content_length;
245+
246+
if (offset > 0) {
247+
TG(post_off) -= offset;
248+
TG(hc)->read_idx -= offset;
249+
}
250+
}
251+
252+
static void thttpd_request_dtor(TLS_D SLS_DC)
253+
{
254+
free(SG(request_info).request_uri);
255+
free(SG(request_info).path_translated);
256+
}
257+
258+
off_t thttpd_php_request(httpd_conn *hc)
259+
{
260+
SLS_FETCH();
261+
TLS_FETCH();
262+
263+
TG(hc) = hc;
264+
265+
thttpd_request_ctor(TLS_C SLS_CC);
266+
267+
thttpd_module_main(TLS_C SLS_CC);
268+
269+
thttpd_request_dtor(TLS_C SLS_CC);
270+
271+
return 0;
272+
}
273+
274+
void thttpd_php_init(void)
275+
{
276+
sapi_startup(&sapi_module);
277+
sapi_module.startup(&sapi_module);
278+
SG(server_context) = (void *) 1;
279+
}
280+
281+
void thttpd_php_shutdown(void)
282+
{
283+
sapi_module.shutdown(&sapi_module);
284+
sapi_shutdown();
285+
}

0 commit comments

Comments
 (0)