1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.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 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Thies C. Arntzen <thies@thieso.net> |
16 | Based on aolserver SAPI by Sascha Schumann <sascha@schumann.cx> |
17 +----------------------------------------------------------------------+
18 */
19
20 #include "php.h"
21 #include "SAPI.h"
22 #include "php_main.h"
23
24 #ifdef HAVE_PHTTPD
25
26 #include "ext/standard/info.h"
27
28 #ifndef ZTS
29 #error PHTTPD module is only useable in thread-safe mode
30 #endif
31
32 #include "php_phttpd.h"
33
34 typedef struct {
35 struct connectioninfo *cip;
36 struct stat sb;
37 } phttpd_globals_struct;
38
39 static int ph_globals_id;
40
41 #define PHG(v) TSRMG(ph_globals_id, phttpd_globals_struct *, v)
42
43 static int
php_phttpd_startup(sapi_module_struct * sapi_module)44 php_phttpd_startup(sapi_module_struct *sapi_module)
45 {
46 fprintf(stderr,"***php_phttpd_startup\n");
47
48 if (php_module_startup(sapi_module, NULL, 0)) {
49 return FAILURE;
50 } else {
51 return SUCCESS;
52 }
53 }
54
55 static int
php_phttpd_sapi_ub_write(const char * str,uint str_length TSRMLS_DC)56 php_phttpd_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
57 {
58 int sent_bytes;
59
60 sent_bytes = fd_write(PHG(cip)->fd, str, str_length);
61
62 if (sent_bytes == -1) {
63 php_handle_aborted_connection();
64 }
65
66 return sent_bytes;
67 }
68
69 static int
php_phttpd_sapi_header_handler(sapi_header_struct * sapi_header,sapi_headers_struct * sapi_headers TSRMLS_DC)70 php_phttpd_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
71 {
72 char *header_name, *header_content;
73 char *p;
74 TSRMLS_FETCH();
75
76 http_sendheaders(PHG(cip)->fd, PHG(cip), SG(sapi_headers).http_response_code, NULL);
77
78 header_name = sapi_header->header;
79 header_content = p = strchr(header_name, ':');
80
81 if (p) {
82 *p = '\0';
83 do {
84 header_content++;
85 } while (*header_content == ' ');
86
87 fd_printf(PHG(cip)->fd,"%s: %s\n", header_name, header_content);
88
89 *p = ':';
90 }
91
92 sapi_free_header(sapi_header);
93
94 return 0;
95 }
96
97 static int
php_phttpd_sapi_send_headers(sapi_headers_struct * sapi_headers TSRMLS_DC)98 php_phttpd_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
99 {
100 TSRMLS_FETCH();
101
102 if (SG(sapi_headers).send_default_content_type) {
103 fd_printf(PHG(cip)->fd,"Content-Type: text/html\n");
104 }
105
106 fd_putc('\n', PHG(cip)->fd);
107
108 return SAPI_HEADER_SENT_SUCCESSFULLY;
109 }
110
111 static char *
php_phttpd_sapi_read_cookies(TSRMLS_D)112 php_phttpd_sapi_read_cookies(TSRMLS_D)
113 {
114
115 /*
116 int i;
117 char *http_cookie = NULL;
118 NTSRMLS_FETCH();
119
120 i = Ns_SetIFind(NSG(conn->headers), "cookie");
121 if(i != -1) {
122 http_cookie = Ns_SetValue(NSG(conn->headers), i);
123 }
124
125 return http_cookie;
126 */
127 fprintf(stderr,"***php_phttpd_sapi_read_cookies\n");
128
129 return 0;
130 }
131
132 static int
php_phttpd_sapi_read_post(char * buf,uint count_bytes TSRMLS_DC)133 php_phttpd_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
134 {
135 /*
136 uint max_read;
137 uint total_read = 0;
138 NTSRMLS_FETCH();
139
140 max_read = MIN(NSG(data_avail), count_bytes);
141
142 total_read = Ns_ConnRead(NSG(conn), buf, max_read);
143
144 if(total_read == NS_ERROR) {
145 total_read = -1;
146 } else {
147 NSG(data_avail) -= total_read;
148 }
149
150 return total_read;
151 */
152 fprintf(stderr,"***php_phttpd_sapi_read_post\n");
153 return 0;
154 }
155
156 static sapi_module_struct phttpd_sapi_module = {
157 "phttpd",
158 "PHTTPD",
159
160 php_phttpd_startup, /* startup */
161 php_module_shutdown_wrapper, /* shutdown */
162
163 NULL, /* activate */
164 NULL, /* deactivate */
165
166 php_phttpd_sapi_ub_write, /* unbuffered write */
167 NULL, /* flush */
168 NULL, /* get uid */
169 NULL, /* getenv */
170
171 php_error, /* error handler */
172
173 php_phttpd_sapi_header_handler, /* header handler */
174 php_phttpd_sapi_send_headers, /* send headers handler */
175 NULL, /* send header handler */
176
177 php_phttpd_sapi_read_post, /* read POST data */
178 php_phttpd_sapi_read_cookies, /* read Cookies */
179
180 NULL, /* register server variables */
181 NULL, /* Log message */
182 NULL, /* Get request time */
183 NULL, /* Child terminate */
184
185 STANDARD_SAPI_MODULE_PROPERTIES
186 };
187
188 static void
php_phttpd_request_ctor(TSRMLS_D TSRMLS_DC)189 php_phttpd_request_ctor(TSRMLS_D TSRMLS_DC)
190 {
191 memset(&SG(request_info), 0, sizeof(sapi_globals_struct)); /* pfusch! */
192
193 SG(request_info).query_string = PHG(cip)->hip->request;
194 SG(request_info).request_method = PHG(cip)->hip->method;
195 SG(request_info).path_translated = malloc(MAXPATHLEN);
196 SG(sapi_headers).http_response_code = 200;
197 if (url_expand(PHG(cip)->hip->url, SG(request_info).path_translated, MAXPATHLEN, &PHG(sb), NULL, NULL) == NULL) {
198 /* handle error */
199 }
200
201 #if 0
202 char *server;
203 Ns_DString ds;
204 char *root;
205 int index;
206 char *tmp;
207
208 server = Ns_ConnServer(NSG(conn));
209
210 Ns_DStringInit(&ds);
211 Ns_UrlToFile(&ds, server, NSG(conn->request->url));
212
213 /* path_translated is the absolute path to the file */
214 SG(request_info).path_translated = strdup(Ns_DStringValue(&ds));
215 Ns_DStringFree(&ds);
216 root = Ns_PageRoot(server);
217 SG(request_info).request_uri = SG(request_info).path_translated + strlen(root);
218 SG(request_info).content_length = Ns_ConnContentLength(NSG(conn));
219 index = Ns_SetIFind(NSG(conn)->headers, "content-type");
220 SG(request_info).content_type = index == -1 ? NULL :
221 Ns_SetValue(NSG(conn)->headers, index);
222
223 tmp = Ns_ConnAuthUser(NSG(conn));
224 if(tmp) {
225 tmp = estrdup(tmp);
226 }
227 SG(request_info).auth_user = tmp;
228
229 tmp = Ns_ConnAuthPasswd(NSG(conn));
230 if(tmp) {
231 tmp = estrdup(tmp);
232 }
233 SG(request_info).auth_password = tmp;
234
235 NSG(data_avail) = SG(request_info).content_length;
236 #endif
237 }
238
239 static void
php_phttpd_request_dtor(TSRMLS_D TSRMLS_DC)240 php_phttpd_request_dtor(TSRMLS_D TSRMLS_DC)
241 {
242 free(SG(request_info).path_translated);
243 }
244
245
php_doit(TSRMLS_D TSRMLS_DC)246 int php_doit(TSRMLS_D TSRMLS_DC)
247 {
248 struct stat sb;
249 zend_file_handle file_handle;
250 struct httpinfo *hip = PHG(cip)->hip;
251 TSRMLS_FETCH();
252
253 if (php_request_startup(TSRMLS_C) == FAILURE) {
254 return -1;
255 }
256
257 file_handle.type = ZEND_HANDLE_FILENAME;
258 file_handle.filename = SG(request_info).path_translated;
259 file_handle.free_filename = 0;
260
261 /*
262 php_phttpd_hash_environment(TSRMLS_C);
263 */
264 php_execute_script(&file_handle TSRMLS_CC);
265 php_request_shutdown(NULL);
266
267 return SG(sapi_headers).http_response_code;
268 }
269
pm_init(const char ** argv)270 int pm_init(const char **argv)
271 {
272 tsrm_startup(1, 1, 0, NULL);
273 sapi_startup(&phttpd_sapi_module);
274 phttpd_sapi_module.startup(&phttpd_sapi_module);
275
276 ts_allocate_id(&ph_globals_id, sizeof(phttpd_globals_struct), NULL, NULL);
277
278 return 0;
279 }
280
pm_exit(void)281 void pm_exit(void)
282 {
283 fprintf(stderr,"***pm_exit\n");
284 }
285
pm_request(struct connectioninfo * cip)286 int pm_request(struct connectioninfo *cip)
287 {
288 struct httpinfo *hip = cip->hip;
289 int status;
290 TSRMLS_FETCH();
291
292 if (strcasecmp(hip->method, "GET") == 0 ||
293 strcasecmp(hip->method, "HEAD") == 0 ||
294 strcasecmp(hip->method, "POST") == 0) {
295 PHG(cip) = cip;
296
297 php_phttpd_request_ctor(TSRMLS_C);
298 status = php_doit(TSRMLS_C);
299 php_phttpd_request_dtor(TSRMLS_C);
300
301 return status;
302 } else {
303 return -2;
304 }
305 }
306
307 #endif
308