This source file includes following definitions.
- nsapi_free
- php_nsapi_init_dynamic_symbols
- php_nsapi_init_globals
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_MINFO_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- sapi_nsapi_ub_write
- sapi_nsapi_flush
- php_nsapi_remove_header
- sapi_nsapi_header_handler
- sapi_nsapi_send_headers
- sapi_nsapi_read_post
- sapi_nsapi_read_cookies
- sapi_nsapi_register_server_variables
- nsapi_log_message
- sapi_nsapi_get_request_time
- php_nsapi_startup
- sapi_nsapi_get_stat
- nsapi_php_ini_entries
- php5_close
- php5_init
- php5_execute
- php5_auth_trans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #define NSAPI 1
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "php.h"
32 #include "php_variables.h"
33 #include "ext/standard/info.h"
34 #include "php_ini.h"
35 #include "php_globals.h"
36 #include "SAPI.h"
37 #include "php_main.h"
38 #include "php_version.h"
39 #include "TSRM.h"
40 #include "ext/standard/php_standard.h"
41 #include <sys/types.h>
42 #include <sys/stat.h>
43
44 #ifndef RTLD_DEFAULT
45 #define RTLD_DEFAULT NULL
46 #endif
47
48
49
50
51 #if !defined(XP_UNIX) && !defined(XP_WIN32)
52 #ifdef PHP_WIN32
53 #define XP_WIN32
54 #else
55 #define XP_UNIX
56 #endif
57 #endif
58
59
60
61
62 #ifdef __hpux
63 #define HPUX
64 #endif
65
66
67
68
69 #include "nsapi.h"
70
71
72 #ifndef PHP_WIN32
73 # undef NSAPI_PUBLIC
74 # define NSAPI_PUBLIC PHPAPI
75 #endif
76
77 #define NSLS_D struct nsapi_request_context *request_context
78 #define NSLS_DC , NSLS_D
79 #define NSLS_C request_context
80 #define NSLS_CC , NSLS_C
81 #define NSG(v) (request_context->v)
82
83
84
85
86 #if !defined(ZTS)
87 #error "NSAPI module needs ZTS to be defined"
88 #endif
89
90
91
92
93 typedef struct nsapi_request_context {
94 pblock *pb;
95 Session *sn;
96 Request *rq;
97 int read_post_bytes;
98 char *path_info;
99 int fixed_script;
100 short http_error;
101 } nsapi_request_context;
102
103
104
105
106
107
108 typedef struct nsapi_equiv {
109 const char *env_var;
110 const char *nsapi_eq;
111 } nsapi_equiv;
112
113 static nsapi_equiv nsapi_reqpb[] = {
114 { "QUERY_STRING", "query" },
115 { "REQUEST_LINE", "clf-request" },
116 { "REQUEST_METHOD", "method" },
117 { "PHP_SELF", "uri" },
118 { "SERVER_PROTOCOL", "protocol" }
119 };
120 static size_t nsapi_reqpb_size = sizeof(nsapi_reqpb)/sizeof(nsapi_reqpb[0]);
121
122 static nsapi_equiv nsapi_vars[] = {
123 { "AUTH_TYPE", "auth-type" },
124 { "CLIENT_CERT", "auth-cert" },
125 { "REMOTE_USER", "auth-user" }
126 };
127 static size_t nsapi_vars_size = sizeof(nsapi_vars)/sizeof(nsapi_vars[0]);
128
129 static nsapi_equiv nsapi_client[] = {
130 { "HTTPS_KEYSIZE", "keysize" },
131 { "HTTPS_SECRETSIZE", "secret-keysize" },
132 { "REMOTE_ADDR", "ip" },
133 { "REMOTE_HOST", "ip" }
134 };
135 static size_t nsapi_client_size = sizeof(nsapi_client)/sizeof(nsapi_client[0]);
136
137
138 static char *nsapi_exclude_from_ini_entries[] = { "fn", "type", "method", "directive", "code", "reason", "script", "bucket", NULL };
139
140 static void nsapi_free(void *addr)
141 {
142 if (addr != NULL) {
143 FREE(addr);
144 }
145 }
146
147
148
149
150
151
152 PHP_MINIT_FUNCTION(nsapi);
153 PHP_MSHUTDOWN_FUNCTION(nsapi);
154 PHP_RINIT_FUNCTION(nsapi);
155 PHP_RSHUTDOWN_FUNCTION(nsapi);
156 PHP_MINFO_FUNCTION(nsapi);
157
158 PHP_FUNCTION(nsapi_virtual);
159 PHP_FUNCTION(nsapi_request_headers);
160 PHP_FUNCTION(nsapi_response_headers);
161
162 ZEND_BEGIN_MODULE_GLOBALS(nsapi)
163 long read_timeout;
164 ZEND_END_MODULE_GLOBALS(nsapi)
165
166 ZEND_DECLARE_MODULE_GLOBALS(nsapi)
167
168 #define NSAPI_G(v) TSRMG(nsapi_globals_id, zend_nsapi_globals *, v)
169
170
171
172 ZEND_BEGIN_ARG_INFO_EX(arginfo_nsapi_virtual, 0, 0, 1)
173 ZEND_ARG_INFO(0, uri)
174 ZEND_END_ARG_INFO()
175
176 ZEND_BEGIN_ARG_INFO(arginfo_nsapi_request_headers, 0)
177 ZEND_END_ARG_INFO()
178
179 ZEND_BEGIN_ARG_INFO(arginfo_nsapi_response_headers, 0)
180 ZEND_END_ARG_INFO()
181
182
183
184
185
186
187 const zend_function_entry nsapi_functions[] = {
188 PHP_FE(nsapi_virtual, arginfo_nsapi_virtual)
189 PHP_FALIAS(virtual, nsapi_virtual, arginfo_nsapi_virtual)
190 PHP_FE(nsapi_request_headers, arginfo_nsapi_request_headers)
191 PHP_FALIAS(getallheaders, nsapi_request_headers, arginfo_nsapi_request_headers)
192 PHP_FALIAS(apache_request_headers, nsapi_request_headers, arginfo_nsapi_request_headers)
193 PHP_FE(nsapi_response_headers, arginfo_nsapi_response_headers)
194 PHP_FALIAS(apache_response_headers, nsapi_response_headers, arginfo_nsapi_response_headers)
195 {NULL, NULL, NULL}
196 };
197
198
199
200
201 zend_module_entry nsapi_module_entry = {
202 STANDARD_MODULE_HEADER,
203 "nsapi",
204 nsapi_functions,
205 PHP_MINIT(nsapi),
206 PHP_MSHUTDOWN(nsapi),
207 NULL,
208 NULL,
209 PHP_MINFO(nsapi),
210 NO_VERSION_YET,
211 STANDARD_MODULE_PROPERTIES
212 };
213
214
215
216
217 PHP_INI_BEGIN()
218 STD_PHP_INI_ENTRY("nsapi.read_timeout", "60", PHP_INI_ALL, OnUpdateLong, read_timeout, zend_nsapi_globals, nsapi_globals)
219 PHP_INI_END()
220
221
222
223
224 typedef int (*nsapi_servact_prototype)(Session *sn, Request *rq);
225 nsapi_servact_prototype nsapi_servact_uri2path = NULL;
226 nsapi_servact_prototype nsapi_servact_pathchecks = NULL;
227 nsapi_servact_prototype nsapi_servact_fileinfo = NULL;
228 nsapi_servact_prototype nsapi_servact_service = NULL;
229
230 #ifdef PHP_WIN32
231
232
233
234
235 static char *nsapi_dlls[] = { "ns-httpd40.dll", "ns-httpd36.dll", "ns-httpd35.dll", "ns-httpd30.dll", NULL };
236
237
238
239 char *nsapi_dll = NULL;
240 #endif
241
242
243
244 static void php_nsapi_init_dynamic_symbols(void)
245 {
246
247 #ifdef PHP_WIN32
248 register int i;
249 DL_HANDLE module = NULL;
250 if (nsapi_dll) {
251
252 module = GetModuleHandle(nsapi_dll);
253 if (!module) {
254 log_error(LOG_WARN, "php5_init", NULL, NULL, "Cannot find DLL specified by server_lib parameter: %s", nsapi_dll);
255 }
256 } else {
257
258 for (i=0; nsapi_dlls[i]; i++) {
259 if (module = GetModuleHandle(nsapi_dlls[i])) {
260 break;
261 }
262 }
263 }
264 if (!module) return;
265 #else
266 DL_HANDLE module = RTLD_DEFAULT;
267 #endif
268 nsapi_servact_uri2path = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_uri2path");
269 nsapi_servact_pathchecks = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_pathchecks");
270 nsapi_servact_fileinfo = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_fileinfo");
271 nsapi_servact_service = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_service");
272 if (!(nsapi_servact_uri2path && nsapi_servact_pathchecks && nsapi_servact_fileinfo && nsapi_servact_service)) {
273
274 nsapi_servact_uri2path = NULL;
275 nsapi_servact_pathchecks = NULL;
276 nsapi_servact_fileinfo = NULL;
277 nsapi_servact_service = NULL;
278 }
279 }
280
281
282
283
284 static void php_nsapi_init_globals(zend_nsapi_globals *nsapi_globals)
285 {
286 nsapi_globals->read_timeout = 60;
287 }
288
289
290
291
292 PHP_MINIT_FUNCTION(nsapi)
293 {
294 php_nsapi_init_dynamic_symbols();
295 ZEND_INIT_MODULE_GLOBALS(nsapi, php_nsapi_init_globals, NULL);
296 REGISTER_INI_ENTRIES();
297 return SUCCESS;
298 }
299
300
301
302
303 PHP_MSHUTDOWN_FUNCTION(nsapi)
304 {
305 UNREGISTER_INI_ENTRIES();
306 return SUCCESS;
307 }
308
309
310
311
312 PHP_MINFO_FUNCTION(nsapi)
313 {
314 php_info_print_table_start();
315 php_info_print_table_row(2, "NSAPI Module Revision", "$Id: 71d7860a23c8ac8b5120062a29fec6557de307a6 $");
316 php_info_print_table_row(2, "Server Software", system_version());
317 php_info_print_table_row(2, "Sub-requests with nsapi_virtual()",
318 (nsapi_servact_service)?((zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0))?"not supported with zlib.output_compression":"enabled"):"not supported on this platform" );
319 php_info_print_table_end();
320
321 DISPLAY_INI_ENTRIES();
322 }
323
324
325
326
327
328
329
330
331
332 PHP_FUNCTION(nsapi_virtual)
333 {
334 int uri_len,rv;
335 char *uri,*value;
336 Request *rq;
337 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
338
339 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &uri, &uri_len) == FAILURE) {
340 return;
341 }
342
343 if (!nsapi_servact_service) {
344 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests not supported on this platform", uri);
345 RETURN_FALSE;
346 } else if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
347 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests do not work with zlib.output_compression", uri);
348 RETURN_FALSE;
349 } else {
350 php_output_end_all(TSRMLS_C);
351 php_header(TSRMLS_C);
352
353
354
355 if ((rq = request_restart_internal(uri, NULL)) == NULL) {
356 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Internal request creation failed", uri);
357 RETURN_FALSE;
358 }
359
360
361 param_free(pblock_remove("host", rq->headers));
362 if (value = pblock_findval("host", rc->rq->headers)) {
363 pblock_nvinsert("host", value, rq->headers);
364 }
365
366
367
368 do {
369 rv = (*nsapi_servact_uri2path)(rc->sn, rq);
370 if (rv != REQ_PROCEED) {
371 continue;
372 }
373
374 rv = (*nsapi_servact_pathchecks)(rc->sn, rq);
375 if (rv != REQ_PROCEED) {
376 continue;
377 }
378
379 rv = (*nsapi_servact_fileinfo)(rc->sn, rq);
380 if (rv != REQ_PROCEED) {
381 continue;
382 }
383
384 rv = (*nsapi_servact_service)(rc->sn, rq);
385 } while (rv == REQ_RESTART);
386
387 if (rq->status_num != 200) {
388 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - HTTP status code %d during subrequest", uri, rq->status_num);
389 request_free(rq);
390 RETURN_FALSE;
391 }
392
393 request_free(rq);
394
395 RETURN_TRUE;
396 }
397 }
398
399
400
401
402 PHP_FUNCTION(nsapi_request_headers)
403 {
404 register int i;
405 struct pb_entry *entry;
406 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
407
408 if (zend_parse_parameters_none() == FAILURE) {
409 return;
410 }
411
412 array_init(return_value);
413
414 for (i=0; i < rc->rq->headers->hsize; i++) {
415 entry=rc->rq->headers->ht[i];
416 while (entry) {
417 add_assoc_string(return_value, entry->param->name, entry->param->value, 1);
418 entry=entry->next;
419 }
420 }
421 }
422
423
424
425
426 PHP_FUNCTION(nsapi_response_headers)
427 {
428 register int i;
429 struct pb_entry *entry;
430 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
431
432 if (zend_parse_parameters_none() == FAILURE) {
433 return;
434 }
435
436 array_init(return_value);
437
438 for (i=0; i < rc->rq->srvhdrs->hsize; i++) {
439 entry=rc->rq->srvhdrs->ht[i];
440 while (entry) {
441 add_assoc_string(return_value, entry->param->name, entry->param->value, 1);
442 entry=entry->next;
443 }
444 }
445 }
446
447
448
449
450
451
452
453 static int sapi_nsapi_ub_write(const char *str, unsigned int str_length TSRMLS_DC)
454 {
455 int retval;
456 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
457
458 if (!SG(headers_sent)) {
459 sapi_send_headers(TSRMLS_C);
460 }
461
462 retval = net_write(rc->sn->csd, (char *)str, str_length);
463 if (retval == IO_ERROR || retval == IO_EOF ) {
464 php_handle_aborted_connection();
465 }
466 return retval;
467 }
468
469
470 static void sapi_nsapi_flush(void *server_context)
471 {
472 nsapi_request_context *rc = (nsapi_request_context *)server_context;
473 TSRMLS_FETCH();
474
475 if (!rc) {
476
477 return;
478 }
479
480 if (!SG(headers_sent)) {
481 sapi_send_headers(TSRMLS_C);
482 }
483
484
485 #if NSAPI_VERSION >= 302
486 if (net_flush(rc->sn->csd) < 0) {
487 php_handle_aborted_connection();
488 }
489 #endif
490 }
491
492
493 static int php_nsapi_remove_header(sapi_header_struct *sapi_header TSRMLS_DC)
494 {
495 char *header_name, *p;
496 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
497
498
499 header_name = pool_strdup(rc->sn->pool, sapi_header->header);
500
501
502 if (p = strchr(header_name, ':')) {
503 *p = 0;
504 }
505
506
507 for (p=header_name; *p; p++) {
508 *p=tolower(*p);
509 }
510
511
512 param_free(pblock_remove(header_name, rc->rq->srvhdrs));
513 pool_free(rc->sn->pool, header_name);
514
515 return ZEND_HASH_APPLY_KEEP;
516 }
517
518 static int sapi_nsapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
519 {
520 char *header_name, *header_content, *p;
521 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
522
523 switch(op) {
524 case SAPI_HEADER_DELETE_ALL:
525
526 zend_llist_apply(&sapi_headers->headers, (llist_apply_func_t) php_nsapi_remove_header TSRMLS_CC);
527 return 0;
528
529 case SAPI_HEADER_DELETE:
530
531 php_nsapi_remove_header(sapi_header TSRMLS_CC);
532 return 0;
533
534 case SAPI_HEADER_ADD:
535 case SAPI_HEADER_REPLACE:
536
537 header_name = pool_strdup(rc->sn->pool, sapi_header->header);
538
539
540 header_content = strchr(header_name, ':');
541 if (header_content) {
542 *header_content = 0;
543 do {
544 header_content++;
545 } while (*header_content==' ');
546
547
548 for (p=header_name; *p; p++) {
549 *p=tolower(*p);
550 }
551
552
553 if (op==SAPI_HEADER_REPLACE || strcmp(header_name, "content-type")==0) {
554 param_free(pblock_remove(header_name, rc->rq->srvhdrs));
555 }
556
557 pblock_nvinsert(header_name, header_content, rc->rq->srvhdrs);
558 }
559
560 pool_free(rc->sn->pool, header_name);
561 return SAPI_HEADER_ADD;
562
563 default:
564 return 0;
565 }
566 }
567
568 static int sapi_nsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
569 {
570 int retval;
571 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
572
573 if (SG(sapi_headers).send_default_content_type) {
574 char *hd;
575 param_free(pblock_remove("content-type", rc->rq->srvhdrs));
576 hd = sapi_get_default_content_type(TSRMLS_C);
577 pblock_nvinsert("content-type", hd, rc->rq->srvhdrs);
578 efree(hd);
579 }
580
581 protocol_status(rc->sn, rc->rq, SG(sapi_headers).http_response_code, NULL);
582 retval = protocol_start_response(rc->sn, rc->rq);
583
584 if (retval == REQ_PROCEED || retval == REQ_NOACTION) {
585 return SAPI_HEADER_SENT_SUCCESSFULLY;
586 } else {
587 return SAPI_HEADER_SEND_FAILED;
588 }
589 }
590
591 static int sapi_nsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
592 {
593 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
594 char *read_ptr = buffer, *content_length_str = NULL;
595 uint bytes_read = 0;
596 int length, content_length = 0;
597 netbuf *nbuf = rc->sn->inbuf;
598
599
600
601
602 count_bytes = MIN(count_bytes, SG(request_info).content_length-rc->read_post_bytes);
603 content_length = SG(request_info).content_length;
604
605 if (content_length <= 0) {
606 return 0;
607 }
608
609
610
611
612 length = nbuf->cursize - nbuf->pos;
613 length = MIN(count_bytes, length);
614 if (length > 0) {
615 memcpy(read_ptr, nbuf->inbuf + nbuf->pos, length);
616 bytes_read += length;
617 read_ptr += length;
618 content_length -= length;
619 nbuf->pos += length;
620 }
621
622
623
624
625 while (content_length > 0 && bytes_read < count_bytes) {
626 int bytes_to_read = count_bytes - bytes_read;
627
628 if (content_length < bytes_to_read) {
629 bytes_to_read = content_length;
630 }
631
632 length = net_read(rc->sn->csd, read_ptr, bytes_to_read, NSAPI_G(read_timeout));
633
634 if (length == IO_ERROR || length == IO_EOF) {
635 break;
636 }
637
638 bytes_read += length;
639 read_ptr += length;
640 content_length -= length;
641 }
642
643 if ( bytes_read > 0 ) {
644 rc->read_post_bytes += bytes_read;
645 }
646 return bytes_read;
647 }
648
649 static char *sapi_nsapi_read_cookies(TSRMLS_D)
650 {
651 char *cookie_string;
652 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
653
654 cookie_string = pblock_findval("cookie", rc->rq->headers);
655 return cookie_string;
656 }
657
658 static void sapi_nsapi_register_server_variables(zval *track_vars_array TSRMLS_DC)
659 {
660 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
661 register size_t i;
662 int pos;
663 char *value,*p;
664 char buf[32];
665 struct pb_entry *entry;
666
667 for (i = 0; i < nsapi_reqpb_size; i++) {
668 value = pblock_findval(nsapi_reqpb[i].nsapi_eq, rc->rq->reqpb);
669 if (value) {
670 php_register_variable((char *)nsapi_reqpb[i].env_var, value, track_vars_array TSRMLS_CC);
671 }
672 }
673
674 for (i=0; i < rc->rq->headers->hsize; i++) {
675 entry=rc->rq->headers->ht[i];
676 while (entry) {
677 if (strcasecmp(entry->param->name, "content-length")==0 || strcasecmp(entry->param->name, "content-type")==0) {
678 value=estrdup(entry->param->name);
679 pos = 0;
680 } else {
681 spprintf(&value, 0, "HTTP_%s", entry->param->name);
682 pos = 5;
683 }
684 if (value) {
685 for(p = value + pos; *p; p++) {
686 *p = toupper(*p);
687 if (!isalnum(*p)) {
688 *p = '_';
689 }
690 }
691 php_register_variable(value, entry->param->value, track_vars_array TSRMLS_CC);
692 efree(value);
693 }
694 entry=entry->next;
695 }
696 }
697
698 for (i = 0; i < nsapi_vars_size; i++) {
699 value = pblock_findval(nsapi_vars[i].nsapi_eq, rc->rq->vars);
700 if (value) {
701 php_register_variable((char *)nsapi_vars[i].env_var, value, track_vars_array TSRMLS_CC);
702 }
703 }
704
705 for (i = 0; i < nsapi_client_size; i++) {
706 value = pblock_findval(nsapi_client[i].nsapi_eq, rc->sn->client);
707 if (value) {
708 php_register_variable((char *)nsapi_client[i].env_var, value, track_vars_array TSRMLS_CC);
709 }
710 }
711
712 if (value = session_dns(rc->sn)) {
713 php_register_variable("REMOTE_HOST", value, track_vars_array TSRMLS_CC);
714 nsapi_free(value);
715 }
716
717 slprintf(buf, sizeof(buf), "%d", conf_getglobals()->Vport);
718 php_register_variable("SERVER_PORT", buf, track_vars_array TSRMLS_CC);
719 php_register_variable("SERVER_NAME", conf_getglobals()->Vserver_hostname, track_vars_array TSRMLS_CC);
720
721 value = http_uri2url_dynamic("", "", rc->sn, rc->rq);
722 php_register_variable("SERVER_URL", value, track_vars_array TSRMLS_CC);
723 nsapi_free(value);
724
725 php_register_variable("SERVER_SOFTWARE", system_version(), track_vars_array TSRMLS_CC);
726 if (security_active) {
727 php_register_variable("HTTPS", "ON", track_vars_array TSRMLS_CC);
728 }
729 php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC);
730
731
732 if (value = request_translate_uri("/", rc->sn)) {
733 pos = strlen(value);
734 php_register_variable_safe("DOCUMENT_ROOT", value, pos-1, track_vars_array TSRMLS_CC);
735 nsapi_free(value);
736 }
737
738
739 if (rc->path_info) {
740 if (value = request_translate_uri(rc->path_info, rc->sn)) {
741 php_register_variable("PATH_TRANSLATED", value, track_vars_array TSRMLS_CC);
742 nsapi_free(value);
743 }
744 php_register_variable("PATH_INFO", rc->path_info, track_vars_array TSRMLS_CC);
745 }
746
747
748 if (SG(request_info).request_uri) {
749 pos = strlen(SG(request_info).request_uri);
750
751 if (SG(request_info).query_string) {
752 spprintf(&value, 0, "%s?%s", SG(request_info).request_uri, SG(request_info).query_string);
753 if (value) {
754 php_register_variable("REQUEST_URI", value, track_vars_array TSRMLS_CC);
755 efree(value);
756 }
757 } else {
758 php_register_variable_safe("REQUEST_URI", SG(request_info).request_uri, pos, track_vars_array TSRMLS_CC);
759 }
760
761 if (rc->path_info) {
762 pos -= strlen(rc->path_info);
763 if (pos<0) {
764 pos = 0;
765 }
766 }
767 php_register_variable_safe("SCRIPT_NAME", SG(request_info).request_uri, pos, track_vars_array TSRMLS_CC);
768 }
769 php_register_variable("SCRIPT_FILENAME", SG(request_info).path_translated, track_vars_array TSRMLS_CC);
770
771
772 if (rc->http_error) {
773 slprintf(buf, sizeof(buf), "%d", rc->http_error);
774 php_register_variable("ERROR_TYPE", buf, track_vars_array TSRMLS_CC);
775 }
776 }
777
778 static void nsapi_log_message(char *message TSRMLS_DC)
779 {
780 nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
781
782 if (rc) {
783 log_error(LOG_INFORM, pblock_findval("fn", rc->pb), rc->sn, rc->rq, "%s", message);
784 } else {
785 log_error(LOG_INFORM, "php5", NULL, NULL, "%s", message);
786 }
787 }
788
789 static double sapi_nsapi_get_request_time(TSRMLS_D)
790 {
791 return REQ_TIME( ((nsapi_request_context *)SG(server_context))->rq );
792 }
793
794 static int php_nsapi_startup(sapi_module_struct *sapi_module)
795 {
796 if (php_module_startup(sapi_module, &nsapi_module_entry, 1)==FAILURE) {
797 return FAILURE;
798 }
799 return SUCCESS;
800 }
801
802 static struct stat* sapi_nsapi_get_stat(TSRMLS_D)
803 {
804 return request_stat_path(
805 SG(request_info).path_translated,
806 ((nsapi_request_context *)SG(server_context))->rq
807 );
808 }
809
810 static sapi_module_struct nsapi_sapi_module = {
811 "nsapi",
812 "NSAPI",
813
814 php_nsapi_startup,
815 php_module_shutdown_wrapper,
816
817 NULL,
818 NULL,
819
820 sapi_nsapi_ub_write,
821 sapi_nsapi_flush,
822 sapi_nsapi_get_stat,
823 NULL,
824
825 php_error,
826
827 sapi_nsapi_header_handler,
828 sapi_nsapi_send_headers,
829 NULL,
830
831 sapi_nsapi_read_post,
832 sapi_nsapi_read_cookies,
833
834 sapi_nsapi_register_server_variables,
835 nsapi_log_message,
836 sapi_nsapi_get_request_time,
837 NULL,
838
839 NULL,
840 NULL,
841
842 STANDARD_SAPI_MODULE_PROPERTIES
843 };
844
845 static void nsapi_php_ini_entries(NSLS_D TSRMLS_DC)
846 {
847 struct pb_entry *entry;
848 register int i,j,ok;
849
850 for (i=0; i < NSG(pb)->hsize; i++) {
851 entry=NSG(pb)->ht[i];
852 while (entry) {
853
854 ok=1;
855 for (j=0; nsapi_exclude_from_ini_entries[j]; j++) {
856 ok&=(strcasecmp(entry->param->name, nsapi_exclude_from_ini_entries[j])!=0);
857 }
858
859 if (ok) {
860
861 if (zend_alter_ini_entry(entry->param->name, strlen(entry->param->name)+1,
862 entry->param->value, strlen(entry->param->value),
863 PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE)==FAILURE) {
864 log_error(LOG_WARN, pblock_findval("fn", NSG(pb)), NSG(sn), NSG(rq), "Cannot change php.ini key \"%s\" to \"%s\"", entry->param->name, entry->param->value);
865 }
866 }
867 entry=entry->next;
868 }
869 }
870 }
871
872 void NSAPI_PUBLIC php5_close(void *vparam)
873 {
874 if (nsapi_sapi_module.shutdown) {
875 nsapi_sapi_module.shutdown(&nsapi_sapi_module);
876 }
877
878 if (nsapi_sapi_module.php_ini_path_override) {
879 free(nsapi_sapi_module.php_ini_path_override);
880 }
881
882 #ifdef PHP_WIN32
883 if (nsapi_dll) {
884 free(nsapi_dll);
885 nsapi_dll = NULL;
886 }
887 #endif
888
889 sapi_shutdown();
890 tsrm_shutdown();
891
892 log_error(LOG_INFORM, "php5_close", NULL, NULL, "Shutdown PHP Module");
893 }
894
895
896
897
898
899
900
901
902
903
904
905
906 int NSAPI_PUBLIC php5_init(pblock *pb, Session *sn, Request *rq)
907 {
908 php_core_globals *core_globals;
909 char *strval;
910 int threads=128;
911
912
913 threads=conf_getglobals()->Vpool_maxthreads;
914 if (threads<1) {
915 threads=128;
916 }
917 tsrm_startup(threads, 1, 0, NULL);
918
919 core_globals = ts_resource(core_globals_id);
920
921
922 if (strval = pblock_findval("php_ini", pb)) {
923 nsapi_sapi_module.php_ini_path_override = strdup(strval);
924 }
925
926 #ifdef PHP_WIN32
927
928
929 if (strval = pblock_findval("server_lib", pb)) {
930 nsapi_dll = strdup(strval);
931 }
932 #endif
933
934
935 sapi_startup(&nsapi_sapi_module);
936 nsapi_sapi_module.startup(&nsapi_sapi_module);
937
938 daemon_atrestart(&php5_close, NULL);
939
940 log_error(LOG_INFORM, pblock_findval("fn", pb), sn, rq, "Initialized PHP Module (%d threads expected)", threads);
941 return REQ_PROCEED;
942 }
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959 int NSAPI_PUBLIC php5_execute(pblock *pb, Session *sn, Request *rq)
960 {
961 int retval;
962 nsapi_request_context *request_context;
963 zend_file_handle file_handle = {0};
964 struct stat *fst;
965
966 char *path_info;
967 char *query_string = pblock_findval("query", rq->reqpb);
968 char *uri = pblock_findval("uri", rq->reqpb);
969 char *request_method = pblock_findval("method", rq->reqpb);
970 char *content_type = pblock_findval("content-type", rq->headers);
971 char *content_length = pblock_findval("content-length", rq->headers);
972 char *directive = pblock_findval("Directive", pb);
973 int error_directive = (directive && !strcasecmp(directive, "error"));
974 int fixed_script = 1;
975
976
977 char *path_translated = pblock_findval("script", pb);
978
979 TSRMLS_FETCH();
980
981
982 if (!path_translated) {
983 path_translated = pblock_findval("path", rq->vars);
984 path_info = pblock_findval("path-info", rq->vars);
985 fixed_script = 0;
986 if (error_directive) {
987
988 log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Missing 'script' parameter");
989 return REQ_NOACTION;
990 }
991 } else {
992
993 path_info = pblock_findval("uri", rq->reqpb);
994 }
995
996
997
998 if (SG(server_context)) {
999
1000 log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot make nesting PHP requests with nsapi_virtual()");
1001 if (error_directive) {
1002 return REQ_NOACTION;
1003 } else {
1004 protocol_status(sn, rq, 500, NULL);
1005 return REQ_ABORTED;
1006 }
1007 }
1008
1009 request_context = (nsapi_request_context *)pool_malloc(sn->pool, sizeof(nsapi_request_context));
1010 if (!request_context) {
1011 log_error(LOG_CATASTROPHE, pblock_findval("fn", pb), sn, rq, "Insufficient memory to process PHP request!");
1012 return REQ_ABORTED;
1013 }
1014 request_context->pb = pb;
1015 request_context->sn = sn;
1016 request_context->rq = rq;
1017 request_context->read_post_bytes = 0;
1018 request_context->fixed_script = fixed_script;
1019 request_context->http_error = (error_directive) ? rq->status_num : 0;
1020 request_context->path_info = path_info;
1021
1022 SG(server_context) = request_context;
1023 SG(request_info).query_string = query_string;
1024 SG(request_info).request_uri = uri;
1025 SG(request_info).request_method = request_method;
1026 SG(request_info).path_translated = path_translated;
1027 SG(request_info).content_type = content_type;
1028 SG(request_info).content_length = (content_length == NULL) ? 0 : strtoul(content_length, 0, 0);
1029 SG(sapi_headers).http_response_code = (error_directive) ? rq->status_num : 200;
1030
1031 nsapi_php_ini_entries(NSLS_C TSRMLS_CC);
1032
1033 php_handle_auth_data(pblock_findval("authorization", rq->headers) TSRMLS_CC);
1034
1035 file_handle.type = ZEND_HANDLE_FILENAME;
1036 file_handle.filename = SG(request_info).path_translated;
1037 file_handle.free_filename = 0;
1038 file_handle.opened_path = NULL;
1039
1040 fst = request_stat_path(SG(request_info).path_translated, rq);
1041 if (fst && S_ISREG(fst->st_mode)) {
1042 if (php_request_startup(TSRMLS_C) == SUCCESS) {
1043 php_execute_script(&file_handle TSRMLS_CC);
1044 php_request_shutdown(NULL);
1045 retval=REQ_PROCEED;
1046 } else {
1047
1048 log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot prepare PHP engine!");
1049 if (error_directive) {
1050 retval=REQ_NOACTION;
1051 } else {
1052 protocol_status(sn, rq, 500, NULL);
1053 retval=REQ_ABORTED;
1054 }
1055 }
1056 } else {
1057
1058 log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot execute PHP script: %s (File not found)", SG(request_info).path_translated);
1059 if (error_directive) {
1060 retval=REQ_NOACTION;
1061 } else {
1062 protocol_status(sn, rq, 404, NULL);
1063 retval=REQ_ABORTED;
1064 }
1065 }
1066
1067 pool_free(sn->pool, request_context);
1068 SG(server_context) = NULL;
1069
1070 return retval;
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088 int NSAPI_PUBLIC php5_auth_trans(pblock * pb, Session * sn, Request * rq)
1089 {
1090
1091
1092
1093
1094 return REQ_PROCEED;
1095 }
1096
1097
1098
1099
1100
1101
1102
1103
1104