1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Andi Gutmans <andi@php.net> |
14 | Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
15 | Zeev Suraski <zeev@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* {{{ includes */
20
21 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
22
23 #include "php.h"
24 #include <stdio.h>
25 #include <fcntl.h>
26 #ifdef PHP_WIN32
27 #include "win32/time.h"
28 #include "win32/signal.h"
29 #include "win32/php_win32_globals.h"
30 #include "win32/winutil.h"
31 #include <process.h>
32 #endif
33 #if HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #endif
36 #if HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #include <signal.h>
41 #include <locale.h>
42 #include "zend.h"
43 #include "zend_types.h"
44 #include "zend_extensions.h"
45 #include "php_ini.h"
46 #include "php_globals.h"
47 #include "php_main.h"
48 #include "php_syslog.h"
49 #include "fopen_wrappers.h"
50 #include "ext/standard/php_standard.h"
51 #include "ext/standard/php_string.h"
52 #include "ext/date/php_date.h"
53 #include "php_variables.h"
54 #include "ext/standard/credits.h"
55 #ifdef PHP_WIN32
56 #include <io.h>
57 #include "win32/php_registry.h"
58 #include "ext/standard/flock_compat.h"
59 #endif
60 #include "php_syslog.h"
61 #include "Zend/zend_exceptions.h"
62
63 #if PHP_SIGCHILD
64 #include <sys/types.h>
65 #include <sys/wait.h>
66 #endif
67
68 #include "zend_compile.h"
69 #include "zend_execute.h"
70 #include "zend_highlight.h"
71 #include "zend_extensions.h"
72 #include "zend_ini.h"
73 #include "zend_dtrace.h"
74 #include "zend_observer.h"
75 #include "zend_system_id.h"
76
77 #include "php_content_types.h"
78 #include "php_ticks.h"
79 #include "php_streams.h"
80 #include "php_open_temporary_file.h"
81
82 #include "SAPI.h"
83 #include "rfc1867.h"
84
85 #include "ext/standard/html_tables.h"
86 /* }}} */
87
88 PHPAPI int (*php_register_internal_extensions_func)(void) = php_register_internal_extensions;
89
90 #ifndef ZTS
91 php_core_globals core_globals;
92 #else
93 PHPAPI int core_globals_id;
94 PHPAPI size_t core_globals_offset;
95 #endif
96
97 #define SAFE_FILENAME(f) ((f)?(f):"-")
98
99 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetFacility)100 static PHP_INI_MH(OnSetFacility)
101 {
102 const char *facility = ZSTR_VAL(new_value);
103
104 #ifdef LOG_AUTH
105 if (!strcmp(facility, "LOG_AUTH") || !strcmp(facility, "auth") || !strcmp(facility, "security")) {
106 PG(syslog_facility) = LOG_AUTH;
107 return SUCCESS;
108 }
109 #endif
110 #ifdef LOG_AUTHPRIV
111 if (!strcmp(facility, "LOG_AUTHPRIV") || !strcmp(facility, "authpriv")) {
112 PG(syslog_facility) = LOG_AUTHPRIV;
113 return SUCCESS;
114 }
115 #endif
116 #ifdef LOG_CRON
117 if (!strcmp(facility, "LOG_CRON") || !strcmp(facility, "cron")) {
118 PG(syslog_facility) = LOG_CRON;
119 return SUCCESS;
120 }
121 #endif
122 #ifdef LOG_DAEMON
123 if (!strcmp(facility, "LOG_DAEMON") || !strcmp(facility, "daemon")) {
124 PG(syslog_facility) = LOG_DAEMON;
125 return SUCCESS;
126 }
127 #endif
128 #ifdef LOG_FTP
129 if (!strcmp(facility, "LOG_FTP") || !strcmp(facility, "ftp")) {
130 PG(syslog_facility) = LOG_FTP;
131 return SUCCESS;
132 }
133 #endif
134 #ifdef LOG_KERN
135 if (!strcmp(facility, "LOG_KERN") || !strcmp(facility, "kern")) {
136 PG(syslog_facility) = LOG_KERN;
137 return SUCCESS;
138 }
139 #endif
140 #ifdef LOG_LPR
141 if (!strcmp(facility, "LOG_LPR") || !strcmp(facility, "lpr")) {
142 PG(syslog_facility) = LOG_LPR;
143 return SUCCESS;
144 }
145 #endif
146 #ifdef LOG_MAIL
147 if (!strcmp(facility, "LOG_MAIL") || !strcmp(facility, "mail")) {
148 PG(syslog_facility) = LOG_MAIL;
149 return SUCCESS;
150 }
151 #endif
152 #ifdef LOG_INTERNAL_MARK
153 if (!strcmp(facility, "LOG_INTERNAL_MARK") || !strcmp(facility, "mark")) {
154 PG(syslog_facility) = LOG_INTERNAL_MARK;
155 return SUCCESS;
156 }
157 #endif
158 #ifdef LOG_NEWS
159 if (!strcmp(facility, "LOG_NEWS") || !strcmp(facility, "news")) {
160 PG(syslog_facility) = LOG_NEWS;
161 return SUCCESS;
162 }
163 #endif
164 #ifdef LOG_SYSLOG
165 if (!strcmp(facility, "LOG_SYSLOG") || !strcmp(facility, "syslog")) {
166 PG(syslog_facility) = LOG_SYSLOG;
167 return SUCCESS;
168 }
169 #endif
170 #ifdef LOG_USER
171 if (!strcmp(facility, "LOG_USER") || !strcmp(facility, "user")) {
172 PG(syslog_facility) = LOG_USER;
173 return SUCCESS;
174 }
175 #endif
176 #ifdef LOG_UUCP
177 if (!strcmp(facility, "LOG_UUCP") || !strcmp(facility, "uucp")) {
178 PG(syslog_facility) = LOG_UUCP;
179 return SUCCESS;
180 }
181 #endif
182 #ifdef LOG_LOCAL0
183 if (!strcmp(facility, "LOG_LOCAL0") || !strcmp(facility, "local0")) {
184 PG(syslog_facility) = LOG_LOCAL0;
185 return SUCCESS;
186 }
187 #endif
188 #ifdef LOG_LOCAL1
189 if (!strcmp(facility, "LOG_LOCAL1") || !strcmp(facility, "local1")) {
190 PG(syslog_facility) = LOG_LOCAL1;
191 return SUCCESS;
192 }
193 #endif
194 #ifdef LOG_LOCAL2
195 if (!strcmp(facility, "LOG_LOCAL2") || !strcmp(facility, "local2")) {
196 PG(syslog_facility) = LOG_LOCAL2;
197 return SUCCESS;
198 }
199 #endif
200 #ifdef LOG_LOCAL3
201 if (!strcmp(facility, "LOG_LOCAL3") || !strcmp(facility, "local3")) {
202 PG(syslog_facility) = LOG_LOCAL3;
203 return SUCCESS;
204 }
205 #endif
206 #ifdef LOG_LOCAL4
207 if (!strcmp(facility, "LOG_LOCAL4") || !strcmp(facility, "local4")) {
208 PG(syslog_facility) = LOG_LOCAL4;
209 return SUCCESS;
210 }
211 #endif
212 #ifdef LOG_LOCAL5
213 if (!strcmp(facility, "LOG_LOCAL5") || !strcmp(facility, "local5")) {
214 PG(syslog_facility) = LOG_LOCAL5;
215 return SUCCESS;
216 }
217 #endif
218 #ifdef LOG_LOCAL6
219 if (!strcmp(facility, "LOG_LOCAL6") || !strcmp(facility, "local6")) {
220 PG(syslog_facility) = LOG_LOCAL6;
221 return SUCCESS;
222 }
223 #endif
224 #ifdef LOG_LOCAL7
225 if (!strcmp(facility, "LOG_LOCAL7") || !strcmp(facility, "local7")) {
226 PG(syslog_facility) = LOG_LOCAL7;
227 return SUCCESS;
228 }
229 #endif
230
231 return FAILURE;
232 }
233 /* }}} */
234
235 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetPrecision)236 static PHP_INI_MH(OnSetPrecision)
237 {
238 zend_long i;
239
240 ZEND_ATOL(i, ZSTR_VAL(new_value));
241 if (i >= -1) {
242 EG(precision) = i;
243 return SUCCESS;
244 } else {
245 return FAILURE;
246 }
247 }
248 /* }}} */
249
250 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetSerializePrecision)251 static PHP_INI_MH(OnSetSerializePrecision)
252 {
253 zend_long i;
254
255 ZEND_ATOL(i, ZSTR_VAL(new_value));
256 if (i >= -1) {
257 PG(serialize_precision) = i;
258 return SUCCESS;
259 } else {
260 return FAILURE;
261 }
262 }
263 /* }}} */
264
265 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnChangeMemoryLimit)266 static PHP_INI_MH(OnChangeMemoryLimit)
267 {
268 size_t value;
269 if (new_value) {
270 value = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
271 } else {
272 value = Z_L(1)<<30; /* effectively, no limit */
273 }
274 if (zend_set_memory_limit_ex(value) == FAILURE) {
275 /* When the memory limit is reset to the original level during deactivation, we may be
276 * using more memory than the original limit while shutdown is still in progress.
277 * Ignore a failure for now, and set the memory limit when the memory manager has been
278 * shut down and the minimal amount of memory is used. */
279 if (stage != ZEND_INI_STAGE_DEACTIVATE) {
280 zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true));
281 return FAILURE;
282 }
283 }
284 PG(memory_limit) = value;
285 return SUCCESS;
286 }
287 /* }}} */
288
289 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetLogFilter)290 static PHP_INI_MH(OnSetLogFilter)
291 {
292 const char *filter = ZSTR_VAL(new_value);
293
294 if (!strcmp(filter, "all")) {
295 PG(syslog_filter) = PHP_SYSLOG_FILTER_ALL;
296 return SUCCESS;
297 }
298 if (!strcmp(filter, "no-ctrl")) {
299 PG(syslog_filter) = PHP_SYSLOG_FILTER_NO_CTRL;
300 return SUCCESS;
301 }
302 if (!strcmp(filter, "ascii")) {
303 PG(syslog_filter) = PHP_SYSLOG_FILTER_ASCII;
304 return SUCCESS;
305 }
306 if (!strcmp(filter, "raw")) {
307 PG(syslog_filter) = PHP_SYSLOG_FILTER_RAW;
308 return SUCCESS;
309 }
310
311 return FAILURE;
312 }
313 /* }}} */
314
315 /* {{{ php_disable_classes */
php_disable_classes(void)316 static void php_disable_classes(void)
317 {
318 char *s = NULL, *e;
319
320 if (!*(INI_STR("disable_classes"))) {
321 return;
322 }
323
324 e = PG(disable_classes) = strdup(INI_STR("disable_classes"));
325
326 while (*e) {
327 switch (*e) {
328 case ' ':
329 case ',':
330 if (s) {
331 *e = '\0';
332 zend_disable_class(s, e-s);
333 s = NULL;
334 }
335 break;
336 default:
337 if (!s) {
338 s = e;
339 }
340 break;
341 }
342 e++;
343 }
344 if (s) {
345 zend_disable_class(s, e-s);
346 }
347 }
348 /* }}} */
349
350 /* {{{ php_binary_init */
php_binary_init(void)351 static void php_binary_init(void)
352 {
353 char *binary_location = NULL;
354 #ifdef PHP_WIN32
355 binary_location = (char *)pemalloc(MAXPATHLEN, 1);
356 if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
357 pefree(binary_location, 1);
358 binary_location = NULL;
359 }
360 #else
361 if (sapi_module.executable_location) {
362 binary_location = (char *)pemalloc(MAXPATHLEN, 1);
363 if (!strchr(sapi_module.executable_location, '/')) {
364 char *envpath, *path;
365 int found = 0;
366
367 if ((envpath = getenv("PATH")) != NULL) {
368 char *search_dir, search_path[MAXPATHLEN];
369 char *last = NULL;
370 zend_stat_t s;
371
372 path = estrdup(envpath);
373 search_dir = php_strtok_r(path, ":", &last);
374
375 while (search_dir) {
376 snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location);
377 if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK) && VCWD_STAT(binary_location, &s) == 0 && S_ISREG(s.st_mode)) {
378 found = 1;
379 break;
380 }
381 search_dir = php_strtok_r(NULL, ":", &last);
382 }
383 efree(path);
384 }
385 if (!found) {
386 pefree(binary_location, 1);
387 binary_location = NULL;
388 }
389 } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
390 pefree(binary_location, 1);
391 binary_location = NULL;
392 }
393 }
394 #endif
395 PG(php_binary) = binary_location;
396 }
397 /* }}} */
398
399 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateTimeout)400 static PHP_INI_MH(OnUpdateTimeout)
401 {
402 if (stage==PHP_INI_STAGE_STARTUP) {
403 /* Don't set a timeout on startup, only per-request */
404 ZEND_ATOL(EG(timeout_seconds), ZSTR_VAL(new_value));
405 return SUCCESS;
406 }
407 zend_unset_timeout();
408 ZEND_ATOL(EG(timeout_seconds), ZSTR_VAL(new_value));
409 if (stage != PHP_INI_STAGE_DEACTIVATE) {
410 /*
411 * If we're restoring INI values, we shouldn't reset the timer.
412 * Otherwise, the timer is active when PHP is idle, such as the
413 * the CLI web server or CGI. Running a script will re-activate
414 * the timeout, so it's not needed to do so at script end.
415 */
416 zend_set_timeout(EG(timeout_seconds), 0);
417 }
418 return SUCCESS;
419 }
420 /* }}} */
421
422 /* {{{ php_get_display_errors_mode() helper function */
php_get_display_errors_mode(char * value,size_t value_length)423 static zend_uchar php_get_display_errors_mode(char *value, size_t value_length)
424 {
425 zend_uchar mode;
426
427 if (!value) {
428 return PHP_DISPLAY_ERRORS_STDOUT;
429 }
430
431 if (value_length == 2 && !strcasecmp("on", value)) {
432 mode = PHP_DISPLAY_ERRORS_STDOUT;
433 } else if (value_length == 3 && !strcasecmp("yes", value)) {
434 mode = PHP_DISPLAY_ERRORS_STDOUT;
435 } else if (value_length == 4 && !strcasecmp("true", value)) {
436 mode = PHP_DISPLAY_ERRORS_STDOUT;
437 } else if (value_length == 6 && !strcasecmp(value, "stderr")) {
438 mode = PHP_DISPLAY_ERRORS_STDERR;
439 } else if (value_length == 6 && !strcasecmp(value, "stdout")) {
440 mode = PHP_DISPLAY_ERRORS_STDOUT;
441 } else {
442 ZEND_ATOL(mode, value);
443 if (mode && mode != PHP_DISPLAY_ERRORS_STDOUT && mode != PHP_DISPLAY_ERRORS_STDERR) {
444 mode = PHP_DISPLAY_ERRORS_STDOUT;
445 }
446 }
447
448 return mode;
449 }
450 /* }}} */
451
452 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDisplayErrors)453 static PHP_INI_MH(OnUpdateDisplayErrors)
454 {
455 PG(display_errors) = php_get_display_errors_mode(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
456
457 return SUCCESS;
458 }
459 /* }}} */
460
461 /* {{{ PHP_INI_DISP */
PHP_INI_DISP(display_errors_mode)462 static PHP_INI_DISP(display_errors_mode)
463 {
464 zend_uchar mode;
465 bool cgi_or_cli;
466 size_t tmp_value_length;
467 char *tmp_value;
468
469 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
470 tmp_value = (ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : NULL );
471 tmp_value_length = (ini_entry->orig_value? ZSTR_LEN(ini_entry->orig_value) : 0);
472 } else if (ini_entry->value) {
473 tmp_value = ZSTR_VAL(ini_entry->value);
474 tmp_value_length = ZSTR_LEN(ini_entry->value);
475 } else {
476 tmp_value = NULL;
477 tmp_value_length = 0;
478 }
479
480 mode = php_get_display_errors_mode(tmp_value, tmp_value_length);
481
482 /* Display 'On' for other SAPIs instead of STDOUT or STDERR */
483 cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg"));
484
485 switch (mode) {
486 case PHP_DISPLAY_ERRORS_STDERR:
487 if (cgi_or_cli ) {
488 PUTS("STDERR");
489 } else {
490 PUTS("On");
491 }
492 break;
493
494 case PHP_DISPLAY_ERRORS_STDOUT:
495 if (cgi_or_cli ) {
496 PUTS("STDOUT");
497 } else {
498 PUTS("On");
499 }
500 break;
501
502 default:
503 PUTS("Off");
504 break;
505 }
506 }
507 /* }}} */
508
php_get_internal_encoding(void)509 PHPAPI const char *php_get_internal_encoding(void) {
510 if (PG(internal_encoding) && PG(internal_encoding)[0]) {
511 return PG(internal_encoding);
512 } else if (SG(default_charset) && SG(default_charset)[0]) {
513 return SG(default_charset);
514 }
515 return "UTF-8";
516 }
517
php_get_input_encoding(void)518 PHPAPI const char *php_get_input_encoding(void) {
519 if (PG(input_encoding) && PG(input_encoding)[0]) {
520 return PG(input_encoding);
521 } else if (SG(default_charset) && SG(default_charset)[0]) {
522 return SG(default_charset);
523 }
524 return "UTF-8";
525 }
526
php_get_output_encoding(void)527 PHPAPI const char *php_get_output_encoding(void) {
528 if (PG(output_encoding) && PG(output_encoding)[0]) {
529 return PG(output_encoding);
530 } else if (SG(default_charset) && SG(default_charset)[0]) {
531 return SG(default_charset);
532 }
533 return "UTF-8";
534 }
535
536 PHPAPI void (*php_internal_encoding_changed)(void) = NULL;
537
538 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDefaultCharset)539 static PHP_INI_MH(OnUpdateDefaultCharset)
540 {
541 if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value))
542 || strpbrk(ZSTR_VAL(new_value), "\r\n")) {
543 return FAILURE;
544 }
545 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
546 if (php_internal_encoding_changed) {
547 php_internal_encoding_changed();
548 }
549 if (new_value) {
550 #ifdef PHP_WIN32
551 php_win32_cp_do_update(ZSTR_VAL(new_value));
552 #endif
553 }
554 return SUCCESS;
555 }
556 /* }}} */
557
558 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDefaultMimeTye)559 static PHP_INI_MH(OnUpdateDefaultMimeTye)
560 {
561 if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value))
562 || strpbrk(ZSTR_VAL(new_value), "\r\n")) {
563 return FAILURE;
564 }
565 return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
566 }
567 /* }}} */
568
569 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateInternalEncoding)570 static PHP_INI_MH(OnUpdateInternalEncoding)
571 {
572 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
573 if (php_internal_encoding_changed) {
574 php_internal_encoding_changed();
575 }
576 if (new_value) {
577 #ifdef PHP_WIN32
578 php_win32_cp_do_update(ZSTR_VAL(new_value));
579 #endif
580 }
581 return SUCCESS;
582 }
583 /* }}} */
584
585 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateInputEncoding)586 static PHP_INI_MH(OnUpdateInputEncoding)
587 {
588 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
589 if (php_internal_encoding_changed) {
590 php_internal_encoding_changed();
591 }
592 if (new_value) {
593 #ifdef PHP_WIN32
594 php_win32_cp_do_update(NULL);
595 #endif
596 }
597 return SUCCESS;
598 }
599 /* }}} */
600
601 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateOutputEncoding)602 static PHP_INI_MH(OnUpdateOutputEncoding)
603 {
604 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
605 if (php_internal_encoding_changed) {
606 php_internal_encoding_changed();
607 }
608 if (new_value) {
609 #ifdef PHP_WIN32
610 php_win32_cp_do_update(NULL);
611 #endif
612 }
613 return SUCCESS;
614 }
615 /* }}} */
616
617 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateErrorLog)618 static PHP_INI_MH(OnUpdateErrorLog)
619 {
620 /* Only do the safemode/open_basedir check at runtime */
621 if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value && strcmp(ZSTR_VAL(new_value), "syslog")) {
622 if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) {
623 return FAILURE;
624 }
625 }
626 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
627 return SUCCESS;
628 }
629 /* }}} */
630
631 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateMailLog)632 static PHP_INI_MH(OnUpdateMailLog)
633 {
634 /* Only do the safemode/open_basedir check at runtime */
635 if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value) {
636 if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) {
637 return FAILURE;
638 }
639 }
640 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
641 return SUCCESS;
642 }
643 /* }}} */
644
645 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnChangeMailForceExtra)646 static PHP_INI_MH(OnChangeMailForceExtra)
647 {
648 /* Don't allow changing it in htaccess */
649 if (stage == PHP_INI_STAGE_HTACCESS) {
650 return FAILURE;
651 }
652 return SUCCESS;
653 }
654 /* }}} */
655
656 /* defined in browscap.c */
657 PHP_INI_MH(OnChangeBrowscap);
658
659
660 /* Need to be read from the environment (?):
661 * PHP_AUTO_PREPEND_FILE
662 * PHP_AUTO_APPEND_FILE
663 * PHP_DOCUMENT_ROOT
664 * PHP_USER_DIR
665 * PHP_INCLUDE_PATH
666 */
667
668 /* Windows use the internal mail */
669 #if defined(PHP_WIN32)
670 # define DEFAULT_SENDMAIL_PATH NULL
671 #else
672 # define DEFAULT_SENDMAIL_PATH PHP_PROG_SENDMAIL " -t -i"
673 #endif
674
675 /* {{{ PHP_INI */
676 PHP_INI_BEGIN()
677 PHP_INI_ENTRY_EX("highlight.comment", HL_COMMENT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
678 PHP_INI_ENTRY_EX("highlight.default", HL_DEFAULT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
679 PHP_INI_ENTRY_EX("highlight.html", HL_HTML_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
680 PHP_INI_ENTRY_EX("highlight.keyword", HL_KEYWORD_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
681 PHP_INI_ENTRY_EX("highlight.string", HL_STRING_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
682
683 STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)
684 STD_PHP_INI_BOOLEAN("display_startup_errors", "1", PHP_INI_ALL, OnUpdateBool, display_startup_errors, php_core_globals, core_globals)
685 STD_PHP_INI_BOOLEAN("enable_dl", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_dl, php_core_globals, core_globals)
686 STD_PHP_INI_BOOLEAN("expose_php", "1", PHP_INI_SYSTEM, OnUpdateBool, expose_php, php_core_globals, core_globals)
687 STD_PHP_INI_ENTRY("docref_root", "", PHP_INI_ALL, OnUpdateString, docref_root, php_core_globals, core_globals)
688 STD_PHP_INI_ENTRY("docref_ext", "", PHP_INI_ALL, OnUpdateString, docref_ext, php_core_globals, core_globals)
689 STD_PHP_INI_BOOLEAN("html_errors", "1", PHP_INI_ALL, OnUpdateBool, html_errors, php_core_globals, core_globals)
690 STD_PHP_INI_BOOLEAN("xmlrpc_errors", "0", PHP_INI_SYSTEM, OnUpdateBool, xmlrpc_errors, php_core_globals, core_globals)
691 STD_PHP_INI_ENTRY("xmlrpc_error_number", "0", PHP_INI_ALL, OnUpdateLong, xmlrpc_error_number, php_core_globals, core_globals)
692 STD_PHP_INI_ENTRY("max_input_time", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, max_input_time, php_core_globals, core_globals)
693 STD_PHP_INI_BOOLEAN("ignore_user_abort", "0", PHP_INI_ALL, OnUpdateBool, ignore_user_abort, php_core_globals, core_globals)
694 STD_PHP_INI_BOOLEAN("implicit_flush", "0", PHP_INI_ALL, OnUpdateBool, implicit_flush, php_core_globals, core_globals)
695 STD_PHP_INI_BOOLEAN("log_errors", "0", PHP_INI_ALL, OnUpdateBool, log_errors, php_core_globals, core_globals)
696 STD_PHP_INI_ENTRY("log_errors_max_len", "1024", PHP_INI_ALL, OnUpdateLong, log_errors_max_len, php_core_globals, core_globals)
697 STD_PHP_INI_BOOLEAN("ignore_repeated_errors", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_errors, php_core_globals, core_globals)
698 STD_PHP_INI_BOOLEAN("ignore_repeated_source", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_source, php_core_globals, core_globals)
699 STD_PHP_INI_BOOLEAN("report_memleaks", "1", PHP_INI_ALL, OnUpdateBool, report_memleaks, php_core_globals, core_globals)
700 STD_PHP_INI_BOOLEAN("report_zend_debug", "0", PHP_INI_ALL, OnUpdateBool, report_zend_debug, php_core_globals, core_globals)
701 STD_PHP_INI_ENTRY("output_buffering", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateLong, output_buffering, php_core_globals, core_globals)
702 STD_PHP_INI_ENTRY("output_handler", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, output_handler, php_core_globals, core_globals)
703 STD_PHP_INI_BOOLEAN("register_argc_argv", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_argc_argv, php_core_globals, core_globals)
704 STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals)
705 STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals)
706
707 STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals)
708 STD_PHP_INI_ENTRY("serialize_precision", "-1", PHP_INI_ALL, OnSetSerializePrecision, serialize_precision, php_core_globals, core_globals)
709 STD_PHP_INI_ENTRY("arg_separator.output", "&", PHP_INI_ALL, OnUpdateStringUnempty, arg_separator.output, php_core_globals, core_globals)
710 STD_PHP_INI_ENTRY("arg_separator.input", "&", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, arg_separator.input, php_core_globals, core_globals)
711
712 STD_PHP_INI_ENTRY("auto_append_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_append_file, php_core_globals, core_globals)
713 STD_PHP_INI_ENTRY("auto_prepend_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_prepend_file, php_core_globals, core_globals)
714 STD_PHP_INI_ENTRY("doc_root", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, doc_root, php_core_globals, core_globals)
715 STD_PHP_INI_ENTRY("default_charset", PHP_DEFAULT_CHARSET, PHP_INI_ALL, OnUpdateDefaultCharset, default_charset, sapi_globals_struct, sapi_globals)
716 STD_PHP_INI_ENTRY("default_mimetype", SAPI_DEFAULT_MIMETYPE, PHP_INI_ALL, OnUpdateDefaultMimeTye, default_mimetype, sapi_globals_struct, sapi_globals)
717 STD_PHP_INI_ENTRY("internal_encoding", NULL, PHP_INI_ALL, OnUpdateInternalEncoding, internal_encoding, php_core_globals, core_globals)
718 STD_PHP_INI_ENTRY("input_encoding", NULL, PHP_INI_ALL, OnUpdateInputEncoding, input_encoding, php_core_globals, core_globals)
719 STD_PHP_INI_ENTRY("output_encoding", NULL, PHP_INI_ALL, OnUpdateOutputEncoding, output_encoding, php_core_globals, core_globals)
720 STD_PHP_INI_ENTRY("error_log", NULL, PHP_INI_ALL, OnUpdateErrorLog, error_log, php_core_globals, core_globals)
721 STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals)
722 STD_PHP_INI_ENTRY("sys_temp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, sys_temp_dir, php_core_globals, core_globals)
723 STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
724 PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
725 STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
726
727 STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
728 STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals)
729 STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, post_max_size, sapi_globals_struct,sapi_globals)
730 STD_PHP_INI_ENTRY("upload_tmp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, upload_tmp_dir, php_core_globals, core_globals)
731 STD_PHP_INI_ENTRY("max_input_nesting_level", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_nesting_level, php_core_globals, core_globals)
732 STD_PHP_INI_ENTRY("max_input_vars", "1000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_vars, php_core_globals, core_globals)
733
734 STD_PHP_INI_ENTRY("user_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, user_dir, php_core_globals, core_globals)
735 STD_PHP_INI_ENTRY("variables_order", "EGPCS", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, variables_order, php_core_globals, core_globals)
736 STD_PHP_INI_ENTRY("request_order", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, request_order, php_core_globals, core_globals)
737
738 STD_PHP_INI_ENTRY("error_append_string", NULL, PHP_INI_ALL, OnUpdateString, error_append_string, php_core_globals, core_globals)
739 STD_PHP_INI_ENTRY("error_prepend_string", NULL, PHP_INI_ALL, OnUpdateString, error_prepend_string, php_core_globals, core_globals)
740
741 PHP_INI_ENTRY("SMTP", "localhost",PHP_INI_ALL, NULL)
742 PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL)
743 STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals)
744 STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailLog, mail_log, php_core_globals, core_globals)
745 PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, OnChangeBrowscap)
746 PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit)
747 PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision)
748 PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL)
749 PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM, NULL)
750 PHP_INI_ENTRY("mail.force_extra_parameters",NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnChangeMailForceExtra)
751 PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
752 PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
753 PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
754 PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
755
756 STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
757 STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
758 STD_PHP_INI_BOOLEAN("enable_post_data_reading", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, enable_post_data_reading, php_core_globals, core_globals)
759
760 STD_PHP_INI_ENTRY("realpath_cache_size", "4096K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
761 STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
762
763 STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
764 STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
765 STD_PHP_INI_ENTRY("hard_timeout", "2", PHP_INI_SYSTEM, OnUpdateLong, hard_timeout, zend_executor_globals, executor_globals)
766 #ifdef PHP_WIN32
767 STD_PHP_INI_BOOLEAN("windows.show_crt_warning", "0", PHP_INI_ALL, OnUpdateBool, windows_show_crt_warning, php_core_globals, core_globals)
768 #endif
769 STD_PHP_INI_ENTRY("syslog.facility", "LOG_USER", PHP_INI_SYSTEM, OnSetFacility, syslog_facility, php_core_globals, core_globals)
770 STD_PHP_INI_ENTRY("syslog.ident", "php", PHP_INI_SYSTEM, OnUpdateString, syslog_ident, php_core_globals, core_globals)
771 STD_PHP_INI_ENTRY("syslog.filter", "no-ctrl", PHP_INI_ALL, OnSetLogFilter, syslog_filter, php_core_globals, core_globals)
772 PHP_INI_END()
773 /* }}} */
774
775 /* True globals (no need for thread safety */
776 /* But don't make them a single int bitfield */
777 static int module_initialized = 0;
778 static int module_startup = 1;
779 static int module_shutdown = 0;
780
781 /* {{{ php_during_module_startup */
php_during_module_startup(void)782 PHPAPI int php_during_module_startup(void)
783 {
784 return module_startup;
785 }
786 /* }}} */
787
788 /* {{{ php_during_module_shutdown */
php_during_module_shutdown(void)789 PHPAPI int php_during_module_shutdown(void)
790 {
791 return module_shutdown;
792 }
793 /* }}} */
794
795 /* {{{ php_get_module_initialized */
php_get_module_initialized(void)796 PHPAPI int php_get_module_initialized(void)
797 {
798 return module_initialized;
799 }
800 /* }}} */
801
802 /* {{{ php_log_err_with_severity */
php_log_err_with_severity(const char * log_message,int syslog_type_int)803 PHPAPI ZEND_COLD void php_log_err_with_severity(const char *log_message, int syslog_type_int)
804 {
805 int fd = -1;
806 time_t error_time;
807
808 if (PG(in_error_log)) {
809 /* prevent recursive invocation */
810 return;
811 }
812 PG(in_error_log) = 1;
813
814 /* Try to use the specified logging location. */
815 if (PG(error_log) != NULL) {
816 #ifdef HAVE_SYSLOG_H
817 if (!strcmp(PG(error_log), "syslog")) {
818 php_syslog(syslog_type_int, "%s", log_message);
819 PG(in_error_log) = 0;
820 return;
821 }
822 #endif
823 fd = VCWD_OPEN_MODE(PG(error_log), O_CREAT | O_APPEND | O_WRONLY, 0644);
824 if (fd != -1) {
825 char *tmp;
826 size_t len;
827 zend_string *error_time_str;
828
829 time(&error_time);
830 #ifdef ZTS
831 if (!php_during_module_startup()) {
832 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
833 } else {
834 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 0);
835 }
836 #else
837 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
838 #endif
839 len = spprintf(&tmp, 0, "[%s] %s%s", ZSTR_VAL(error_time_str), log_message, PHP_EOL);
840 #ifdef PHP_WIN32
841 php_flock(fd, LOCK_EX);
842 /* XXX should eventually write in a loop if len > UINT_MAX */
843 php_ignore_value(write(fd, tmp, (unsigned)len));
844 php_flock(fd, LOCK_UN);
845 #else
846 php_ignore_value(write(fd, tmp, len));
847 #endif
848 efree(tmp);
849 zend_string_free(error_time_str);
850 close(fd);
851 PG(in_error_log) = 0;
852 return;
853 }
854 }
855
856 /* Otherwise fall back to the default logging location, if we have one */
857
858 if (sapi_module.log_message) {
859 sapi_module.log_message(log_message, syslog_type_int);
860 }
861 PG(in_error_log) = 0;
862 }
863 /* }}} */
864
865 /* {{{ php_write
866 wrapper for modules to use PHPWRITE */
php_write(void * buf,size_t size)867 PHPAPI size_t php_write(void *buf, size_t size)
868 {
869 return PHPWRITE(buf, size);
870 }
871 /* }}} */
872
873 /* {{{ php_printf */
php_printf(const char * format,...)874 PHPAPI size_t php_printf(const char *format, ...)
875 {
876 va_list args;
877 size_t ret;
878 char *buffer;
879 size_t size;
880
881 va_start(args, format);
882 size = vspprintf(&buffer, 0, format, args);
883 ret = PHPWRITE(buffer, size);
884 efree(buffer);
885 va_end(args);
886
887 return ret;
888 }
889 /* }}} */
890
891 /* {{{ php_printf_unchecked */
php_printf_unchecked(const char * format,...)892 PHPAPI size_t php_printf_unchecked(const char *format, ...)
893 {
894 va_list args;
895 size_t ret;
896 char *buffer;
897 size_t size;
898
899 va_start(args, format);
900 size = vspprintf(&buffer, 0, format, args);
901 ret = PHPWRITE(buffer, size);
902 efree(buffer);
903 va_end(args);
904
905 return ret;
906 }
907 /* }}} */
908
escape_html(const char * buffer,size_t buffer_len)909 static zend_string *escape_html(const char *buffer, size_t buffer_len) {
910 zend_string *result = php_escape_html_entities_ex(
911 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT,
912 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
913 if (!result || ZSTR_LEN(result) == 0) {
914 /* Retry with substituting invalid chars on fail. */
915 result = php_escape_html_entities_ex(
916 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT | ENT_HTML_SUBSTITUTE_ERRORS,
917 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
918 }
919 return result;
920 }
921
922 /* {{{ php_verror */
923 /* php_verror is called from php_error_docref<n> functions.
924 * Its purpose is to unify error messages and automatically generate clickable
925 * html error messages if corresponding ini setting (html_errors) is activated.
926 * See: CODING_STANDARDS.md for details.
927 */
php_verror(const char * docref,const char * params,int type,const char * format,va_list args)928 PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args)
929 {
930 zend_string *replace_buffer = NULL, *replace_origin = NULL;
931 char *buffer = NULL, *docref_buf = NULL, *target = NULL;
932 char *docref_target = "", *docref_root = "";
933 char *p;
934 int buffer_len = 0;
935 const char *space = "";
936 const char *class_name = "";
937 const char *function;
938 int origin_len;
939 char *origin;
940 zend_string *message;
941 int is_function = 0;
942
943 /* get error text into buffer and escape for html if necessary */
944 buffer_len = (int)vspprintf(&buffer, 0, format, args);
945
946 if (PG(html_errors)) {
947 replace_buffer = escape_html(buffer, buffer_len);
948 efree(buffer);
949
950 if (replace_buffer) {
951 buffer = ZSTR_VAL(replace_buffer);
952 buffer_len = (int)ZSTR_LEN(replace_buffer);
953 } else {
954 buffer = "";
955 buffer_len = 0;
956 }
957 }
958
959 /* which function caused the problem if any at all */
960 if (php_during_module_startup()) {
961 function = "PHP Startup";
962 } else if (php_during_module_shutdown()) {
963 function = "PHP Shutdown";
964 } else if (EG(current_execute_data) &&
965 EG(current_execute_data)->func &&
966 ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
967 EG(current_execute_data)->opline &&
968 EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL
969 ) {
970 switch (EG(current_execute_data)->opline->extended_value) {
971 case ZEND_EVAL:
972 function = "eval";
973 is_function = 1;
974 break;
975 case ZEND_INCLUDE:
976 function = "include";
977 is_function = 1;
978 break;
979 case ZEND_INCLUDE_ONCE:
980 function = "include_once";
981 is_function = 1;
982 break;
983 case ZEND_REQUIRE:
984 function = "require";
985 is_function = 1;
986 break;
987 case ZEND_REQUIRE_ONCE:
988 function = "require_once";
989 is_function = 1;
990 break;
991 default:
992 function = "Unknown";
993 }
994 } else {
995 function = get_active_function_name();
996 if (!function || !strlen(function)) {
997 function = "Unknown";
998 } else {
999 is_function = 1;
1000 class_name = get_active_class_name(&space);
1001 }
1002 }
1003
1004 /* if we still have memory then format the origin */
1005 if (is_function) {
1006 origin_len = (int)spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params);
1007 } else {
1008 origin_len = (int)spprintf(&origin, 0, "%s", function);
1009 }
1010
1011 if (PG(html_errors)) {
1012 replace_origin = escape_html(origin, origin_len);
1013 efree(origin);
1014 origin = ZSTR_VAL(replace_origin);
1015 }
1016
1017 /* origin and buffer available, so lets come up with the error message */
1018 if (docref && docref[0] == '#') {
1019 docref_target = strchr(docref, '#');
1020 docref = NULL;
1021 }
1022
1023 /* no docref given but function is known (the default) */
1024 if (!docref && is_function) {
1025 int doclen;
1026 while (*function == '_') {
1027 function++;
1028 }
1029 if (space[0] == '\0') {
1030 doclen = (int)spprintf(&docref_buf, 0, "function.%s", function);
1031 } else {
1032 doclen = (int)spprintf(&docref_buf, 0, "%s.%s", class_name, function);
1033 }
1034 while((p = strchr(docref_buf, '_')) != NULL) {
1035 *p = '-';
1036 }
1037 docref = php_strtolower(docref_buf, doclen);
1038 }
1039
1040 /* we have a docref for a function AND
1041 * - we show errors in html mode AND
1042 * - the user wants to see the links
1043 */
1044 if (docref && is_function && PG(html_errors) && strlen(PG(docref_root))) {
1045 if (strncmp(docref, "http://", 7)) {
1046 /* We don't have 'http://' so we use docref_root */
1047
1048 char *ref; /* temp copy for duplicated docref */
1049
1050 docref_root = PG(docref_root);
1051
1052 ref = estrdup(docref);
1053 if (docref_buf) {
1054 efree(docref_buf);
1055 }
1056 docref_buf = ref;
1057 /* strip of the target if any */
1058 p = strrchr(ref, '#');
1059 if (p) {
1060 target = estrdup(p);
1061 if (target) {
1062 docref_target = target;
1063 *p = '\0';
1064 }
1065 }
1066 /* add the extension if it is set in ini */
1067 if (PG(docref_ext) && strlen(PG(docref_ext))) {
1068 spprintf(&docref_buf, 0, "%s%s", ref, PG(docref_ext));
1069 efree(ref);
1070 }
1071 docref = docref_buf;
1072 }
1073 /* display html formatted or only show the additional links */
1074 if (PG(html_errors)) {
1075 message = zend_strpprintf(0, "%s [<a href='%s%s%s'>%s</a>]: %s", origin, docref_root, docref, docref_target, docref, buffer);
1076 } else {
1077 message = zend_strpprintf(0, "%s [%s%s%s]: %s", origin, docref_root, docref, docref_target, buffer);
1078 }
1079 if (target) {
1080 efree(target);
1081 }
1082 } else {
1083 message = zend_strpprintf(0, "%s: %s", origin, buffer);
1084 }
1085 if (replace_origin) {
1086 zend_string_free(replace_origin);
1087 } else {
1088 efree(origin);
1089 }
1090 if (docref_buf) {
1091 efree(docref_buf);
1092 }
1093
1094 if (replace_buffer) {
1095 zend_string_free(replace_buffer);
1096 } else {
1097 efree(buffer);
1098 }
1099
1100 zend_error_zstr(type, message);
1101 zend_string_release(message);
1102 }
1103 /* }}} */
1104
1105 /* {{{ php_error_docref */
1106 /* Generate an error which links to docref or the php.net documentation if docref is NULL */
php_error_docref(const char * docref,int type,const char * format,...)1107 PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...)
1108 {
1109 va_list args;
1110
1111 va_start(args, format);
1112 php_verror(docref, "", type, format, args);
1113 va_end(args);
1114 }
1115 /* }}} */
1116
1117 /* {{{ php_error_docref1 */
1118 /* See: CODING_STANDARDS.md for details. */
php_error_docref1(const char * docref,const char * param1,int type,const char * format,...)1119 PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...)
1120 {
1121 va_list args;
1122
1123 va_start(args, format);
1124 php_verror(docref, param1, type, format, args);
1125 va_end(args);
1126 }
1127 /* }}} */
1128
1129 /* {{{ php_error_docref2 */
1130 /* See: CODING_STANDARDS.md for details. */
php_error_docref2(const char * docref,const char * param1,const char * param2,int type,const char * format,...)1131 PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)
1132 {
1133 char *params;
1134 va_list args;
1135
1136 spprintf(¶ms, 0, "%s,%s", param1, param2);
1137 va_start(args, format);
1138 php_verror(docref, params ? params : "...", type, format, args);
1139 va_end(args);
1140 if (params) {
1141 efree(params);
1142 }
1143 }
1144 /* }}} */
1145
1146 #ifdef PHP_WIN32
php_win32_docref1_from_error(DWORD error,const char * param1)1147 PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1) {
1148 char *buf = php_win32_error_to_msg(error);
1149 size_t buf_len;
1150
1151 buf_len = strlen(buf);
1152 if (buf_len >= 2) {
1153 buf[buf_len - 1] = '\0';
1154 buf[buf_len - 2] = '\0';
1155 }
1156 php_error_docref1(NULL, param1, E_WARNING, "%s (code: %lu)", buf, error);
1157 php_win32_error_msg_free(buf);
1158 }
1159
php_win32_docref2_from_error(DWORD error,const char * param1,const char * param2)1160 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) {
1161 char *buf = php_win32_error_to_msg(error);
1162 php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", buf, error);
1163 php_win32_error_msg_free(buf);
1164 }
1165 #endif
1166
1167 /* {{{ php_html_puts */
php_html_puts(const char * str,size_t size)1168 PHPAPI void php_html_puts(const char *str, size_t size)
1169 {
1170 zend_html_puts(str, size);
1171 }
1172 /* }}} */
1173
clear_last_error()1174 static void clear_last_error() {
1175 if (PG(last_error_message)) {
1176 zend_string_release(PG(last_error_message));
1177 PG(last_error_message) = NULL;
1178 }
1179 if (PG(last_error_file)) {
1180 free(PG(last_error_file));
1181 PG(last_error_file) = NULL;
1182 }
1183 }
1184
1185 #if ZEND_DEBUG
1186 /* {{{ report_zend_debug_error_notify_cb */
report_zend_debug_error_notify_cb(int type,const char * error_filename,uint32_t error_lineno,zend_string * message)1187 static void report_zend_debug_error_notify_cb(int type, const char *error_filename, uint32_t error_lineno, zend_string *message)
1188 {
1189 if (PG(report_zend_debug)) {
1190 zend_bool trigger_break;
1191
1192 switch (type) {
1193 case E_ERROR:
1194 case E_CORE_ERROR:
1195 case E_COMPILE_ERROR:
1196 case E_USER_ERROR:
1197 trigger_break=1;
1198 break;
1199 default:
1200 trigger_break=0;
1201 break;
1202 }
1203
1204 zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s", error_filename, error_lineno, ZSTR_VAL(message));
1205 }
1206 }
1207 /* }}} */
1208 #endif
1209
1210 /* {{{ php_error_cb
1211 extended error handling function */
php_error_cb(int orig_type,const char * error_filename,const uint32_t error_lineno,zend_string * message)1212 static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, const uint32_t error_lineno, zend_string *message)
1213 {
1214 zend_bool display;
1215 int type = orig_type & E_ALL;
1216
1217 /* check for repeated errors to be ignored */
1218 if (PG(ignore_repeated_errors) && PG(last_error_message)) {
1219 /* no check for PG(last_error_file) is needed since it cannot
1220 * be NULL if PG(last_error_message) is not NULL */
1221 if (!zend_string_equals(PG(last_error_message), message)
1222 || (!PG(ignore_repeated_source)
1223 && ((PG(last_error_lineno) != (int)error_lineno)
1224 || strcmp(PG(last_error_file), error_filename)))) {
1225 display = 1;
1226 } else {
1227 display = 0;
1228 }
1229 } else {
1230 display = 1;
1231 }
1232
1233 /* according to error handling mode, throw exception or show it */
1234 if (EG(error_handling) == EH_THROW) {
1235 switch (type) {
1236 case E_WARNING:
1237 case E_CORE_WARNING:
1238 case E_COMPILE_WARNING:
1239 case E_USER_WARNING:
1240 /* throw an exception if we are in EH_THROW mode and the type is warning.
1241 * fatal errors are real errors and cannot be made exceptions.
1242 * exclude deprecated for the sake of BC to old damaged code.
1243 * notices are no errors and are not treated as such like E_WARNINGS.
1244 * DO NOT overwrite a pending exception.
1245 */
1246 if (!EG(exception)) {
1247 zend_throw_error_exception(EG(exception_class), message, 0, type);
1248 }
1249 return;
1250 default:
1251 break;
1252 }
1253 }
1254
1255 /* store the error if it has changed */
1256 if (display) {
1257 clear_last_error();
1258 if (!error_filename) {
1259 error_filename = "Unknown";
1260 }
1261 PG(last_error_type) = type;
1262 PG(last_error_message) = zend_string_copy(message);
1263 PG(last_error_file) = strdup(error_filename);
1264 PG(last_error_lineno) = error_lineno;
1265 }
1266
1267 /* display/log the error if necessary */
1268 if (display && ((EG(error_reporting) & type) || (type & E_CORE))
1269 && (PG(log_errors) || PG(display_errors) || (!module_initialized))) {
1270 char *error_type_str;
1271 int syslog_type_int = LOG_NOTICE;
1272
1273 switch (type) {
1274 case E_ERROR:
1275 case E_CORE_ERROR:
1276 case E_COMPILE_ERROR:
1277 case E_USER_ERROR:
1278 error_type_str = "Fatal error";
1279 syslog_type_int = LOG_ERR;
1280 break;
1281 case E_RECOVERABLE_ERROR:
1282 error_type_str = "Recoverable fatal error";
1283 syslog_type_int = LOG_ERR;
1284 break;
1285 case E_WARNING:
1286 case E_CORE_WARNING:
1287 case E_COMPILE_WARNING:
1288 case E_USER_WARNING:
1289 error_type_str = "Warning";
1290 syslog_type_int = LOG_WARNING;
1291 break;
1292 case E_PARSE:
1293 error_type_str = "Parse error";
1294 syslog_type_int = LOG_ERR;
1295 break;
1296 case E_NOTICE:
1297 case E_USER_NOTICE:
1298 error_type_str = "Notice";
1299 syslog_type_int = LOG_NOTICE;
1300 break;
1301 case E_STRICT:
1302 error_type_str = "Strict Standards";
1303 syslog_type_int = LOG_INFO;
1304 break;
1305 case E_DEPRECATED:
1306 case E_USER_DEPRECATED:
1307 error_type_str = "Deprecated";
1308 syslog_type_int = LOG_INFO;
1309 break;
1310 default:
1311 error_type_str = "Unknown error";
1312 break;
1313 }
1314
1315 if (PG(log_errors)
1316 || (!module_initialized && (!PG(display_startup_errors) || !PG(display_errors)))) {
1317 char *log_buffer;
1318 #ifdef PHP_WIN32
1319 if (type == E_CORE_ERROR || type == E_CORE_WARNING) {
1320 syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, ZSTR_VAL(message), GetCommandLine());
1321 }
1322 #endif
1323 spprintf(&log_buffer, 0, "PHP %s: %s in %s on line %" PRIu32, error_type_str, ZSTR_VAL(message), error_filename, error_lineno);
1324 php_log_err_with_severity(log_buffer, syslog_type_int);
1325 efree(log_buffer);
1326 }
1327
1328 if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) {
1329 if (PG(xmlrpc_errors)) {
1330 php_printf("<?xml version=\"1.0\"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><int>" ZEND_LONG_FMT "</int></value></member><member><name>faultString</name><value><string>%s:%s in %s on line %" PRIu32 "</string></value></member></struct></value></fault></methodResponse>", PG(xmlrpc_error_number), error_type_str, ZSTR_VAL(message), error_filename, error_lineno);
1331 } else {
1332 char *prepend_string = INI_STR("error_prepend_string");
1333 char *append_string = INI_STR("error_append_string");
1334
1335 if (PG(html_errors)) {
1336 if (type == E_ERROR || type == E_PARSE) {
1337 zend_string *buf = escape_html(ZSTR_VAL(message), ZSTR_LEN(message));
1338 php_printf("%s<br />\n<b>%s</b>: %s in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(buf), error_filename, error_lineno, STR_PRINT(append_string));
1339 zend_string_free(buf);
1340 } else {
1341 php_printf("%s<br />\n<b>%s</b>: %s in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(message), error_filename, error_lineno, STR_PRINT(append_string));
1342 }
1343 } else {
1344 /* Write CLI/CGI errors to stderr if display_errors = "stderr" */
1345 if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
1346 PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
1347 ) {
1348 fprintf(stderr, "%s: %s in %s on line %" PRIu32 "\n", error_type_str, ZSTR_VAL(message), error_filename, error_lineno);
1349 #ifdef PHP_WIN32
1350 fflush(stderr);
1351 #endif
1352 } else {
1353 php_printf("%s\n%s: %s in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(message), error_filename, error_lineno, STR_PRINT(append_string));
1354 }
1355 }
1356 }
1357 }
1358 }
1359
1360 /* Bail out if we can't recover */
1361 switch (type) {
1362 case E_CORE_ERROR:
1363 if(!module_initialized) {
1364 /* bad error in module startup - no way we can live with this */
1365 exit(-2);
1366 }
1367 /* no break - intentionally */
1368 case E_ERROR:
1369 case E_RECOVERABLE_ERROR:
1370 case E_PARSE:
1371 case E_COMPILE_ERROR:
1372 case E_USER_ERROR:
1373 EG(exit_status) = 255;
1374 if (module_initialized) {
1375 if (!PG(display_errors) &&
1376 !SG(headers_sent) &&
1377 SG(sapi_headers).http_response_code == 200
1378 ) {
1379 sapi_header_line ctr = {0};
1380
1381 ctr.line = "HTTP/1.0 500 Internal Server Error";
1382 ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1;
1383 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
1384 }
1385 /* the parser would return 1 (failure), we can bail out nicely */
1386 if (!(orig_type & E_DONT_BAIL)) {
1387 /* restore memory limit */
1388 zend_set_memory_limit(PG(memory_limit));
1389 zend_objects_store_mark_destructed(&EG(objects_store));
1390 zend_bailout();
1391 return;
1392 }
1393 }
1394 break;
1395 }
1396 }
1397 /* }}} */
1398
1399 /* {{{ php_get_current_user */
php_get_current_user(void)1400 PHPAPI char *php_get_current_user(void)
1401 {
1402 zend_stat_t *pstat;
1403
1404 if (SG(request_info).current_user) {
1405 return SG(request_info).current_user;
1406 }
1407
1408 /* FIXME: I need to have this somehow handled if
1409 USE_SAPI is defined, because cgi will also be
1410 interfaced in USE_SAPI */
1411
1412 pstat = sapi_get_stat();
1413
1414 if (!pstat) {
1415 return "";
1416 } else {
1417 #ifdef PHP_WIN32
1418 char *name = php_win32_get_username();
1419 int len;
1420
1421 if (!name) {
1422 return "";
1423 }
1424 len = (int)strlen(name);
1425 name[len] = '\0';
1426 SG(request_info).current_user_length = len;
1427 SG(request_info).current_user = estrndup(name, len);
1428 free(name);
1429 return SG(request_info).current_user;
1430 #else
1431 struct passwd *pwd;
1432 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1433 struct passwd _pw;
1434 struct passwd *retpwptr = NULL;
1435 int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1436 char *pwbuf;
1437
1438 if (pwbuflen < 1) {
1439 return "";
1440 }
1441 pwbuf = emalloc(pwbuflen);
1442 if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
1443 efree(pwbuf);
1444 return "";
1445 }
1446 if (retpwptr == NULL) {
1447 efree(pwbuf);
1448 return "";
1449 }
1450 pwd = &_pw;
1451 #else
1452 if ((pwd=getpwuid(pstat->st_uid))==NULL) {
1453 return "";
1454 }
1455 #endif
1456 SG(request_info).current_user_length = strlen(pwd->pw_name);
1457 SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
1458 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1459 efree(pwbuf);
1460 #endif
1461 return SG(request_info).current_user;
1462 #endif
1463 }
1464 }
1465 /* }}} */
1466
1467 /* {{{ Sets the maximum time a script can run */
PHP_FUNCTION(set_time_limit)1468 PHP_FUNCTION(set_time_limit)
1469 {
1470 zend_long new_timeout;
1471 char *new_timeout_str;
1472 int new_timeout_strlen;
1473 zend_string *key;
1474
1475 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) {
1476 RETURN_THROWS();
1477 }
1478
1479 new_timeout_strlen = (int)zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout);
1480
1481 key = zend_string_init("max_execution_time", sizeof("max_execution_time")-1, 0);
1482 if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) {
1483 RETVAL_TRUE;
1484 } else {
1485 RETVAL_FALSE;
1486 }
1487 zend_string_release_ex(key, 0);
1488 efree(new_timeout_str);
1489 }
1490 /* }}} */
1491
1492 /* {{{ php_fopen_wrapper_for_zend */
php_fopen_wrapper_for_zend(const char * filename,zend_string ** opened_path)1493 static FILE *php_fopen_wrapper_for_zend(const char *filename, zend_string **opened_path)
1494 {
1495 return php_stream_open_wrapper_as_file((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE, opened_path);
1496 }
1497 /* }}} */
1498
php_zend_stream_closer(void * handle)1499 static void php_zend_stream_closer(void *handle) /* {{{ */
1500 {
1501 php_stream_close((php_stream*)handle);
1502 }
1503 /* }}} */
1504
php_zend_stream_fsizer(void * handle)1505 static size_t php_zend_stream_fsizer(void *handle) /* {{{ */
1506 {
1507 php_stream *stream = handle;
1508 php_stream_statbuf ssb;
1509
1510 /* File size reported by stat() may be inaccurate if stream filters are used.
1511 * TODO: Should stat() be generally disabled if filters are used? */
1512 if (stream->readfilters.head) {
1513 return 0;
1514 }
1515
1516 if (php_stream_stat(stream, &ssb) == 0) {
1517 return ssb.sb.st_size;
1518 }
1519 return 0;
1520 }
1521 /* }}} */
1522
php_stream_open_for_zend(const char * filename,zend_file_handle * handle)1523 static zend_result php_stream_open_for_zend(const char *filename, zend_file_handle *handle) /* {{{ */
1524 {
1525 return php_stream_open_for_zend_ex(filename, handle, USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE);
1526 }
1527 /* }}} */
1528
php_stream_open_for_zend_ex(const char * filename,zend_file_handle * handle,int mode)1529 PHPAPI zend_result php_stream_open_for_zend_ex(const char *filename, zend_file_handle *handle, int mode) /* {{{ */
1530 {
1531 zend_string *opened_path;
1532 php_stream *stream = php_stream_open_wrapper((char *)filename, "rb", mode, &opened_path);
1533 if (stream) {
1534 memset(handle, 0, sizeof(zend_file_handle));
1535 handle->type = ZEND_HANDLE_STREAM;
1536 handle->filename = (char*)filename;
1537 handle->opened_path = opened_path;
1538 handle->handle.stream.handle = stream;
1539 handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read;
1540 handle->handle.stream.fsizer = php_zend_stream_fsizer;
1541 handle->handle.stream.isatty = 0;
1542 handle->handle.stream.closer = php_zend_stream_closer;
1543 /* suppress warning if this stream is not explicitly closed */
1544 php_stream_auto_cleanup(stream);
1545 /* Disable buffering to avoid double buffering between PHP and Zend streams. */
1546 php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1547
1548 return SUCCESS;
1549 }
1550 return FAILURE;
1551 }
1552 /* }}} */
1553
php_resolve_path_for_zend(const char * filename,size_t filename_len)1554 static zend_string *php_resolve_path_for_zend(const char *filename, size_t filename_len) /* {{{ */
1555 {
1556 return php_resolve_path(filename, filename_len, PG(include_path));
1557 }
1558 /* }}} */
1559
1560 /* {{{ php_get_configuration_directive_for_zend */
php_get_configuration_directive_for_zend(zend_string * name)1561 static zval *php_get_configuration_directive_for_zend(zend_string *name)
1562 {
1563 return cfg_get_entry_ex(name);
1564 }
1565 /* }}} */
1566
1567 /* {{{ php_free_request_globals */
php_free_request_globals(void)1568 static void php_free_request_globals(void)
1569 {
1570 clear_last_error();
1571 if (PG(php_sys_temp_dir)) {
1572 efree(PG(php_sys_temp_dir));
1573 PG(php_sys_temp_dir) = NULL;
1574 }
1575 }
1576 /* }}} */
1577
1578 /* {{{ php_message_handler_for_zend */
php_message_handler_for_zend(zend_long message,const void * data)1579 static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data)
1580 {
1581 switch (message) {
1582 case ZMSG_FAILED_INCLUDE_FOPEN:
1583 php_error_docref("function.include", E_WARNING, "Failed opening '%s' for inclusion (include_path='%s')", php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path)));
1584 break;
1585 case ZMSG_FAILED_REQUIRE_FOPEN:
1586 zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path)));
1587 break;
1588 case ZMSG_FAILED_HIGHLIGHT_FOPEN:
1589 php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd((char *) data));
1590 break;
1591 case ZMSG_MEMORY_LEAK_DETECTED:
1592 case ZMSG_MEMORY_LEAK_REPEATED:
1593 #if ZEND_DEBUG
1594 if (EG(error_reporting) & E_WARNING) {
1595 char memory_leak_buf[1024];
1596
1597 if (message==ZMSG_MEMORY_LEAK_DETECTED) {
1598 zend_leak_info *t = (zend_leak_info *) data;
1599
1600 snprintf(memory_leak_buf, 512, "%s(%" PRIu32 ") : Freeing " ZEND_ADDR_FMT " (%zu bytes), script=%s\n", t->filename, t->lineno, (size_t)t->addr, t->size, SAFE_FILENAME(SG(request_info).path_translated));
1601 if (t->orig_filename) {
1602 char relay_buf[512];
1603
1604 snprintf(relay_buf, 512, "%s(%" PRIu32 ") : Actual location (location was relayed)\n", t->orig_filename, t->orig_lineno);
1605 strlcat(memory_leak_buf, relay_buf, sizeof(memory_leak_buf));
1606 }
1607 } else {
1608 unsigned long leak_count = (zend_uintptr_t) data;
1609
1610 snprintf(memory_leak_buf, 512, "Last leak repeated %lu time%s\n", leak_count, (leak_count>1?"s":""));
1611 }
1612 # if defined(PHP_WIN32)
1613 if (IsDebuggerPresent()) {
1614 OutputDebugString(memory_leak_buf);
1615 } else {
1616 fprintf(stderr, "%s", memory_leak_buf);
1617 }
1618 # else
1619 fprintf(stderr, "%s", memory_leak_buf);
1620 # endif
1621 }
1622 #endif
1623 break;
1624 case ZMSG_MEMORY_LEAKS_GRAND_TOTAL:
1625 #if ZEND_DEBUG
1626 if (EG(error_reporting) & E_WARNING) {
1627 char memory_leak_buf[512];
1628
1629 snprintf(memory_leak_buf, 512, "=== Total %d memory leaks detected ===\n", *((uint32_t *) data));
1630 # if defined(PHP_WIN32)
1631 if (IsDebuggerPresent()) {
1632 OutputDebugString(memory_leak_buf);
1633 } else {
1634 fprintf(stderr, "%s", memory_leak_buf);
1635 }
1636 # else
1637 fprintf(stderr, "%s", memory_leak_buf);
1638 # endif
1639 }
1640 #endif
1641 break;
1642 case ZMSG_LOG_SCRIPT_NAME: {
1643 struct tm *ta, tmbuf;
1644 time_t curtime;
1645 char *datetime_str, asctimebuf[52];
1646 char memory_leak_buf[4096];
1647
1648 time(&curtime);
1649 ta = php_localtime_r(&curtime, &tmbuf);
1650 datetime_str = php_asctime_r(ta, asctimebuf);
1651 if (datetime_str) {
1652 datetime_str[strlen(datetime_str)-1]=0; /* get rid of the trailing newline */
1653 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[%s] Script: '%s'\n", datetime_str, SAFE_FILENAME(SG(request_info).path_translated));
1654 } else {
1655 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[null] Script: '%s'\n", SAFE_FILENAME(SG(request_info).path_translated));
1656 }
1657 # if defined(PHP_WIN32)
1658 if (IsDebuggerPresent()) {
1659 OutputDebugString(memory_leak_buf);
1660 } else {
1661 fprintf(stderr, "%s", memory_leak_buf);
1662 }
1663 # else
1664 fprintf(stderr, "%s", memory_leak_buf);
1665 # endif
1666 }
1667 break;
1668 }
1669 }
1670 /* }}} */
1671
1672
php_on_timeout(int seconds)1673 void php_on_timeout(int seconds)
1674 {
1675 PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
1676 }
1677
1678 #if PHP_SIGCHILD
1679 /* {{{ sigchld_handler */
sigchld_handler(int apar)1680 static void sigchld_handler(int apar)
1681 {
1682 int errno_save = errno;
1683
1684 while (waitpid(-1, NULL, WNOHANG) > 0);
1685 signal(SIGCHLD, sigchld_handler);
1686
1687 errno = errno_save;
1688 }
1689 /* }}} */
1690 #endif
1691
1692 /* {{{ php_request_startup */
php_request_startup(void)1693 int php_request_startup(void)
1694 {
1695 int retval = SUCCESS;
1696
1697 zend_interned_strings_activate();
1698
1699 #ifdef HAVE_DTRACE
1700 DTRACE_REQUEST_STARTUP(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
1701 #endif /* HAVE_DTRACE */
1702
1703 #ifdef PHP_WIN32
1704 # if defined(ZTS)
1705 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1706 # endif
1707 PG(com_initialized) = 0;
1708 #endif
1709
1710 #if PHP_SIGCHILD
1711 signal(SIGCHLD, sigchld_handler);
1712 #endif
1713
1714 zend_try {
1715 PG(in_error_log) = 0;
1716 PG(during_request_startup) = 1;
1717
1718 php_output_activate();
1719
1720 /* initialize global variables */
1721 PG(modules_activated) = 0;
1722 PG(header_is_being_sent) = 0;
1723 PG(connection_status) = PHP_CONNECTION_NORMAL;
1724 PG(in_user_include) = 0;
1725
1726 zend_activate();
1727 sapi_activate();
1728
1729 #ifdef ZEND_SIGNALS
1730 zend_signal_activate();
1731 #endif
1732
1733 if (PG(max_input_time) == -1) {
1734 zend_set_timeout(EG(timeout_seconds), 1);
1735 } else {
1736 zend_set_timeout(PG(max_input_time), 1);
1737 }
1738
1739 /* Disable realpath cache if an open_basedir is set */
1740 if (PG(open_basedir) && *PG(open_basedir)) {
1741 CWDG(realpath_cache_size_limit) = 0;
1742 }
1743
1744 if (PG(expose_php)) {
1745 sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
1746 }
1747
1748 if (PG(output_handler) && PG(output_handler)[0]) {
1749 zval oh;
1750
1751 ZVAL_STRING(&oh, PG(output_handler));
1752 php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1753 zval_ptr_dtor(&oh);
1754 } else if (PG(output_buffering)) {
1755 php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1756 } else if (PG(implicit_flush)) {
1757 php_output_set_implicit_flush(1);
1758 }
1759
1760 /* We turn this off in php_execute_script() */
1761 /* PG(during_request_startup) = 0; */
1762
1763 php_hash_environment();
1764 zend_activate_modules();
1765 PG(modules_activated)=1;
1766 } zend_catch {
1767 retval = FAILURE;
1768 } zend_end_try();
1769
1770 SG(sapi_started) = 1;
1771
1772 return retval;
1773 }
1774 /* }}} */
1775
1776 /* {{{ php_request_shutdown */
php_request_shutdown(void * dummy)1777 void php_request_shutdown(void *dummy)
1778 {
1779 zend_bool report_memleaks;
1780
1781 EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
1782
1783 report_memleaks = PG(report_memleaks);
1784
1785 /* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed
1786 * inside zend_executor callback functions.
1787 */
1788 EG(current_execute_data) = NULL;
1789
1790 php_deactivate_ticks();
1791
1792 /* 0. Call any open observer end handlers that are still open after a zend_bailout */
1793 if (ZEND_OBSERVER_ENABLED) {
1794 zend_observer_fcall_end_all();
1795 }
1796
1797 /* 1. Call all possible shutdown functions registered with register_shutdown_function() */
1798 if (PG(modules_activated)) {
1799 php_call_shutdown_functions();
1800 }
1801
1802 /* 2. Call all possible __destruct() functions */
1803 zend_try {
1804 zend_call_destructors();
1805 } zend_end_try();
1806
1807 /* 3. Flush all output buffers */
1808 zend_try {
1809 zend_bool send_buffer = SG(request_info).headers_only ? 0 : 1;
1810
1811 if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR &&
1812 (size_t)PG(memory_limit) < zend_memory_usage(1)
1813 ) {
1814 send_buffer = 0;
1815 }
1816
1817 if (!send_buffer) {
1818 php_output_discard_all();
1819 } else {
1820 php_output_end_all();
1821 }
1822 } zend_end_try();
1823
1824 /* 4. Reset max_execution_time (no longer executing php code after response sent) */
1825 zend_try {
1826 zend_unset_timeout();
1827 } zend_end_try();
1828
1829 /* 5. Call all extensions RSHUTDOWN functions */
1830 if (PG(modules_activated)) {
1831 zend_deactivate_modules();
1832 }
1833
1834 /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
1835 zend_try {
1836 php_output_deactivate();
1837 } zend_end_try();
1838
1839 /* 7. Free shutdown functions */
1840 if (PG(modules_activated)) {
1841 php_free_shutdown_functions();
1842 }
1843
1844 /* 8. Destroy super-globals */
1845 zend_try {
1846 int i;
1847
1848 for (i=0; i<NUM_TRACK_VARS; i++) {
1849 zval_ptr_dtor(&PG(http_globals)[i]);
1850 }
1851 } zend_end_try();
1852
1853 /* 9. Shutdown scanner/executor/compiler and restore ini entries */
1854 zend_deactivate();
1855
1856 /* 10. free request-bound globals */
1857 php_free_request_globals();
1858
1859 /* 11. Call all extensions post-RSHUTDOWN functions */
1860 zend_try {
1861 zend_post_deactivate_modules();
1862 } zend_end_try();
1863
1864 /* 12. SAPI related shutdown*/
1865 zend_try {
1866 sapi_deactivate_module();
1867 } zend_end_try();
1868 /* free SAPI stuff */
1869 sapi_deactivate_destroy();
1870
1871 /* 13. free virtual CWD memory */
1872 virtual_cwd_deactivate();
1873
1874 /* 14. Destroy stream hashes */
1875 zend_try {
1876 php_shutdown_stream_hashes();
1877 } zend_end_try();
1878
1879 /* 15. Free Willy (here be crashes) */
1880 zend_interned_strings_deactivate();
1881 zend_try {
1882 shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
1883 } zend_end_try();
1884
1885 /* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed.
1886 * At this point, no memory beyond a single chunk should be in use. */
1887 zend_set_memory_limit(PG(memory_limit));
1888
1889 /* 16. Deactivate Zend signals */
1890 #ifdef ZEND_SIGNALS
1891 zend_signal_deactivate();
1892 #endif
1893
1894 #ifdef PHP_WIN32
1895 if (PG(com_initialized)) {
1896 CoUninitialize();
1897 PG(com_initialized) = 0;
1898 }
1899 #endif
1900
1901 #ifdef HAVE_DTRACE
1902 DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
1903 #endif /* HAVE_DTRACE */
1904 }
1905 /* }}} */
1906
1907 /* {{{ php_com_initialize */
php_com_initialize(void)1908 PHPAPI void php_com_initialize(void)
1909 {
1910 #ifdef PHP_WIN32
1911 if (!PG(com_initialized)) {
1912 if (CoInitialize(NULL) == S_OK) {
1913 PG(com_initialized) = 1;
1914 }
1915 }
1916 #endif
1917 }
1918 /* }}} */
1919
1920 #ifdef ZTS
1921 /* {{{ core_globals_ctor */
core_globals_ctor(php_core_globals * core_globals)1922 static void core_globals_ctor(php_core_globals *core_globals)
1923 {
1924 memset(core_globals, 0, sizeof(*core_globals));
1925 php_startup_ticks();
1926 }
1927 /* }}} */
1928 #endif
1929
1930 /* {{{ core_globals_dtor */
core_globals_dtor(php_core_globals * core_globals)1931 static void core_globals_dtor(php_core_globals *core_globals)
1932 {
1933 /* These should have been freed earlier. */
1934 ZEND_ASSERT(!core_globals->last_error_message);
1935 ZEND_ASSERT(!core_globals->last_error_file);
1936
1937 if (core_globals->disable_classes) {
1938 free(core_globals->disable_classes);
1939 }
1940 if (core_globals->php_binary) {
1941 free(core_globals->php_binary);
1942 }
1943
1944 php_shutdown_ticks();
1945 }
1946 /* }}} */
1947
PHP_MINFO_FUNCTION(php_core)1948 PHP_MINFO_FUNCTION(php_core) { /* {{{ */
1949 php_info_print_table_start();
1950 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1951 php_info_print_table_end();
1952 DISPLAY_INI_ENTRIES();
1953 }
1954 /* }}} */
1955
1956 /* {{{ php_register_extensions */
php_register_extensions(zend_module_entry * const * ptr,int count)1957 int php_register_extensions(zend_module_entry * const * ptr, int count)
1958 {
1959 zend_module_entry * const * end = ptr + count;
1960
1961 while (ptr < end) {
1962 if (*ptr) {
1963 if (zend_register_internal_module(*ptr)==NULL) {
1964 return FAILURE;
1965 }
1966 }
1967 ptr++;
1968 }
1969 return SUCCESS;
1970 }
1971
1972 /* A very long time ago php_module_startup() was refactored in a way
1973 * which broke calling it with more than one additional module.
1974 * This alternative to php_register_extensions() works around that
1975 * by walking the shallower structure.
1976 *
1977 * See algo: https://bugs.php.net/bug.php?id=63159
1978 */
php_register_extensions_bc(zend_module_entry * ptr,int count)1979 static int php_register_extensions_bc(zend_module_entry *ptr, int count)
1980 {
1981 while (count--) {
1982 if (zend_register_internal_module(ptr++) == NULL) {
1983 return FAILURE;
1984 }
1985 }
1986 return SUCCESS;
1987 }
1988 /* }}} */
1989
1990 #ifdef PHP_WIN32
1991 static _invalid_parameter_handler old_invalid_parameter_handler;
1992
dummy_invalid_parameter_handler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pEwserved)1993 void dummy_invalid_parameter_handler(
1994 const wchar_t *expression,
1995 const wchar_t *function,
1996 const wchar_t *file,
1997 unsigned int line,
1998 uintptr_t pEwserved)
1999 {
2000 static int called = 0;
2001 char buf[1024];
2002 int len;
2003
2004 if (!called) {
2005 if(PG(windows_show_crt_warning)) {
2006 called = 1;
2007 if (function) {
2008 if (file) {
2009 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws' (%ws:%u)", function, file, line);
2010 } else {
2011 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws'", function);
2012 }
2013 } else {
2014 len = _snprintf(buf, sizeof(buf)-1, "Invalid CRT parameter detected (function not known)");
2015 }
2016 zend_error(E_WARNING, "%s", buf);
2017 called = 0;
2018 }
2019 }
2020 }
2021 #endif
2022
2023 /* {{{ php_module_startup */
php_module_startup(sapi_module_struct * sf,zend_module_entry * additional_modules,uint32_t num_additional_modules)2024 int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules)
2025 {
2026 zend_utility_functions zuf;
2027 zend_utility_values zuv;
2028 int retval = SUCCESS, module_number=0; /* for REGISTER_INI_ENTRIES() */
2029 char *php_os;
2030 zend_module_entry *module;
2031
2032 #ifdef PHP_WIN32
2033 WORD wVersionRequested = MAKEWORD(2, 0);
2034 WSADATA wsaData;
2035
2036 php_os = "WINNT";
2037
2038 old_invalid_parameter_handler =
2039 _set_invalid_parameter_handler(dummy_invalid_parameter_handler);
2040 if (old_invalid_parameter_handler != NULL) {
2041 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2042 }
2043
2044 /* Disable the message box for assertions.*/
2045 _CrtSetReportMode(_CRT_ASSERT, 0);
2046 #else
2047 php_os = PHP_OS;
2048 #endif
2049
2050 #ifdef ZTS
2051 (void)ts_resource(0);
2052 #endif
2053
2054 #ifdef PHP_WIN32
2055 if (!php_win32_init_random_bytes()) {
2056 fprintf(stderr, "\ncrypt algorithm provider initialization failed\n");
2057 return FAILURE;
2058 }
2059 #endif
2060
2061 module_shutdown = 0;
2062 module_startup = 1;
2063 sapi_initialize_empty_request();
2064 sapi_activate();
2065
2066 if (module_initialized) {
2067 return SUCCESS;
2068 }
2069
2070 sapi_module = *sf;
2071
2072 php_output_startup();
2073
2074 #ifdef ZTS
2075 ts_allocate_fast_id(&core_globals_id, &core_globals_offset, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
2076 #ifdef PHP_WIN32
2077 ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, (ts_allocate_dtor) php_win32_core_globals_dtor);
2078 #endif
2079 #else
2080 memset(&core_globals, 0, sizeof(core_globals));
2081 php_startup_ticks();
2082 #endif
2083 gc_globals_ctor();
2084
2085 zuf.error_function = php_error_cb;
2086 zuf.printf_function = php_printf;
2087 zuf.write_function = php_output_write;
2088 zuf.fopen_function = php_fopen_wrapper_for_zend;
2089 zuf.message_handler = php_message_handler_for_zend;
2090 zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
2091 zuf.ticks_function = php_run_ticks;
2092 zuf.on_timeout = php_on_timeout;
2093 zuf.stream_open_function = php_stream_open_for_zend;
2094 zuf.printf_to_smart_string_function = php_printf_to_smart_string;
2095 zuf.printf_to_smart_str_function = php_printf_to_smart_str;
2096 zuf.getenv_function = sapi_getenv;
2097 zuf.resolve_path_function = php_resolve_path_for_zend;
2098 zend_startup(&zuf);
2099 zend_update_current_locale();
2100
2101 zend_observer_startup();
2102 #if ZEND_DEBUG
2103 zend_observer_error_register(report_zend_debug_error_notify_cb);
2104 #endif
2105
2106 #if HAVE_TZSET
2107 tzset();
2108 #endif
2109
2110 #ifdef PHP_WIN32
2111 char *img_err;
2112 if (!php_win32_crt_compatible(&img_err)) {
2113 php_error(E_CORE_WARNING, img_err);
2114 efree(img_err);
2115 return FAILURE;
2116 }
2117
2118 /* start up winsock services */
2119 if (WSAStartup(wVersionRequested, &wsaData) != 0) {
2120 php_printf("\nwinsock.dll unusable. %d\n", WSAGetLastError());
2121 return FAILURE;
2122 }
2123 php_win32_signal_ctrl_handler_init();
2124 #endif
2125
2126 le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);
2127
2128 /* Register constants */
2129 REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS);
2130 REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS);
2131 REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS);
2132 REGISTER_MAIN_LONG_CONSTANT("PHP_RELEASE_VERSION", PHP_RELEASE_VERSION, CONST_PERSISTENT | CONST_CS);
2133 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, sizeof(PHP_EXTRA_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
2134 REGISTER_MAIN_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT | CONST_CS);
2135 #ifdef ZTS
2136 REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 1, CONST_PERSISTENT | CONST_CS);
2137 #else
2138 REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 0, CONST_PERSISTENT | CONST_CS);
2139 #endif
2140 REGISTER_MAIN_LONG_CONSTANT("PHP_DEBUG", PHP_DEBUG, CONST_PERSISTENT | CONST_CS);
2141 REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS", php_os, strlen(php_os), CONST_PERSISTENT | CONST_CS);
2142 REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS_FAMILY", PHP_OS_FAMILY, sizeof(PHP_OS_FAMILY)-1, CONST_PERSISTENT | CONST_CS);
2143 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SAPI", sapi_module.name, strlen(sapi_module.name), CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2144 REGISTER_MAIN_STRINGL_CONSTANT("DEFAULT_INCLUDE_PATH", PHP_INCLUDE_PATH, sizeof(PHP_INCLUDE_PATH)-1, CONST_PERSISTENT | CONST_CS);
2145 REGISTER_MAIN_STRINGL_CONSTANT("PEAR_INSTALL_DIR", PEAR_INSTALLDIR, sizeof(PEAR_INSTALLDIR)-1, CONST_PERSISTENT | CONST_CS);
2146 REGISTER_MAIN_STRINGL_CONSTANT("PEAR_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
2147 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
2148 REGISTER_MAIN_STRINGL_CONSTANT("PHP_PREFIX", PHP_PREFIX, sizeof(PHP_PREFIX)-1, CONST_PERSISTENT | CONST_CS);
2149 REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINDIR", PHP_BINDIR, sizeof(PHP_BINDIR)-1, CONST_PERSISTENT | CONST_CS);
2150 #ifndef PHP_WIN32
2151 REGISTER_MAIN_STRINGL_CONSTANT("PHP_MANDIR", PHP_MANDIR, sizeof(PHP_MANDIR)-1, CONST_PERSISTENT | CONST_CS);
2152 #endif
2153 REGISTER_MAIN_STRINGL_CONSTANT("PHP_LIBDIR", PHP_LIBDIR, sizeof(PHP_LIBDIR)-1, CONST_PERSISTENT | CONST_CS);
2154 REGISTER_MAIN_STRINGL_CONSTANT("PHP_DATADIR", PHP_DATADIR, sizeof(PHP_DATADIR)-1, CONST_PERSISTENT | CONST_CS);
2155 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SYSCONFDIR", PHP_SYSCONFDIR, sizeof(PHP_SYSCONFDIR)-1, CONST_PERSISTENT | CONST_CS);
2156 REGISTER_MAIN_STRINGL_CONSTANT("PHP_LOCALSTATEDIR", PHP_LOCALSTATEDIR, sizeof(PHP_LOCALSTATEDIR)-1, CONST_PERSISTENT | CONST_CS);
2157 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, strlen(PHP_CONFIG_FILE_PATH), CONST_PERSISTENT | CONST_CS);
2158 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
2159 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
2160 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
2161 REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
2162 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", ZEND_LONG_MAX, CONST_PERSISTENT | CONST_CS);
2163 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MIN", ZEND_LONG_MIN, CONST_PERSISTENT | CONST_CS);
2164 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", SIZEOF_ZEND_LONG, CONST_PERSISTENT | CONST_CS);
2165 REGISTER_MAIN_LONG_CONSTANT("PHP_FD_SETSIZE", FD_SETSIZE, CONST_PERSISTENT | CONST_CS);
2166 REGISTER_MAIN_LONG_CONSTANT("PHP_FLOAT_DIG", DBL_DIG, CONST_PERSISTENT | CONST_CS);
2167 REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_EPSILON", DBL_EPSILON, CONST_PERSISTENT | CONST_CS);
2168 REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_MAX", DBL_MAX, CONST_PERSISTENT | CONST_CS);
2169 REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_MIN", DBL_MIN, CONST_PERSISTENT | CONST_CS);
2170
2171 #ifdef PHP_WIN32
2172 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MAJOR", EG(windows_version_info).dwMajorVersion, CONST_PERSISTENT | CONST_CS);
2173 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MINOR", EG(windows_version_info).dwMinorVersion, CONST_PERSISTENT | CONST_CS);
2174 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_BUILD", EG(windows_version_info).dwBuildNumber, CONST_PERSISTENT | CONST_CS);
2175 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PLATFORM", EG(windows_version_info).dwPlatformId, CONST_PERSISTENT | CONST_CS);
2176 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MAJOR", EG(windows_version_info).wServicePackMajor, CONST_PERSISTENT | CONST_CS);
2177 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MINOR", EG(windows_version_info).wServicePackMinor, CONST_PERSISTENT | CONST_CS);
2178 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SUITEMASK", EG(windows_version_info).wSuiteMask, CONST_PERSISTENT | CONST_CS);
2179 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PRODUCTTYPE", EG(windows_version_info).wProductType, CONST_PERSISTENT | CONST_CS);
2180 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_DOMAIN_CONTROLLER", VER_NT_DOMAIN_CONTROLLER, CONST_PERSISTENT | CONST_CS);
2181 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_SERVER", VER_NT_SERVER, CONST_PERSISTENT | CONST_CS);
2182 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_WORKSTATION", VER_NT_WORKSTATION, CONST_PERSISTENT | CONST_CS);
2183 #endif
2184
2185 php_binary_init();
2186 if (PG(php_binary)) {
2187 REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", PG(php_binary), strlen(PG(php_binary)), CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2188 } else {
2189 REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2190 }
2191
2192 php_output_register_constants();
2193 php_rfc1867_register_constants();
2194
2195 /* this will read in php.ini, set up the configuration parameters,
2196 load zend extensions and register php function extensions
2197 to be loaded later */
2198 if (php_init_config() == FAILURE) {
2199 return FAILURE;
2200 }
2201
2202 /* Register PHP core ini entries */
2203 REGISTER_INI_ENTRIES();
2204
2205 /* Register Zend ini entries */
2206 zend_register_standard_ini_entries();
2207
2208 #ifdef ZEND_WIN32
2209 /* Until the current ini values was setup, the current cp is 65001.
2210 If the actual ini values are different, some stuff needs to be updated.
2211 It concerns at least main_cwd_state and there might be more. As we're
2212 still in the startup phase, lets use the chance and reinit the relevant
2213 item according to the current codepage. Still, if ini_set() is used
2214 later on, a more intelligent way to update such stuff is needed.
2215 Startup/shutdown routines could involve touching globals and thus
2216 can't always be used on demand. */
2217 if (!php_win32_cp_use_unicode()) {
2218 virtual_cwd_main_cwd_init(1);
2219 }
2220 #endif
2221
2222 /* Disable realpath cache if an open_basedir is set */
2223 if (PG(open_basedir) && *PG(open_basedir)) {
2224 CWDG(realpath_cache_size_limit) = 0;
2225 }
2226
2227 PG(have_called_openlog) = 0;
2228
2229 /* initialize stream wrappers registry
2230 * (this uses configuration parameters from php.ini)
2231 */
2232 if (php_init_stream_wrappers(module_number) == FAILURE) {
2233 php_printf("PHP: Unable to initialize stream url wrappers.\n");
2234 return FAILURE;
2235 }
2236
2237 zuv.html_errors = 1;
2238 php_startup_auto_globals();
2239 zend_set_utility_values(&zuv);
2240 php_startup_sapi_content_types();
2241
2242 /* Begin to fingerprint the process state */
2243 zend_startup_system_id();
2244
2245 /* startup extensions statically compiled in */
2246 if (php_register_internal_extensions_func() == FAILURE) {
2247 php_printf("Unable to start builtin modules\n");
2248 return FAILURE;
2249 }
2250
2251 /* start additional PHP extensions */
2252 php_register_extensions_bc(additional_modules, num_additional_modules);
2253
2254 /* load and startup extensions compiled as shared objects (aka DLLs)
2255 as requested by php.ini entries
2256 these are loaded after initialization of internal extensions
2257 as extensions *might* rely on things from ext/standard
2258 which is always an internal extension and to be initialized
2259 ahead of all other internals
2260 */
2261 php_ini_register_extensions();
2262 zend_startup_modules();
2263
2264 /* start Zend extensions */
2265 zend_startup_extensions();
2266
2267 zend_collect_module_handlers();
2268
2269 /* register additional functions */
2270 if (sapi_module.additional_functions) {
2271 if ((module = zend_hash_str_find_ptr(&module_registry, "standard", sizeof("standard")-1)) != NULL) {
2272 EG(current_module) = module;
2273 zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT);
2274 EG(current_module) = NULL;
2275 }
2276 }
2277
2278 /* disable certain classes and functions as requested by php.ini */
2279 zend_disable_functions(INI_STR("disable_functions"));
2280 php_disable_classes();
2281
2282 /* make core report what it should */
2283 if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) {
2284 module->version = PHP_VERSION;
2285 module->info_func = PHP_MINFO(php_core);
2286 }
2287
2288 /* freeze the list of observer fcall_init handlers */
2289 zend_observer_post_startup();
2290
2291 /* Extensions that add engine hooks after this point do so at their own peril */
2292 zend_finalize_system_id();
2293
2294 module_initialized = 1;
2295
2296 if (zend_post_startup() != SUCCESS) {
2297 return FAILURE;
2298 }
2299
2300 /* Check for deprecated directives */
2301 /* NOTE: If you add anything here, remember to add it to build/Makefile.global! */
2302 {
2303 struct {
2304 const long error_level;
2305 const char *phrase;
2306 const char *directives[18]; /* Remember to change this if the number of directives change */
2307 } directives[2] = {
2308 {
2309 E_DEPRECATED,
2310 "Directive '%s' is deprecated",
2311 {
2312 "allow_url_include",
2313 NULL
2314 }
2315 },
2316 {
2317 E_CORE_ERROR,
2318 "Directive '%s' is no longer available in PHP",
2319 {
2320 "allow_call_time_pass_reference",
2321 "asp_tags",
2322 "define_syslog_variables",
2323 "highlight.bg",
2324 "magic_quotes_gpc",
2325 "magic_quotes_runtime",
2326 "magic_quotes_sybase",
2327 "register_globals",
2328 "register_long_arrays",
2329 "safe_mode",
2330 "safe_mode_gid",
2331 "safe_mode_include_dir",
2332 "safe_mode_exec_dir",
2333 "safe_mode_allowed_env_vars",
2334 "safe_mode_protected_env_vars",
2335 "zend.ze1_compatibility_mode",
2336 "track_errors",
2337 NULL
2338 }
2339 }
2340 };
2341
2342 unsigned int i;
2343
2344 zend_try {
2345 /* 2 = Count of deprecation structs */
2346 for (i = 0; i < 2; i++) {
2347 const char **p = directives[i].directives;
2348
2349 while(*p) {
2350 zend_long value;
2351
2352 if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
2353 zend_error(directives[i].error_level, directives[i].phrase, *p);
2354 }
2355
2356 ++p;
2357 }
2358 }
2359 } zend_catch {
2360 retval = FAILURE;
2361 } zend_end_try();
2362 }
2363
2364 virtual_cwd_deactivate();
2365
2366 sapi_deactivate();
2367 module_startup = 0;
2368
2369 /* Don't leak errors from startup into the per-request phase. */
2370 clear_last_error();
2371 shutdown_memory_manager(1, 0);
2372 virtual_cwd_activate();
2373
2374 zend_interned_strings_switch_storage(1);
2375
2376 #if ZEND_RC_DEBUG
2377 zend_rc_debug = 1;
2378 #endif
2379
2380 /* we're done */
2381 return retval;
2382 }
2383 /* }}} */
2384
2385 /* {{{ php_module_shutdown_wrapper */
php_module_shutdown_wrapper(sapi_module_struct * sapi_globals)2386 int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
2387 {
2388 php_module_shutdown();
2389 return SUCCESS;
2390 }
2391 /* }}} */
2392
2393 /* {{{ php_module_shutdown */
php_module_shutdown(void)2394 void php_module_shutdown(void)
2395 {
2396 int module_number=0; /* for UNREGISTER_INI_ENTRIES() */
2397
2398 module_shutdown = 1;
2399
2400 if (!module_initialized) {
2401 return;
2402 }
2403
2404 zend_interned_strings_switch_storage(0);
2405
2406 #if ZEND_RC_DEBUG
2407 zend_rc_debug = 0;
2408 #endif
2409
2410 #ifdef PHP_WIN32
2411 (void)php_win32_shutdown_random_bytes();
2412 php_win32_signal_ctrl_handler_shutdown();
2413 #endif
2414
2415 sapi_flush();
2416
2417 zend_shutdown();
2418
2419 #ifdef PHP_WIN32
2420 /*close winsock */
2421 WSACleanup();
2422 #endif
2423
2424 /* Destroys filter & transport registries too */
2425 php_shutdown_stream_wrappers(module_number);
2426
2427 UNREGISTER_INI_ENTRIES();
2428
2429 /* close down the ini config */
2430 php_shutdown_config();
2431 clear_last_error();
2432
2433 #ifndef ZTS
2434 zend_ini_shutdown();
2435 shutdown_memory_manager(CG(unclean_shutdown), 1);
2436 #else
2437 zend_ini_global_shutdown();
2438 #endif
2439
2440 php_output_shutdown();
2441
2442 #ifndef ZTS
2443 zend_interned_strings_dtor();
2444 #endif
2445
2446 if (zend_post_shutdown_cb) {
2447 void (*cb)(void) = zend_post_shutdown_cb;
2448
2449 zend_post_shutdown_cb = NULL;
2450 cb();
2451 }
2452
2453 module_initialized = 0;
2454
2455 #ifndef ZTS
2456 core_globals_dtor(&core_globals);
2457 gc_globals_dtor();
2458 #else
2459 ts_free_id(core_globals_id);
2460 #endif
2461
2462 #ifdef PHP_WIN32
2463 if (old_invalid_parameter_handler == NULL) {
2464 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2465 }
2466 #endif
2467
2468 zend_observer_shutdown();
2469 }
2470 /* }}} */
2471
2472 /* {{{ php_execute_script */
php_execute_script(zend_file_handle * primary_file)2473 PHPAPI int php_execute_script(zend_file_handle *primary_file)
2474 {
2475 zend_file_handle *prepend_file_p, *append_file_p;
2476 zend_file_handle prepend_file, append_file;
2477 #ifdef HAVE_BROKEN_GETCWD
2478 volatile int old_cwd_fd = -1;
2479 #else
2480 char *old_cwd;
2481 ALLOCA_FLAG(use_heap)
2482 #endif
2483 int retval = 0;
2484
2485 #ifndef HAVE_BROKEN_GETCWD
2486 # define OLD_CWD_SIZE 4096
2487 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2488 old_cwd[0] = '\0';
2489 #endif
2490
2491 zend_try {
2492 char realfile[MAXPATHLEN];
2493
2494 #ifdef PHP_WIN32
2495 if(primary_file->filename) {
2496 UpdateIniFromRegistry((char*)primary_file->filename);
2497 }
2498 #endif
2499
2500 PG(during_request_startup) = 0;
2501
2502 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2503 #ifdef HAVE_BROKEN_GETCWD
2504 /* this looks nasty to me */
2505 old_cwd_fd = open(".", 0);
2506 #else
2507 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2508 #endif
2509 VCWD_CHDIR_FILE(primary_file->filename);
2510 }
2511
2512 /* Only lookup the real file path and add it to the included_files list if already opened
2513 * otherwise it will get opened and added to the included_files list in zend_execute_scripts
2514 */
2515 if (primary_file->filename &&
2516 strcmp("Standard input code", primary_file->filename) &&
2517 primary_file->opened_path == NULL &&
2518 primary_file->type != ZEND_HANDLE_FILENAME
2519 ) {
2520 if (expand_filepath(primary_file->filename, realfile)) {
2521 primary_file->opened_path = zend_string_init(realfile, strlen(realfile), 0);
2522 zend_hash_add_empty_element(&EG(included_files), primary_file->opened_path);
2523 }
2524 }
2525
2526 if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
2527 zend_stream_init_filename(&prepend_file, PG(auto_prepend_file));
2528 prepend_file_p = &prepend_file;
2529 } else {
2530 prepend_file_p = NULL;
2531 }
2532
2533 if (PG(auto_append_file) && PG(auto_append_file)[0]) {
2534 zend_stream_init_filename(&append_file, PG(auto_append_file));
2535 append_file_p = &append_file;
2536 } else {
2537 append_file_p = NULL;
2538 }
2539 if (PG(max_input_time) != -1) {
2540 #ifdef PHP_WIN32
2541 zend_unset_timeout();
2542 #endif
2543 zend_set_timeout(INI_INT("max_execution_time"), 0);
2544 }
2545
2546 retval = (zend_execute_scripts(ZEND_REQUIRE, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS);
2547 } zend_end_try();
2548
2549 if (EG(exception)) {
2550 zend_try {
2551 zend_exception_error(EG(exception), E_ERROR);
2552 } zend_end_try();
2553 }
2554
2555 #ifdef HAVE_BROKEN_GETCWD
2556 if (old_cwd_fd != -1) {
2557 fchdir(old_cwd_fd);
2558 close(old_cwd_fd);
2559 }
2560 #else
2561 if (old_cwd[0] != '\0') {
2562 php_ignore_value(VCWD_CHDIR(old_cwd));
2563 }
2564 free_alloca(old_cwd, use_heap);
2565 #endif
2566 return retval;
2567 }
2568 /* }}} */
2569
2570 /* {{{ php_execute_simple_script */
php_execute_simple_script(zend_file_handle * primary_file,zval * ret)2571 PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret)
2572 {
2573 char *old_cwd;
2574 ALLOCA_FLAG(use_heap)
2575
2576 EG(exit_status) = 0;
2577 #define OLD_CWD_SIZE 4096
2578 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2579 old_cwd[0] = '\0';
2580
2581 zend_try {
2582 #ifdef PHP_WIN32
2583 if(primary_file->filename) {
2584 UpdateIniFromRegistry((char*)primary_file->filename);
2585 }
2586 #endif
2587
2588 PG(during_request_startup) = 0;
2589
2590 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2591 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2592 VCWD_CHDIR_FILE(primary_file->filename);
2593 }
2594 zend_execute_scripts(ZEND_REQUIRE, ret, 1, primary_file);
2595 } zend_end_try();
2596
2597 if (old_cwd[0] != '\0') {
2598 php_ignore_value(VCWD_CHDIR(old_cwd));
2599 }
2600
2601 free_alloca(old_cwd, use_heap);
2602 return EG(exit_status);
2603 }
2604 /* }}} */
2605
2606 /* {{{ php_handle_aborted_connection */
php_handle_aborted_connection(void)2607 PHPAPI void php_handle_aborted_connection(void)
2608 {
2609
2610 PG(connection_status) = PHP_CONNECTION_ABORTED;
2611 php_output_set_status(PHP_OUTPUT_DISABLED);
2612
2613 if (!PG(ignore_user_abort)) {
2614 zend_bailout();
2615 }
2616 }
2617 /* }}} */
2618
2619 /* {{{ php_handle_auth_data */
php_handle_auth_data(const char * auth)2620 PHPAPI int php_handle_auth_data(const char *auth)
2621 {
2622 int ret = -1;
2623 size_t auth_len = auth != NULL ? strlen(auth) : 0;
2624
2625 if (auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Basic ", sizeof("Basic ")-1, sizeof("Basic ")-1) == 0) {
2626 char *pass;
2627 zend_string *user;
2628
2629 user = php_base64_decode((const unsigned char*)auth + 6, auth_len - 6);
2630 if (user) {
2631 pass = strchr(ZSTR_VAL(user), ':');
2632 if (pass) {
2633 *pass++ = '\0';
2634 SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
2635 SG(request_info).auth_password = estrdup(pass);
2636 ret = 0;
2637 }
2638 zend_string_free(user);
2639 }
2640 }
2641
2642 if (ret == -1) {
2643 SG(request_info).auth_user = SG(request_info).auth_password = NULL;
2644 } else {
2645 SG(request_info).auth_digest = NULL;
2646 }
2647
2648 if (ret == -1 && auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Digest ", sizeof("Digest ")-1, sizeof("Digest ")-1) == 0) {
2649 SG(request_info).auth_digest = estrdup(auth + 7);
2650 ret = 0;
2651 }
2652
2653 if (ret == -1) {
2654 SG(request_info).auth_digest = NULL;
2655 }
2656
2657 return ret;
2658 }
2659 /* }}} */
2660
2661 /* {{{ php_lint_script */
php_lint_script(zend_file_handle * file)2662 PHPAPI int php_lint_script(zend_file_handle *file)
2663 {
2664 zend_op_array *op_array;
2665 int retval = FAILURE;
2666
2667 zend_try {
2668 op_array = zend_compile_file(file, ZEND_INCLUDE);
2669 zend_destroy_file_handle(file);
2670
2671 if (op_array) {
2672 destroy_op_array(op_array);
2673 efree(op_array);
2674 retval = SUCCESS;
2675 }
2676 } zend_end_try();
2677 if (EG(exception)) {
2678 zend_exception_error(EG(exception), E_ERROR);
2679 }
2680
2681 return retval;
2682 }
2683 /* }}} */
2684
2685 #ifdef ZTS
2686 /* {{{ php_reserve_tsrm_memory */
php_reserve_tsrm_memory(void)2687 PHPAPI void php_reserve_tsrm_memory(void)
2688 {
2689 tsrm_reserve(
2690 TSRM_ALIGNED_SIZE(sizeof(zend_compiler_globals)) +
2691 TSRM_ALIGNED_SIZE(sizeof(zend_executor_globals)) +
2692 TSRM_ALIGNED_SIZE(sizeof(zend_php_scanner_globals)) +
2693 TSRM_ALIGNED_SIZE(sizeof(zend_ini_scanner_globals)) +
2694 TSRM_ALIGNED_SIZE(sizeof(virtual_cwd_globals)) +
2695 #ifdef ZEND_SIGNALS
2696 TSRM_ALIGNED_SIZE(sizeof(zend_signal_globals_t)) +
2697 #endif
2698 TSRM_ALIGNED_SIZE(zend_mm_globals_size()) +
2699 TSRM_ALIGNED_SIZE(zend_gc_globals_size()) +
2700 TSRM_ALIGNED_SIZE(sizeof(php_core_globals)) +
2701 TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct))
2702 );
2703 }
2704 /* }}} */
2705
2706 /* {{{ php_tsrm_startup */
php_tsrm_startup(void)2707 PHPAPI int php_tsrm_startup(void)
2708 {
2709 int ret = tsrm_startup(1, 1, 0, NULL);
2710 php_reserve_tsrm_memory();
2711 (void)ts_resource(0);
2712 return ret;
2713 }
2714 /* }}} */
2715 #endif
2716