This source file includes following definitions.
- user_config_cache_entry_dtor
- fcgi_log
- print_module_info
- module_name_cmp
- print_modules
- print_extension_info
- extension_name_cmp
- print_extensions
- sapi_cgi_single_write
- sapi_cgi_ub_write
- sapi_fcgi_ub_write
- sapi_cgi_flush
- sapi_fcgi_flush
- sapi_cgi_send_headers
- sapi_cgi_read_post
- sapi_fcgi_read_post
- sapi_cgi_getenv
- sapi_fcgi_getenv
- _sapi_cgi_putenv
- sapi_cgi_read_cookies
- sapi_fcgi_read_cookies
- cgi_php_load_env_var
- cgi_php_import_environment_variables
- sapi_cgi_register_variables
- sapi_cgi_log_message
- php_cgi_ini_activate_user_config
- sapi_cgi_activate
- sapi_cgi_deactivate
- php_cgi_startup
- php_cgi_usage
- is_valid_path
- init_request_info
- fastcgi_cleanup
- PHP_INI_BEGIN
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_MINFO_FUNCTION
- PHP_FUNCTION
- add_request_header
- PHP_FUNCTION
- add_response_header
- PHP_FUNCTION
- main
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
26 #include "php.h"
27 #include "php_globals.h"
28 #include "php_variables.h"
29 #include "zend_modules.h"
30
31 #include "SAPI.h"
32
33 #include <stdio.h>
34
35 #ifdef PHP_WIN32
36 # include "win32/time.h"
37 # include "win32/signal.h"
38 # include <process.h>
39 #endif
40
41 #if HAVE_SYS_TIME_H
42 # include <sys/time.h>
43 #endif
44
45 #if HAVE_UNISTD_H
46 # include <unistd.h>
47 #endif
48
49 #if HAVE_SIGNAL_H
50 # include <signal.h>
51 #endif
52
53 #if HAVE_SETLOCALE
54 # include <locale.h>
55 #endif
56
57 #if HAVE_SYS_TYPES_H
58 # include <sys/types.h>
59 #endif
60
61 #if HAVE_SYS_WAIT_H
62 # include <sys/wait.h>
63 #endif
64
65 #include "zend.h"
66 #include "zend_extensions.h"
67 #include "php_ini.h"
68 #include "php_globals.h"
69 #include "php_main.h"
70 #include "fopen_wrappers.h"
71 #include "http_status_codes.h"
72 #include "ext/standard/php_standard.h"
73 #include "ext/standard/url.h"
74
75 #ifdef PHP_WIN32
76 # include <io.h>
77 # include <fcntl.h>
78 # include "win32/php_registry.h"
79 #endif
80
81 #ifdef __riscos__
82 # include <unixlib/local.h>
83 int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
84 #endif
85
86 #include "zend_compile.h"
87 #include "zend_execute.h"
88 #include "zend_highlight.h"
89
90 #include "php_getopt.h"
91
92 #include "fastcgi.h"
93
94 #if defined(PHP_WIN32) && defined(HAVE_OPENSSL)
95 # include "openssl/applink.c"
96 #endif
97
98 #ifndef PHP_WIN32
99
100 struct sigaction act, old_term, old_quit, old_int;
101 #endif
102
103 static void (*php_php_import_environment_variables)(zval *array_ptr);
104
105 #ifndef PHP_WIN32
106
107
108
109
110 static int children = 0;
111
112
113
114
115
116 static int parent = 1;
117
118
119 static int exit_signal = 0;
120
121
122 static int parent_waiting = 0;
123
124
125
126
127 static pid_t pgroup;
128 #endif
129
130 #define PHP_MODE_STANDARD 1
131 #define PHP_MODE_HIGHLIGHT 2
132 #define PHP_MODE_LINT 4
133 #define PHP_MODE_STRIP 5
134
135 static char *php_optarg = NULL;
136 static int php_optind = 1;
137 static zend_module_entry cgi_module_entry;
138
139 static const opt_struct OPTIONS[] = {
140 {'a', 0, "interactive"},
141 {'b', 1, "bindpath"},
142 {'C', 0, "no-chdir"},
143 {'c', 1, "php-ini"},
144 {'d', 1, "define"},
145 {'e', 0, "profile-info"},
146 {'f', 1, "file"},
147 {'h', 0, "help"},
148 {'i', 0, "info"},
149 {'l', 0, "syntax-check"},
150 {'m', 0, "modules"},
151 {'n', 0, "no-php-ini"},
152 {'q', 0, "no-header"},
153 {'s', 0, "syntax-highlight"},
154 {'s', 0, "syntax-highlighting"},
155 {'w', 0, "strip"},
156 {'?', 0, "usage"},
157 {'v', 0, "version"},
158 {'z', 1, "zend-extension"},
159 {'T', 1, "timing"},
160 {'-', 0, NULL}
161 };
162
163 typedef struct _php_cgi_globals_struct {
164 HashTable user_config_cache;
165 char *redirect_status_env;
166 zend_bool rfc2616_headers;
167 zend_bool nph;
168 zend_bool check_shebang_line;
169 zend_bool fix_pathinfo;
170 zend_bool force_redirect;
171 zend_bool discard_path;
172 zend_bool fcgi_logging;
173 #ifdef PHP_WIN32
174 zend_bool impersonate;
175 #endif
176 } php_cgi_globals_struct;
177
178
179
180
181
182
183
184
185
186
187 typedef struct _user_config_cache_entry {
188 time_t expires;
189 HashTable *user_config;
190 } user_config_cache_entry;
191
192 static void user_config_cache_entry_dtor(zval *el)
193 {
194 user_config_cache_entry *entry = (user_config_cache_entry *)Z_PTR_P(el);
195 zend_hash_destroy(entry->user_config);
196 free(entry->user_config);
197 free(entry);
198 }
199
200
201 #ifdef ZTS
202 static int php_cgi_globals_id;
203 #define CGIG(v) ZEND_TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
204 #if defined(PHP_WIN32)
205 ZEND_TSRMLS_CACHE_DEFINE()
206 #endif
207 #else
208 static php_cgi_globals_struct php_cgi_globals;
209 #define CGIG(v) (php_cgi_globals.v)
210 #endif
211
212 #ifdef PHP_WIN32
213 #define TRANSLATE_SLASHES(path) \
214 { \
215 char *tmp = path; \
216 while (*tmp) { \
217 if (*tmp == '\\') *tmp = '/'; \
218 tmp++; \
219 } \
220 }
221 #else
222 #define TRANSLATE_SLASHES(path)
223 #endif
224
225 #ifndef HAVE_ATTRIBUTE_WEAK
226 static void fcgi_log(int type, const char *format, ...) {
227 va_list ap;
228
229 va_start(ap, format);
230 vfprintf(stderr, format, ap);
231 va_end(ap);
232 }
233 #endif
234
235 static int print_module_info(zval *element)
236 {
237 zend_module_entry *module = Z_PTR_P(element);
238 php_printf("%s\n", module->name);
239 return ZEND_HASH_APPLY_KEEP;
240 }
241
242 static int module_name_cmp(const void *a, const void *b)
243 {
244 Bucket *f = (Bucket *) a;
245 Bucket *s = (Bucket *) b;
246
247 return strcasecmp( ((zend_module_entry *)Z_PTR(f->val))->name,
248 ((zend_module_entry *)Z_PTR(s->val))->name);
249 }
250
251 static void print_modules(void)
252 {
253 HashTable sorted_registry;
254
255 zend_hash_init(&sorted_registry, 64, NULL, NULL, 1);
256 zend_hash_copy(&sorted_registry, &module_registry, NULL);
257 zend_hash_sort(&sorted_registry, module_name_cmp, 0);
258 zend_hash_apply(&sorted_registry, print_module_info);
259 zend_hash_destroy(&sorted_registry);
260 }
261
262 static int print_extension_info(zend_extension *ext, void *arg)
263 {
264 php_printf("%s\n", ext->name);
265 return 0;
266 }
267
268 static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s)
269 {
270 return strcmp( ((zend_extension *)(*f)->data)->name,
271 ((zend_extension *)(*s)->data)->name);
272 }
273
274 static void print_extensions(void)
275 {
276 zend_llist sorted_exts;
277
278 zend_llist_copy(&sorted_exts, &zend_extensions);
279 sorted_exts.dtor = NULL;
280 zend_llist_sort(&sorted_exts, extension_name_cmp);
281 zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL);
282 zend_llist_destroy(&sorted_exts);
283 }
284
285 #ifndef STDOUT_FILENO
286 #define STDOUT_FILENO 1
287 #endif
288
289 static inline size_t sapi_cgi_single_write(const char *str, size_t str_length)
290 {
291 #ifdef PHP_WRITE_STDOUT
292 int ret;
293
294 ret = write(STDOUT_FILENO, str, str_length);
295 if (ret <= 0) return 0;
296 return ret;
297 #else
298 size_t ret;
299
300 ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
301 return ret;
302 #endif
303 }
304
305 static size_t sapi_cgi_ub_write(const char *str, size_t str_length)
306 {
307 const char *ptr = str;
308 size_t remaining = str_length;
309 size_t ret;
310
311 while (remaining > 0) {
312 ret = sapi_cgi_single_write(ptr, remaining);
313 if (!ret) {
314 php_handle_aborted_connection();
315 return str_length - remaining;
316 }
317 ptr += ret;
318 remaining -= ret;
319 }
320
321 return str_length;
322 }
323
324 static size_t sapi_fcgi_ub_write(const char *str, size_t str_length)
325 {
326 const char *ptr = str;
327 size_t remaining = str_length;
328 fcgi_request *request = (fcgi_request*) SG(server_context);
329
330 while (remaining > 0) {
331 int to_write = remaining > INT_MAX ? INT_MAX : (int)remaining;
332 int ret = fcgi_write(request, FCGI_STDOUT, ptr, to_write);
333
334 if (ret <= 0) {
335 php_handle_aborted_connection();
336 return str_length - remaining;
337 }
338 ptr += ret;
339 remaining -= ret;
340 }
341
342 return str_length;
343 }
344
345 static void sapi_cgi_flush(void *server_context)
346 {
347 if (fflush(stdout) == EOF) {
348 php_handle_aborted_connection();
349 }
350 }
351
352 static void sapi_fcgi_flush(void *server_context)
353 {
354 fcgi_request *request = (fcgi_request*) server_context;
355
356 if (
357 #ifndef PHP_WIN32
358 !parent &&
359 #endif
360 request && !fcgi_flush(request, 0)) {
361
362 php_handle_aborted_connection();
363 }
364 }
365
366 #define SAPI_CGI_MAX_HEADER_LENGTH 1024
367
368 static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
369 {
370 char buf[SAPI_CGI_MAX_HEADER_LENGTH];
371 sapi_header_struct *h;
372 zend_llist_position pos;
373 zend_bool ignore_status = 0;
374 int response_status = SG(sapi_headers).http_response_code;
375
376 if (SG(request_info).no_headers == 1) {
377 return SAPI_HEADER_SENT_SUCCESSFULLY;
378 }
379
380 if (CGIG(nph) || SG(sapi_headers).http_response_code != 200)
381 {
382 int len;
383 zend_bool has_status = 0;
384
385 if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
386 char *s;
387 len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
388 if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
389 response_status = atoi((s + 1));
390 }
391
392 if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
393 len = SAPI_CGI_MAX_HEADER_LENGTH;
394 }
395
396 } else {
397 char *s;
398
399 if (SG(sapi_headers).http_status_line &&
400 (s = strchr(SG(sapi_headers).http_status_line, ' ')) != 0 &&
401 (s - SG(sapi_headers).http_status_line) >= 5 &&
402 strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
403 ) {
404 len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
405 response_status = atoi((s + 1));
406 } else {
407 h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
408 while (h) {
409 if (h->header_len > sizeof("Status:")-1 &&
410 strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
411 ) {
412 has_status = 1;
413 break;
414 }
415 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
416 }
417 if (!has_status) {
418 http_response_status_code_pair *err = (http_response_status_code_pair*)http_status_map;
419
420 while (err->code != 0) {
421 if (err->code == SG(sapi_headers).http_response_code) {
422 break;
423 }
424 err++;
425 }
426 if (err->str) {
427 len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->str);
428 } else {
429 len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
430 }
431 }
432 }
433 }
434
435 if (!has_status) {
436 PHPWRITE_H(buf, len);
437 ignore_status = 1;
438 }
439 }
440
441 h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
442 while (h) {
443
444 if (h->header_len) {
445 if (h->header_len > sizeof("Status:")-1 &&
446 strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
447 ) {
448 if (!ignore_status) {
449 ignore_status = 1;
450 PHPWRITE_H(h->header, h->header_len);
451 PHPWRITE_H("\r\n", 2);
452 }
453 } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 &&
454 strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0
455 ) {
456 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
457 continue;
458 } else {
459 PHPWRITE_H(h->header, h->header_len);
460 PHPWRITE_H("\r\n", 2);
461 }
462 }
463 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
464 }
465 PHPWRITE_H("\r\n", 2);
466
467 return SAPI_HEADER_SENT_SUCCESSFULLY;
468 }
469
470 #ifndef STDIN_FILENO
471 # define STDIN_FILENO 0
472 #endif
473
474 static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
475 {
476 size_t read_bytes = 0;
477 int tmp_read_bytes;
478 size_t remaining_bytes;
479
480 assert(SG(request_info).content_length >= SG(read_post_bytes));
481
482 remaining_bytes = (size_t)(SG(request_info).content_length - SG(read_post_bytes));
483
484 count_bytes = MIN(count_bytes, remaining_bytes);
485 while (read_bytes < count_bytes) {
486 #ifdef PHP_WIN32
487 size_t diff = count_bytes - read_bytes;
488 unsigned int to_read = (diff > UINT_MAX) ? UINT_MAX : (unsigned int)diff;
489
490 tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, to_read);
491 #else
492 tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
493 #endif
494 if (tmp_read_bytes <= 0) {
495 break;
496 }
497 read_bytes += tmp_read_bytes;
498 }
499 return read_bytes;
500 }
501
502 static size_t sapi_fcgi_read_post(char *buffer, size_t count_bytes)
503 {
504 size_t read_bytes = 0;
505 int tmp_read_bytes;
506 fcgi_request *request = (fcgi_request*) SG(server_context);
507 size_t remaining = SG(request_info).content_length - SG(read_post_bytes);
508
509 if (remaining < count_bytes) {
510 count_bytes = remaining;
511 }
512 while (read_bytes < count_bytes) {
513 size_t diff = count_bytes - read_bytes;
514 int to_read = (diff > INT_MAX) ? INT_MAX : (int)diff;
515
516 tmp_read_bytes = fcgi_read(request, buffer + read_bytes, to_read);
517 if (tmp_read_bytes <= 0) {
518 break;
519 }
520 read_bytes += tmp_read_bytes;
521 }
522 return read_bytes;
523 }
524
525 static char *sapi_cgi_getenv(char *name, size_t name_len)
526 {
527 return getenv(name);
528 }
529
530 static char *sapi_fcgi_getenv(char *name, size_t name_len)
531 {
532
533
534
535
536 fcgi_request *request = (fcgi_request*) SG(server_context);
537 char *ret = fcgi_getenv(request, name, (int)name_len);
538
539 if (ret) return ret;
540
541
542 return getenv(name);
543 }
544
545 static char *_sapi_cgi_putenv(char *name, size_t name_len, char *value)
546 {
547 #if !HAVE_SETENV || !HAVE_UNSETENV
548 size_t len;
549 char *buf;
550 #endif
551
552 #if HAVE_SETENV
553 if (value) {
554 setenv(name, value, 1);
555 }
556 #endif
557 #if HAVE_UNSETENV
558 if (!value) {
559 unsetenv(name);
560 }
561 #endif
562
563 #if !HAVE_SETENV || !HAVE_UNSETENV
564
565
566
567
568
569 len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2;
570 buf = (char *) malloc(len);
571 if (buf == NULL) {
572 return getenv(name);
573 }
574 #endif
575 #if !HAVE_SETENV
576 if (value) {
577 len = slprintf(buf, len - 1, "%s=%s", name, value);
578 putenv(buf);
579 }
580 #endif
581 #if !HAVE_UNSETENV
582 if (!value) {
583 len = slprintf(buf, len - 1, "%s=", name);
584 putenv(buf);
585 }
586 #endif
587 return getenv(name);
588 }
589
590 static char *sapi_cgi_read_cookies(void)
591 {
592 return getenv("HTTP_COOKIE");
593 }
594
595 static char *sapi_fcgi_read_cookies(void)
596 {
597 fcgi_request *request = (fcgi_request*) SG(server_context);
598
599 return FCGI_GETENV(request, "HTTP_COOKIE");
600 }
601
602 static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg)
603 {
604 zval *array_ptr = (zval*)arg;
605 int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER;
606 size_t new_val_len;
607
608 if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len)) {
609 php_register_variable_safe(var, val, new_val_len, array_ptr);
610 }
611 }
612
613 static void cgi_php_import_environment_variables(zval *array_ptr)
614 {
615 if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
616 Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) &&
617 zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_ENV])) > 0
618 ) {
619 zval_dtor(array_ptr);
620 ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_ENV]);
621 return;
622 } else if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
623 Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_SERVER]) &&
624 zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])) > 0
625 ) {
626 zval_dtor(array_ptr);
627 ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_SERVER]);
628 return;
629 }
630
631
632 php_php_import_environment_variables(array_ptr);
633
634 if (fcgi_is_fastcgi()) {
635 fcgi_request *request = (fcgi_request*) SG(server_context);
636 fcgi_loadenv(request, cgi_php_load_env_var, array_ptr);
637 }
638 }
639
640 static void sapi_cgi_register_variables(zval *track_vars_array)
641 {
642 size_t php_self_len;
643 char *php_self;
644
645
646
647
648 php_import_environment_variables(track_vars_array);
649
650 if (CGIG(fix_pathinfo)) {
651 char *script_name = SG(request_info).request_uri;
652 char *path_info;
653 int free_php_self;
654 ALLOCA_FLAG(use_heap)
655
656 if (fcgi_is_fastcgi()) {
657 fcgi_request *request = (fcgi_request*) SG(server_context);
658
659 path_info = FCGI_GETENV(request, "PATH_INFO");
660 } else {
661 path_info = getenv("PATH_INFO");
662 }
663
664 if (path_info) {
665 size_t path_info_len = strlen(path_info);
666
667 if (script_name) {
668 size_t script_name_len = strlen(script_name);
669
670 php_self_len = script_name_len + path_info_len;
671 php_self = do_alloca(php_self_len + 1, use_heap);
672 memcpy(php_self, script_name, script_name_len + 1);
673 memcpy(php_self + script_name_len, path_info, path_info_len + 1);
674 free_php_self = 1;
675 } else {
676 php_self = path_info;
677 php_self_len = path_info_len;
678 free_php_self = 0;
679 }
680 } else if (script_name) {
681 php_self = script_name;
682 php_self_len = strlen(script_name);
683 free_php_self = 0;
684 } else {
685 php_self = "";
686 php_self_len = 0;
687 free_php_self = 0;
688 }
689
690
691 if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len)) {
692 php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array);
693 }
694 if (free_php_self) {
695 free_alloca(php_self, use_heap);
696 }
697 } else {
698 php_self = SG(request_info).request_uri ? SG(request_info).request_uri : "";
699 php_self_len = strlen(php_self);
700 if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len)) {
701 php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array);
702 }
703 }
704 }
705
706 static void sapi_cgi_log_message(char *message)
707 {
708 if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
709 fcgi_request *request;
710
711 request = (fcgi_request*) SG(server_context);
712 if (request) {
713 int ret, len = (int)strlen(message);
714 char *buf = malloc(len+2);
715
716 memcpy(buf, message, len);
717 memcpy(buf + len, "\n", sizeof("\n"));
718 ret = fcgi_write(request, FCGI_STDERR, buf, (int)(len + 1));
719 free(buf);
720 if (ret < 0) {
721 php_handle_aborted_connection();
722 }
723 } else {
724 fprintf(stderr, "%s\n", message);
725 }
726
727 } else {
728 fprintf(stderr, "%s\n", message);
729 }
730 }
731
732
733
734 static void php_cgi_ini_activate_user_config(char *path, size_t path_len, const char *doc_root, size_t doc_root_len, int start)
735 {
736 char *ptr;
737 user_config_cache_entry *new_entry, *entry;
738 time_t request_time = (time_t)sapi_get_request_time();
739
740
741 if ((entry = zend_hash_str_find_ptr(&CGIG(user_config_cache), path, path_len)) == NULL) {
742 new_entry = pemalloc(sizeof(user_config_cache_entry), 1);
743 new_entry->expires = 0;
744 new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1);
745 zend_hash_init(new_entry->user_config, 8, NULL, (dtor_func_t) config_zval_dtor, 1);
746 entry = zend_hash_str_update_ptr(&CGIG(user_config_cache), path, path_len, new_entry);
747 }
748
749
750 if (request_time > entry->expires) {
751 char *real_path = NULL;
752 size_t real_path_len;
753 char *s1, *s2;
754 size_t s_len;
755
756
757 zend_hash_clean(entry->user_config);
758
759 if (!IS_ABSOLUTE_PATH(path, path_len)) {
760 real_path = tsrm_realpath(path, NULL);
761 if (real_path == NULL) {
762 return;
763 }
764 real_path_len = strlen(real_path);
765 path = real_path;
766 path_len = real_path_len;
767 }
768
769 if (path_len > doc_root_len) {
770 s1 = (char *) doc_root;
771 s2 = path;
772 s_len = doc_root_len;
773 } else {
774 s1 = path;
775 s2 = (char *) doc_root;
776 s_len = path_len;
777 }
778
779
780
781
782
783 #ifdef PHP_WIN32
784 if (strnicmp(s1, s2, s_len) == 0) {
785 #else
786 if (strncmp(s1, s2, s_len) == 0) {
787 #endif
788 ptr = s2 + start;
789 while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) {
790 *ptr = 0;
791 php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config);
792 *ptr = '/';
793 ptr++;
794 }
795 } else {
796 php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config);
797 }
798
799 if (real_path) {
800 efree(real_path);
801 }
802 entry->expires = request_time + PG(user_ini_cache_ttl);
803 }
804
805
806 php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS);
807 }
808
809
810 static int sapi_cgi_activate(void)
811 {
812 char *path, *doc_root, *server_name;
813 size_t path_len, doc_root_len, server_name_len;
814
815
816 if (!SG(request_info).path_translated) {
817 return FAILURE;
818 }
819
820 if (php_ini_has_per_host_config()) {
821
822 if (fcgi_is_fastcgi()) {
823 fcgi_request *request = (fcgi_request*) SG(server_context);
824
825 server_name = FCGI_GETENV(request, "SERVER_NAME");
826 } else {
827 server_name = getenv("SERVER_NAME");
828 }
829
830 if (server_name) {
831 server_name_len = strlen(server_name);
832 server_name = estrndup(server_name, server_name_len);
833 zend_str_tolower(server_name, server_name_len);
834 php_ini_activate_per_host_config(server_name, server_name_len);
835 efree(server_name);
836 }
837 }
838
839 if (php_ini_has_per_dir_config() ||
840 (PG(user_ini_filename) && *PG(user_ini_filename))
841 ) {
842
843 path_len = strlen(SG(request_info).path_translated);
844
845
846 if (!IS_SLASH(SG(request_info).path_translated[path_len])) {
847 path = emalloc(path_len + 2);
848 memcpy(path, SG(request_info).path_translated, path_len + 1);
849 path_len = zend_dirname(path, path_len);
850 path[path_len++] = DEFAULT_SLASH;
851 } else {
852 path = estrndup(SG(request_info).path_translated, path_len);
853 path_len = zend_dirname(path, path_len);
854 }
855 path[path_len] = 0;
856
857
858 php_ini_activate_per_dir_config(path, path_len);
859
860
861 if (PG(user_ini_filename) && *PG(user_ini_filename)) {
862 if (fcgi_is_fastcgi()) {
863 fcgi_request *request = (fcgi_request*) SG(server_context);
864
865 doc_root = FCGI_GETENV(request, "DOCUMENT_ROOT");
866 } else {
867 doc_root = getenv("DOCUMENT_ROOT");
868 }
869
870 if (doc_root) {
871 doc_root_len = strlen(doc_root);
872 if (doc_root_len > 0 && IS_SLASH(doc_root[doc_root_len - 1])) {
873 --doc_root_len;
874 }
875 #ifdef PHP_WIN32
876
877 doc_root = estrndup(doc_root, doc_root_len);
878 zend_str_tolower(doc_root, doc_root_len);
879 #endif
880 php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, (doc_root_len > 0 && (doc_root_len - 1)));
881
882 #ifdef PHP_WIN32
883 efree(doc_root);
884 #endif
885 }
886 }
887
888 efree(path);
889 }
890
891 return SUCCESS;
892 }
893
894 static int sapi_cgi_deactivate(void)
895 {
896
897
898
899
900 if (SG(sapi_started)) {
901 if (fcgi_is_fastcgi()) {
902 if (
903 #ifndef PHP_WIN32
904 !parent &&
905 #endif
906 !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) {
907 php_handle_aborted_connection();
908 }
909 } else {
910 sapi_cgi_flush(SG(server_context));
911 }
912 }
913 return SUCCESS;
914 }
915
916 static int php_cgi_startup(sapi_module_struct *sapi_module)
917 {
918 if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
919 return FAILURE;
920 }
921 return SUCCESS;
922 }
923
924
925
926 static sapi_module_struct cgi_sapi_module = {
927 "cgi-fcgi",
928 "CGI/FastCGI",
929
930 php_cgi_startup,
931 php_module_shutdown_wrapper,
932
933 sapi_cgi_activate,
934 sapi_cgi_deactivate,
935
936 sapi_cgi_ub_write,
937 sapi_cgi_flush,
938 NULL,
939 sapi_cgi_getenv,
940
941 php_error,
942
943 NULL,
944 sapi_cgi_send_headers,
945 NULL,
946
947 sapi_cgi_read_post,
948 sapi_cgi_read_cookies,
949
950 sapi_cgi_register_variables,
951 sapi_cgi_log_message,
952 NULL,
953 NULL,
954
955 STANDARD_SAPI_MODULE_PROPERTIES
956 };
957
958
959
960 ZEND_BEGIN_ARG_INFO(arginfo_dl, 0)
961 ZEND_ARG_INFO(0, extension_filename)
962 ZEND_END_ARG_INFO()
963
964
965 static const zend_function_entry additional_functions[] = {
966 ZEND_FE(dl, arginfo_dl)
967 {NULL, NULL, NULL}
968 };
969
970
971
972 static void php_cgi_usage(char *argv0)
973 {
974 char *prog;
975
976 prog = strrchr(argv0, '/');
977 if (prog) {
978 prog++;
979 } else {
980 prog = "php";
981 }
982
983 php_printf( "Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n"
984 " %s <file> [args...]\n"
985 " -a Run interactively\n"
986 " -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n"
987 " -C Do not chdir to the script's directory\n"
988 " -c <path>|<file> Look for php.ini file in this directory\n"
989 " -n No php.ini file will be used\n"
990 " -d foo[=bar] Define INI entry foo with value 'bar'\n"
991 " -e Generate extended information for debugger/profiler\n"
992 " -f <file> Parse <file>. Implies `-q'\n"
993 " -h This help\n"
994 " -i PHP information\n"
995 " -l Syntax check only (lint)\n"
996 " -m Show compiled in modules\n"
997 " -q Quiet-mode. Suppress HTTP Header output.\n"
998 " -s Display colour syntax highlighted source.\n"
999 " -v Version number\n"
1000 " -w Display source with stripped comments and whitespace.\n"
1001 " -z <file> Load Zend extension <file>.\n"
1002 " -T <count> Measure execution time of script repeated <count> times.\n",
1003 prog, prog);
1004 }
1005
1006
1007
1008
1009
1010
1011
1012 static int is_valid_path(const char *path)
1013 {
1014 const char *p = path;
1015
1016 if (UNEXPECTED(!p)) {
1017 return 0;
1018 }
1019 if (UNEXPECTED(*p == '.') && *(p+1) == '.' && (!*(p+2) || IS_SLASH(*(p+2)))) {
1020 return 0;
1021 }
1022 while (*p) {
1023 if (IS_SLASH(*p)) {
1024 p++;
1025 if (UNEXPECTED(*p == '.')) {
1026 p++;
1027 if (UNEXPECTED(*p == '.')) {
1028 p++;
1029 if (UNEXPECTED(!*p) || UNEXPECTED(IS_SLASH(*p))) {
1030 return 0;
1031 }
1032 }
1033 }
1034 }
1035 p++;
1036 }
1037 return 1;
1038 }
1039
1040
1041 #define CGI_GETENV(name) \
1042 ((has_env) ? \
1043 FCGI_GETENV(request, name) : \
1044 getenv(name))
1045
1046 #define CGI_PUTENV(name, value) \
1047 ((has_env) ? \
1048 FCGI_PUTENV(request, name, value) : \
1049 _sapi_cgi_putenv(name, sizeof(name)-1, value))
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117 static void init_request_info(fcgi_request *request)
1118 {
1119 int has_env = fcgi_has_env(request);
1120 char *env_script_filename = CGI_GETENV("SCRIPT_FILENAME");
1121 char *env_path_translated = CGI_GETENV("PATH_TRANSLATED");
1122 char *script_path_translated = env_script_filename;
1123
1124
1125
1126
1127 if (!script_path_translated && env_path_translated) {
1128 script_path_translated = env_path_translated;
1129 }
1130
1131
1132 SG(request_info).path_translated = NULL;
1133 SG(request_info).request_method = NULL;
1134 SG(request_info).proto_num = 1000;
1135 SG(request_info).query_string = NULL;
1136 SG(request_info).request_uri = NULL;
1137 SG(request_info).content_type = NULL;
1138 SG(request_info).content_length = 0;
1139 SG(sapi_headers).http_response_code = 200;
1140
1141
1142
1143
1144
1145 if (script_path_translated) {
1146 const char *auth;
1147 char *content_length = CGI_GETENV("CONTENT_LENGTH");
1148 char *content_type = CGI_GETENV("CONTENT_TYPE");
1149 char *env_path_info = CGI_GETENV("PATH_INFO");
1150 char *env_script_name = CGI_GETENV("SCRIPT_NAME");
1151
1152 #ifdef PHP_WIN32
1153
1154 char *env_server_software = CGI_GETENV("SERVER_SOFTWARE");
1155
1156 if (env_server_software &&
1157 env_script_name &&
1158 env_path_info &&
1159 strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 &&
1160 strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0
1161 ) {
1162 env_path_info = CGI_PUTENV("ORIG_PATH_INFO", env_path_info);
1163 env_path_info += strlen(env_script_name);
1164 if (*env_path_info == 0) {
1165 env_path_info = NULL;
1166 }
1167 env_path_info = CGI_PUTENV("PATH_INFO", env_path_info);
1168 }
1169 #endif
1170
1171 if (CGIG(fix_pathinfo)) {
1172 zend_stat_t st;
1173 char *real_path = NULL;
1174 char *env_redirect_url = CGI_GETENV("REDIRECT_URL");
1175 char *env_document_root = CGI_GETENV("DOCUMENT_ROOT");
1176 char *orig_path_translated = env_path_translated;
1177 char *orig_path_info = env_path_info;
1178 char *orig_script_name = env_script_name;
1179 char *orig_script_filename = env_script_filename;
1180 size_t script_path_translated_len;
1181
1182 if (!env_document_root && PG(doc_root)) {
1183 env_document_root = CGI_PUTENV("DOCUMENT_ROOT", PG(doc_root));
1184
1185 TRANSLATE_SLASHES(env_document_root);
1186 }
1187
1188 if (env_path_translated != NULL && env_redirect_url != NULL &&
1189 env_path_translated != script_path_translated &&
1190 strcmp(env_path_translated, script_path_translated) != 0) {
1191
1192
1193
1194
1195
1196 script_path_translated = env_path_translated;
1197
1198 env_script_name = env_redirect_url;
1199 }
1200
1201 #ifdef __riscos__
1202
1203 __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
1204 script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0);
1205 #endif
1206
1207
1208
1209
1210
1211
1212 if (script_path_translated &&
1213 (script_path_translated_len = strlen(script_path_translated)) > 0 &&
1214 (script_path_translated[script_path_translated_len-1] == '/' ||
1215 #ifdef PHP_WIN32
1216 script_path_translated[script_path_translated_len-1] == '\\' ||
1217 #endif
1218 (real_path = tsrm_realpath(script_path_translated, NULL)) == NULL)
1219 ) {
1220 char *pt = estrndup(script_path_translated, script_path_translated_len);
1221 size_t len = script_path_translated_len;
1222 char *ptr;
1223
1224 while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) {
1225 *ptr = 0;
1226 if (zend_stat(pt, &st) == 0 && S_ISREG(st.st_mode)) {
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242 size_t slen = len - strlen(pt);
1243 size_t pilen = env_path_info ? strlen(env_path_info) : 0;
1244 char *path_info = env_path_info ? env_path_info + pilen - slen : NULL;
1245
1246 if (orig_path_info != path_info) {
1247 if (orig_path_info) {
1248 char old;
1249
1250 CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
1251 old = path_info[0];
1252 path_info[0] = 0;
1253 if (!orig_script_name ||
1254 strcmp(orig_script_name, env_path_info) != 0) {
1255 if (orig_script_name) {
1256 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
1257 }
1258 SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_path_info);
1259 } else {
1260 SG(request_info).request_uri = orig_script_name;
1261 }
1262 path_info[0] = old;
1263 }
1264 env_path_info = CGI_PUTENV("PATH_INFO", path_info);
1265 }
1266 if (!orig_script_filename ||
1267 strcmp(orig_script_filename, pt) != 0) {
1268 if (orig_script_filename) {
1269 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
1270 }
1271 script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", pt);
1272 }
1273 TRANSLATE_SLASHES(pt);
1274
1275
1276
1277
1278 if (env_document_root) {
1279 size_t l = strlen(env_document_root);
1280 size_t path_translated_len = 0;
1281 char *path_translated = NULL;
1282
1283 if (l && env_document_root[l - 1] == '/') {
1284 --l;
1285 }
1286
1287
1288
1289
1290
1291
1292
1293 path_translated_len = l + (env_path_info ? strlen(env_path_info) : 0);
1294 path_translated = (char *) emalloc(path_translated_len + 1);
1295 memcpy(path_translated, env_document_root, l);
1296 if (env_path_info) {
1297 memcpy(path_translated + l, env_path_info, (path_translated_len - l));
1298 }
1299 path_translated[path_translated_len] = '\0';
1300 if (orig_path_translated) {
1301 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
1302 }
1303 env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
1304 efree(path_translated);
1305 } else if ( env_script_name &&
1306 strstr(pt, env_script_name)
1307 ) {
1308
1309 size_t ptlen = strlen(pt) - strlen(env_script_name);
1310 size_t path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0);
1311 char *path_translated = NULL;
1312
1313 path_translated = (char *) emalloc(path_translated_len + 1);
1314 memcpy(path_translated, pt, ptlen);
1315 if (env_path_info) {
1316 memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen);
1317 }
1318 path_translated[path_translated_len] = '\0';
1319 if (orig_path_translated) {
1320 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
1321 }
1322 env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
1323 efree(path_translated);
1324 }
1325 break;
1326 }
1327 }
1328 if (!ptr) {
1329
1330
1331
1332
1333
1334 if (orig_script_filename) {
1335 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
1336 }
1337 script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", NULL);
1338 SG(sapi_headers).http_response_code = 404;
1339 }
1340 if (!SG(request_info).request_uri) {
1341 if (!orig_script_name ||
1342 strcmp(orig_script_name, env_script_name) != 0) {
1343 if (orig_script_name) {
1344 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
1345 }
1346 SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
1347 } else {
1348 SG(request_info).request_uri = orig_script_name;
1349 }
1350 }
1351 if (pt) {
1352 efree(pt);
1353 }
1354 } else {
1355
1356 if (!orig_script_filename ||
1357 (script_path_translated != orig_script_filename &&
1358 strcmp(script_path_translated, orig_script_filename) != 0)) {
1359 if (orig_script_filename) {
1360 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
1361 }
1362 script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", script_path_translated);
1363 }
1364 if (env_redirect_url) {
1365 if (orig_path_info) {
1366 CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
1367 CGI_PUTENV("PATH_INFO", NULL);
1368 }
1369 if (orig_path_translated) {
1370 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
1371 CGI_PUTENV("PATH_TRANSLATED", NULL);
1372 }
1373 }
1374 if (env_script_name != orig_script_name) {
1375 if (orig_script_name) {
1376 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
1377 }
1378 SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
1379 } else {
1380 SG(request_info).request_uri = env_script_name;
1381 }
1382 efree(real_path);
1383 }
1384 } else {
1385
1386 if (env_path_info) {
1387 SG(request_info).request_uri = env_path_info;
1388 } else {
1389 SG(request_info).request_uri = env_script_name;
1390 }
1391 if (!CGIG(discard_path) && env_path_translated) {
1392 script_path_translated = env_path_translated;
1393 }
1394 }
1395
1396 if (is_valid_path(script_path_translated)) {
1397 SG(request_info).path_translated = estrdup(script_path_translated);
1398 }
1399
1400 SG(request_info).request_method = CGI_GETENV("REQUEST_METHOD");
1401
1402 SG(request_info).query_string = CGI_GETENV("QUERY_STRING");
1403 SG(request_info).content_type = (content_type ? content_type : "" );
1404 SG(request_info).content_length = (content_length ? atol(content_length) : 0);
1405
1406
1407 auth = CGI_GETENV("HTTP_AUTHORIZATION");
1408 php_handle_auth_data(auth);
1409 }
1410 }
1411
1412
1413 #ifndef PHP_WIN32
1414
1415
1416
1417 void fastcgi_cleanup(int signal)
1418 {
1419 #ifdef DEBUG_FASTCGI
1420 fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
1421 #endif
1422
1423 sigaction(SIGTERM, &old_term, 0);
1424
1425
1426 kill(-pgroup, SIGTERM);
1427
1428 if (parent && parent_waiting) {
1429 exit_signal = 1;
1430 } else {
1431 exit(0);
1432 }
1433 }
1434 #endif
1435
1436 PHP_INI_BEGIN()
1437 STD_PHP_INI_ENTRY("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals)
1438 STD_PHP_INI_ENTRY("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals)
1439 STD_PHP_INI_ENTRY("cgi.check_shebang_line", "1", PHP_INI_SYSTEM, OnUpdateBool, check_shebang_line, php_cgi_globals_struct, php_cgi_globals)
1440 STD_PHP_INI_ENTRY("cgi.force_redirect", "1", PHP_INI_SYSTEM, OnUpdateBool, force_redirect, php_cgi_globals_struct, php_cgi_globals)
1441 STD_PHP_INI_ENTRY("cgi.redirect_status_env", NULL, PHP_INI_SYSTEM, OnUpdateString, redirect_status_env, php_cgi_globals_struct, php_cgi_globals)
1442 STD_PHP_INI_ENTRY("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals)
1443 STD_PHP_INI_ENTRY("cgi.discard_path", "0", PHP_INI_SYSTEM, OnUpdateBool, discard_path, php_cgi_globals_struct, php_cgi_globals)
1444 STD_PHP_INI_ENTRY("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals)
1445 #ifdef PHP_WIN32
1446 STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals)
1447 #endif
1448 PHP_INI_END()
1449
1450
1451
1452 static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals)
1453 {
1454 #ifdef ZTS
1455 ZEND_TSRMLS_CACHE_UPDATE();
1456 #endif
1457 php_cgi_globals->rfc2616_headers = 0;
1458 php_cgi_globals->nph = 0;
1459 php_cgi_globals->check_shebang_line = 1;
1460 php_cgi_globals->force_redirect = 1;
1461 php_cgi_globals->redirect_status_env = NULL;
1462 php_cgi_globals->fix_pathinfo = 1;
1463 php_cgi_globals->discard_path = 0;
1464 php_cgi_globals->fcgi_logging = 1;
1465 #ifdef PHP_WIN32
1466 php_cgi_globals->impersonate = 0;
1467 #endif
1468 zend_hash_init(&php_cgi_globals->user_config_cache, 8, NULL, user_config_cache_entry_dtor, 1);
1469 }
1470
1471
1472
1473
1474 static PHP_MINIT_FUNCTION(cgi)
1475 {
1476 REGISTER_INI_ENTRIES();
1477 return SUCCESS;
1478 }
1479
1480
1481
1482
1483 static PHP_MSHUTDOWN_FUNCTION(cgi)
1484 {
1485 zend_hash_destroy(&CGIG(user_config_cache));
1486
1487 UNREGISTER_INI_ENTRIES();
1488 return SUCCESS;
1489 }
1490
1491
1492
1493
1494 static PHP_MINFO_FUNCTION(cgi)
1495 {
1496 DISPLAY_INI_ENTRIES();
1497 }
1498
1499
1500 PHP_FUNCTION(apache_child_terminate)
1501 {
1502 if (zend_parse_parameters_none()) {
1503 return;
1504 }
1505 if (fcgi_is_fastcgi()) {
1506 fcgi_terminate();
1507 }
1508 }
1509
1510
1511 static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg)
1512 {
1513 zval *return_value = (zval*)arg;
1514 char *str = NULL;
1515 char *p;
1516 ALLOCA_FLAG(use_heap)
1517
1518 if (var_len > 5 &&
1519 var[0] == 'H' &&
1520 var[1] == 'T' &&
1521 var[2] == 'T' &&
1522 var[3] == 'P' &&
1523 var[4] == '_') {
1524
1525 var_len -= 5;
1526 p = var + 5;
1527 var = str = do_alloca(var_len + 1, use_heap);
1528 *str++ = *p++;
1529 while (*p) {
1530 if (*p == '_') {
1531 *str++ = '-';
1532 p++;
1533 if (*p) {
1534 *str++ = *p++;
1535 }
1536 } else if (*p >= 'A' && *p <= 'Z') {
1537 *str++ = (*p++ - 'A' + 'a');
1538 } else {
1539 *str++ = *p++;
1540 }
1541 }
1542 *str = 0;
1543 } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
1544 memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
1545 var = "Content-Type";
1546 } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
1547 memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
1548 var = "Content-Length";
1549 } else {
1550 return;
1551 }
1552 add_assoc_stringl_ex(return_value, var, var_len, val, val_len);
1553 if (str) {
1554 free_alloca(var, use_heap);
1555 }
1556 }
1557
1558
1559 PHP_FUNCTION(apache_request_headers)
1560 {
1561 if (zend_parse_parameters_none()) {
1562 return;
1563 }
1564 array_init(return_value);
1565 if (fcgi_is_fastcgi()) {
1566 fcgi_request *request = (fcgi_request*) SG(server_context);
1567
1568 fcgi_loadenv(request, add_request_header, return_value);
1569 } else {
1570 char buf[128];
1571 char **env, *p, *q, *var, *val, *t = buf;
1572 size_t alloc_size = sizeof(buf);
1573 zend_ulong var_len;
1574
1575 for (env = environ; env != NULL && *env != NULL; env++) {
1576 val = strchr(*env, '=');
1577 if (!val) {
1578 continue;
1579 }
1580 var_len = val - *env;
1581 if (var_len >= alloc_size) {
1582 alloc_size = var_len + 64;
1583 t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
1584 }
1585 var = *env;
1586 if (var_len > 5 &&
1587 var[0] == 'H' &&
1588 var[1] == 'T' &&
1589 var[2] == 'T' &&
1590 var[3] == 'P' &&
1591 var[4] == '_') {
1592
1593 var_len -= 5;
1594
1595 if (var_len >= alloc_size) {
1596 alloc_size = var_len + 64;
1597 t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
1598 }
1599 p = var + 5;
1600
1601 var = q = t;
1602
1603 *q++ = *p++;
1604 while (*p) {
1605 if (*p == '=') {
1606
1607 break;
1608 } else if (*p == '_') {
1609 *q++ = '-';
1610 p++;
1611
1612 if (*p && *p!='=') {
1613 *q++ = *p++;
1614 }
1615 } else if (*p >= 'A' && *p <= 'Z') {
1616
1617 *q++ = (*p++ - 'A' + 'a');
1618 } else {
1619 *q++ = *p++;
1620 }
1621 }
1622 *q = 0;
1623 } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
1624 memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
1625 var = "Content-Type";
1626 } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
1627 memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
1628 var = "Content-Length";
1629 } else {
1630 continue;
1631 }
1632 val++;
1633 add_assoc_string_ex(return_value, var, var_len, val);
1634 }
1635 if (t != buf && t != NULL) {
1636 efree(t);
1637 }
1638 }
1639 }
1640
1641
1642 static void add_response_header(sapi_header_struct *h, zval *return_value)
1643 {
1644 char *s, *p;
1645 size_t len = 0;
1646 ALLOCA_FLAG(use_heap)
1647
1648 if (h->header_len > 0) {
1649 p = strchr(h->header, ':');
1650 if (NULL != p) {
1651 len = p - h->header;
1652 }
1653 if (len > 0) {
1654 do {
1655 len--;
1656 } while (len != 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t'));
1657 if (len) {
1658 s = do_alloca(len + 1, use_heap);
1659 memcpy(s, h->header, len);
1660 s[len] = 0;
1661 do {
1662 p++;
1663 } while (*p == ' ' || *p == '\t');
1664 add_assoc_stringl_ex(return_value, s, len, p, h->header_len - (p - h->header));
1665 free_alloca(s, use_heap);
1666 }
1667 }
1668 }
1669 }
1670
1671
1672 PHP_FUNCTION(apache_response_headers)
1673 {
1674 if (zend_parse_parameters_none() == FAILURE) {
1675 return;
1676 }
1677
1678 array_init(return_value);
1679 zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value);
1680 }
1681
1682
1683 ZEND_BEGIN_ARG_INFO(arginfo_no_args, 0)
1684 ZEND_END_ARG_INFO()
1685
1686 const zend_function_entry cgi_functions[] = {
1687 PHP_FE(apache_child_terminate, arginfo_no_args)
1688 PHP_FE(apache_request_headers, arginfo_no_args)
1689 PHP_FE(apache_response_headers, arginfo_no_args)
1690 PHP_FALIAS(getallheaders, apache_request_headers, arginfo_no_args)
1691 {NULL, NULL, NULL}
1692 };
1693
1694 static zend_module_entry cgi_module_entry = {
1695 STANDARD_MODULE_HEADER,
1696 "cgi-fcgi",
1697 cgi_functions,
1698 PHP_MINIT(cgi),
1699 PHP_MSHUTDOWN(cgi),
1700 NULL,
1701 NULL,
1702 PHP_MINFO(cgi),
1703 NO_VERSION_YET,
1704 STANDARD_MODULE_PROPERTIES
1705 };
1706
1707
1708
1709 int main(int argc, char *argv[])
1710 {
1711 int free_query_string = 0;
1712 int exit_status = SUCCESS;
1713 int cgi = 0, c, i;
1714 size_t len;
1715 zend_file_handle file_handle;
1716 char *s;
1717
1718
1719 int behavior = PHP_MODE_STANDARD;
1720 int no_headers = 0;
1721 int orig_optind = php_optind;
1722 char *orig_optarg = php_optarg;
1723 char *script_file = NULL;
1724 size_t ini_entries_len = 0;
1725
1726
1727 int max_requests = 500;
1728 int requests = 0;
1729 int fastcgi;
1730 char *bindpath = NULL;
1731 int fcgi_fd = 0;
1732 fcgi_request *request = NULL;
1733 int warmup_repeats = 0;
1734 int repeats = 1;
1735 int benchmark = 0;
1736 #if HAVE_GETTIMEOFDAY
1737 struct timeval start, end;
1738 #else
1739 time_t start, end;
1740 #endif
1741 #ifndef PHP_WIN32
1742 int status = 0;
1743 #endif
1744 char *query_string;
1745 char *decoded_query_string;
1746 int skip_getopt = 0;
1747
1748 #if 0 && defined(PHP_DEBUG)
1749
1750
1751 {
1752 char szMessage [256];
1753 wsprintf (szMessage, "Please attach a debugger to the process 0x%X [%d] (%s) and click OK", GetCurrentProcessId(), GetCurrentProcessId(), argv[0]);
1754 MessageBox(NULL, szMessage, "CGI Debug Time!", MB_OK|MB_SERVICE_NOTIFICATION);
1755 }
1756 #endif
1757
1758 #ifdef HAVE_SIGNAL_H
1759 #if defined(SIGPIPE) && defined(SIG_IGN)
1760 signal(SIGPIPE, SIG_IGN);
1761
1762
1763
1764
1765
1766 #endif
1767 #endif
1768
1769 #ifdef ZTS
1770 tsrm_startup(1, 1, 0, NULL);
1771 (void)ts_resource(0);
1772 ZEND_TSRMLS_CACHE_UPDATE();
1773 #endif
1774
1775 #ifdef ZEND_SIGNALS
1776 zend_signal_startup();
1777 #endif
1778
1779 #ifdef ZTS
1780 ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL);
1781 #else
1782 php_cgi_globals_ctor(&php_cgi_globals);
1783 #endif
1784
1785 sapi_startup(&cgi_sapi_module);
1786 fastcgi = fcgi_is_fastcgi();
1787 cgi_sapi_module.php_ini_path_override = NULL;
1788
1789 #ifdef PHP_WIN32
1790 _fmode = _O_BINARY;
1791 setmode(_fileno(stdin), O_BINARY);
1792 setmode(_fileno(stdout), O_BINARY);
1793 setmode(_fileno(stderr), O_BINARY);
1794 #endif
1795
1796 if (!fastcgi) {
1797
1798
1799 if (getenv("SERVER_SOFTWARE") ||
1800 getenv("SERVER_NAME") ||
1801 getenv("GATEWAY_INTERFACE") ||
1802 getenv("REQUEST_METHOD")
1803 ) {
1804 cgi = 1;
1805 }
1806 }
1807
1808 if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
1809
1810 unsigned char *p;
1811 decoded_query_string = strdup(query_string);
1812 php_url_decode(decoded_query_string, strlen(decoded_query_string));
1813 for (p = (unsigned char *)decoded_query_string; *p && *p <= ' '; p++) {
1814
1815 }
1816 if(*p == '-') {
1817 skip_getopt = 1;
1818 }
1819 free(decoded_query_string);
1820 }
1821
1822 while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
1823 switch (c) {
1824 case 'c':
1825 if (cgi_sapi_module.php_ini_path_override) {
1826 free(cgi_sapi_module.php_ini_path_override);
1827 }
1828 cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
1829 break;
1830 case 'n':
1831 cgi_sapi_module.php_ini_ignore = 1;
1832 break;
1833 case 'd': {
1834
1835 size_t len = strlen(php_optarg);
1836 char *val;
1837
1838 if ((val = strchr(php_optarg, '='))) {
1839 val++;
1840 if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
1841 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
1842 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
1843 ini_entries_len += (val - php_optarg);
1844 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1);
1845 ini_entries_len++;
1846 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
1847 ini_entries_len += len - (val - php_optarg);
1848 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
1849 ini_entries_len += sizeof("\n\0\"") - 2;
1850 } else {
1851 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
1852 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
1853 memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
1854 ini_entries_len += len + sizeof("\n\0") - 2;
1855 }
1856 } else {
1857 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
1858 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
1859 memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
1860 ini_entries_len += len + sizeof("=1\n\0") - 2;
1861 }
1862 break;
1863 }
1864
1865
1866
1867 case 'b':
1868 if (!fastcgi) {
1869 bindpath = strdup(php_optarg);
1870 }
1871 break;
1872 case 's':
1873 behavior = PHP_MODE_HIGHLIGHT;
1874 break;
1875 }
1876 }
1877 php_optind = orig_optind;
1878 php_optarg = orig_optarg;
1879
1880 if (fastcgi || bindpath) {
1881
1882 cgi_sapi_module.ub_write = sapi_fcgi_ub_write;
1883 cgi_sapi_module.flush = sapi_fcgi_flush;
1884 cgi_sapi_module.read_post = sapi_fcgi_read_post;
1885 cgi_sapi_module.getenv = sapi_fcgi_getenv;
1886 cgi_sapi_module.read_cookies = sapi_fcgi_read_cookies;
1887 }
1888
1889 #ifdef ZTS
1890 SG(request_info).path_translated = NULL;
1891 #endif
1892
1893 cgi_sapi_module.executable_location = argv[0];
1894 if (!cgi && !fastcgi && !bindpath) {
1895 cgi_sapi_module.additional_functions = additional_functions;
1896 }
1897
1898
1899 if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
1900 #ifdef ZTS
1901 tsrm_shutdown();
1902 #endif
1903 return FAILURE;
1904 }
1905
1906
1907 if (cgi && CGIG(force_redirect)) {
1908
1909
1910
1911
1912
1913
1914 if (!getenv("REDIRECT_STATUS") &&
1915 !getenv ("HTTP_REDIRECT_STATUS") &&
1916
1917
1918 (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
1919 ) {
1920 zend_try {
1921 SG(sapi_headers).http_response_code = 400;
1922 PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
1923 <p>This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\
1924 means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
1925 set, e.g. via an Apache Action directive.</p>\n\
1926 <p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\
1927 manual page for CGI security</a>.</p>\n\
1928 <p>For more information about changing this behaviour or re-enabling this webserver,\n\
1929 consult the installation file that came with this distribution, or visit \n\
1930 <a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n");
1931 } zend_catch {
1932 } zend_end_try();
1933 #if defined(ZTS) && !defined(PHP_DEBUG)
1934
1935
1936
1937
1938
1939
1940 tsrm_shutdown();
1941 #endif
1942 return FAILURE;
1943 }
1944 }
1945
1946 #ifndef HAVE_ATTRIBUTE_WEAK
1947 fcgi_set_logger(fcgi_log);
1948 #endif
1949
1950 if (bindpath) {
1951 int backlog = 128;
1952 if (getenv("PHP_FCGI_BACKLOG")) {
1953 backlog = atoi(getenv("PHP_FCGI_BACKLOG"));
1954 }
1955 fcgi_fd = fcgi_listen(bindpath, backlog);
1956 if (fcgi_fd < 0) {
1957 fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath);
1958 #ifdef ZTS
1959 tsrm_shutdown();
1960 #endif
1961 return FAILURE;
1962 }
1963 fastcgi = fcgi_is_fastcgi();
1964 }
1965 if (fastcgi) {
1966
1967 if (getenv("PHP_FCGI_MAX_REQUESTS")) {
1968 max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
1969 if (max_requests < 0) {
1970 fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
1971 return FAILURE;
1972 }
1973 }
1974
1975
1976 php_php_import_environment_variables = php_import_environment_variables;
1977 php_import_environment_variables = cgi_php_import_environment_variables;
1978
1979
1980 request = fcgi_init_request(fcgi_fd, NULL, NULL, NULL);
1981
1982 #ifndef PHP_WIN32
1983
1984 if (getenv("PHP_FCGI_CHILDREN")) {
1985 char * children_str = getenv("PHP_FCGI_CHILDREN");
1986 children = atoi(children_str);
1987 if (children < 0) {
1988 fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
1989 return FAILURE;
1990 }
1991 fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
1992
1993 fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
1994 } else {
1995 fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
1996 fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
1997 }
1998
1999 if (children) {
2000 int running = 0;
2001 pid_t pid;
2002
2003
2004 setsid();
2005 pgroup = getpgrp();
2006 #ifdef DEBUG_FASTCGI
2007 fprintf(stderr, "Process group %d\n", pgroup);
2008 #endif
2009
2010
2011 act.sa_flags = 0;
2012 act.sa_handler = fastcgi_cleanup;
2013 if (sigaction(SIGTERM, &act, &old_term) ||
2014 sigaction(SIGINT, &act, &old_int) ||
2015 sigaction(SIGQUIT, &act, &old_quit)
2016 ) {
2017 perror("Can't set signals");
2018 exit(1);
2019 }
2020
2021 if (fcgi_in_shutdown()) {
2022 goto parent_out;
2023 }
2024
2025 while (parent) {
2026 do {
2027 #ifdef DEBUG_FASTCGI
2028 fprintf(stderr, "Forking, %d running\n", running);
2029 #endif
2030 pid = fork();
2031 switch (pid) {
2032 case 0:
2033
2034
2035
2036
2037 parent = 0;
2038
2039
2040 sigaction(SIGTERM, &old_term, 0);
2041 sigaction(SIGQUIT, &old_quit, 0);
2042 sigaction(SIGINT, &old_int, 0);
2043 break;
2044 case -1:
2045 perror("php (pre-forking)");
2046 exit(1);
2047 break;
2048 default:
2049
2050 running++;
2051 break;
2052 }
2053 } while (parent && (running < children));
2054
2055 if (parent) {
2056 #ifdef DEBUG_FASTCGI
2057 fprintf(stderr, "Wait for kids, pid %d\n", getpid());
2058 #endif
2059 parent_waiting = 1;
2060 while (1) {
2061 if (wait(&status) >= 0) {
2062 running--;
2063 break;
2064 } else if (exit_signal) {
2065 break;
2066 }
2067 }
2068 if (exit_signal) {
2069 #if 0
2070 while (running > 0) {
2071 while (wait(&status) < 0) {
2072 }
2073 running--;
2074 }
2075 #endif
2076 goto parent_out;
2077 }
2078 }
2079 }
2080 } else {
2081 parent = 0;
2082 }
2083
2084 #endif
2085 }
2086
2087 zend_first_try {
2088 while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1, 2)) != -1) {
2089 switch (c) {
2090 case 'T':
2091 benchmark = 1;
2092 {
2093 char *comma = strchr(php_optarg, ',');
2094 if (comma) {
2095 warmup_repeats = atoi(php_optarg);
2096 repeats = atoi(comma + 1);
2097 } else {
2098 repeats = atoi(php_optarg);
2099 }
2100 }
2101 #ifdef HAVE_GETTIMEOFDAY
2102 gettimeofday(&start, NULL);
2103 #else
2104 time(&start);
2105 #endif
2106 break;
2107 case 'h':
2108 case '?':
2109 if (request) {
2110 fcgi_destroy_request(request);
2111 }
2112 fcgi_shutdown();
2113 no_headers = 1;
2114 SG(headers_sent) = 1;
2115 php_cgi_usage(argv[0]);
2116 php_output_end_all();
2117 exit_status = 0;
2118 goto out;
2119 }
2120 }
2121 php_optind = orig_optind;
2122 php_optarg = orig_optarg;
2123
2124
2125
2126 #ifdef PHP_WIN32
2127
2128
2129 if (fastcgi && CGIG(impersonate)) {
2130 fcgi_impersonate();
2131 }
2132 #endif
2133 while (!fastcgi || fcgi_accept_request(request) >= 0) {
2134 SG(server_context) = fastcgi ? (void *)request : (void *) 1;
2135 init_request_info(request);
2136
2137 if (!cgi && !fastcgi) {
2138 while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
2139 switch (c) {
2140
2141 case 'a':
2142 printf("Interactive mode enabled\n\n");
2143 break;
2144
2145 case 'C':
2146 SG(options) |= SAPI_OPTION_NO_CHDIR;
2147 break;
2148
2149 case 'e':
2150 CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
2151 break;
2152
2153 case 'f':
2154 if (script_file) {
2155 efree(script_file);
2156 }
2157 script_file = estrdup(php_optarg);
2158 no_headers = 1;
2159 break;
2160
2161 case 'i':
2162 if (script_file) {
2163 efree(script_file);
2164 }
2165 if (php_request_startup() == FAILURE) {
2166 SG(server_context) = NULL;
2167 php_module_shutdown();
2168 return FAILURE;
2169 }
2170 if (no_headers) {
2171 SG(headers_sent) = 1;
2172 SG(request_info).no_headers = 1;
2173 }
2174 php_print_info(0xFFFFFFFF);
2175 php_request_shutdown((void *) 0);
2176 fcgi_shutdown();
2177 exit_status = 0;
2178 goto out;
2179
2180 case 'l':
2181 no_headers = 1;
2182 behavior = PHP_MODE_LINT;
2183 break;
2184
2185 case 'm':
2186 if (script_file) {
2187 efree(script_file);
2188 }
2189 SG(headers_sent) = 1;
2190 php_printf("[PHP Modules]\n");
2191 print_modules();
2192 php_printf("\n[Zend Modules]\n");
2193 print_extensions();
2194 php_printf("\n");
2195 php_output_end_all();
2196 fcgi_shutdown();
2197 exit_status = 0;
2198 goto out;
2199
2200 case 'q':
2201 no_headers = 1;
2202 break;
2203
2204 case 'v':
2205 if (script_file) {
2206 efree(script_file);
2207 }
2208 no_headers = 1;
2209 if (php_request_startup() == FAILURE) {
2210 SG(server_context) = NULL;
2211 php_module_shutdown();
2212 return FAILURE;
2213 }
2214 if (no_headers) {
2215 SG(headers_sent) = 1;
2216 SG(request_info).no_headers = 1;
2217 }
2218 #if ZEND_DEBUG
2219 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
2220 #else
2221 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
2222 #endif
2223 php_request_shutdown((void *) 0);
2224 fcgi_shutdown();
2225 exit_status = 0;
2226 goto out;
2227
2228 case 'w':
2229 behavior = PHP_MODE_STRIP;
2230 break;
2231
2232 case 'z':
2233 zend_load_extension(php_optarg);
2234 break;
2235
2236 default:
2237 break;
2238 }
2239 }
2240
2241 if (script_file) {
2242
2243 if (SG(request_info).path_translated) efree(SG(request_info).path_translated);
2244 SG(request_info).path_translated = script_file;
2245
2246
2247 SG(request_info).argc = argc - (php_optind - 1);
2248 SG(request_info).argv = &argv[php_optind - 1];
2249 SG(request_info).argv[0] = script_file;
2250 } else if (argc > php_optind) {
2251
2252 if (SG(request_info).path_translated) efree(SG(request_info).path_translated);
2253 SG(request_info).path_translated = estrdup(argv[php_optind]);
2254
2255 SG(request_info).argc = argc - php_optind;
2256 SG(request_info).argv = &argv[php_optind];
2257 }
2258
2259 if (no_headers) {
2260 SG(headers_sent) = 1;
2261 SG(request_info).no_headers = 1;
2262 }
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273 if (!SG(request_info).query_string && argc > php_optind) {
2274 size_t slen = strlen(PG(arg_separator).input);
2275 len = 0;
2276 for (i = php_optind; i < argc; i++) {
2277 if (i < (argc - 1)) {
2278 len += strlen(argv[i]) + slen;
2279 } else {
2280 len += strlen(argv[i]);
2281 }
2282 }
2283
2284 len += 2;
2285 s = malloc(len);
2286 *s = '\0';
2287 for (i = php_optind; i < argc; i++) {
2288 strlcat(s, argv[i], len);
2289 if (i < (argc - 1)) {
2290 strlcat(s, PG(arg_separator).input, len);
2291 }
2292 }
2293 SG(request_info).query_string = s;
2294 free_query_string = 1;
2295 }
2296 }
2297
2298
2299
2300
2301
2302
2303 if (SG(request_info).path_translated || cgi || fastcgi) {
2304 file_handle.type = ZEND_HANDLE_FILENAME;
2305 file_handle.filename = SG(request_info).path_translated;
2306 file_handle.handle.fp = NULL;
2307 } else {
2308 file_handle.filename = "-";
2309 file_handle.type = ZEND_HANDLE_FP;
2310 file_handle.handle.fp = stdin;
2311 }
2312
2313 file_handle.opened_path = NULL;
2314 file_handle.free_filename = 0;
2315
2316
2317
2318 if (php_request_startup() == FAILURE) {
2319 if (fastcgi) {
2320 fcgi_finish_request(request, 1);
2321 }
2322 SG(server_context) = NULL;
2323 php_module_shutdown();
2324 return FAILURE;
2325 }
2326 if (no_headers) {
2327 SG(headers_sent) = 1;
2328 SG(request_info).no_headers = 1;
2329 }
2330
2331
2332
2333
2334
2335
2336 if (cgi || fastcgi || SG(request_info).path_translated) {
2337 if (php_fopen_primary_script(&file_handle) == FAILURE) {
2338 zend_try {
2339 if (errno == EACCES) {
2340 SG(sapi_headers).http_response_code = 403;
2341 PUTS("Access denied.\n");
2342 } else {
2343 SG(sapi_headers).http_response_code = 404;
2344 PUTS("No input file specified.\n");
2345 }
2346 } zend_catch {
2347 } zend_end_try();
2348
2349
2350
2351 if (fastcgi) {
2352 goto fastcgi_request_done;
2353 }
2354
2355 if (SG(request_info).path_translated) {
2356 efree(SG(request_info).path_translated);
2357 SG(request_info).path_translated = NULL;
2358 }
2359
2360 if (free_query_string && SG(request_info).query_string) {
2361 free(SG(request_info).query_string);
2362 SG(request_info).query_string = NULL;
2363 }
2364
2365 php_request_shutdown((void *) 0);
2366 SG(server_context) = NULL;
2367 php_module_shutdown();
2368 sapi_shutdown();
2369 #ifdef ZTS
2370 tsrm_shutdown();
2371 #endif
2372 return FAILURE;
2373 }
2374 }
2375
2376 if (CGIG(check_shebang_line)) {
2377
2378 switch (file_handle.type) {
2379 case ZEND_HANDLE_FD:
2380 if (file_handle.handle.fd < 0) {
2381 break;
2382 }
2383 file_handle.type = ZEND_HANDLE_FP;
2384 file_handle.handle.fp = fdopen(file_handle.handle.fd, "rb");
2385
2386 case ZEND_HANDLE_FP:
2387 if (!file_handle.handle.fp ||
2388 (file_handle.handle.fp == stdin)) {
2389 break;
2390 }
2391 c = fgetc(file_handle.handle.fp);
2392 if (c == '#') {
2393 while (c != '\n' && c != '\r' && c != EOF) {
2394 c = fgetc(file_handle.handle.fp);
2395 }
2396
2397 if (c == '\r') {
2398 if (fgetc(file_handle.handle.fp) != '\n') {
2399 zend_long pos = zend_ftell(file_handle.handle.fp);
2400 zend_fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
2401 }
2402 }
2403 CG(start_lineno) = 2;
2404 } else {
2405 rewind(file_handle.handle.fp);
2406 }
2407 break;
2408 case ZEND_HANDLE_STREAM:
2409 c = php_stream_getc((php_stream*)file_handle.handle.stream.handle);
2410 if (c == '#') {
2411 while (c != '\n' && c != '\r' && c != EOF) {
2412 c = php_stream_getc((php_stream*)file_handle.handle.stream.handle);
2413 }
2414
2415 if (c == '\r') {
2416 if (php_stream_getc((php_stream*)file_handle.handle.stream.handle) != '\n') {
2417 zend_off_t pos = php_stream_tell((php_stream*)file_handle.handle.stream.handle);
2418 php_stream_seek((php_stream*)file_handle.handle.stream.handle, pos - 1, SEEK_SET);
2419 }
2420 }
2421 CG(start_lineno) = 2;
2422 } else {
2423 php_stream_rewind((php_stream*)file_handle.handle.stream.handle);
2424 }
2425 break;
2426 case ZEND_HANDLE_MAPPED:
2427 if (file_handle.handle.stream.mmap.buf[0] == '#') {
2428 size_t i = 1;
2429
2430 c = file_handle.handle.stream.mmap.buf[i++];
2431 while (c != '\n' && c != '\r' && i < file_handle.handle.stream.mmap.len) {
2432 c = file_handle.handle.stream.mmap.buf[i++];
2433 }
2434 if (c == '\r') {
2435 if (i < file_handle.handle.stream.mmap.len && file_handle.handle.stream.mmap.buf[i] == '\n') {
2436 i++;
2437 }
2438 }
2439 if(i > file_handle.handle.stream.mmap.len) {
2440 i = file_handle.handle.stream.mmap.len;
2441 }
2442 file_handle.handle.stream.mmap.buf += i;
2443 file_handle.handle.stream.mmap.len -= i;
2444 }
2445 break;
2446 default:
2447 break;
2448 }
2449 }
2450
2451 switch (behavior) {
2452 case PHP_MODE_STANDARD:
2453 php_execute_script(&file_handle);
2454 break;
2455 case PHP_MODE_LINT:
2456 PG(during_request_startup) = 0;
2457 exit_status = php_lint_script(&file_handle);
2458 if (exit_status == SUCCESS) {
2459 zend_printf("No syntax errors detected in %s\n", file_handle.filename);
2460 } else {
2461 zend_printf("Errors parsing %s\n", file_handle.filename);
2462 }
2463 break;
2464 case PHP_MODE_STRIP:
2465 if (open_file_for_scanning(&file_handle) == SUCCESS) {
2466 zend_strip();
2467 zend_file_handle_dtor(&file_handle);
2468 php_output_teardown();
2469 }
2470 return SUCCESS;
2471 break;
2472 case PHP_MODE_HIGHLIGHT:
2473 {
2474 zend_syntax_highlighter_ini syntax_highlighter_ini;
2475
2476 if (open_file_for_scanning(&file_handle) == SUCCESS) {
2477 php_get_highlight_struct(&syntax_highlighter_ini);
2478 zend_highlight(&syntax_highlighter_ini);
2479 if (fastcgi) {
2480 goto fastcgi_request_done;
2481 }
2482 zend_file_handle_dtor(&file_handle);
2483 php_output_teardown();
2484 }
2485 return SUCCESS;
2486 }
2487 break;
2488 }
2489
2490 fastcgi_request_done:
2491 {
2492 if (SG(request_info).path_translated) {
2493 efree(SG(request_info).path_translated);
2494 SG(request_info).path_translated = NULL;
2495 }
2496
2497 php_request_shutdown((void *) 0);
2498
2499 if (exit_status == 0) {
2500 exit_status = EG(exit_status);
2501 }
2502
2503 if (free_query_string && SG(request_info).query_string) {
2504 free(SG(request_info).query_string);
2505 SG(request_info).query_string = NULL;
2506 }
2507 }
2508
2509 if (!fastcgi) {
2510 if (benchmark) {
2511 if (warmup_repeats) {
2512 warmup_repeats--;
2513 if (!warmup_repeats) {
2514 #ifdef HAVE_GETTIMEOFDAY
2515 gettimeofday(&start, NULL);
2516 #else
2517 time(&start);
2518 #endif
2519 }
2520 continue;
2521 } else {
2522 repeats--;
2523 if (repeats > 0) {
2524 script_file = NULL;
2525 php_optind = orig_optind;
2526 php_optarg = orig_optarg;
2527 continue;
2528 }
2529 }
2530 }
2531 break;
2532 }
2533
2534
2535 requests++;
2536 if (max_requests && (requests == max_requests)) {
2537 fcgi_finish_request(request, 1);
2538 if (bindpath) {
2539 free(bindpath);
2540 }
2541 if (max_requests != 1) {
2542
2543 exit_status = 0;
2544 }
2545 break;
2546 }
2547
2548 }
2549
2550 if (request) {
2551 fcgi_destroy_request(request);
2552 }
2553 fcgi_shutdown();
2554
2555 if (cgi_sapi_module.php_ini_path_override) {
2556 free(cgi_sapi_module.php_ini_path_override);
2557 }
2558 if (cgi_sapi_module.ini_entries) {
2559 free(cgi_sapi_module.ini_entries);
2560 }
2561 } zend_catch {
2562 exit_status = 255;
2563 } zend_end_try();
2564
2565 out:
2566 if (benchmark) {
2567 int sec;
2568 #ifdef HAVE_GETTIMEOFDAY
2569 int usec;
2570
2571 gettimeofday(&end, NULL);
2572 sec = (int)(end.tv_sec - start.tv_sec);
2573 if (end.tv_usec >= start.tv_usec) {
2574 usec = (int)(end.tv_usec - start.tv_usec);
2575 } else {
2576 sec -= 1;
2577 usec = (int)(end.tv_usec + 1000000 - start.tv_usec);
2578 }
2579 fprintf(stderr, "\nElapsed time: %d.%06d sec\n", sec, usec);
2580 #else
2581 time(&end);
2582 sec = (int)(end - start);
2583 fprintf(stderr, "\nElapsed time: %d sec\n", sec);
2584 #endif
2585 }
2586
2587 #ifndef PHP_WIN32
2588 parent_out:
2589 #endif
2590
2591 SG(server_context) = NULL;
2592 php_module_shutdown();
2593 sapi_shutdown();
2594
2595 #ifdef ZTS
2596 tsrm_shutdown();
2597 #endif
2598
2599 #if defined(PHP_WIN32) && ZEND_DEBUG && 0
2600 _CrtDumpMemoryLeaks();
2601 #endif
2602
2603 return exit_status;
2604 }
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614