This source file includes following definitions.
- php_info_isapi
- sapi_isapi_ub_write
- sapi_isapi_header_handler
- accumulate_header_length
- concat_header
- sapi_isapi_send_headers
- php_isapi_startup
- sapi_isapi_read_post
- sapi_isapi_read_cookies
- sapi_isapi_register_zeus_ssl_variables
- sapi_isapi_register_zeus_variables
- sapi_isapi_register_iis_variables
- sapi_isapi_register_server_variables2
- sapi_isapi_register_server_variables
- GetFilterVersion
- HttpFilterProc
- init_request_info
- php_isapi_report_exception
- GetExtensionVersion
- my_endthread
- exceptionhandler
- HttpExtensionProc
- __declspec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "php.h"
22 #include <httpext.h>
23 #include <httpfilt.h>
24 #include <httpext.h>
25 #include "php_main.h"
26 #include "SAPI.h"
27 #include "php_globals.h"
28 #include "ext/standard/info.h"
29 #include "php_variables.h"
30 #include "php_ini.h"
31
32 #ifdef PHP_WIN32
33 # include <process.h>
34 #else
35 # define __try
36 # define __except(val)
37 # define __declspec(foo)
38 #endif
39
40
41 #ifdef WITH_ZEUS
42 # include "httpext.h"
43 # include <errno.h>
44 # define GetLastError() errno
45 #endif
46
47 #ifdef PHP_WIN32
48 #define PHP_ENABLE_SEH
49 #endif
50
51
52
53
54
55
56
57
58
59
60 #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST POSSIBLE STATUS DESCRIPTION")
61 #define ISAPI_SERVER_VAR_BUF_SIZE 1024
62 #define ISAPI_POST_DATA_BUF 1024
63
64 static zend_bool bFilterLoaded=0;
65 static zend_bool bTerminateThreadsOnError=0;
66
67 static char *isapi_special_server_variable_names[] = {
68 "ALL_HTTP",
69 "HTTPS",
70 #ifndef WITH_ZEUS
71 "SCRIPT_NAME",
72 #endif
73 NULL
74 };
75
76 #define NUM_SPECIAL_VARS (sizeof(isapi_special_server_variable_names)/sizeof(char *))
77 #define SPECIAL_VAR_ALL_HTTP 0
78 #define SPECIAL_VAR_HTTPS 1
79 #define SPECIAL_VAR_PHP_SELF 2
80
81 static char *isapi_server_variable_names[] = {
82 "AUTH_PASSWORD",
83 "AUTH_TYPE",
84 "AUTH_USER",
85 "CONTENT_LENGTH",
86 "CONTENT_TYPE",
87 "PATH_TRANSLATED",
88 "QUERY_STRING",
89 "REMOTE_ADDR",
90 "REMOTE_HOST",
91 "REMOTE_USER",
92 "REQUEST_METHOD",
93 "SERVER_NAME",
94 "SERVER_PORT",
95 "SERVER_PROTOCOL",
96 "SERVER_SOFTWARE",
97 #ifndef WITH_ZEUS
98 "APPL_MD_PATH",
99 "APPL_PHYSICAL_PATH",
100 "INSTANCE_ID",
101 "INSTANCE_META_PATH",
102 "LOGON_USER",
103 "REQUEST_URI",
104 "URL",
105 #else
106 "DOCUMENT_ROOT",
107 #endif
108 NULL
109 };
110
111
112 static char *isapi_secure_server_variable_names[] = {
113 "CERT_COOKIE",
114 "CERT_FLAGS",
115 "CERT_ISSUER",
116 "CERT_KEYSIZE",
117 "CERT_SECRETKEYSIZE",
118 "CERT_SERIALNUMBER",
119 "CERT_SERVER_ISSUER",
120 "CERT_SERVER_SUBJECT",
121 "CERT_SUBJECT",
122 "HTTPS_KEYSIZE",
123 "HTTPS_SECRETKEYSIZE",
124 "HTTPS_SERVER_ISSUER",
125 "HTTPS_SERVER_SUBJECT",
126 "SERVER_PORT_SECURE",
127 #ifdef WITH_ZEUS
128 "SSL_CLIENT_CN",
129 "SSL_CLIENT_EMAIL",
130 "SSL_CLIENT_OU",
131 "SSL_CLIENT_O",
132 "SSL_CLIENT_L",
133 "SSL_CLIENT_ST",
134 "SSL_CLIENT_C",
135 "SSL_CLIENT_I_CN",
136 "SSL_CLIENT_I_EMAIL",
137 "SSL_CLIENT_I_OU",
138 "SSL_CLIENT_I_O",
139 "SSL_CLIENT_I_L",
140 "SSL_CLIENT_I_ST",
141 "SSL_CLIENT_I_C",
142 #endif
143 NULL
144 };
145
146
147 static void php_info_isapi(ZEND_MODULE_INFO_FUNC_ARGS)
148 {
149 char **p;
150 char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
151 DWORD variable_len;
152 char **all_variables[] = {
153 isapi_server_variable_names,
154 isapi_special_server_variable_names,
155 isapi_secure_server_variable_names,
156 NULL
157 };
158 char ***server_variable_names;
159 LPEXTENSION_CONTROL_BLOCK lpECB;
160
161 lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
162
163 php_info_print_table_start();
164 php_info_print_table_header(2, "Server Variable", "Value");
165 server_variable_names = all_variables;
166 while (*server_variable_names) {
167 p = *server_variable_names;
168 while (*p) {
169 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
170 if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len)
171 && variable_buf[0]) {
172 php_info_print_table_row(2, *p, variable_buf);
173 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
174 char *tmp_variable_buf;
175
176 tmp_variable_buf = (char *) emalloc(variable_len);
177 if (lpECB->GetServerVariable(lpECB->ConnID, *p, tmp_variable_buf, &variable_len)
178 && variable_buf[0]) {
179 php_info_print_table_row(2, *p, tmp_variable_buf);
180 }
181 efree(tmp_variable_buf);
182 }
183 p++;
184 }
185 server_variable_names++;
186 }
187 php_info_print_table_end();
188 }
189
190
191 static zend_module_entry php_isapi_module = {
192 STANDARD_MODULE_HEADER,
193 "ISAPI",
194 NULL,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199 php_info_isapi,
200 NULL,
201 STANDARD_MODULE_PROPERTIES
202 };
203
204
205 static int sapi_isapi_ub_write(const char *str, uint str_length TSRMLS_DC)
206 {
207 DWORD num_bytes = str_length;
208 LPEXTENSION_CONTROL_BLOCK ecb;
209
210 ecb = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
211 if (ecb->WriteClient(ecb->ConnID, (char *) str, &num_bytes, HSE_IO_SYNC) == FALSE) {
212 php_handle_aborted_connection();
213 }
214 return num_bytes;
215 }
216
217
218 static int sapi_isapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
219 {
220 return SAPI_HEADER_ADD;
221 }
222
223
224
225 static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC)
226 {
227 *total_length += sapi_header->header_len+2;
228 }
229
230
231 static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC)
232 {
233 memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len);
234 *combined_headers_ptr += sapi_header->header_len;
235 **combined_headers_ptr = '\r';
236 (*combined_headers_ptr)++;
237 **combined_headers_ptr = '\n';
238 (*combined_headers_ptr)++;
239 }
240
241
242 static int sapi_isapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
243 {
244 uint total_length = 2;
245 char *combined_headers, *combined_headers_ptr;
246 LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
247 HSE_SEND_HEADER_EX_INFO header_info;
248 sapi_header_struct default_content_type;
249 char *status_buf = NULL;
250
251
252 if (SG(sapi_headers).send_default_content_type) {
253 sapi_get_default_content_type_header(&default_content_type TSRMLS_CC);
254 accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC);
255 }
256 zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC);
257
258
259 combined_headers = (char *) emalloc(total_length+1);
260 combined_headers_ptr = combined_headers;
261 if (SG(sapi_headers).send_default_content_type) {
262 concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC);
263 sapi_free_header(&default_content_type);
264 }
265 zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC);
266 *combined_headers_ptr++ = '\r';
267 *combined_headers_ptr++ = '\n';
268 *combined_headers_ptr = 0;
269
270 switch (SG(sapi_headers).http_response_code) {
271 case 200:
272 header_info.pszStatus = "200 OK";
273 break;
274 case 302:
275 header_info.pszStatus = "302 Moved Temporarily";
276 break;
277 case 401:
278 header_info.pszStatus = "401 Authorization Required";
279 break;
280 default: {
281 const char *sline = SG(sapi_headers).http_status_line;
282 int sline_len;
283
284
285
286 if (sline && ((sline_len = strlen(sline)) > 12) && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
287 if ((sline_len - 9) > MAX_STATUS_LENGTH) {
288 status_buf = estrndup(sline + 9, MAX_STATUS_LENGTH);
289 } else {
290 status_buf = estrndup(sline + 9, sline_len - 9);
291 }
292 } else {
293 status_buf = emalloc(MAX_STATUS_LENGTH + 1);
294 snprintf(status_buf, MAX_STATUS_LENGTH, "%d Undescribed", SG(sapi_headers).http_response_code);
295 }
296 header_info.pszStatus = status_buf;
297 break;
298 }
299 }
300 header_info.cchStatus = strlen(header_info.pszStatus);
301 header_info.pszHeader = combined_headers;
302 header_info.cchHeader = total_length;
303 header_info.fKeepConn = FALSE;
304 lpECB->dwHttpStatusCode = SG(sapi_headers).http_response_code;
305
306 lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
307
308 efree(combined_headers);
309 if (status_buf) {
310 efree(status_buf);
311 }
312 return SAPI_HEADER_SENT_SUCCESSFULLY;
313 }
314
315
316 static int php_isapi_startup(sapi_module_struct *sapi_module)
317 {
318 if (php_module_startup(sapi_module, &php_isapi_module, 1)==FAILURE) {
319 return FAILURE;
320 } else {
321 bTerminateThreadsOnError = (zend_bool) INI_INT("isapi.terminate_threads_on_error");
322 return SUCCESS;
323 }
324 }
325
326
327 static int sapi_isapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
328 {
329 LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
330 DWORD read_from_buf=0;
331 DWORD read_from_input=0;
332 DWORD total_read=0;
333
334 if ((DWORD) SG(read_post_bytes) < lpECB->cbAvailable) {
335 read_from_buf = MIN(lpECB->cbAvailable-SG(read_post_bytes), count_bytes);
336 memcpy(buffer, lpECB->lpbData+SG(read_post_bytes), read_from_buf);
337 total_read += read_from_buf;
338 }
339 if (read_from_buf<count_bytes
340 && (SG(read_post_bytes)+read_from_buf) < lpECB->cbTotalBytes) {
341 DWORD cbRead=0, cbSize;
342
343 read_from_input = MIN(count_bytes-read_from_buf, lpECB->cbTotalBytes-SG(read_post_bytes)-read_from_buf);
344 while (cbRead < read_from_input) {
345 cbSize = read_from_input - cbRead;
346 if (!lpECB->ReadClient(lpECB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) {
347 break;
348 }
349 cbRead += cbSize;
350 }
351 total_read += cbRead;
352 }
353 return total_read;
354 }
355
356
357 static char *sapi_isapi_read_cookies(TSRMLS_D)
358 {
359 LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
360 char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
361 DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
362
363 if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) {
364 return estrndup(variable_buf, variable_len);
365 } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
366 char *tmp_variable_buf = (char *) emalloc(variable_len+1);
367
368 if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) {
369 tmp_variable_buf[variable_len] = 0;
370 return tmp_variable_buf;
371 } else {
372 efree(tmp_variable_buf);
373 }
374 }
375 return STR_EMPTY_ALLOC();
376 }
377
378
379 #ifdef WITH_ZEUS
380
381 static void sapi_isapi_register_zeus_ssl_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC)
382 {
383 char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
384 DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
385 char static_cons_buf[ISAPI_SERVER_VAR_BUF_SIZE];
386
387
388
389
390 strcpy( static_cons_buf, "/C=" );
391 if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_C", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
392 strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE);
393 }
394 strlcat( static_cons_buf, "/ST=", ISAPI_SERVER_VAR_BUF_SIZE);
395 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
396 if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_ST", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
397 strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE );
398 }
399 php_register_variable( "SSL_CLIENT_DN", static_cons_buf, track_vars_array TSRMLS_CC );
400
401 strcpy( static_cons_buf, "/C=" );
402 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
403 if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_I_C", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
404 strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE );
405 }
406 strlcat( static_cons_buf, "/ST=", ISAPI_SERVER_VAR_BUF_SIZE);
407 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
408 if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_I_ST", static_variable_buf, &variable_len ) && static_variable_buf[0] ) {
409 strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE );
410 }
411 php_register_variable( "SSL_CLIENT_I_DN", static_cons_buf, track_vars_array TSRMLS_CC );
412 }
413
414 static void sapi_isapi_register_zeus_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC)
415 {
416 char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
417 DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
418 DWORD scriptname_len = ISAPI_SERVER_VAR_BUF_SIZE;
419 DWORD pathinfo_len = 0;
420 char *strtok_buf = NULL;
421
422
423
424
425 lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &scriptname_len);
426
427
428
429
430 if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
431
432
433 php_register_variable( "PHP_SELF", static_variable_buf, track_vars_array TSRMLS_CC );
434
435
436 pathinfo_len = variable_len - scriptname_len;
437 php_register_variable( "PATH_INFO", static_variable_buf + scriptname_len - 1, track_vars_array TSRMLS_CC );
438
439 if ( strlen(lpECB->lpszQueryString) + variable_len + 1 < ISAPI_SERVER_VAR_BUF_SIZE ) {
440
441 if ( strlen(lpECB->lpszQueryString) ) {
442 static_variable_buf[ variable_len - 1 ] = '?';
443 strcpy( static_variable_buf + variable_len, lpECB->lpszQueryString );
444 }
445 php_register_variable( "URL", static_variable_buf, track_vars_array TSRMLS_CC );
446 php_register_variable( "REQUEST_URI", static_variable_buf, track_vars_array TSRMLS_CC );
447 }
448 }
449
450
451 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
452 if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_TRANSLATED", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
453 static_variable_buf[ variable_len - pathinfo_len - 1 ] = '\0';
454 php_register_variable( "PATH_TRANSLATED", static_variable_buf, track_vars_array TSRMLS_CC );
455 }
456
457
458 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
459 if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_USER", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
460 php_register_variable( "PHP_AUTH_USER", static_variable_buf, track_vars_array TSRMLS_CC );
461 }
462 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
463 if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_PASSWORD", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
464 php_register_variable( "PHP_AUTH_PW", static_variable_buf, track_vars_array TSRMLS_CC );
465 }
466 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
467 if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_TYPE", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
468 php_register_variable( "AUTH_TYPE", static_variable_buf, track_vars_array TSRMLS_CC );
469 }
470
471
472 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
473 if ( lpECB->GetServerVariable(lpECB->ConnID, "CERT_COOKIE", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
474 sapi_isapi_register_zeus_ssl_variables( lpECB, track_vars_array TSRMLS_CC );
475 }
476
477 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
478 if ( lpECB->GetServerVariable(lpECB->ConnID, "SERVER_SOFTWARE", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
479 php_register_variable( "SERVER_SIGNATURE", static_variable_buf, track_vars_array TSRMLS_CC );
480 }
481 }
482 #else
483
484 static void sapi_isapi_register_iis_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC)
485 {
486 char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
487 char path_info_buf[ISAPI_SERVER_VAR_BUF_SIZE];
488 DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
489 DWORD scriptname_len = ISAPI_SERVER_VAR_BUF_SIZE;
490 DWORD pathinfo_len = 0;
491 HSE_URL_MAPEX_INFO humi;
492
493
494
495
496 lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &scriptname_len);
497 php_register_variable("SCRIPT_FILENAME", SG(request_info).path_translated, track_vars_array TSRMLS_CC);
498
499
500
501
502
503 if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
504
505
506 php_register_variable( "ORIG_PATH_INFO", static_variable_buf, track_vars_array TSRMLS_CC );
507 pathinfo_len = variable_len - scriptname_len;
508 strncpy(path_info_buf, static_variable_buf + scriptname_len - 1, sizeof(path_info_buf)-1);
509 php_register_variable( "PATH_INFO", path_info_buf, track_vars_array TSRMLS_CC );
510
511 if ( strlen(lpECB->lpszQueryString) + variable_len + 1 < ISAPI_SERVER_VAR_BUF_SIZE ) {
512
513 if ( strlen(lpECB->lpszQueryString) ) {
514 static_variable_buf[ variable_len - 1 ] = '?';
515 strcpy( static_variable_buf + variable_len, lpECB->lpszQueryString );
516 }
517 php_register_variable( "URL", static_variable_buf, track_vars_array TSRMLS_CC );
518 php_register_variable( "REQUEST_URI", static_variable_buf, track_vars_array TSRMLS_CC );
519 }
520 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
521 if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_TRANSLATED", static_variable_buf, &variable_len) && static_variable_buf[0] ) {
522 php_register_variable( "ORIG_PATH_TRANSLATED", static_variable_buf, track_vars_array TSRMLS_CC );
523 }
524 if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, path_info_buf, &pathinfo_len, (LPDWORD) &humi)) {
525
526 if (humi.lpszPath[variable_len-2] == '\\') {
527 humi.lpszPath[variable_len-2] = 0;
528 }
529 php_register_variable("PATH_TRANSLATED", humi.lpszPath, track_vars_array TSRMLS_CC);
530 }
531 }
532
533 static_variable_buf[0] = '/';
534 static_variable_buf[1] = 0;
535 variable_len = 2;
536 if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, static_variable_buf, &variable_len, (LPDWORD) &humi)) {
537
538 if (humi.lpszPath[variable_len-2] == '\\') {
539 humi.lpszPath[variable_len-2] = 0;
540 }
541 php_register_variable("DOCUMENT_ROOT", humi.lpszPath, track_vars_array TSRMLS_CC);
542 }
543
544 if (!SG(request_info).auth_user || !SG(request_info).auth_password ||
545 !SG(request_info).auth_user[0] || !SG(request_info).auth_password[0]) {
546 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
547 if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_AUTHORIZATION", static_variable_buf, &variable_len)
548 && static_variable_buf[0]) {
549 php_handle_auth_data(static_variable_buf TSRMLS_CC);
550 }
551 }
552
553 if (SG(request_info).auth_user) {
554 php_register_variable("PHP_AUTH_USER", SG(request_info).auth_user, track_vars_array TSRMLS_CC );
555 }
556 if (SG(request_info).auth_password) {
557 php_register_variable("PHP_AUTH_PW", SG(request_info).auth_password, track_vars_array TSRMLS_CC );
558 }
559 }
560 #endif
561
562 static void sapi_isapi_register_server_variables2(char **server_variables, LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array, char **recorded_values TSRMLS_DC)
563 {
564 char **p=server_variables;
565 DWORD variable_len;
566 char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
567 char *variable_buf;
568
569 while (*p) {
570 variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
571 if (lpECB->GetServerVariable(lpECB->ConnID, *p, static_variable_buf, &variable_len)
572 && static_variable_buf[0]) {
573 php_register_variable(*p, static_variable_buf, track_vars_array TSRMLS_CC);
574 if (recorded_values) {
575 recorded_values[p-server_variables] = estrndup(static_variable_buf, variable_len);
576 }
577 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
578 variable_buf = (char *) emalloc(variable_len+1);
579 if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len)
580 && variable_buf[0]) {
581 php_register_variable(*p, variable_buf, track_vars_array TSRMLS_CC);
582 }
583 if (recorded_values) {
584 recorded_values[p-server_variables] = variable_buf;
585 } else {
586 efree(variable_buf);
587 }
588 } else {
589 php_register_variable(*p, "", track_vars_array TSRMLS_CC);
590 }
591 p++;
592 }
593 }
594
595
596 static void sapi_isapi_register_server_variables(zval *track_vars_array TSRMLS_DC)
597 {
598 DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
599 char *variable;
600 char *strtok_buf = NULL;
601 char *isapi_special_server_variables[NUM_SPECIAL_VARS];
602 LPEXTENSION_CONTROL_BLOCK lpECB;
603
604 lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
605
606
607 memset(isapi_special_server_variables, 0, sizeof(isapi_special_server_variables));
608 sapi_isapi_register_server_variables2(isapi_special_server_variable_names, lpECB, track_vars_array, isapi_special_server_variables TSRMLS_CC);
609 if (SG(request_info).cookie_data) {
610 php_register_variable("HTTP_COOKIE", SG(request_info).cookie_data, track_vars_array TSRMLS_CC);
611 }
612
613
614 sapi_isapi_register_server_variables2(isapi_server_variable_names, lpECB, track_vars_array, NULL TSRMLS_CC);
615
616 if (isapi_special_server_variables[SPECIAL_VAR_HTTPS]
617 && (atoi(isapi_special_server_variables[SPECIAL_VAR_HTTPS])
618 || !strcasecmp(isapi_special_server_variables[SPECIAL_VAR_HTTPS], "on"))
619 ) {
620
621 sapi_isapi_register_server_variables2(isapi_secure_server_variable_names, lpECB, track_vars_array, NULL TSRMLS_CC);
622 }
623
624 if (isapi_special_server_variables[SPECIAL_VAR_HTTPS]) {
625 efree(isapi_special_server_variables[SPECIAL_VAR_HTTPS]);
626 }
627
628
629 #ifdef WITH_ZEUS
630 sapi_isapi_register_zeus_variables(lpECB, track_vars_array TSRMLS_CC);
631 #else
632 sapi_isapi_register_iis_variables(lpECB, track_vars_array TSRMLS_CC);
633 #endif
634
635
636 if (isapi_special_server_variables[SPECIAL_VAR_PHP_SELF]) {
637 php_register_variable("PHP_SELF", isapi_special_server_variables[SPECIAL_VAR_PHP_SELF], track_vars_array TSRMLS_CC);
638 efree(isapi_special_server_variables[SPECIAL_VAR_PHP_SELF]);
639 }
640
641 if (isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP]) {
642
643 variable = php_strtok_r(isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP], "\r\n", &strtok_buf);
644 while (variable) {
645 char *colon = strchr(variable, ':');
646
647 if (colon) {
648 char *value = colon+1;
649
650 while (*value==' ') {
651 value++;
652 }
653 *colon = 0;
654 php_register_variable(variable, value, track_vars_array TSRMLS_CC);
655 *colon = ':';
656 }
657 variable = php_strtok_r(NULL, "\r\n", &strtok_buf);
658 }
659 efree(isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP]);
660 }
661 }
662
663
664 static sapi_module_struct isapi_sapi_module = {
665 "isapi",
666 "ISAPI",
667
668 php_isapi_startup,
669 php_module_shutdown_wrapper,
670
671 NULL,
672 NULL,
673
674 sapi_isapi_ub_write,
675 NULL,
676 NULL,
677 NULL,
678
679 php_error,
680
681 sapi_isapi_header_handler,
682 sapi_isapi_send_headers,
683 NULL,
684
685 sapi_isapi_read_post,
686 sapi_isapi_read_cookies,
687
688 sapi_isapi_register_server_variables,
689 NULL,
690 NULL,
691 NULL,
692
693 STANDARD_SAPI_MODULE_PROPERTIES
694 };
695
696
697 BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pFilterVersion)
698 {
699 bFilterLoaded = 1;
700 pFilterVersion->dwFilterVersion = HTTP_FILTER_REVISION;
701 strcpy(pFilterVersion->lpszFilterDesc, isapi_sapi_module.pretty_name);
702 pFilterVersion->dwFlags= (SF_NOTIFY_AUTHENTICATION | SF_NOTIFY_PREPROC_HEADERS);
703 return TRUE;
704 }
705
706
707 DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
708 {
709 TSRMLS_FETCH();
710
711 switch (notificationType) {
712 case SF_NOTIFY_PREPROC_HEADERS:
713 SG(request_info).auth_user = NULL;
714 SG(request_info).auth_password = NULL;
715 SG(request_info).auth_digest = NULL;
716 break;
717 case SF_NOTIFY_AUTHENTICATION: {
718 char *auth_user = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszUser;
719 char *auth_password = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszPassword;
720
721 if (auth_user && auth_user[0]) {
722 SG(request_info).auth_user = estrdup(auth_user);
723 }
724 if (auth_password && auth_password[0]) {
725 SG(request_info).auth_password = estrdup(auth_password);
726 }
727 return SF_STATUS_REQ_HANDLED_NOTIFICATION;
728 }
729 break;
730 }
731 return SF_STATUS_REQ_NEXT_NOTIFICATION;
732 }
733
734
735 static void init_request_info(LPEXTENSION_CONTROL_BLOCK lpECB TSRMLS_DC)
736 {
737 DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
738 char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
739 #ifndef WITH_ZEUS
740 HSE_URL_MAPEX_INFO humi;
741 #endif
742
743 SG(request_info).request_method = lpECB->lpszMethod;
744 SG(request_info).query_string = lpECB->lpszQueryString;
745 SG(request_info).request_uri = lpECB->lpszPathInfo;
746 SG(request_info).content_type = lpECB->lpszContentType;
747 SG(request_info).content_length = lpECB->cbTotalBytes;
748 SG(sapi_headers).http_response_code = 200;
749 if (!bFilterLoaded) {
750 SG(request_info).auth_user = SG(request_info).auth_password = SG(request_info).auth_digest = NULL;
751 }
752
753 #ifdef WITH_ZEUS
754
755
756
757 if(lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_FILENAME", static_variable_buf, &variable_len)) {
758 SG(request_info).path_translated = estrdup(static_variable_buf);
759 } else
760 #else
761
762
763
764 lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len);
765 if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, static_variable_buf, &variable_len, (LPDWORD) &humi)) {
766 SG(request_info).path_translated = estrdup(humi.lpszPath);
767 } else
768 #endif
769
770 SG(request_info).path_translated = estrdup(lpECB->lpszPathTranslated);
771
772
773
774 if (strstr(SG(request_info).path_translated,"..")) {
775 SG(sapi_headers).http_response_code = 404;
776 efree(SG(request_info).path_translated);
777 SG(request_info).path_translated = NULL;
778 }
779 }
780
781
782 static void php_isapi_report_exception(char *message, int message_len TSRMLS_DC)
783 {
784 if (!SG(headers_sent)) {
785 HSE_SEND_HEADER_EX_INFO header_info;
786 LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
787
788 header_info.pszStatus = "500 Internal Server Error";
789 header_info.cchStatus = strlen(header_info.pszStatus);
790 header_info.pszHeader = "Content-Type: text/html\r\n\r\n";
791 header_info.cchHeader = strlen(header_info.pszHeader);
792
793 lpECB->dwHttpStatusCode = 500;
794 lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
795 SG(headers_sent)=1;
796 }
797 sapi_isapi_ub_write(message, message_len TSRMLS_CC);
798 }
799
800
801 BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
802 {
803 pVer->dwExtensionVersion = HSE_VERSION;
804 #ifdef WITH_ZEUS
805 strncpy( pVer->lpszExtensionDesc, isapi_sapi_module.name, HSE_MAX_EXT_DLL_NAME_LEN);
806 #else
807 lstrcpyn(pVer->lpszExtensionDesc, isapi_sapi_module.name, HSE_MAX_EXT_DLL_NAME_LEN);
808 #endif
809 return TRUE;
810 }
811
812
813 static void my_endthread()
814 {
815 #ifdef PHP_WIN32
816 if (bTerminateThreadsOnError) {
817 _endthread();
818 }
819 #endif
820 }
821
822 #ifdef PHP_WIN32
823
824
825
826 BOOL exceptionhandler(LPEXCEPTION_POINTERS *e, LPEXCEPTION_POINTERS ep)
827 {
828 *e=ep;
829 return TRUE;
830 }
831 #endif
832
833 DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
834 {
835 zend_file_handle file_handle;
836 zend_bool stack_overflown=0;
837 int retval = FAILURE;
838 #ifdef PHP_ENABLE_SEH
839 LPEXCEPTION_POINTERS e;
840 #endif
841 TSRMLS_FETCH();
842
843 zend_first_try {
844 #ifdef PHP_ENABLE_SEH
845 __try {
846 #endif
847 init_request_info(lpECB TSRMLS_CC);
848 SG(server_context) = lpECB;
849
850 php_request_startup(TSRMLS_C);
851
852 file_handle.filename = SG(request_info).path_translated;
853 file_handle.free_filename = 0;
854 file_handle.type = ZEND_HANDLE_FILENAME;
855 file_handle.opened_path = NULL;
856
857
858 if (file_handle.filename)
859 retval = php_fopen_primary_script(&file_handle TSRMLS_CC);
860
861 if (!file_handle.filename || retval == FAILURE) {
862 SG(sapi_headers).http_response_code = 404;
863 PUTS("No input file specified.\n");
864 } else {
865 php_execute_script(&file_handle TSRMLS_CC);
866 }
867
868 if (SG(request_info).cookie_data) {
869 efree(SG(request_info).cookie_data);
870 }
871 if (SG(request_info).path_translated)
872 efree(SG(request_info).path_translated);
873 #ifdef PHP_ENABLE_SEH
874 } __except(exceptionhandler(&e, GetExceptionInformation())) {
875 char buf[1024];
876 if (_exception_code()==EXCEPTION_STACK_OVERFLOW) {
877 LPBYTE lpPage;
878 static SYSTEM_INFO si;
879 static MEMORY_BASIC_INFORMATION mi;
880 static DWORD dwOldProtect;
881
882 GetSystemInfo(&si);
883
884
885 _asm mov lpPage, esp;
886
887
888 VirtualQuery(lpPage, &mi, sizeof(mi));
889
890
891 lpPage = (LPBYTE) (mi.BaseAddress) - si.dwPageSize;
892
893
894 if (!VirtualFree(mi.AllocationBase, (LPBYTE)lpPage - (LPBYTE) mi.AllocationBase, MEM_DECOMMIT)) {
895 _endthread();
896 }
897
898
899 if (!VirtualProtect(lpPage, si.dwPageSize, PAGE_GUARD | PAGE_READWRITE, &dwOldProtect)) {
900 _endthread();
901 }
902
903 CG(unclean_shutdown)=1;
904 _snprintf(buf, sizeof(buf)-1,"PHP has encountered a Stack overflow");
905 php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC);
906 } else if (_exception_code()==EXCEPTION_ACCESS_VIOLATION) {
907 _snprintf(buf, sizeof(buf)-1,"PHP has encountered an Access Violation at %p", e->ExceptionRecord->ExceptionAddress);
908 php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC);
909 my_endthread();
910 } else {
911 _snprintf(buf, sizeof(buf)-1,"PHP has encountered an Unhandled Exception Code %d at %p", e->ExceptionRecord->ExceptionCode , e->ExceptionRecord->ExceptionAddress);
912 php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC);
913 my_endthread();
914 }
915 }
916 #endif
917 #ifdef PHP_ENABLE_SEH
918 __try {
919 php_request_shutdown(NULL);
920 } __except(EXCEPTION_EXECUTE_HANDLER) {
921 my_endthread();
922 }
923 #else
924 php_request_shutdown(NULL);
925 #endif
926 } zend_catch {
927 zend_try {
928 php_request_shutdown(NULL);
929 } zend_end_try();
930 return HSE_STATUS_ERROR;
931 } zend_end_try();
932
933 return HSE_STATUS_SUCCESS;
934 }
935
936
937
938 __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
939 {
940 switch (fdwReason) {
941 case DLL_PROCESS_ATTACH:
942 #ifdef WITH_ZEUS
943 tsrm_startup(128, 1, TSRM_ERROR_LEVEL_CORE, "TSRM.log");
944 #else
945 tsrm_startup(128, 1, TSRM_ERROR_LEVEL_CORE, "C:\\TSRM.log");
946 #endif
947 sapi_startup(&isapi_sapi_module);
948 if (isapi_sapi_module.startup) {
949 isapi_sapi_module.startup(&sapi_module);
950 }
951 break;
952 case DLL_THREAD_ATTACH:
953 break;
954 case DLL_THREAD_DETACH:
955 ts_free_thread();
956 break;
957 case DLL_PROCESS_DETACH:
958 if (isapi_sapi_module.shutdown) {
959 isapi_sapi_module.shutdown(&sapi_module);
960 }
961 sapi_shutdown();
962 tsrm_shutdown();
963 break;
964 }
965 return TRUE;
966 }
967
968
969
970
971
972
973