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