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 *)malloc(MAXPATHLEN);
356 if (binary_location && GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
357 free(binary_location);
358 PG(php_binary) = NULL;
359 }
360 #else
361 if (sapi_module.executable_location) {
362 binary_location = (char *)malloc(MAXPATHLEN);
363 if (binary_location && !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 free(binary_location);
387 binary_location = NULL;
388 }
389 } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
390 free(binary_location);
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
755 STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
756 STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
757 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)
758
759 STD_PHP_INI_ENTRY("realpath_cache_size", "4096K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
760 STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
761
762 STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
763 STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
764 STD_PHP_INI_ENTRY("hard_timeout", "2", PHP_INI_SYSTEM, OnUpdateLong, hard_timeout, zend_executor_globals, executor_globals)
765 #ifdef PHP_WIN32
766 STD_PHP_INI_BOOLEAN("windows.show_crt_warning", "0", PHP_INI_ALL, OnUpdateBool, windows_show_crt_warning, php_core_globals, core_globals)
767 #endif
768 STD_PHP_INI_ENTRY("syslog.facility", "LOG_USER", PHP_INI_SYSTEM, OnSetFacility, syslog_facility, php_core_globals, core_globals)
769 STD_PHP_INI_ENTRY("syslog.ident", "php", PHP_INI_SYSTEM, OnUpdateString, syslog_ident, php_core_globals, core_globals)
770 STD_PHP_INI_ENTRY("syslog.filter", "no-ctrl", PHP_INI_ALL, OnSetLogFilter, syslog_filter, php_core_globals, core_globals)
771 PHP_INI_END()
772 /* }}} */
773
774 /* True globals (no need for thread safety */
775 /* But don't make them a single int bitfield */
776 static int module_initialized = 0;
777 static int module_startup = 1;
778 static int module_shutdown = 0;
779
780 /* {{{ php_during_module_startup */
php_during_module_startup(void)781 PHPAPI int php_during_module_startup(void)
782 {
783 return module_startup;
784 }
785 /* }}} */
786
787 /* {{{ php_during_module_shutdown */
php_during_module_shutdown(void)788 PHPAPI int php_during_module_shutdown(void)
789 {
790 return module_shutdown;
791 }
792 /* }}} */
793
794 /* {{{ php_get_module_initialized */
php_get_module_initialized(void)795 PHPAPI int php_get_module_initialized(void)
796 {
797 return module_initialized;
798 }
799 /* }}} */
800
801 /* {{{ php_log_err_with_severity */
php_log_err_with_severity(const char * log_message,int syslog_type_int)802 PHPAPI ZEND_COLD void php_log_err_with_severity(const char *log_message, int syslog_type_int)
803 {
804 int fd = -1;
805 time_t error_time;
806
807 if (PG(in_error_log)) {
808 /* prevent recursive invocation */
809 return;
810 }
811 PG(in_error_log) = 1;
812
813 /* Try to use the specified logging location. */
814 if (PG(error_log) != NULL) {
815 #ifdef HAVE_SYSLOG_H
816 if (!strcmp(PG(error_log), "syslog")) {
817 php_syslog(syslog_type_int, "%s", log_message);
818 PG(in_error_log) = 0;
819 return;
820 }
821 #endif
822 fd = VCWD_OPEN_MODE(PG(error_log), O_CREAT | O_APPEND | O_WRONLY, 0644);
823 if (fd != -1) {
824 char *tmp;
825 size_t len;
826 zend_string *error_time_str;
827
828 time(&error_time);
829 #ifdef ZTS
830 if (!php_during_module_startup()) {
831 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
832 } else {
833 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 0);
834 }
835 #else
836 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
837 #endif
838 len = spprintf(&tmp, 0, "[%s] %s%s", ZSTR_VAL(error_time_str), log_message, PHP_EOL);
839 #ifdef PHP_WIN32
840 php_flock(fd, 2);
841 /* XXX should eventually write in a loop if len > UINT_MAX */
842 php_ignore_value(write(fd, tmp, (unsigned)len));
843 #else
844 php_ignore_value(write(fd, tmp, len));
845 #endif
846 efree(tmp);
847 zend_string_free(error_time_str);
848 close(fd);
849 PG(in_error_log) = 0;
850 return;
851 }
852 }
853
854 /* Otherwise fall back to the default logging location, if we have one */
855
856 if (sapi_module.log_message) {
857 sapi_module.log_message(log_message, syslog_type_int);
858 }
859 PG(in_error_log) = 0;
860 }
861 /* }}} */
862
863 /* {{{ php_write
864 wrapper for modules to use PHPWRITE */
php_write(void * buf,size_t size)865 PHPAPI size_t php_write(void *buf, size_t size)
866 {
867 return PHPWRITE(buf, size);
868 }
869 /* }}} */
870
871 /* {{{ php_printf */
php_printf(const char * format,...)872 PHPAPI size_t php_printf(const char *format, ...)
873 {
874 va_list args;
875 size_t ret;
876 char *buffer;
877 size_t size;
878
879 va_start(args, format);
880 size = vspprintf(&buffer, 0, format, args);
881 ret = PHPWRITE(buffer, size);
882 efree(buffer);
883 va_end(args);
884
885 return ret;
886 }
887 /* }}} */
888
889 /* {{{ php_printf_unchecked */
php_printf_unchecked(const char * format,...)890 PHPAPI size_t php_printf_unchecked(const char *format, ...)
891 {
892 va_list args;
893 size_t ret;
894 char *buffer;
895 size_t size;
896
897 va_start(args, format);
898 size = vspprintf(&buffer, 0, format, args);
899 ret = PHPWRITE(buffer, size);
900 efree(buffer);
901 va_end(args);
902
903 return ret;
904 }
905 /* }}} */
906
escape_html(const char * buffer,size_t buffer_len)907 static zend_string *escape_html(const char *buffer, size_t buffer_len) {
908 zend_string *result = php_escape_html_entities_ex(
909 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT,
910 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
911 if (!result || ZSTR_LEN(result) == 0) {
912 /* Retry with substituting invalid chars on fail. */
913 result = php_escape_html_entities_ex(
914 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT | ENT_HTML_SUBSTITUTE_ERRORS,
915 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
916 }
917 return result;
918 }
919
920 /* {{{ php_verror */
921 /* php_verror is called from php_error_docref<n> functions.
922 * Its purpose is to unify error messages and automatically generate clickable
923 * html error messages if corresponding ini setting (html_errors) is activated.
924 * See: CODING_STANDARDS.md for details.
925 */
php_verror(const char * docref,const char * params,int type,const char * format,va_list args)926 PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args)
927 {
928 zend_string *replace_buffer = NULL, *replace_origin = NULL;
929 char *buffer = NULL, *docref_buf = NULL, *target = NULL;
930 char *docref_target = "", *docref_root = "";
931 char *p;
932 int buffer_len = 0;
933 const char *space = "";
934 const char *class_name = "";
935 const char *function;
936 int origin_len;
937 char *origin;
938 zend_string *message;
939 int is_function = 0;
940
941 /* get error text into buffer and escape for html if necessary */
942 buffer_len = (int)vspprintf(&buffer, 0, format, args);
943
944 if (PG(html_errors)) {
945 replace_buffer = escape_html(buffer, buffer_len);
946 efree(buffer);
947
948 if (replace_buffer) {
949 buffer = ZSTR_VAL(replace_buffer);
950 buffer_len = (int)ZSTR_LEN(replace_buffer);
951 } else {
952 buffer = "";
953 buffer_len = 0;
954 }
955 }
956
957 /* which function caused the problem if any at all */
958 if (php_during_module_startup()) {
959 function = "PHP Startup";
960 } else if (php_during_module_shutdown()) {
961 function = "PHP Shutdown";
962 } else if (EG(current_execute_data) &&
963 EG(current_execute_data)->func &&
964 ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
965 EG(current_execute_data)->opline &&
966 EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL
967 ) {
968 switch (EG(current_execute_data)->opline->extended_value) {
969 case ZEND_EVAL:
970 function = "eval";
971 is_function = 1;
972 break;
973 case ZEND_INCLUDE:
974 function = "include";
975 is_function = 1;
976 break;
977 case ZEND_INCLUDE_ONCE:
978 function = "include_once";
979 is_function = 1;
980 break;
981 case ZEND_REQUIRE:
982 function = "require";
983 is_function = 1;
984 break;
985 case ZEND_REQUIRE_ONCE:
986 function = "require_once";
987 is_function = 1;
988 break;
989 default:
990 function = "Unknown";
991 }
992 } else {
993 function = get_active_function_name();
994 if (!function || !strlen(function)) {
995 function = "Unknown";
996 } else {
997 is_function = 1;
998 class_name = get_active_class_name(&space);
999 }
1000 }
1001
1002 /* if we still have memory then format the origin */
1003 if (is_function) {
1004 origin_len = (int)spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params);
1005 } else {
1006 origin_len = (int)spprintf(&origin, 0, "%s", function);
1007 }
1008
1009 if (PG(html_errors)) {
1010 replace_origin = escape_html(origin, origin_len);
1011 efree(origin);
1012 origin = ZSTR_VAL(replace_origin);
1013 }
1014
1015 /* origin and buffer available, so lets come up with the error message */
1016 if (docref && docref[0] == '#') {
1017 docref_target = strchr(docref, '#');
1018 docref = NULL;
1019 }
1020
1021 /* no docref given but function is known (the default) */
1022 if (!docref && is_function) {
1023 int doclen;
1024 while (*function == '_') {
1025 function++;
1026 }
1027 if (space[0] == '\0') {
1028 doclen = (int)spprintf(&docref_buf, 0, "function.%s", function);
1029 } else {
1030 doclen = (int)spprintf(&docref_buf, 0, "%s.%s", class_name, function);
1031 }
1032 while((p = strchr(docref_buf, '_')) != NULL) {
1033 *p = '-';
1034 }
1035 docref = php_strtolower(docref_buf, doclen);
1036 }
1037
1038 /* we have a docref for a function AND
1039 * - we show errors in html mode AND
1040 * - the user wants to see the links
1041 */
1042 if (docref && is_function && PG(html_errors) && strlen(PG(docref_root))) {
1043 if (strncmp(docref, "http://", 7)) {
1044 /* We don't have 'http://' so we use docref_root */
1045
1046 char *ref; /* temp copy for duplicated docref */
1047
1048 docref_root = PG(docref_root);
1049
1050 ref = estrdup(docref);
1051 if (docref_buf) {
1052 efree(docref_buf);
1053 }
1054 docref_buf = ref;
1055 /* strip of the target if any */
1056 p = strrchr(ref, '#');
1057 if (p) {
1058 target = estrdup(p);
1059 if (target) {
1060 docref_target = target;
1061 *p = '\0';
1062 }
1063 }
1064 /* add the extension if it is set in ini */
1065 if (PG(docref_ext) && strlen(PG(docref_ext))) {
1066 spprintf(&docref_buf, 0, "%s%s", ref, PG(docref_ext));
1067 efree(ref);
1068 }
1069 docref = docref_buf;
1070 }
1071 /* display html formatted or only show the additional links */
1072 if (PG(html_errors)) {
1073 message = zend_strpprintf(0, "%s [<a href='%s%s%s'>%s</a>]: %s", origin, docref_root, docref, docref_target, docref, buffer);
1074 } else {
1075 message = zend_strpprintf(0, "%s [%s%s%s]: %s", origin, docref_root, docref, docref_target, buffer);
1076 }
1077 if (target) {
1078 efree(target);
1079 }
1080 } else {
1081 message = zend_strpprintf(0, "%s: %s", origin, buffer);
1082 }
1083 if (replace_origin) {
1084 zend_string_free(replace_origin);
1085 } else {
1086 efree(origin);
1087 }
1088 if (docref_buf) {
1089 efree(docref_buf);
1090 }
1091
1092 if (replace_buffer) {
1093 zend_string_free(replace_buffer);
1094 } else {
1095 efree(buffer);
1096 }
1097
1098 zend_error_zstr(type, message);
1099 zend_string_release(message);
1100 }
1101 /* }}} */
1102
1103 /* {{{ php_error_docref */
1104 /* 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,...)1105 PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...)
1106 {
1107 va_list args;
1108
1109 va_start(args, format);
1110 php_verror(docref, "", type, format, args);
1111 va_end(args);
1112 }
1113 /* }}} */
1114
1115 /* {{{ php_error_docref1 */
1116 /* See: CODING_STANDARDS.md for details. */
php_error_docref1(const char * docref,const char * param1,int type,const char * format,...)1117 PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...)
1118 {
1119 va_list args;
1120
1121 va_start(args, format);
1122 php_verror(docref, param1, type, format, args);
1123 va_end(args);
1124 }
1125 /* }}} */
1126
1127 /* {{{ php_error_docref2 */
1128 /* See: CODING_STANDARDS.md for details. */
php_error_docref2(const char * docref,const char * param1,const char * param2,int type,const char * format,...)1129 PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)
1130 {
1131 char *params;
1132 va_list args;
1133
1134 spprintf(¶ms, 0, "%s,%s", param1, param2);
1135 va_start(args, format);
1136 php_verror(docref, params ? params : "...", type, format, args);
1137 va_end(args);
1138 if (params) {
1139 efree(params);
1140 }
1141 }
1142 /* }}} */
1143
1144 #ifdef PHP_WIN32
php_win32_docref1_from_error(DWORD error,const char * param1)1145 PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1) {
1146 char *buf = php_win32_error_to_msg(error);
1147 size_t buf_len;
1148
1149 buf_len = strlen(buf);
1150 if (buf_len >= 2) {
1151 buf[buf_len - 1] = '\0';
1152 buf[buf_len - 2] = '\0';
1153 }
1154 php_error_docref1(NULL, param1, E_WARNING, "%s (code: %lu)", buf, error);
1155 php_win32_error_msg_free(buf);
1156 }
1157
php_win32_docref2_from_error(DWORD error,const char * param1,const char * param2)1158 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) {
1159 char *buf = php_win32_error_to_msg(error);
1160 php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", buf, error);
1161 php_win32_error_msg_free(buf);
1162 }
1163 #endif
1164
1165 /* {{{ php_html_puts */
php_html_puts(const char * str,size_t size)1166 PHPAPI void php_html_puts(const char *str, size_t size)
1167 {
1168 zend_html_puts(str, size);
1169 }
1170 /* }}} */
1171
clear_last_error()1172 static void clear_last_error() {
1173 if (PG(last_error_message)) {
1174 zend_string_release(PG(last_error_message));
1175 PG(last_error_message) = NULL;
1176 }
1177 if (PG(last_error_file)) {
1178 free(PG(last_error_file));
1179 PG(last_error_file) = NULL;
1180 }
1181 }
1182
1183 #if ZEND_DEBUG
1184 /* {{{ 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)1185 static void report_zend_debug_error_notify_cb(int type, const char *error_filename, uint32_t error_lineno, zend_string *message)
1186 {
1187 if (PG(report_zend_debug)) {
1188 zend_bool trigger_break;
1189
1190 switch (type) {
1191 case E_ERROR:
1192 case E_CORE_ERROR:
1193 case E_COMPILE_ERROR:
1194 case E_USER_ERROR:
1195 trigger_break=1;
1196 break;
1197 default:
1198 trigger_break=0;
1199 break;
1200 }
1201
1202 zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s", error_filename, error_lineno, ZSTR_VAL(message));
1203 }
1204 }
1205 /* }}} */
1206 #endif
1207
1208 /* {{{ php_error_cb
1209 extended error handling function */
php_error_cb(int orig_type,const char * error_filename,const uint32_t error_lineno,zend_string * message)1210 static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, const uint32_t error_lineno, zend_string *message)
1211 {
1212 zend_bool display;
1213 int type = orig_type & E_ALL;
1214
1215 /* check for repeated errors to be ignored */
1216 if (PG(ignore_repeated_errors) && PG(last_error_message)) {
1217 /* no check for PG(last_error_file) is needed since it cannot
1218 * be NULL if PG(last_error_message) is not NULL */
1219 if (!zend_string_equals(PG(last_error_message), message)
1220 || (!PG(ignore_repeated_source)
1221 && ((PG(last_error_lineno) != (int)error_lineno)
1222 || strcmp(PG(last_error_file), error_filename)))) {
1223 display = 1;
1224 } else {
1225 display = 0;
1226 }
1227 } else {
1228 display = 1;
1229 }
1230
1231 /* according to error handling mode, throw exception or show it */
1232 if (EG(error_handling) == EH_THROW) {
1233 switch (type) {
1234 case E_WARNING:
1235 case E_CORE_WARNING:
1236 case E_COMPILE_WARNING:
1237 case E_USER_WARNING:
1238 /* throw an exception if we are in EH_THROW mode and the type is warning.
1239 * fatal errors are real errors and cannot be made exceptions.
1240 * exclude deprecated for the sake of BC to old damaged code.
1241 * notices are no errors and are not treated as such like E_WARNINGS.
1242 * DO NOT overwrite a pending exception.
1243 */
1244 if (!EG(exception)) {
1245 zend_throw_error_exception(EG(exception_class), message, 0, type);
1246 }
1247 return;
1248 default:
1249 break;
1250 }
1251 }
1252
1253 /* store the error if it has changed */
1254 if (display) {
1255 clear_last_error();
1256 if (!error_filename) {
1257 error_filename = "Unknown";
1258 }
1259 PG(last_error_type) = type;
1260 PG(last_error_message) = zend_string_copy(message);
1261 PG(last_error_file) = strdup(error_filename);
1262 PG(last_error_lineno) = error_lineno;
1263 }
1264
1265 /* display/log the error if necessary */
1266 if (display && ((EG(error_reporting) & type) || (type & E_CORE))
1267 && (PG(log_errors) || PG(display_errors) || (!module_initialized))) {
1268 char *error_type_str;
1269 int syslog_type_int = LOG_NOTICE;
1270
1271 switch (type) {
1272 case E_ERROR:
1273 case E_CORE_ERROR:
1274 case E_COMPILE_ERROR:
1275 case E_USER_ERROR:
1276 error_type_str = "Fatal error";
1277 syslog_type_int = LOG_ERR;
1278 break;
1279 case E_RECOVERABLE_ERROR:
1280 error_type_str = "Recoverable fatal error";
1281 syslog_type_int = LOG_ERR;
1282 break;
1283 case E_WARNING:
1284 case E_CORE_WARNING:
1285 case E_COMPILE_WARNING:
1286 case E_USER_WARNING:
1287 error_type_str = "Warning";
1288 syslog_type_int = LOG_WARNING;
1289 break;
1290 case E_PARSE:
1291 error_type_str = "Parse error";
1292 syslog_type_int = LOG_ERR;
1293 break;
1294 case E_NOTICE:
1295 case E_USER_NOTICE:
1296 error_type_str = "Notice";
1297 syslog_type_int = LOG_NOTICE;
1298 break;
1299 case E_STRICT:
1300 error_type_str = "Strict Standards";
1301 syslog_type_int = LOG_INFO;
1302 break;
1303 case E_DEPRECATED:
1304 case E_USER_DEPRECATED:
1305 error_type_str = "Deprecated";
1306 syslog_type_int = LOG_INFO;
1307 break;
1308 default:
1309 error_type_str = "Unknown error";
1310 break;
1311 }
1312
1313 if (PG(log_errors)
1314 || (!module_initialized && (!PG(display_startup_errors) || !PG(display_errors)))) {
1315 char *log_buffer;
1316 #ifdef PHP_WIN32
1317 if (type == E_CORE_ERROR || type == E_CORE_WARNING) {
1318 syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, ZSTR_VAL(message), GetCommandLine());
1319 }
1320 #endif
1321 spprintf(&log_buffer, 0, "PHP %s: %s in %s on line %" PRIu32, error_type_str, ZSTR_VAL(message), error_filename, error_lineno);
1322 php_log_err_with_severity(log_buffer, syslog_type_int);
1323 efree(log_buffer);
1324 }
1325
1326 if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) {
1327 if (PG(xmlrpc_errors)) {
1328 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);
1329 } else {
1330 char *prepend_string = INI_STR("error_prepend_string");
1331 char *append_string = INI_STR("error_append_string");
1332
1333 if (PG(html_errors)) {
1334 if (type == E_ERROR || type == E_PARSE) {
1335 zend_string *buf = escape_html(ZSTR_VAL(message), ZSTR_LEN(message));
1336 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));
1337 zend_string_free(buf);
1338 } else {
1339 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));
1340 }
1341 } else {
1342 /* Write CLI/CGI errors to stderr if display_errors = "stderr" */
1343 if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
1344 PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
1345 ) {
1346 fprintf(stderr, "%s: %s in %s on line %" PRIu32 "\n", error_type_str, ZSTR_VAL(message), error_filename, error_lineno);
1347 #ifdef PHP_WIN32
1348 fflush(stderr);
1349 #endif
1350 } else {
1351 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));
1352 }
1353 }
1354 }
1355 }
1356 }
1357
1358 /* Bail out if we can't recover */
1359 switch (type) {
1360 case E_CORE_ERROR:
1361 if(!module_initialized) {
1362 /* bad error in module startup - no way we can live with this */
1363 exit(-2);
1364 }
1365 /* no break - intentionally */
1366 case E_ERROR:
1367 case E_RECOVERABLE_ERROR:
1368 case E_PARSE:
1369 case E_COMPILE_ERROR:
1370 case E_USER_ERROR:
1371 EG(exit_status) = 255;
1372 if (module_initialized) {
1373 if (!PG(display_errors) &&
1374 !SG(headers_sent) &&
1375 SG(sapi_headers).http_response_code == 200
1376 ) {
1377 sapi_header_line ctr = {0};
1378
1379 ctr.line = "HTTP/1.0 500 Internal Server Error";
1380 ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1;
1381 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
1382 }
1383 /* the parser would return 1 (failure), we can bail out nicely */
1384 if (!(orig_type & E_DONT_BAIL)) {
1385 /* restore memory limit */
1386 zend_set_memory_limit(PG(memory_limit));
1387 zend_objects_store_mark_destructed(&EG(objects_store));
1388 zend_bailout();
1389 return;
1390 }
1391 }
1392 break;
1393 }
1394 }
1395 /* }}} */
1396
1397 /* {{{ php_get_current_user */
php_get_current_user(void)1398 PHPAPI char *php_get_current_user(void)
1399 {
1400 zend_stat_t *pstat;
1401
1402 if (SG(request_info).current_user) {
1403 return SG(request_info).current_user;
1404 }
1405
1406 /* FIXME: I need to have this somehow handled if
1407 USE_SAPI is defined, because cgi will also be
1408 interfaced in USE_SAPI */
1409
1410 pstat = sapi_get_stat();
1411
1412 if (!pstat) {
1413 return "";
1414 } else {
1415 #ifdef PHP_WIN32
1416 char *name = php_win32_get_username();
1417 int len;
1418
1419 if (!name) {
1420 return "";
1421 }
1422 len = (int)strlen(name);
1423 name[len] = '\0';
1424 SG(request_info).current_user_length = len;
1425 SG(request_info).current_user = estrndup(name, len);
1426 free(name);
1427 return SG(request_info).current_user;
1428 #else
1429 struct passwd *pwd;
1430 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1431 struct passwd _pw;
1432 struct passwd *retpwptr = NULL;
1433 int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1434 char *pwbuf;
1435
1436 if (pwbuflen < 1) {
1437 return "";
1438 }
1439 pwbuf = emalloc(pwbuflen);
1440 if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
1441 efree(pwbuf);
1442 return "";
1443 }
1444 if (retpwptr == NULL) {
1445 efree(pwbuf);
1446 return "";
1447 }
1448 pwd = &_pw;
1449 #else
1450 if ((pwd=getpwuid(pstat->st_uid))==NULL) {
1451 return "";
1452 }
1453 #endif
1454 SG(request_info).current_user_length = strlen(pwd->pw_name);
1455 SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
1456 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1457 efree(pwbuf);
1458 #endif
1459 return SG(request_info).current_user;
1460 #endif
1461 }
1462 }
1463 /* }}} */
1464
1465 /* {{{ Sets the maximum time a script can run */
PHP_FUNCTION(set_time_limit)1466 PHP_FUNCTION(set_time_limit)
1467 {
1468 zend_long new_timeout;
1469 char *new_timeout_str;
1470 int new_timeout_strlen;
1471 zend_string *key;
1472
1473 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) {
1474 RETURN_THROWS();
1475 }
1476
1477 new_timeout_strlen = (int)zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout);
1478
1479 key = zend_string_init("max_execution_time", sizeof("max_execution_time")-1, 0);
1480 if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) {
1481 RETVAL_TRUE;
1482 } else {
1483 RETVAL_FALSE;
1484 }
1485 zend_string_release_ex(key, 0);
1486 efree(new_timeout_str);
1487 }
1488 /* }}} */
1489
1490 /* {{{ php_fopen_wrapper_for_zend */
php_fopen_wrapper_for_zend(const char * filename,zend_string ** opened_path)1491 static FILE *php_fopen_wrapper_for_zend(const char *filename, zend_string **opened_path)
1492 {
1493 return php_stream_open_wrapper_as_file((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE, opened_path);
1494 }
1495 /* }}} */
1496
php_zend_stream_closer(void * handle)1497 static void php_zend_stream_closer(void *handle) /* {{{ */
1498 {
1499 php_stream_close((php_stream*)handle);
1500 }
1501 /* }}} */
1502
php_zend_stream_fsizer(void * handle)1503 static size_t php_zend_stream_fsizer(void *handle) /* {{{ */
1504 {
1505 php_stream *stream = handle;
1506 php_stream_statbuf ssb;
1507
1508 /* File size reported by stat() may be inaccurate if stream filters are used.
1509 * TODO: Should stat() be generally disabled if filters are used? */
1510 if (stream->readfilters.head) {
1511 return 0;
1512 }
1513
1514 if (php_stream_stat(stream, &ssb) == 0) {
1515 return ssb.sb.st_size;
1516 }
1517 return 0;
1518 }
1519 /* }}} */
1520
php_stream_open_for_zend(const char * filename,zend_file_handle * handle)1521 static zend_result php_stream_open_for_zend(const char *filename, zend_file_handle *handle) /* {{{ */
1522 {
1523 return php_stream_open_for_zend_ex(filename, handle, USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE);
1524 }
1525 /* }}} */
1526
php_stream_open_for_zend_ex(const char * filename,zend_file_handle * handle,int mode)1527 PHPAPI zend_result php_stream_open_for_zend_ex(const char *filename, zend_file_handle *handle, int mode) /* {{{ */
1528 {
1529 zend_string *opened_path;
1530 php_stream *stream = php_stream_open_wrapper((char *)filename, "rb", mode, &opened_path);
1531 if (stream) {
1532 memset(handle, 0, sizeof(zend_file_handle));
1533 handle->type = ZEND_HANDLE_STREAM;
1534 handle->filename = (char*)filename;
1535 handle->opened_path = opened_path;
1536 handle->handle.stream.handle = stream;
1537 handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read;
1538 handle->handle.stream.fsizer = php_zend_stream_fsizer;
1539 handle->handle.stream.isatty = 0;
1540 handle->handle.stream.closer = php_zend_stream_closer;
1541 /* suppress warning if this stream is not explicitly closed */
1542 php_stream_auto_cleanup(stream);
1543 /* Disable buffering to avoid double buffering between PHP and Zend streams. */
1544 php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1545
1546 return SUCCESS;
1547 }
1548 return FAILURE;
1549 }
1550 /* }}} */
1551
php_resolve_path_for_zend(const char * filename,size_t filename_len)1552 static zend_string *php_resolve_path_for_zend(const char *filename, size_t filename_len) /* {{{ */
1553 {
1554 return php_resolve_path(filename, filename_len, PG(include_path));
1555 }
1556 /* }}} */
1557
1558 /* {{{ php_get_configuration_directive_for_zend */
php_get_configuration_directive_for_zend(zend_string * name)1559 static zval *php_get_configuration_directive_for_zend(zend_string *name)
1560 {
1561 return cfg_get_entry_ex(name);
1562 }
1563 /* }}} */
1564
1565 /* {{{ php_free_request_globals */
php_free_request_globals(void)1566 static void php_free_request_globals(void)
1567 {
1568 clear_last_error();
1569 if (PG(php_sys_temp_dir)) {
1570 efree(PG(php_sys_temp_dir));
1571 PG(php_sys_temp_dir) = NULL;
1572 }
1573 }
1574 /* }}} */
1575
1576 /* {{{ php_message_handler_for_zend */
php_message_handler_for_zend(zend_long message,const void * data)1577 static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data)
1578 {
1579 switch (message) {
1580 case ZMSG_FAILED_INCLUDE_FOPEN:
1581 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)));
1582 break;
1583 case ZMSG_FAILED_REQUIRE_FOPEN:
1584 zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path)));
1585 break;
1586 case ZMSG_FAILED_HIGHLIGHT_FOPEN:
1587 php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd((char *) data));
1588 break;
1589 case ZMSG_MEMORY_LEAK_DETECTED:
1590 case ZMSG_MEMORY_LEAK_REPEATED:
1591 #if ZEND_DEBUG
1592 if (EG(error_reporting) & E_WARNING) {
1593 char memory_leak_buf[1024];
1594
1595 if (message==ZMSG_MEMORY_LEAK_DETECTED) {
1596 zend_leak_info *t = (zend_leak_info *) data;
1597
1598 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));
1599 if (t->orig_filename) {
1600 char relay_buf[512];
1601
1602 snprintf(relay_buf, 512, "%s(%" PRIu32 ") : Actual location (location was relayed)\n", t->orig_filename, t->orig_lineno);
1603 strlcat(memory_leak_buf, relay_buf, sizeof(memory_leak_buf));
1604 }
1605 } else {
1606 unsigned long leak_count = (zend_uintptr_t) data;
1607
1608 snprintf(memory_leak_buf, 512, "Last leak repeated %lu time%s\n", leak_count, (leak_count>1?"s":""));
1609 }
1610 # if defined(PHP_WIN32)
1611 if (IsDebuggerPresent()) {
1612 OutputDebugString(memory_leak_buf);
1613 } else {
1614 fprintf(stderr, "%s", memory_leak_buf);
1615 }
1616 # else
1617 fprintf(stderr, "%s", memory_leak_buf);
1618 # endif
1619 }
1620 #endif
1621 break;
1622 case ZMSG_MEMORY_LEAKS_GRAND_TOTAL:
1623 #if ZEND_DEBUG
1624 if (EG(error_reporting) & E_WARNING) {
1625 char memory_leak_buf[512];
1626
1627 snprintf(memory_leak_buf, 512, "=== Total %d memory leaks detected ===\n", *((uint32_t *) data));
1628 # if defined(PHP_WIN32)
1629 if (IsDebuggerPresent()) {
1630 OutputDebugString(memory_leak_buf);
1631 } else {
1632 fprintf(stderr, "%s", memory_leak_buf);
1633 }
1634 # else
1635 fprintf(stderr, "%s", memory_leak_buf);
1636 # endif
1637 }
1638 #endif
1639 break;
1640 case ZMSG_LOG_SCRIPT_NAME: {
1641 struct tm *ta, tmbuf;
1642 time_t curtime;
1643 char *datetime_str, asctimebuf[52];
1644 char memory_leak_buf[4096];
1645
1646 time(&curtime);
1647 ta = php_localtime_r(&curtime, &tmbuf);
1648 datetime_str = php_asctime_r(ta, asctimebuf);
1649 if (datetime_str) {
1650 datetime_str[strlen(datetime_str)-1]=0; /* get rid of the trailing newline */
1651 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[%s] Script: '%s'\n", datetime_str, SAFE_FILENAME(SG(request_info).path_translated));
1652 } else {
1653 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[null] Script: '%s'\n", SAFE_FILENAME(SG(request_info).path_translated));
1654 }
1655 # if defined(PHP_WIN32)
1656 if (IsDebuggerPresent()) {
1657 OutputDebugString(memory_leak_buf);
1658 } else {
1659 fprintf(stderr, "%s", memory_leak_buf);
1660 }
1661 # else
1662 fprintf(stderr, "%s", memory_leak_buf);
1663 # endif
1664 }
1665 break;
1666 }
1667 }
1668 /* }}} */
1669
1670
php_on_timeout(int seconds)1671 void php_on_timeout(int seconds)
1672 {
1673 PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
1674 }
1675
1676 #if PHP_SIGCHILD
1677 /* {{{ sigchld_handler */
sigchld_handler(int apar)1678 static void sigchld_handler(int apar)
1679 {
1680 int errno_save = errno;
1681
1682 while (waitpid(-1, NULL, WNOHANG) > 0);
1683 signal(SIGCHLD, sigchld_handler);
1684
1685 errno = errno_save;
1686 }
1687 /* }}} */
1688 #endif
1689
1690 /* {{{ php_request_startup */
php_request_startup(void)1691 int php_request_startup(void)
1692 {
1693 int retval = SUCCESS;
1694
1695 zend_interned_strings_activate();
1696
1697 #ifdef HAVE_DTRACE
1698 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));
1699 #endif /* HAVE_DTRACE */
1700
1701 #ifdef PHP_WIN32
1702 # if defined(ZTS)
1703 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1704 # endif
1705 PG(com_initialized) = 0;
1706 #endif
1707
1708 #if PHP_SIGCHILD
1709 signal(SIGCHLD, sigchld_handler);
1710 #endif
1711
1712 zend_try {
1713 PG(in_error_log) = 0;
1714 PG(during_request_startup) = 1;
1715
1716 php_output_activate();
1717
1718 /* initialize global variables */
1719 PG(modules_activated) = 0;
1720 PG(header_is_being_sent) = 0;
1721 PG(connection_status) = PHP_CONNECTION_NORMAL;
1722 PG(in_user_include) = 0;
1723
1724 zend_activate();
1725 sapi_activate();
1726
1727 #ifdef ZEND_SIGNALS
1728 zend_signal_activate();
1729 #endif
1730
1731 if (PG(max_input_time) == -1) {
1732 zend_set_timeout(EG(timeout_seconds), 1);
1733 } else {
1734 zend_set_timeout(PG(max_input_time), 1);
1735 }
1736
1737 /* Disable realpath cache if an open_basedir is set */
1738 if (PG(open_basedir) && *PG(open_basedir)) {
1739 CWDG(realpath_cache_size_limit) = 0;
1740 }
1741
1742 if (PG(expose_php)) {
1743 sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
1744 }
1745
1746 if (PG(output_handler) && PG(output_handler)[0]) {
1747 zval oh;
1748
1749 ZVAL_STRING(&oh, PG(output_handler));
1750 php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1751 zval_ptr_dtor(&oh);
1752 } else if (PG(output_buffering)) {
1753 php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1754 } else if (PG(implicit_flush)) {
1755 php_output_set_implicit_flush(1);
1756 }
1757
1758 /* We turn this off in php_execute_script() */
1759 /* PG(during_request_startup) = 0; */
1760
1761 php_hash_environment();
1762 zend_activate_modules();
1763 PG(modules_activated)=1;
1764 } zend_catch {
1765 retval = FAILURE;
1766 } zend_end_try();
1767
1768 SG(sapi_started) = 1;
1769
1770 return retval;
1771 }
1772 /* }}} */
1773
1774 /* {{{ php_request_shutdown */
php_request_shutdown(void * dummy)1775 void php_request_shutdown(void *dummy)
1776 {
1777 zend_bool report_memleaks;
1778
1779 EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
1780
1781 report_memleaks = PG(report_memleaks);
1782
1783 /* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed
1784 * inside zend_executor callback functions.
1785 */
1786 EG(current_execute_data) = NULL;
1787
1788 php_deactivate_ticks();
1789
1790 /* 0. Call any open observer end handlers that are still open after a zend_bailout */
1791 if (ZEND_OBSERVER_ENABLED) {
1792 zend_observer_fcall_end_all();
1793 }
1794
1795 /* 1. Call all possible shutdown functions registered with register_shutdown_function() */
1796 if (PG(modules_activated)) {
1797 php_call_shutdown_functions();
1798 }
1799
1800 /* 2. Call all possible __destruct() functions */
1801 zend_try {
1802 zend_call_destructors();
1803 } zend_end_try();
1804
1805 /* 3. Flush all output buffers */
1806 zend_try {
1807 zend_bool send_buffer = SG(request_info).headers_only ? 0 : 1;
1808
1809 if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR &&
1810 (size_t)PG(memory_limit) < zend_memory_usage(1)
1811 ) {
1812 send_buffer = 0;
1813 }
1814
1815 if (!send_buffer) {
1816 php_output_discard_all();
1817 } else {
1818 php_output_end_all();
1819 }
1820 } zend_end_try();
1821
1822 /* 4. Reset max_execution_time (no longer executing php code after response sent) */
1823 zend_try {
1824 zend_unset_timeout();
1825 } zend_end_try();
1826
1827 /* 5. Call all extensions RSHUTDOWN functions */
1828 if (PG(modules_activated)) {
1829 zend_deactivate_modules();
1830 }
1831
1832 /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
1833 zend_try {
1834 php_output_deactivate();
1835 } zend_end_try();
1836
1837 /* 7. Free shutdown functions */
1838 if (PG(modules_activated)) {
1839 php_free_shutdown_functions();
1840 }
1841
1842 /* 8. Destroy super-globals */
1843 zend_try {
1844 int i;
1845
1846 for (i=0; i<NUM_TRACK_VARS; i++) {
1847 zval_ptr_dtor(&PG(http_globals)[i]);
1848 }
1849 } zend_end_try();
1850
1851 /* 9. Shutdown scanner/executor/compiler and restore ini entries */
1852 zend_deactivate();
1853
1854 /* 10. free request-bound globals */
1855 php_free_request_globals();
1856
1857 /* 11. Call all extensions post-RSHUTDOWN functions */
1858 zend_try {
1859 zend_post_deactivate_modules();
1860 } zend_end_try();
1861
1862 /* 12. SAPI related shutdown (free stuff) */
1863 zend_try {
1864 sapi_deactivate();
1865 } zend_end_try();
1866
1867 /* 13. free virtual CWD memory */
1868 virtual_cwd_deactivate();
1869
1870 /* 14. Destroy stream hashes */
1871 zend_try {
1872 php_shutdown_stream_hashes();
1873 } zend_end_try();
1874
1875 /* 15. Free Willy (here be crashes) */
1876 zend_interned_strings_deactivate();
1877 zend_try {
1878 shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
1879 } zend_end_try();
1880
1881 /* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed.
1882 * At this point, no memory beyond a single chunk should be in use. */
1883 zend_set_memory_limit(PG(memory_limit));
1884
1885 /* 16. Deactivate Zend signals */
1886 #ifdef ZEND_SIGNALS
1887 zend_signal_deactivate();
1888 #endif
1889
1890 #ifdef PHP_WIN32
1891 if (PG(com_initialized)) {
1892 CoUninitialize();
1893 PG(com_initialized) = 0;
1894 }
1895 #endif
1896
1897 #ifdef HAVE_DTRACE
1898 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));
1899 #endif /* HAVE_DTRACE */
1900 }
1901 /* }}} */
1902
1903 /* {{{ php_com_initialize */
php_com_initialize(void)1904 PHPAPI void php_com_initialize(void)
1905 {
1906 #ifdef PHP_WIN32
1907 if (!PG(com_initialized)) {
1908 if (CoInitialize(NULL) == S_OK) {
1909 PG(com_initialized) = 1;
1910 }
1911 }
1912 #endif
1913 }
1914 /* }}} */
1915
1916 #ifdef ZTS
1917 /* {{{ core_globals_ctor */
core_globals_ctor(php_core_globals * core_globals)1918 static void core_globals_ctor(php_core_globals *core_globals)
1919 {
1920 memset(core_globals, 0, sizeof(*core_globals));
1921 php_startup_ticks();
1922 }
1923 /* }}} */
1924 #endif
1925
1926 /* {{{ core_globals_dtor */
core_globals_dtor(php_core_globals * core_globals)1927 static void core_globals_dtor(php_core_globals *core_globals)
1928 {
1929 /* These should have been freed earlier. */
1930 ZEND_ASSERT(!core_globals->last_error_message);
1931 ZEND_ASSERT(!core_globals->last_error_file);
1932
1933 if (core_globals->disable_classes) {
1934 free(core_globals->disable_classes);
1935 }
1936 if (core_globals->php_binary) {
1937 free(core_globals->php_binary);
1938 }
1939
1940 php_shutdown_ticks();
1941 }
1942 /* }}} */
1943
PHP_MINFO_FUNCTION(php_core)1944 PHP_MINFO_FUNCTION(php_core) { /* {{{ */
1945 php_info_print_table_start();
1946 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1947 php_info_print_table_end();
1948 DISPLAY_INI_ENTRIES();
1949 }
1950 /* }}} */
1951
1952 /* {{{ php_register_extensions */
php_register_extensions(zend_module_entry * const * ptr,int count)1953 int php_register_extensions(zend_module_entry * const * ptr, int count)
1954 {
1955 zend_module_entry * const * end = ptr + count;
1956
1957 while (ptr < end) {
1958 if (*ptr) {
1959 if (zend_register_internal_module(*ptr)==NULL) {
1960 return FAILURE;
1961 }
1962 }
1963 ptr++;
1964 }
1965 return SUCCESS;
1966 }
1967
1968 /* A very long time ago php_module_startup() was refactored in a way
1969 * which broke calling it with more than one additional module.
1970 * This alternative to php_register_extensions() works around that
1971 * by walking the shallower structure.
1972 *
1973 * See algo: https://bugs.php.net/bug.php?id=63159
1974 */
php_register_extensions_bc(zend_module_entry * ptr,int count)1975 static int php_register_extensions_bc(zend_module_entry *ptr, int count)
1976 {
1977 while (count--) {
1978 if (zend_register_internal_module(ptr++) == NULL) {
1979 return FAILURE;
1980 }
1981 }
1982 return SUCCESS;
1983 }
1984 /* }}} */
1985
1986 #ifdef PHP_WIN32
1987 static _invalid_parameter_handler old_invalid_parameter_handler;
1988
dummy_invalid_parameter_handler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pEwserved)1989 void dummy_invalid_parameter_handler(
1990 const wchar_t *expression,
1991 const wchar_t *function,
1992 const wchar_t *file,
1993 unsigned int line,
1994 uintptr_t pEwserved)
1995 {
1996 static int called = 0;
1997 char buf[1024];
1998 int len;
1999
2000 if (!called) {
2001 if(PG(windows_show_crt_warning)) {
2002 called = 1;
2003 if (function) {
2004 if (file) {
2005 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws' (%ws:%u)", function, file, line);
2006 } else {
2007 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws'", function);
2008 }
2009 } else {
2010 len = _snprintf(buf, sizeof(buf)-1, "Invalid CRT parameter detected (function not known)");
2011 }
2012 zend_error(E_WARNING, "%s", buf);
2013 called = 0;
2014 }
2015 }
2016 }
2017 #endif
2018
2019 /* {{{ php_module_startup */
php_module_startup(sapi_module_struct * sf,zend_module_entry * additional_modules,uint32_t num_additional_modules)2020 int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules)
2021 {
2022 zend_utility_functions zuf;
2023 zend_utility_values zuv;
2024 int retval = SUCCESS, module_number=0; /* for REGISTER_INI_ENTRIES() */
2025 char *php_os;
2026 zend_module_entry *module;
2027
2028 #ifdef PHP_WIN32
2029 WORD wVersionRequested = MAKEWORD(2, 0);
2030 WSADATA wsaData;
2031
2032 php_os = "WINNT";
2033
2034 old_invalid_parameter_handler =
2035 _set_invalid_parameter_handler(dummy_invalid_parameter_handler);
2036 if (old_invalid_parameter_handler != NULL) {
2037 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2038 }
2039
2040 /* Disable the message box for assertions.*/
2041 _CrtSetReportMode(_CRT_ASSERT, 0);
2042 #else
2043 php_os = PHP_OS;
2044 #endif
2045
2046 #ifdef ZTS
2047 (void)ts_resource(0);
2048 #endif
2049
2050 #ifdef PHP_WIN32
2051 if (!php_win32_init_random_bytes()) {
2052 fprintf(stderr, "\ncrypt algorithm provider initialization failed\n");
2053 return FAILURE;
2054 }
2055 #endif
2056
2057 module_shutdown = 0;
2058 module_startup = 1;
2059 sapi_initialize_empty_request();
2060 sapi_activate();
2061
2062 if (module_initialized) {
2063 return SUCCESS;
2064 }
2065
2066 sapi_module = *sf;
2067
2068 php_output_startup();
2069
2070 #ifdef ZTS
2071 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);
2072 #ifdef PHP_WIN32
2073 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);
2074 #endif
2075 #else
2076 memset(&core_globals, 0, sizeof(core_globals));
2077 php_startup_ticks();
2078 #endif
2079 gc_globals_ctor();
2080
2081 zuf.error_function = php_error_cb;
2082 zuf.printf_function = php_printf;
2083 zuf.write_function = php_output_write;
2084 zuf.fopen_function = php_fopen_wrapper_for_zend;
2085 zuf.message_handler = php_message_handler_for_zend;
2086 zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
2087 zuf.ticks_function = php_run_ticks;
2088 zuf.on_timeout = php_on_timeout;
2089 zuf.stream_open_function = php_stream_open_for_zend;
2090 zuf.printf_to_smart_string_function = php_printf_to_smart_string;
2091 zuf.printf_to_smart_str_function = php_printf_to_smart_str;
2092 zuf.getenv_function = sapi_getenv;
2093 zuf.resolve_path_function = php_resolve_path_for_zend;
2094 zend_startup(&zuf);
2095 zend_update_current_locale();
2096
2097 zend_observer_startup();
2098 #if ZEND_DEBUG
2099 zend_observer_error_register(report_zend_debug_error_notify_cb);
2100 #endif
2101
2102 #if HAVE_TZSET
2103 tzset();
2104 #endif
2105
2106 #ifdef PHP_WIN32
2107 char *img_err;
2108 if (!php_win32_crt_compatible(&img_err)) {
2109 php_error(E_CORE_WARNING, img_err);
2110 efree(img_err);
2111 return FAILURE;
2112 }
2113
2114 /* start up winsock services */
2115 if (WSAStartup(wVersionRequested, &wsaData) != 0) {
2116 php_printf("\nwinsock.dll unusable. %d\n", WSAGetLastError());
2117 return FAILURE;
2118 }
2119 php_win32_signal_ctrl_handler_init();
2120 #endif
2121
2122 le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);
2123
2124 /* Register constants */
2125 REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS);
2126 REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS);
2127 REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS);
2128 REGISTER_MAIN_LONG_CONSTANT("PHP_RELEASE_VERSION", PHP_RELEASE_VERSION, CONST_PERSISTENT | CONST_CS);
2129 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, sizeof(PHP_EXTRA_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
2130 REGISTER_MAIN_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT | CONST_CS);
2131 #ifdef ZTS
2132 REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 1, CONST_PERSISTENT | CONST_CS);
2133 #else
2134 REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 0, CONST_PERSISTENT | CONST_CS);
2135 #endif
2136 REGISTER_MAIN_LONG_CONSTANT("PHP_DEBUG", PHP_DEBUG, CONST_PERSISTENT | CONST_CS);
2137 REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS", php_os, strlen(php_os), CONST_PERSISTENT | CONST_CS);
2138 REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS_FAMILY", PHP_OS_FAMILY, sizeof(PHP_OS_FAMILY)-1, CONST_PERSISTENT | CONST_CS);
2139 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SAPI", sapi_module.name, strlen(sapi_module.name), CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2140 REGISTER_MAIN_STRINGL_CONSTANT("DEFAULT_INCLUDE_PATH", PHP_INCLUDE_PATH, sizeof(PHP_INCLUDE_PATH)-1, CONST_PERSISTENT | CONST_CS);
2141 REGISTER_MAIN_STRINGL_CONSTANT("PEAR_INSTALL_DIR", PEAR_INSTALLDIR, sizeof(PEAR_INSTALLDIR)-1, CONST_PERSISTENT | CONST_CS);
2142 REGISTER_MAIN_STRINGL_CONSTANT("PEAR_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
2143 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
2144 REGISTER_MAIN_STRINGL_CONSTANT("PHP_PREFIX", PHP_PREFIX, sizeof(PHP_PREFIX)-1, CONST_PERSISTENT | CONST_CS);
2145 REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINDIR", PHP_BINDIR, sizeof(PHP_BINDIR)-1, CONST_PERSISTENT | CONST_CS);
2146 #ifndef PHP_WIN32
2147 REGISTER_MAIN_STRINGL_CONSTANT("PHP_MANDIR", PHP_MANDIR, sizeof(PHP_MANDIR)-1, CONST_PERSISTENT | CONST_CS);
2148 #endif
2149 REGISTER_MAIN_STRINGL_CONSTANT("PHP_LIBDIR", PHP_LIBDIR, sizeof(PHP_LIBDIR)-1, CONST_PERSISTENT | CONST_CS);
2150 REGISTER_MAIN_STRINGL_CONSTANT("PHP_DATADIR", PHP_DATADIR, sizeof(PHP_DATADIR)-1, CONST_PERSISTENT | CONST_CS);
2151 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SYSCONFDIR", PHP_SYSCONFDIR, sizeof(PHP_SYSCONFDIR)-1, CONST_PERSISTENT | CONST_CS);
2152 REGISTER_MAIN_STRINGL_CONSTANT("PHP_LOCALSTATEDIR", PHP_LOCALSTATEDIR, sizeof(PHP_LOCALSTATEDIR)-1, CONST_PERSISTENT | CONST_CS);
2153 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, strlen(PHP_CONFIG_FILE_PATH), CONST_PERSISTENT | CONST_CS);
2154 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);
2155 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
2156 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
2157 REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
2158 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", ZEND_LONG_MAX, CONST_PERSISTENT | CONST_CS);
2159 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MIN", ZEND_LONG_MIN, CONST_PERSISTENT | CONST_CS);
2160 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", SIZEOF_ZEND_LONG, CONST_PERSISTENT | CONST_CS);
2161 REGISTER_MAIN_LONG_CONSTANT("PHP_FD_SETSIZE", FD_SETSIZE, CONST_PERSISTENT | CONST_CS);
2162 REGISTER_MAIN_LONG_CONSTANT("PHP_FLOAT_DIG", DBL_DIG, CONST_PERSISTENT | CONST_CS);
2163 REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_EPSILON", DBL_EPSILON, CONST_PERSISTENT | CONST_CS);
2164 REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_MAX", DBL_MAX, CONST_PERSISTENT | CONST_CS);
2165 REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_MIN", DBL_MIN, CONST_PERSISTENT | CONST_CS);
2166
2167 #ifdef PHP_WIN32
2168 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MAJOR", EG(windows_version_info).dwMajorVersion, CONST_PERSISTENT | CONST_CS);
2169 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MINOR", EG(windows_version_info).dwMinorVersion, CONST_PERSISTENT | CONST_CS);
2170 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_BUILD", EG(windows_version_info).dwBuildNumber, CONST_PERSISTENT | CONST_CS);
2171 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PLATFORM", EG(windows_version_info).dwPlatformId, CONST_PERSISTENT | CONST_CS);
2172 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MAJOR", EG(windows_version_info).wServicePackMajor, CONST_PERSISTENT | CONST_CS);
2173 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MINOR", EG(windows_version_info).wServicePackMinor, CONST_PERSISTENT | CONST_CS);
2174 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SUITEMASK", EG(windows_version_info).wSuiteMask, CONST_PERSISTENT | CONST_CS);
2175 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PRODUCTTYPE", EG(windows_version_info).wProductType, CONST_PERSISTENT | CONST_CS);
2176 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_DOMAIN_CONTROLLER", VER_NT_DOMAIN_CONTROLLER, CONST_PERSISTENT | CONST_CS);
2177 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_SERVER", VER_NT_SERVER, CONST_PERSISTENT | CONST_CS);
2178 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_WORKSTATION", VER_NT_WORKSTATION, CONST_PERSISTENT | CONST_CS);
2179 #endif
2180
2181 php_binary_init();
2182 if (PG(php_binary)) {
2183 REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", PG(php_binary), strlen(PG(php_binary)), CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2184 } else {
2185 REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2186 }
2187
2188 php_output_register_constants();
2189 php_rfc1867_register_constants();
2190
2191 /* this will read in php.ini, set up the configuration parameters,
2192 load zend extensions and register php function extensions
2193 to be loaded later */
2194 if (php_init_config() == FAILURE) {
2195 return FAILURE;
2196 }
2197
2198 /* Register PHP core ini entries */
2199 REGISTER_INI_ENTRIES();
2200
2201 /* Register Zend ini entries */
2202 zend_register_standard_ini_entries();
2203
2204 #ifdef ZEND_WIN32
2205 /* Until the current ini values was setup, the current cp is 65001.
2206 If the actual ini values are different, some stuff needs to be updated.
2207 It concerns at least main_cwd_state and there might be more. As we're
2208 still in the startup phase, lets use the chance and reinit the relevant
2209 item according to the current codepage. Still, if ini_set() is used
2210 later on, a more intelligent way to update such stuff is needed.
2211 Startup/shutdown routines could involve touching globals and thus
2212 can't always be used on demand. */
2213 if (!php_win32_cp_use_unicode()) {
2214 virtual_cwd_main_cwd_init(1);
2215 }
2216 #endif
2217
2218 /* Disable realpath cache if an open_basedir is set */
2219 if (PG(open_basedir) && *PG(open_basedir)) {
2220 CWDG(realpath_cache_size_limit) = 0;
2221 }
2222
2223 PG(have_called_openlog) = 0;
2224
2225 /* initialize stream wrappers registry
2226 * (this uses configuration parameters from php.ini)
2227 */
2228 if (php_init_stream_wrappers(module_number) == FAILURE) {
2229 php_printf("PHP: Unable to initialize stream url wrappers.\n");
2230 return FAILURE;
2231 }
2232
2233 zuv.html_errors = 1;
2234 php_startup_auto_globals();
2235 zend_set_utility_values(&zuv);
2236 php_startup_sapi_content_types();
2237
2238 /* Begin to fingerprint the process state */
2239 zend_startup_system_id();
2240
2241 /* startup extensions statically compiled in */
2242 if (php_register_internal_extensions_func() == FAILURE) {
2243 php_printf("Unable to start builtin modules\n");
2244 return FAILURE;
2245 }
2246
2247 /* start additional PHP extensions */
2248 php_register_extensions_bc(additional_modules, num_additional_modules);
2249
2250 /* load and startup extensions compiled as shared objects (aka DLLs)
2251 as requested by php.ini entries
2252 these are loaded after initialization of internal extensions
2253 as extensions *might* rely on things from ext/standard
2254 which is always an internal extension and to be initialized
2255 ahead of all other internals
2256 */
2257 php_ini_register_extensions();
2258 zend_startup_modules();
2259
2260 /* start Zend extensions */
2261 zend_startup_extensions();
2262
2263 zend_collect_module_handlers();
2264
2265 /* register additional functions */
2266 if (sapi_module.additional_functions) {
2267 if ((module = zend_hash_str_find_ptr(&module_registry, "standard", sizeof("standard")-1)) != NULL) {
2268 EG(current_module) = module;
2269 zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT);
2270 EG(current_module) = NULL;
2271 }
2272 }
2273
2274 /* disable certain classes and functions as requested by php.ini */
2275 zend_disable_functions(INI_STR("disable_functions"));
2276 php_disable_classes();
2277
2278 /* make core report what it should */
2279 if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) {
2280 module->version = PHP_VERSION;
2281 module->info_func = PHP_MINFO(php_core);
2282 }
2283
2284 /* Extensions that add engine hooks after this point do so at their own peril */
2285 zend_finalize_system_id();
2286
2287 module_initialized = 1;
2288
2289 if (zend_post_startup() != SUCCESS) {
2290 return FAILURE;
2291 }
2292
2293 /* Check for deprecated directives */
2294 /* NOTE: If you add anything here, remember to add it to build/Makefile.global! */
2295 {
2296 struct {
2297 const long error_level;
2298 const char *phrase;
2299 const char *directives[18]; /* Remember to change this if the number of directives change */
2300 } directives[2] = {
2301 {
2302 E_DEPRECATED,
2303 "Directive '%s' is deprecated",
2304 {
2305 "allow_url_include",
2306 NULL
2307 }
2308 },
2309 {
2310 E_CORE_ERROR,
2311 "Directive '%s' is no longer available in PHP",
2312 {
2313 "allow_call_time_pass_reference",
2314 "asp_tags",
2315 "define_syslog_variables",
2316 "highlight.bg",
2317 "magic_quotes_gpc",
2318 "magic_quotes_runtime",
2319 "magic_quotes_sybase",
2320 "register_globals",
2321 "register_long_arrays",
2322 "safe_mode",
2323 "safe_mode_gid",
2324 "safe_mode_include_dir",
2325 "safe_mode_exec_dir",
2326 "safe_mode_allowed_env_vars",
2327 "safe_mode_protected_env_vars",
2328 "zend.ze1_compatibility_mode",
2329 "track_errors",
2330 NULL
2331 }
2332 }
2333 };
2334
2335 unsigned int i;
2336
2337 zend_try {
2338 /* 2 = Count of deprecation structs */
2339 for (i = 0; i < 2; i++) {
2340 const char **p = directives[i].directives;
2341
2342 while(*p) {
2343 zend_long value;
2344
2345 if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
2346 zend_error(directives[i].error_level, directives[i].phrase, *p);
2347 }
2348
2349 ++p;
2350 }
2351 }
2352 } zend_catch {
2353 retval = FAILURE;
2354 } zend_end_try();
2355 }
2356
2357 virtual_cwd_deactivate();
2358
2359 sapi_deactivate();
2360 module_startup = 0;
2361
2362 /* Don't leak errors from startup into the per-request phase. */
2363 clear_last_error();
2364 shutdown_memory_manager(1, 0);
2365 virtual_cwd_activate();
2366
2367 zend_interned_strings_switch_storage(1);
2368
2369 #if ZEND_RC_DEBUG
2370 zend_rc_debug = 1;
2371 #endif
2372
2373 /* we're done */
2374 return retval;
2375 }
2376 /* }}} */
2377
2378 /* {{{ php_module_shutdown_wrapper */
php_module_shutdown_wrapper(sapi_module_struct * sapi_globals)2379 int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
2380 {
2381 php_module_shutdown();
2382 return SUCCESS;
2383 }
2384 /* }}} */
2385
2386 /* {{{ php_module_shutdown */
php_module_shutdown(void)2387 void php_module_shutdown(void)
2388 {
2389 int module_number=0; /* for UNREGISTER_INI_ENTRIES() */
2390
2391 module_shutdown = 1;
2392
2393 if (!module_initialized) {
2394 return;
2395 }
2396
2397 zend_interned_strings_switch_storage(0);
2398
2399 #if ZEND_RC_DEBUG
2400 zend_rc_debug = 0;
2401 #endif
2402
2403 #ifdef PHP_WIN32
2404 (void)php_win32_shutdown_random_bytes();
2405 php_win32_signal_ctrl_handler_shutdown();
2406 #endif
2407
2408 sapi_flush();
2409
2410 zend_shutdown();
2411
2412 #ifdef PHP_WIN32
2413 /*close winsock */
2414 WSACleanup();
2415 #endif
2416
2417 /* Destroys filter & transport registries too */
2418 php_shutdown_stream_wrappers(module_number);
2419
2420 UNREGISTER_INI_ENTRIES();
2421
2422 /* close down the ini config */
2423 php_shutdown_config();
2424 clear_last_error();
2425
2426 #ifndef ZTS
2427 zend_ini_shutdown();
2428 shutdown_memory_manager(CG(unclean_shutdown), 1);
2429 #else
2430 zend_ini_global_shutdown();
2431 #endif
2432
2433 php_output_shutdown();
2434
2435 #ifndef ZTS
2436 zend_interned_strings_dtor();
2437 #endif
2438
2439 if (zend_post_shutdown_cb) {
2440 void (*cb)(void) = zend_post_shutdown_cb;
2441
2442 zend_post_shutdown_cb = NULL;
2443 cb();
2444 }
2445
2446 module_initialized = 0;
2447
2448 #ifndef ZTS
2449 core_globals_dtor(&core_globals);
2450 gc_globals_dtor();
2451 #else
2452 ts_free_id(core_globals_id);
2453 #endif
2454
2455 #ifdef PHP_WIN32
2456 if (old_invalid_parameter_handler == NULL) {
2457 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2458 }
2459 #endif
2460
2461 zend_observer_shutdown();
2462 }
2463 /* }}} */
2464
2465 /* {{{ php_execute_script */
php_execute_script(zend_file_handle * primary_file)2466 PHPAPI int php_execute_script(zend_file_handle *primary_file)
2467 {
2468 zend_file_handle *prepend_file_p, *append_file_p;
2469 zend_file_handle prepend_file, append_file;
2470 #ifdef HAVE_BROKEN_GETCWD
2471 volatile int old_cwd_fd = -1;
2472 #else
2473 char *old_cwd;
2474 ALLOCA_FLAG(use_heap)
2475 #endif
2476 int retval = 0;
2477
2478 #ifndef HAVE_BROKEN_GETCWD
2479 # define OLD_CWD_SIZE 4096
2480 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2481 old_cwd[0] = '\0';
2482 #endif
2483
2484 zend_try {
2485 char realfile[MAXPATHLEN];
2486
2487 #ifdef PHP_WIN32
2488 if(primary_file->filename) {
2489 UpdateIniFromRegistry((char*)primary_file->filename);
2490 }
2491 #endif
2492
2493 PG(during_request_startup) = 0;
2494
2495 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2496 #ifdef HAVE_BROKEN_GETCWD
2497 /* this looks nasty to me */
2498 old_cwd_fd = open(".", 0);
2499 #else
2500 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2501 #endif
2502 VCWD_CHDIR_FILE(primary_file->filename);
2503 }
2504
2505 /* Only lookup the real file path and add it to the included_files list if already opened
2506 * otherwise it will get opened and added to the included_files list in zend_execute_scripts
2507 */
2508 if (primary_file->filename &&
2509 strcmp("Standard input code", primary_file->filename) &&
2510 primary_file->opened_path == NULL &&
2511 primary_file->type != ZEND_HANDLE_FILENAME
2512 ) {
2513 if (expand_filepath(primary_file->filename, realfile)) {
2514 primary_file->opened_path = zend_string_init(realfile, strlen(realfile), 0);
2515 zend_hash_add_empty_element(&EG(included_files), primary_file->opened_path);
2516 }
2517 }
2518
2519 if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
2520 zend_stream_init_filename(&prepend_file, PG(auto_prepend_file));
2521 prepend_file_p = &prepend_file;
2522 } else {
2523 prepend_file_p = NULL;
2524 }
2525
2526 if (PG(auto_append_file) && PG(auto_append_file)[0]) {
2527 zend_stream_init_filename(&append_file, PG(auto_append_file));
2528 append_file_p = &append_file;
2529 } else {
2530 append_file_p = NULL;
2531 }
2532 if (PG(max_input_time) != -1) {
2533 #ifdef PHP_WIN32
2534 zend_unset_timeout();
2535 #endif
2536 zend_set_timeout(INI_INT("max_execution_time"), 0);
2537 }
2538
2539 retval = (zend_execute_scripts(ZEND_REQUIRE, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS);
2540 } zend_end_try();
2541
2542 if (EG(exception)) {
2543 zend_try {
2544 zend_exception_error(EG(exception), E_ERROR);
2545 } zend_end_try();
2546 }
2547
2548 #ifdef HAVE_BROKEN_GETCWD
2549 if (old_cwd_fd != -1) {
2550 fchdir(old_cwd_fd);
2551 close(old_cwd_fd);
2552 }
2553 #else
2554 if (old_cwd[0] != '\0') {
2555 php_ignore_value(VCWD_CHDIR(old_cwd));
2556 }
2557 free_alloca(old_cwd, use_heap);
2558 #endif
2559 return retval;
2560 }
2561 /* }}} */
2562
2563 /* {{{ php_execute_simple_script */
php_execute_simple_script(zend_file_handle * primary_file,zval * ret)2564 PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret)
2565 {
2566 char *old_cwd;
2567 ALLOCA_FLAG(use_heap)
2568
2569 EG(exit_status) = 0;
2570 #define OLD_CWD_SIZE 4096
2571 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2572 old_cwd[0] = '\0';
2573
2574 zend_try {
2575 #ifdef PHP_WIN32
2576 if(primary_file->filename) {
2577 UpdateIniFromRegistry((char*)primary_file->filename);
2578 }
2579 #endif
2580
2581 PG(during_request_startup) = 0;
2582
2583 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2584 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2585 VCWD_CHDIR_FILE(primary_file->filename);
2586 }
2587 zend_execute_scripts(ZEND_REQUIRE, ret, 1, primary_file);
2588 } zend_end_try();
2589
2590 if (old_cwd[0] != '\0') {
2591 php_ignore_value(VCWD_CHDIR(old_cwd));
2592 }
2593
2594 free_alloca(old_cwd, use_heap);
2595 return EG(exit_status);
2596 }
2597 /* }}} */
2598
2599 /* {{{ php_handle_aborted_connection */
php_handle_aborted_connection(void)2600 PHPAPI void php_handle_aborted_connection(void)
2601 {
2602
2603 PG(connection_status) = PHP_CONNECTION_ABORTED;
2604 php_output_set_status(PHP_OUTPUT_DISABLED);
2605
2606 if (!PG(ignore_user_abort)) {
2607 zend_bailout();
2608 }
2609 }
2610 /* }}} */
2611
2612 /* {{{ php_handle_auth_data */
php_handle_auth_data(const char * auth)2613 PHPAPI int php_handle_auth_data(const char *auth)
2614 {
2615 int ret = -1;
2616 size_t auth_len = auth != NULL ? strlen(auth) : 0;
2617
2618 if (auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Basic ", sizeof("Basic ")-1, sizeof("Basic ")-1) == 0) {
2619 char *pass;
2620 zend_string *user;
2621
2622 user = php_base64_decode((const unsigned char*)auth + 6, auth_len - 6);
2623 if (user) {
2624 pass = strchr(ZSTR_VAL(user), ':');
2625 if (pass) {
2626 *pass++ = '\0';
2627 SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
2628 SG(request_info).auth_password = estrdup(pass);
2629 ret = 0;
2630 }
2631 zend_string_free(user);
2632 }
2633 }
2634
2635 if (ret == -1) {
2636 SG(request_info).auth_user = SG(request_info).auth_password = NULL;
2637 } else {
2638 SG(request_info).auth_digest = NULL;
2639 }
2640
2641 if (ret == -1 && auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Digest ", sizeof("Digest ")-1, sizeof("Digest ")-1) == 0) {
2642 SG(request_info).auth_digest = estrdup(auth + 7);
2643 ret = 0;
2644 }
2645
2646 if (ret == -1) {
2647 SG(request_info).auth_digest = NULL;
2648 }
2649
2650 return ret;
2651 }
2652 /* }}} */
2653
2654 /* {{{ php_lint_script */
php_lint_script(zend_file_handle * file)2655 PHPAPI int php_lint_script(zend_file_handle *file)
2656 {
2657 zend_op_array *op_array;
2658 int retval = FAILURE;
2659
2660 zend_try {
2661 op_array = zend_compile_file(file, ZEND_INCLUDE);
2662 zend_destroy_file_handle(file);
2663
2664 if (op_array) {
2665 destroy_op_array(op_array);
2666 efree(op_array);
2667 retval = SUCCESS;
2668 }
2669 } zend_end_try();
2670 if (EG(exception)) {
2671 zend_exception_error(EG(exception), E_ERROR);
2672 }
2673
2674 return retval;
2675 }
2676 /* }}} */
2677
2678 #ifdef ZTS
2679 /* {{{ php_reserve_tsrm_memory */
php_reserve_tsrm_memory(void)2680 PHPAPI void php_reserve_tsrm_memory(void)
2681 {
2682 tsrm_reserve(
2683 TSRM_ALIGNED_SIZE(sizeof(zend_compiler_globals)) +
2684 TSRM_ALIGNED_SIZE(sizeof(zend_executor_globals)) +
2685 TSRM_ALIGNED_SIZE(sizeof(zend_php_scanner_globals)) +
2686 TSRM_ALIGNED_SIZE(sizeof(zend_ini_scanner_globals)) +
2687 TSRM_ALIGNED_SIZE(sizeof(virtual_cwd_globals)) +
2688 #ifdef ZEND_SIGNALS
2689 TSRM_ALIGNED_SIZE(sizeof(zend_signal_globals_t)) +
2690 #endif
2691 TSRM_ALIGNED_SIZE(zend_mm_globals_size()) +
2692 TSRM_ALIGNED_SIZE(zend_gc_globals_size()) +
2693 TSRM_ALIGNED_SIZE(sizeof(php_core_globals)) +
2694 TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct))
2695 );
2696 }
2697 /* }}} */
2698
2699 /* {{{ php_tsrm_startup */
php_tsrm_startup(void)2700 PHPAPI int php_tsrm_startup(void)
2701 {
2702 int ret = tsrm_startup(1, 1, 0, NULL);
2703 php_reserve_tsrm_memory();
2704 (void)ts_resource(0);
2705 return ret;
2706 }
2707 /* }}} */
2708 #endif
2709