1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2016 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
75 http_sendheaders(PHG(cip)->fd, PHG(cip), SG(sapi_headers).http_response_code, NULL);
76
77 header_name = sapi_header->header;
78 header_content = p = strchr(header_name, ':');
79
80 if (p) {
81 *p = '\0';
82 do {
83 header_content++;
84 } while (*header_content == ' ');
85
86 fd_printf(PHG(cip)->fd,"%s: %s\n", header_name, header_content);
87
88 *p = ':';
89 }
90
91 sapi_free_header(sapi_header);
92
93 return 0;
94 }
95
96 static int
php_phttpd_sapi_send_headers(sapi_headers_struct * sapi_headers TSRMLS_DC)97 php_phttpd_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
98 {
99 if (SG(sapi_headers).send_default_content_type) {
100 fd_printf(PHG(cip)->fd,"Content-Type: text/html\n");
101 }
102
103 fd_putc('\n', PHG(cip)->fd);
104
105 return SAPI_HEADER_SENT_SUCCESSFULLY;
106 }
107
108 static char *
php_phttpd_sapi_read_cookies(TSRMLS_D)109 php_phttpd_sapi_read_cookies(TSRMLS_D)
110 {
111
112 /*
113 int i;
114 char *http_cookie = NULL;
115
116 i = Ns_SetIFind(NSG(conn->headers), "cookie");
117 if(i != -1) {
118 http_cookie = Ns_SetValue(NSG(conn->headers), i);
119 }
120
121 return http_cookie;
122 */
123 fprintf(stderr,"***php_phttpd_sapi_read_cookies\n");
124
125 return 0;
126 }
127
128 static int
php_phttpd_sapi_read_post(char * buf,uint count_bytes TSRMLS_DC)129 php_phttpd_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
130 {
131 /*
132 uint max_read;
133 uint total_read = 0;
134
135 max_read = MIN(NSG(data_avail), count_bytes);
136
137 total_read = Ns_ConnRead(NSG(conn), buf, max_read);
138
139 if(total_read == NS_ERROR) {
140 total_read = -1;
141 } else {
142 NSG(data_avail) -= total_read;
143 }
144
145 return total_read;
146 */
147 fprintf(stderr,"***php_phttpd_sapi_read_post\n");
148 return 0;
149 }
150
151 static sapi_module_struct phttpd_sapi_module = {
152 "phttpd",
153 "PHTTPD",
154
155 php_phttpd_startup, /* startup */
156 php_module_shutdown_wrapper, /* shutdown */
157
158 NULL, /* activate */
159 NULL, /* deactivate */
160
161 php_phttpd_sapi_ub_write, /* unbuffered write */
162 NULL, /* flush */
163 NULL, /* get uid */
164 NULL, /* getenv */
165
166 php_error, /* error handler */
167
168 php_phttpd_sapi_header_handler, /* header handler */
169 php_phttpd_sapi_send_headers, /* send headers handler */
170 NULL, /* send header handler */
171
172 php_phttpd_sapi_read_post, /* read POST data */
173 php_phttpd_sapi_read_cookies, /* read Cookies */
174
175 NULL, /* register server variables */
176 NULL, /* Log message */
177 NULL, /* Get request time */
178 NULL, /* Child terminate */
179
180 STANDARD_SAPI_MODULE_PROPERTIES
181 };
182
183 static void
php_phttpd_request_ctor(TSRMLS_D TSRMLS_DC)184 php_phttpd_request_ctor(TSRMLS_D TSRMLS_DC)
185 {
186 memset(&SG(request_info), 0, sizeof(sapi_globals_struct)); /* pfusch! */
187
188 SG(request_info).query_string = PHG(cip)->hip->request;
189 SG(request_info).request_method = PHG(cip)->hip->method;
190 SG(request_info).path_translated = malloc(MAXPATHLEN);
191 SG(sapi_headers).http_response_code = 200;
192 if (url_expand(PHG(cip)->hip->url, SG(request_info).path_translated, MAXPATHLEN, &PHG(sb), NULL, NULL) == NULL) {
193 /* handle error */
194 }
195
196 #if 0
197 char *server;
198 Ns_DString ds;
199 char *root;
200 int index;
201 char *tmp;
202
203 server = Ns_ConnServer(NSG(conn));
204
205 Ns_DStringInit(&ds);
206 Ns_UrlToFile(&ds, server, NSG(conn->request->url));
207
208 /* path_translated is the absolute path to the file */
209 SG(request_info).path_translated = strdup(Ns_DStringValue(&ds));
210 Ns_DStringFree(&ds);
211 root = Ns_PageRoot(server);
212 SG(request_info).request_uri = SG(request_info).path_translated + strlen(root);
213 SG(request_info).content_length = Ns_ConnContentLength(NSG(conn));
214 index = Ns_SetIFind(NSG(conn)->headers, "content-type");
215 SG(request_info).content_type = index == -1 ? NULL :
216 Ns_SetValue(NSG(conn)->headers, index);
217
218 tmp = Ns_ConnAuthUser(NSG(conn));
219 if(tmp) {
220 tmp = estrdup(tmp);
221 }
222 SG(request_info).auth_user = tmp;
223
224 tmp = Ns_ConnAuthPasswd(NSG(conn));
225 if(tmp) {
226 tmp = estrdup(tmp);
227 }
228 SG(request_info).auth_password = tmp;
229
230 NSG(data_avail) = SG(request_info).content_length;
231 #endif
232 }
233
234 static void
php_phttpd_request_dtor(TSRMLS_D TSRMLS_DC)235 php_phttpd_request_dtor(TSRMLS_D TSRMLS_DC)
236 {
237 free(SG(request_info).path_translated);
238 }
239
240
php_doit(TSRMLS_D)241 int php_doit(TSRMLS_D)
242 {
243 struct stat sb;
244 zend_file_handle file_handle;
245 struct httpinfo *hip = PHG(cip)->hip;
246
247 if (php_request_startup(TSRMLS_C) == FAILURE) {
248 return -1;
249 }
250
251 file_handle.type = ZEND_HANDLE_FILENAME;
252 file_handle.filename = SG(request_info).path_translated;
253 file_handle.free_filename = 0;
254
255 /*
256 php_phttpd_hash_environment(TSRMLS_C);
257 */
258 php_execute_script(&file_handle TSRMLS_CC);
259 php_request_shutdown(NULL);
260
261 return SG(sapi_headers).http_response_code;
262 }
263
pm_init(const char ** argv)264 int pm_init(const char **argv)
265 {
266 tsrm_startup(1, 1, 0, NULL);
267 sapi_startup(&phttpd_sapi_module);
268 phttpd_sapi_module.startup(&phttpd_sapi_module);
269
270 ts_allocate_id(&ph_globals_id, sizeof(phttpd_globals_struct), NULL, NULL);
271
272 return 0;
273 }
274
pm_exit(void)275 void pm_exit(void)
276 {
277 fprintf(stderr,"***pm_exit\n");
278 }
279
pm_request(struct connectioninfo * cip)280 int pm_request(struct connectioninfo *cip)
281 {
282 struct httpinfo *hip = cip->hip;
283 int status;
284 TSRMLS_FETCH();
285
286 if (strcasecmp(hip->method, "GET") == 0 ||
287 strcasecmp(hip->method, "HEAD") == 0 ||
288 strcasecmp(hip->method, "POST") == 0) {
289 PHG(cip) = cip;
290
291 php_phttpd_request_ctor(TSRMLS_C);
292 status = php_doit(TSRMLS_C);
293 php_phttpd_request_dtor(TSRMLS_C);
294
295 return status;
296 } else {
297 return -2;
298 }
299 }
300
301 #endif
302