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