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