1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Andi Gutmans <andi@php.net> |
14 | Zeev Suraski <zeev@php.net> |
15 +----------------------------------------------------------------------+
16 */
17
18 #include "php.h"
19 #include "php_streams.h"
20 #include "php_main.h"
21 #include "php_globals.h"
22 #include "php_variables.h"
23 #include "php_ini.h"
24 #include "php_standard.h"
25 #include "php_math.h"
26 #include "php_http.h"
27 #include "php_incomplete_class.h"
28 #include "php_getopt.h"
29 #include "ext/standard/info.h"
30 #include "ext/session/php_session.h"
31 #include "zend_exceptions.h"
32 #include "zend_operators.h"
33 #include "ext/standard/php_dns.h"
34 #include "ext/standard/php_uuencode.h"
35 #include "ext/standard/php_mt_rand.h"
36 #include "ext/standard/crc32_x86.h"
37
38 #ifdef PHP_WIN32
39 #include "win32/php_win32_globals.h"
40 #include "win32/time.h"
41 #include "win32/ioutil.h"
42 #endif
43
44 typedef struct yy_buffer_state *YY_BUFFER_STATE;
45
46 #include "zend.h"
47 #include "zend_ini_scanner.h"
48 #include "zend_language_scanner.h"
49 #include <zend_language_parser.h>
50
51 #include "zend_portability.h"
52
53 #include <stdarg.h>
54 #include <stdlib.h>
55 #include <math.h>
56 #include <time.h>
57 #include <stdio.h>
58
59 #ifndef PHP_WIN32
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #endif
63
64 #ifndef PHP_WIN32
65 # include <netdb.h>
66 #else
67 #include "win32/inet.h"
68 #endif
69
70 #if HAVE_ARPA_INET_H
71 # include <arpa/inet.h>
72 #endif
73
74 #if HAVE_UNISTD_H
75 # include <unistd.h>
76 #endif
77
78 #include <string.h>
79 #include <locale.h>
80
81 #if HAVE_SYS_MMAN_H
82 # include <sys/mman.h>
83 #endif
84
85 #if HAVE_SYS_LOADAVG_H
86 # include <sys/loadavg.h>
87 #endif
88
89 #ifdef PHP_WIN32
90 # include "win32/unistd.h"
91 #endif
92
93 #ifndef INADDR_NONE
94 #define INADDR_NONE ((zend_ulong) -1)
95 #endif
96
97 #include "zend_globals.h"
98 #include "php_globals.h"
99 #include "SAPI.h"
100 #include "php_ticks.h"
101
102 #ifdef ZTS
103 PHPAPI int basic_globals_id;
104 #else
105 PHPAPI php_basic_globals basic_globals;
106 #endif
107
108 #include "php_fopen_wrappers.h"
109 #include "streamsfuncs.h"
110 #include "basic_functions_arginfo.h"
111
112 typedef struct _user_tick_function_entry {
113 zend_fcall_info fci;
114 zend_fcall_info_cache fci_cache;
115 bool calling;
116 } user_tick_function_entry;
117
118 #if HAVE_PUTENV
119 typedef struct {
120 char *putenv_string;
121 char *previous_value;
122 zend_string *key;
123 } putenv_entry;
124 #endif
125
126 /* some prototypes for local functions */
127 static void user_shutdown_function_dtor(zval *zv);
128 static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry);
129
130 static const zend_module_dep standard_deps[] = { /* {{{ */
131 ZEND_MOD_OPTIONAL("session")
132 ZEND_MOD_END
133 };
134 /* }}} */
135
136 zend_module_entry basic_functions_module = { /* {{{ */
137 STANDARD_MODULE_HEADER_EX,
138 NULL,
139 standard_deps,
140 "standard", /* extension name */
141 ext_functions, /* function list */
142 PHP_MINIT(basic), /* process startup */
143 PHP_MSHUTDOWN(basic), /* process shutdown */
144 PHP_RINIT(basic), /* request startup */
145 PHP_RSHUTDOWN(basic), /* request shutdown */
146 PHP_MINFO(basic), /* extension info */
147 PHP_STANDARD_VERSION, /* extension version */
148 STANDARD_MODULE_PROPERTIES
149 };
150 /* }}} */
151
152 #if defined(HAVE_PUTENV)
php_putenv_destructor(zval * zv)153 static void php_putenv_destructor(zval *zv) /* {{{ */
154 {
155 putenv_entry *pe = Z_PTR_P(zv);
156
157 if (pe->previous_value) {
158 # if defined(PHP_WIN32)
159 /* MSVCRT has a bug in putenv() when setting a variable that
160 * is already set; if the SetEnvironmentVariable() API call
161 * fails, the Crt will double free() a string.
162 * We try to avoid this by setting our own value first */
163 SetEnvironmentVariable(ZSTR_VAL(pe->key), "bugbug");
164 # endif
165 putenv(pe->previous_value);
166 # if defined(PHP_WIN32)
167 efree(pe->previous_value);
168 # endif
169 } else {
170 # if HAVE_UNSETENV
171 unsetenv(ZSTR_VAL(pe->key));
172 # elif defined(PHP_WIN32)
173 SetEnvironmentVariable(ZSTR_VAL(pe->key), NULL);
174 # ifndef ZTS
175 _putenv_s(ZSTR_VAL(pe->key), "");
176 # endif
177 # else
178 char **env;
179
180 for (env = environ; env != NULL && *env != NULL; env++) {
181 if (!strncmp(*env, ZSTR_VAL(pe->key), ZSTR_LEN(pe->key))
182 && (*env)[ZSTR_LEN(pe->key)] == '=') { /* found it */
183 *env = "";
184 break;
185 }
186 }
187 # endif
188 }
189 #ifdef HAVE_TZSET
190 /* don't forget to reset the various libc globals that
191 * we might have changed by an earlier call to tzset(). */
192 if (zend_string_equals_literal_ci(pe->key, "TZ")) {
193 tzset();
194 }
195 #endif
196
197 free(pe->putenv_string);
198 zend_string_release(pe->key);
199 efree(pe);
200 }
201 /* }}} */
202 #endif
203
basic_globals_ctor(php_basic_globals * basic_globals_p)204 static void basic_globals_ctor(php_basic_globals *basic_globals_p) /* {{{ */
205 {
206 BG(mt_rand_is_seeded) = 0;
207 BG(mt_rand_mode) = MT_RAND_MT19937;
208 BG(umask) = -1;
209 BG(next) = NULL;
210 BG(left) = -1;
211 BG(user_tick_functions) = NULL;
212 BG(user_filter_map) = NULL;
213 BG(serialize_lock) = 0;
214
215 memset(&BG(serialize), 0, sizeof(BG(serialize)));
216 memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
217
218 memset(&BG(url_adapt_session_ex), 0, sizeof(BG(url_adapt_session_ex)));
219 memset(&BG(url_adapt_output_ex), 0, sizeof(BG(url_adapt_output_ex)));
220
221 BG(url_adapt_session_ex).type = 1;
222 BG(url_adapt_output_ex).type = 0;
223
224 zend_hash_init(&BG(url_adapt_session_hosts_ht), 0, NULL, NULL, 1);
225 zend_hash_init(&BG(url_adapt_output_hosts_ht), 0, NULL, NULL, 1);
226
227 #if defined(_REENTRANT)
228 memset(&BG(mblen_state), 0, sizeof(BG(mblen_state)));
229 #endif
230
231 BG(page_uid) = -1;
232 BG(page_gid) = -1;
233
234 BG(syslog_device) = NULL;
235 }
236 /* }}} */
237
basic_globals_dtor(php_basic_globals * basic_globals_p)238 static void basic_globals_dtor(php_basic_globals *basic_globals_p) /* {{{ */
239 {
240 if (basic_globals_p->url_adapt_session_ex.tags) {
241 zend_hash_destroy(basic_globals_p->url_adapt_session_ex.tags);
242 free(basic_globals_p->url_adapt_session_ex.tags);
243 }
244 if (basic_globals_p->url_adapt_output_ex.tags) {
245 zend_hash_destroy(basic_globals_p->url_adapt_output_ex.tags);
246 free(basic_globals_p->url_adapt_output_ex.tags);
247 }
248
249 zend_hash_destroy(&basic_globals_p->url_adapt_session_hosts_ht);
250 zend_hash_destroy(&basic_globals_p->url_adapt_output_hosts_ht);
251 }
252 /* }}} */
253
php_get_nan(void)254 PHPAPI double php_get_nan(void) /* {{{ */
255 {
256 return ZEND_NAN;
257 }
258 /* }}} */
259
php_get_inf(void)260 PHPAPI double php_get_inf(void) /* {{{ */
261 {
262 return ZEND_INFINITY;
263 }
264 /* }}} */
265
266 #define BASIC_MINIT_SUBMODULE(module) \
267 if (PHP_MINIT(module)(INIT_FUNC_ARGS_PASSTHRU) != SUCCESS) {\
268 return FAILURE; \
269 }
270
271 #define BASIC_RINIT_SUBMODULE(module) \
272 PHP_RINIT(module)(INIT_FUNC_ARGS_PASSTHRU);
273
274 #define BASIC_MINFO_SUBMODULE(module) \
275 PHP_MINFO(module)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
276
277 #define BASIC_RSHUTDOWN_SUBMODULE(module) \
278 PHP_RSHUTDOWN(module)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
279
280 #define BASIC_MSHUTDOWN_SUBMODULE(module) \
281 PHP_MSHUTDOWN(module)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
282
PHP_MINIT_FUNCTION(basic)283 PHP_MINIT_FUNCTION(basic) /* {{{ */
284 {
285 #ifdef ZTS
286 ts_allocate_id(&basic_globals_id, sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, (ts_allocate_dtor) basic_globals_dtor);
287 #ifdef PHP_WIN32
288 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 );
289 #endif
290 #else
291 basic_globals_ctor(&basic_globals);
292 #ifdef PHP_WIN32
293 php_win32_core_globals_ctor(&the_php_win32_core_globals);
294 #endif
295 #endif
296
297 php_ce_incomplete_class = register_class___PHP_Incomplete_Class();
298 php_register_incomplete_class_handlers();
299
300 assertion_error_ce = register_class_AssertionError(zend_ce_error);
301
302 REGISTER_LONG_CONSTANT("CONNECTION_ABORTED", PHP_CONNECTION_ABORTED, CONST_CS | CONST_PERSISTENT);
303 REGISTER_LONG_CONSTANT("CONNECTION_NORMAL", PHP_CONNECTION_NORMAL, CONST_CS | CONST_PERSISTENT);
304 REGISTER_LONG_CONSTANT("CONNECTION_TIMEOUT", PHP_CONNECTION_TIMEOUT, CONST_CS | CONST_PERSISTENT);
305
306 REGISTER_LONG_CONSTANT("INI_USER", ZEND_INI_USER, CONST_CS | CONST_PERSISTENT);
307 REGISTER_LONG_CONSTANT("INI_PERDIR", ZEND_INI_PERDIR, CONST_CS | CONST_PERSISTENT);
308 REGISTER_LONG_CONSTANT("INI_SYSTEM", ZEND_INI_SYSTEM, CONST_CS | CONST_PERSISTENT);
309 REGISTER_LONG_CONSTANT("INI_ALL", ZEND_INI_ALL, CONST_CS | CONST_PERSISTENT);
310
311 REGISTER_LONG_CONSTANT("INI_SCANNER_NORMAL", ZEND_INI_SCANNER_NORMAL, CONST_CS | CONST_PERSISTENT);
312 REGISTER_LONG_CONSTANT("INI_SCANNER_RAW", ZEND_INI_SCANNER_RAW, CONST_CS | CONST_PERSISTENT);
313 REGISTER_LONG_CONSTANT("INI_SCANNER_TYPED", ZEND_INI_SCANNER_TYPED, CONST_CS | CONST_PERSISTENT);
314
315 REGISTER_LONG_CONSTANT("PHP_URL_SCHEME", PHP_URL_SCHEME, CONST_CS | CONST_PERSISTENT);
316 REGISTER_LONG_CONSTANT("PHP_URL_HOST", PHP_URL_HOST, CONST_CS | CONST_PERSISTENT);
317 REGISTER_LONG_CONSTANT("PHP_URL_PORT", PHP_URL_PORT, CONST_CS | CONST_PERSISTENT);
318 REGISTER_LONG_CONSTANT("PHP_URL_USER", PHP_URL_USER, CONST_CS | CONST_PERSISTENT);
319 REGISTER_LONG_CONSTANT("PHP_URL_PASS", PHP_URL_PASS, CONST_CS | CONST_PERSISTENT);
320 REGISTER_LONG_CONSTANT("PHP_URL_PATH", PHP_URL_PATH, CONST_CS | CONST_PERSISTENT);
321 REGISTER_LONG_CONSTANT("PHP_URL_QUERY", PHP_URL_QUERY, CONST_CS | CONST_PERSISTENT);
322 REGISTER_LONG_CONSTANT("PHP_URL_FRAGMENT", PHP_URL_FRAGMENT, CONST_CS | CONST_PERSISTENT);
323 REGISTER_LONG_CONSTANT("PHP_QUERY_RFC1738", PHP_QUERY_RFC1738, CONST_CS | CONST_PERSISTENT);
324 REGISTER_LONG_CONSTANT("PHP_QUERY_RFC3986", PHP_QUERY_RFC3986, CONST_CS | CONST_PERSISTENT);
325
326 #define REGISTER_MATH_CONSTANT(x) REGISTER_DOUBLE_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
327 REGISTER_MATH_CONSTANT(M_E);
328 REGISTER_MATH_CONSTANT(M_LOG2E);
329 REGISTER_MATH_CONSTANT(M_LOG10E);
330 REGISTER_MATH_CONSTANT(M_LN2);
331 REGISTER_MATH_CONSTANT(M_LN10);
332 REGISTER_MATH_CONSTANT(M_PI);
333 REGISTER_MATH_CONSTANT(M_PI_2);
334 REGISTER_MATH_CONSTANT(M_PI_4);
335 REGISTER_MATH_CONSTANT(M_1_PI);
336 REGISTER_MATH_CONSTANT(M_2_PI);
337 REGISTER_MATH_CONSTANT(M_SQRTPI);
338 REGISTER_MATH_CONSTANT(M_2_SQRTPI);
339 REGISTER_MATH_CONSTANT(M_LNPI);
340 REGISTER_MATH_CONSTANT(M_EULER);
341 REGISTER_MATH_CONSTANT(M_SQRT2);
342 REGISTER_MATH_CONSTANT(M_SQRT1_2);
343 REGISTER_MATH_CONSTANT(M_SQRT3);
344 REGISTER_DOUBLE_CONSTANT("INF", ZEND_INFINITY, CONST_CS | CONST_PERSISTENT);
345 REGISTER_DOUBLE_CONSTANT("NAN", ZEND_NAN, CONST_CS | CONST_PERSISTENT);
346
347 REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_UP", PHP_ROUND_HALF_UP, CONST_CS | CONST_PERSISTENT);
348 REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_DOWN", PHP_ROUND_HALF_DOWN, CONST_CS | CONST_PERSISTENT);
349 REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_EVEN", PHP_ROUND_HALF_EVEN, CONST_CS | CONST_PERSISTENT);
350 REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_ODD", PHP_ROUND_HALF_ODD, CONST_CS | CONST_PERSISTENT);
351
352 #if ENABLE_TEST_CLASS
353 test_class_startup();
354 #endif
355
356 register_phpinfo_constants(INIT_FUNC_ARGS_PASSTHRU);
357 register_html_constants(INIT_FUNC_ARGS_PASSTHRU);
358 register_string_constants(INIT_FUNC_ARGS_PASSTHRU);
359
360 BASIC_MINIT_SUBMODULE(var)
361 BASIC_MINIT_SUBMODULE(file)
362 BASIC_MINIT_SUBMODULE(pack)
363 BASIC_MINIT_SUBMODULE(browscap)
364 BASIC_MINIT_SUBMODULE(standard_filters)
365 BASIC_MINIT_SUBMODULE(user_filters)
366 BASIC_MINIT_SUBMODULE(password)
367 BASIC_MINIT_SUBMODULE(mt_rand)
368
369 #if defined(ZTS)
370 BASIC_MINIT_SUBMODULE(localeconv)
371 #endif
372
373 #if defined(HAVE_NL_LANGINFO)
374 BASIC_MINIT_SUBMODULE(nl_langinfo)
375 #endif
376
377 #if ZEND_INTRIN_SSE4_2_FUNC_PTR
378 BASIC_MINIT_SUBMODULE(string_intrin)
379 #endif
380
381 #if ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_PTR
382 BASIC_MINIT_SUBMODULE(crc32_x86_intrin)
383 #endif
384
385 #if ZEND_INTRIN_AVX2_FUNC_PTR || ZEND_INTRIN_SSSE3_FUNC_PTR
386 BASIC_MINIT_SUBMODULE(base64_intrin)
387 #endif
388
389 BASIC_MINIT_SUBMODULE(crypt)
390 BASIC_MINIT_SUBMODULE(lcg)
391
392 BASIC_MINIT_SUBMODULE(dir)
393 #ifdef HAVE_SYSLOG_H
394 BASIC_MINIT_SUBMODULE(syslog)
395 #endif
396 BASIC_MINIT_SUBMODULE(array)
397 BASIC_MINIT_SUBMODULE(assert)
398 BASIC_MINIT_SUBMODULE(url_scanner_ex)
399 #ifdef PHP_CAN_SUPPORT_PROC_OPEN
400 BASIC_MINIT_SUBMODULE(proc_open)
401 #endif
402 BASIC_MINIT_SUBMODULE(exec)
403
404 BASIC_MINIT_SUBMODULE(user_streams)
405 BASIC_MINIT_SUBMODULE(imagetypes)
406
407 php_register_url_stream_wrapper("php", &php_stream_php_wrapper);
408 php_register_url_stream_wrapper("file", &php_plain_files_wrapper);
409 #ifdef HAVE_GLOB
410 php_register_url_stream_wrapper("glob", &php_glob_stream_wrapper);
411 #endif
412 php_register_url_stream_wrapper("data", &php_stream_rfc2397_wrapper);
413 php_register_url_stream_wrapper("http", &php_stream_http_wrapper);
414 php_register_url_stream_wrapper("ftp", &php_stream_ftp_wrapper);
415
416 #if defined(PHP_WIN32) || HAVE_DNS_SEARCH_FUNC
417 # if defined(PHP_WIN32) || HAVE_FULL_DNS_FUNCS
418 BASIC_MINIT_SUBMODULE(dns)
419 # endif
420 #endif
421
422 BASIC_MINIT_SUBMODULE(random)
423
424 BASIC_MINIT_SUBMODULE(hrtime)
425
426 return SUCCESS;
427 }
428 /* }}} */
429
PHP_MSHUTDOWN_FUNCTION(basic)430 PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */
431 {
432 #ifdef ZTS
433 ts_free_id(basic_globals_id);
434 #ifdef PHP_WIN32
435 ts_free_id(php_win32_core_globals_id);
436 #endif
437 #else
438 basic_globals_dtor(&basic_globals);
439 #ifdef PHP_WIN32
440 php_win32_core_globals_dtor(&the_php_win32_core_globals);
441 #endif
442 #endif
443
444 php_unregister_url_stream_wrapper("php");
445 php_unregister_url_stream_wrapper("http");
446 php_unregister_url_stream_wrapper("ftp");
447
448 BASIC_MSHUTDOWN_SUBMODULE(browscap)
449 BASIC_MSHUTDOWN_SUBMODULE(array)
450 BASIC_MSHUTDOWN_SUBMODULE(assert)
451 BASIC_MSHUTDOWN_SUBMODULE(url_scanner_ex)
452 BASIC_MSHUTDOWN_SUBMODULE(file)
453 BASIC_MSHUTDOWN_SUBMODULE(standard_filters)
454 #if defined(ZTS)
455 BASIC_MSHUTDOWN_SUBMODULE(localeconv)
456 #endif
457 BASIC_MSHUTDOWN_SUBMODULE(crypt)
458 BASIC_MSHUTDOWN_SUBMODULE(random)
459 BASIC_MSHUTDOWN_SUBMODULE(password)
460
461 return SUCCESS;
462 }
463 /* }}} */
464
PHP_RINIT_FUNCTION(basic)465 PHP_RINIT_FUNCTION(basic) /* {{{ */
466 {
467 memset(BG(strtok_table), 0, 256);
468
469 BG(serialize_lock) = 0;
470 memset(&BG(serialize), 0, sizeof(BG(serialize)));
471 memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
472
473 BG(strtok_string) = NULL;
474 BG(strtok_last) = NULL;
475 BG(ctype_string) = NULL;
476 BG(locale_changed) = 0;
477 BG(user_compare_fci) = empty_fcall_info;
478 BG(user_compare_fci_cache) = empty_fcall_info_cache;
479 BG(page_uid) = -1;
480 BG(page_gid) = -1;
481 BG(page_inode) = -1;
482 BG(page_mtime) = -1;
483 #ifdef HAVE_PUTENV
484 zend_hash_init(&BG(putenv_ht), 1, NULL, php_putenv_destructor, 0);
485 #endif
486 BG(user_shutdown_function_names) = NULL;
487
488 PHP_RINIT(filestat)(INIT_FUNC_ARGS_PASSTHRU);
489 BASIC_RINIT_SUBMODULE(dir)
490 BASIC_RINIT_SUBMODULE(url_scanner_ex)
491
492 /* Setup default context */
493 FG(default_context) = NULL;
494
495 /* Default to global wrappers only */
496 FG(stream_wrappers) = NULL;
497
498 /* Default to global filters only */
499 FG(stream_filters) = NULL;
500
501 return SUCCESS;
502 }
503 /* }}} */
504
PHP_RSHUTDOWN_FUNCTION(basic)505 PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
506 {
507 if (BG(strtok_string)) {
508 zend_string_release(BG(strtok_string));
509 BG(strtok_string) = NULL;
510 }
511 #ifdef HAVE_PUTENV
512 tsrm_env_lock();
513 zend_hash_destroy(&BG(putenv_ht));
514 tsrm_env_unlock();
515 #endif
516
517 BG(mt_rand_is_seeded) = 0;
518
519 if (BG(umask) != -1) {
520 umask(BG(umask));
521 }
522
523 /* Check if locale was changed and change it back
524 * to the value in startup environment */
525 if (BG(locale_changed)) {
526 setlocale(LC_ALL, "C");
527 zend_reset_lc_ctype_locale();
528 zend_update_current_locale();
529 if (BG(ctype_string)) {
530 zend_string_release_ex(BG(ctype_string), 0);
531 BG(ctype_string) = NULL;
532 }
533 }
534
535 /* FG(stream_wrappers) and FG(stream_filters) are destroyed
536 * during php_request_shutdown() */
537
538 PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
539 #ifdef HAVE_SYSLOG_H
540 BASIC_RSHUTDOWN_SUBMODULE(syslog);
541 #endif
542 BASIC_RSHUTDOWN_SUBMODULE(assert)
543 BASIC_RSHUTDOWN_SUBMODULE(url_scanner_ex)
544 BASIC_RSHUTDOWN_SUBMODULE(streams)
545 #ifdef PHP_WIN32
546 BASIC_RSHUTDOWN_SUBMODULE(win32_core_globals)
547 #endif
548
549 if (BG(user_tick_functions)) {
550 zend_llist_destroy(BG(user_tick_functions));
551 efree(BG(user_tick_functions));
552 BG(user_tick_functions) = NULL;
553 }
554
555 BASIC_RSHUTDOWN_SUBMODULE(user_filters)
556 BASIC_RSHUTDOWN_SUBMODULE(browscap)
557
558 BG(page_uid) = -1;
559 BG(page_gid) = -1;
560 return SUCCESS;
561 }
562 /* }}} */
563
PHP_MINFO_FUNCTION(basic)564 PHP_MINFO_FUNCTION(basic) /* {{{ */
565 {
566 php_info_print_table_start();
567 BASIC_MINFO_SUBMODULE(dl)
568 BASIC_MINFO_SUBMODULE(mail)
569 php_info_print_table_end();
570 BASIC_MINFO_SUBMODULE(assert)
571 }
572 /* }}} */
573
574 /* {{{ Given the name of a constant this function will return the constant's associated value */
PHP_FUNCTION(constant)575 PHP_FUNCTION(constant)
576 {
577 zend_string *const_name;
578 zval *c;
579 zend_class_entry *scope;
580
581 ZEND_PARSE_PARAMETERS_START(1, 1)
582 Z_PARAM_STR(const_name)
583 ZEND_PARSE_PARAMETERS_END();
584
585 scope = zend_get_executed_scope();
586 c = zend_get_constant_ex(const_name, scope, ZEND_FETCH_CLASS_EXCEPTION);
587 if (!c) {
588 RETURN_THROWS();
589 }
590
591 ZVAL_COPY_OR_DUP(return_value, c);
592 if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
593 if (UNEXPECTED(zval_update_constant_ex(return_value, scope) != SUCCESS)) {
594 RETURN_THROWS();
595 }
596 }
597 }
598 /* }}} */
599
600 #ifdef HAVE_INET_NTOP
601 /* {{{ Converts a packed inet address to a human readable IP address string */
PHP_FUNCTION(inet_ntop)602 PHP_FUNCTION(inet_ntop)
603 {
604 char *address;
605 size_t address_len;
606 int af = AF_INET;
607 char buffer[40];
608
609 ZEND_PARSE_PARAMETERS_START(1, 1)
610 Z_PARAM_STRING(address, address_len)
611 ZEND_PARSE_PARAMETERS_END();
612
613 #ifdef HAVE_IPV6
614 if (address_len == 16) {
615 af = AF_INET6;
616 } else
617 #endif
618 if (address_len != 4) {
619 RETURN_FALSE;
620 }
621
622 if (!inet_ntop(af, address, buffer, sizeof(buffer))) {
623 RETURN_FALSE;
624 }
625
626 RETURN_STRING(buffer);
627 }
628 /* }}} */
629 #endif /* HAVE_INET_NTOP */
630
631 #ifdef HAVE_INET_PTON
632 /* {{{ Converts a human readable IP address to a packed binary string */
PHP_FUNCTION(inet_pton)633 PHP_FUNCTION(inet_pton)
634 {
635 int ret, af = AF_INET;
636 char *address;
637 size_t address_len;
638 char buffer[17];
639
640 ZEND_PARSE_PARAMETERS_START(1, 1)
641 Z_PARAM_STRING(address, address_len)
642 ZEND_PARSE_PARAMETERS_END();
643
644 memset(buffer, 0, sizeof(buffer));
645
646 #ifdef HAVE_IPV6
647 if (strchr(address, ':')) {
648 af = AF_INET6;
649 } else
650 #endif
651 if (!strchr(address, '.')) {
652 RETURN_FALSE;
653 }
654
655 ret = inet_pton(af, address, buffer);
656
657 if (ret <= 0) {
658 RETURN_FALSE;
659 }
660
661 RETURN_STRINGL(buffer, af == AF_INET ? 4 : 16);
662 }
663 /* }}} */
664 #endif /* HAVE_INET_PTON */
665
666 /* {{{ Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address */
PHP_FUNCTION(ip2long)667 PHP_FUNCTION(ip2long)
668 {
669 char *addr;
670 size_t addr_len;
671 #ifdef HAVE_INET_PTON
672 struct in_addr ip;
673 #else
674 zend_ulong ip;
675 #endif
676
677 ZEND_PARSE_PARAMETERS_START(1, 1)
678 Z_PARAM_STRING(addr, addr_len)
679 ZEND_PARSE_PARAMETERS_END();
680
681 #ifdef HAVE_INET_PTON
682 if (addr_len == 0 || inet_pton(AF_INET, addr, &ip) != 1) {
683 RETURN_FALSE;
684 }
685 RETURN_LONG(ntohl(ip.s_addr));
686 #else
687 if (addr_len == 0 || (ip = inet_addr(addr)) == INADDR_NONE) {
688 /* The only special case when we should return -1 ourselves,
689 * because inet_addr() considers it wrong. We return 0xFFFFFFFF and
690 * not -1 or ~0 because of 32/64bit issues. */
691 if (addr_len == sizeof("255.255.255.255") - 1 &&
692 !memcmp(addr, "255.255.255.255", sizeof("255.255.255.255") - 1)
693 ) {
694 RETURN_LONG(0xFFFFFFFF);
695 }
696 RETURN_FALSE;
697 }
698 RETURN_LONG(ntohl(ip));
699 #endif
700 }
701 /* }}} */
702
703 /* {{{ Converts an (IPv4) Internet network address into a string in Internet standard dotted format */
PHP_FUNCTION(long2ip)704 PHP_FUNCTION(long2ip)
705 {
706 zend_ulong ip;
707 zend_long sip;
708 struct in_addr myaddr;
709 #ifdef HAVE_INET_PTON
710 char str[40];
711 #endif
712
713 ZEND_PARSE_PARAMETERS_START(1, 1)
714 Z_PARAM_LONG(sip)
715 ZEND_PARSE_PARAMETERS_END();
716
717 /* autoboxes on 32bit platforms, but that's expected */
718 ip = (zend_ulong)sip;
719
720 myaddr.s_addr = htonl(ip);
721 #ifdef HAVE_INET_PTON
722 if (inet_ntop(AF_INET, &myaddr, str, sizeof(str))) {
723 RETURN_STRING(str);
724 } else {
725 RETURN_FALSE;
726 }
727 #else
728 RETURN_STRING(inet_ntoa(myaddr));
729 #endif
730 }
731 /* }}} */
732
733 /********************
734 * System Functions *
735 ********************/
736
php_getenv(const char * str,size_t str_len)737 PHPAPI zend_string *php_getenv(const char *str, size_t str_len) {
738 #ifdef PHP_WIN32
739 {
740 wchar_t *keyw = php_win32_cp_conv_any_to_w(str, str_len, PHP_WIN32_CP_IGNORE_LEN_P);
741 if (!keyw) {
742 return NULL;
743 }
744
745 SetLastError(0);
746 /* If the given buffer is not large enough to hold the data, the return value is
747 * the buffer size, in characters, required to hold the string and its terminating
748 * null character. We use this return value to alloc the final buffer. */
749 wchar_t dummybuf;
750 DWORD size = GetEnvironmentVariableW(keyw, &dummybuf, 0);
751 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
752 /* The environment variable doesn't exist. */
753 free(keyw);
754 return NULL;
755 }
756
757 if (size == 0) {
758 /* env exists, but it is empty */
759 free(keyw);
760 return ZSTR_EMPTY_ALLOC();
761 }
762
763 wchar_t *valw = emalloc((size + 1) * sizeof(wchar_t));
764 size = GetEnvironmentVariableW(keyw, valw, size);
765 if (size == 0) {
766 /* has been removed between the two calls */
767 free(keyw);
768 efree(valw);
769 return ZSTR_EMPTY_ALLOC();
770 } else {
771 char *ptr = php_win32_cp_w_to_any(valw);
772 zend_string *result = zend_string_init(ptr, strlen(ptr), 0);
773 free(ptr);
774 free(keyw);
775 efree(valw);
776 return result;
777 }
778 }
779 #else
780 tsrm_env_lock();
781
782 /* system method returns a const */
783 char *ptr = getenv(str);
784 zend_string *result = NULL;
785 if (ptr) {
786 result = zend_string_init(ptr, strlen(ptr), 0);
787 }
788
789 tsrm_env_unlock();
790 return result;
791 #endif
792 }
793
794 /* {{{ Get the value of an environment variable or every available environment variable
795 if no varname is present */
PHP_FUNCTION(getenv)796 PHP_FUNCTION(getenv)
797 {
798 char *str = NULL;
799 size_t str_len;
800 bool local_only = 0;
801
802 ZEND_PARSE_PARAMETERS_START(0, 2)
803 Z_PARAM_OPTIONAL
804 Z_PARAM_STRING_OR_NULL(str, str_len)
805 Z_PARAM_BOOL(local_only)
806 ZEND_PARSE_PARAMETERS_END();
807
808 if (!str) {
809 array_init(return_value);
810 php_import_environment_variables(return_value);
811 return;
812 }
813
814 if (!local_only) {
815 /* SAPI method returns an emalloc()'d string */
816 char *ptr = sapi_getenv(str, str_len);
817 if (ptr) {
818 // TODO: avoid reallocation ???
819 RETVAL_STRING(ptr);
820 efree(ptr);
821 return;
822 }
823 }
824
825 zend_string *res = php_getenv(str, str_len);
826 if (res) {
827 RETURN_STR(res);
828 }
829 RETURN_FALSE;
830 }
831 /* }}} */
832
833 #ifdef HAVE_PUTENV
834 /* {{{ Set the value of an environment variable */
PHP_FUNCTION(putenv)835 PHP_FUNCTION(putenv)
836 {
837 char *setting;
838 size_t setting_len;
839 char *p, **env;
840 putenv_entry pe;
841 #ifdef PHP_WIN32
842 const char *value = NULL;
843 int error_code;
844 #endif
845
846 ZEND_PARSE_PARAMETERS_START(1, 1)
847 Z_PARAM_STRING(setting, setting_len)
848 ZEND_PARSE_PARAMETERS_END();
849
850 if (setting_len == 0 || setting[0] == '=') {
851 zend_argument_value_error(1, "must have a valid syntax");
852 RETURN_THROWS();
853 }
854
855 pe.putenv_string = zend_strndup(setting, setting_len);
856 if ((p = strchr(setting, '='))) {
857 pe.key = zend_string_init(setting, p - setting, 0);
858 #ifdef PHP_WIN32
859 value = p + 1;
860 #endif
861 } else {
862 pe.key = zend_string_init(setting, setting_len, 0);
863 }
864
865 tsrm_env_lock();
866 zend_hash_del(&BG(putenv_ht), pe.key);
867
868 /* find previous value */
869 pe.previous_value = NULL;
870 for (env = environ; env != NULL && *env != NULL; env++) {
871 if (!strncmp(*env, ZSTR_VAL(pe.key), ZSTR_LEN(pe.key))
872 && (*env)[ZSTR_LEN(pe.key)] == '=') { /* found it */
873 #if defined(PHP_WIN32)
874 /* must copy previous value because MSVCRT's putenv can free the string without notice */
875 pe.previous_value = estrdup(*env);
876 #else
877 pe.previous_value = *env;
878 #endif
879 break;
880 }
881 }
882
883 #if HAVE_UNSETENV
884 if (!p) { /* no '=' means we want to unset it */
885 unsetenv(pe.putenv_string);
886 }
887 if (!p || putenv(pe.putenv_string) == 0) { /* success */
888 #else
889 # ifndef PHP_WIN32
890 if (putenv(pe.putenv_string) == 0) { /* success */
891 # else
892 wchar_t *keyw, *valw = NULL;
893
894 keyw = php_win32_cp_any_to_w(ZSTR_VAL(pe.key));
895 if (value) {
896 valw = php_win32_cp_any_to_w(value);
897 }
898 /* valw may be NULL, but the failed conversion still needs to be checked. */
899 if (!keyw || !valw && value) {
900 tsrm_env_unlock();
901 free(pe.putenv_string);
902 zend_string_release(pe.key);
903 free(keyw);
904 free(valw);
905 RETURN_FALSE;
906 }
907
908 error_code = SetEnvironmentVariableW(keyw, valw);
909
910 if (error_code != 0
911 # ifndef ZTS
912 /* We need both SetEnvironmentVariable and _putenv here as some
913 dependency lib could use either way to read the environment.
914 Obviously the CRT version will be useful more often. But
915 generally, doing both brings us on the safe track at least
916 in NTS build. */
917 && _wputenv_s(keyw, valw ? valw : L"") == 0
918 # endif
919 ) { /* success */
920 # endif
921 #endif
922 zend_hash_add_mem(&BG(putenv_ht), pe.key, &pe, sizeof(putenv_entry));
923 #ifdef HAVE_TZSET
924 if (zend_string_equals_literal_ci(pe.key, "TZ")) {
925 tzset();
926 }
927 #endif
928 tsrm_env_unlock();
929 #if defined(PHP_WIN32)
930 free(keyw);
931 free(valw);
932 #endif
933 RETURN_TRUE;
934 } else {
935 free(pe.putenv_string);
936 zend_string_release(pe.key);
937 #if defined(PHP_WIN32)
938 free(keyw);
939 free(valw);
940 #endif
941 RETURN_FALSE;
942 }
943 }
944 /* }}} */
945 #endif
946
947 /* {{{ free_argv()
948 Free the memory allocated to an argv array. */
949 static void free_argv(char **argv, int argc)
950 {
951 int i;
952
953 if (argv) {
954 for (i = 0; i < argc; i++) {
955 if (argv[i]) {
956 efree(argv[i]);
957 }
958 }
959 efree(argv);
960 }
961 }
962 /* }}} */
963
964 /* {{{ free_longopts()
965 Free the memory allocated to an longopt array. */
966 static void free_longopts(opt_struct *longopts)
967 {
968 opt_struct *p;
969
970 if (longopts) {
971 for (p = longopts; p && p->opt_char != '-'; p++) {
972 if (p->opt_name != NULL) {
973 efree((char *)(p->opt_name));
974 }
975 }
976 }
977 }
978 /* }}} */
979
980 /* {{{ parse_opts()
981 Convert the typical getopt input characters to the php_getopt struct array */
982 static int parse_opts(char * opts, opt_struct ** result)
983 {
984 opt_struct * paras = NULL;
985 unsigned int i, count = 0;
986 unsigned int opts_len = (unsigned int)strlen(opts);
987
988 for (i = 0; i < opts_len; i++) {
989 if ((opts[i] >= 48 && opts[i] <= 57) ||
990 (opts[i] >= 65 && opts[i] <= 90) ||
991 (opts[i] >= 97 && opts[i] <= 122)
992 ) {
993 count++;
994 }
995 }
996
997 paras = safe_emalloc(sizeof(opt_struct), count, 0);
998 memset(paras, 0, sizeof(opt_struct) * count);
999 *result = paras;
1000 while ( (*opts >= 48 && *opts <= 57) || /* 0 - 9 */
1001 (*opts >= 65 && *opts <= 90) || /* A - Z */
1002 (*opts >= 97 && *opts <= 122) /* a - z */
1003 ) {
1004 paras->opt_char = *opts;
1005 paras->need_param = *(++opts) == ':';
1006 paras->opt_name = NULL;
1007 if (paras->need_param == 1) {
1008 opts++;
1009 if (*opts == ':') {
1010 paras->need_param++;
1011 opts++;
1012 }
1013 }
1014 paras++;
1015 }
1016 return count;
1017 }
1018 /* }}} */
1019
1020 /* {{{ Get options from the command line argument list */
1021 PHP_FUNCTION(getopt)
1022 {
1023 char *options = NULL, **argv = NULL;
1024 char opt[2] = { '\0' };
1025 char *optname;
1026 int argc = 0, o;
1027 size_t options_len = 0, len;
1028 char *php_optarg = NULL;
1029 int php_optind = 1;
1030 zval val, *args = NULL, *p_longopts = NULL;
1031 zval *zoptind = NULL;
1032 size_t optname_len = 0;
1033 opt_struct *opts, *orig_opts;
1034
1035 ZEND_PARSE_PARAMETERS_START(1, 3)
1036 Z_PARAM_STRING(options, options_len)
1037 Z_PARAM_OPTIONAL
1038 Z_PARAM_ARRAY(p_longopts)
1039 Z_PARAM_ZVAL(zoptind)
1040 ZEND_PARSE_PARAMETERS_END();
1041
1042 /* Init zoptind to 1 */
1043 if (zoptind) {
1044 ZEND_TRY_ASSIGN_REF_LONG(zoptind, 1);
1045 }
1046
1047 /* Get argv from the global symbol table. We calculate argc ourselves
1048 * in order to be on the safe side, even though it is also available
1049 * from the symbol table. */
1050 if ((Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY || zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER))) &&
1051 ((args = zend_hash_find_ex_ind(Z_ARRVAL_P(&PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL ||
1052 (args = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL)
1053 ) {
1054 int pos = 0;
1055 zval *entry;
1056
1057 if (Z_TYPE_P(args) != IS_ARRAY) {
1058 RETURN_FALSE;
1059 }
1060 argc = zend_hash_num_elements(Z_ARRVAL_P(args));
1061
1062 /* Attempt to allocate enough memory to hold all of the arguments
1063 * and a trailing NULL */
1064 argv = (char **) safe_emalloc(sizeof(char *), (argc + 1), 0);
1065
1066 /* Iterate over the hash to construct the argv array. */
1067 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), entry) {
1068 zend_string *tmp_arg_str;
1069 zend_string *arg_str = zval_get_tmp_string(entry, &tmp_arg_str);
1070
1071 argv[pos++] = estrdup(ZSTR_VAL(arg_str));
1072
1073 zend_tmp_string_release(tmp_arg_str);
1074 } ZEND_HASH_FOREACH_END();
1075
1076 /* The C Standard requires argv[argc] to be NULL - this might
1077 * keep some getopt implementations happy. */
1078 argv[argc] = NULL;
1079 } else {
1080 /* Return false if we can't find argv. */
1081 RETURN_FALSE;
1082 }
1083
1084 len = parse_opts(options, &opts);
1085
1086 if (p_longopts) {
1087 int count;
1088 zval *entry;
1089
1090 count = zend_hash_num_elements(Z_ARRVAL_P(p_longopts));
1091
1092 /* the first <len> slots are filled by the one short ops
1093 * we now extend our array and jump to the new added structs */
1094 opts = (opt_struct *) erealloc(opts, sizeof(opt_struct) * (len + count + 1));
1095 orig_opts = opts;
1096 opts += len;
1097
1098 memset(opts, 0, count * sizeof(opt_struct));
1099
1100 /* Iterate over the hash to construct the argv array. */
1101 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(p_longopts), entry) {
1102 zend_string *tmp_arg_str;
1103 zend_string *arg_str = zval_get_tmp_string(entry, &tmp_arg_str);
1104
1105 opts->need_param = 0;
1106 opts->opt_name = estrdup(ZSTR_VAL(arg_str));
1107 len = strlen(opts->opt_name);
1108 if ((len > 0) && (opts->opt_name[len - 1] == ':')) {
1109 opts->need_param++;
1110 opts->opt_name[len - 1] = '\0';
1111 if ((len > 1) && (opts->opt_name[len - 2] == ':')) {
1112 opts->need_param++;
1113 opts->opt_name[len - 2] = '\0';
1114 }
1115 }
1116 opts->opt_char = 0;
1117 opts++;
1118
1119 zend_tmp_string_release(tmp_arg_str);
1120 } ZEND_HASH_FOREACH_END();
1121 } else {
1122 opts = (opt_struct*) erealloc(opts, sizeof(opt_struct) * (len + 1));
1123 orig_opts = opts;
1124 opts += len;
1125 }
1126
1127 /* php_getopt want to identify the last param */
1128 opts->opt_char = '-';
1129 opts->need_param = 0;
1130 opts->opt_name = NULL;
1131
1132 /* Initialize the return value as an array. */
1133 array_init(return_value);
1134
1135 /* after our pointer arithmetic jump back to the first element */
1136 opts = orig_opts;
1137
1138 while ((o = php_getopt(argc, argv, opts, &php_optarg, &php_optind, 0, 1)) != -1) {
1139 /* Skip unknown arguments. */
1140 if (o == PHP_GETOPT_INVALID_ARG) {
1141 continue;
1142 }
1143
1144 /* Prepare the option character and the argument string. */
1145 if (o == 0) {
1146 optname = opts[php_optidx].opt_name;
1147 } else {
1148 if (o == 1) {
1149 o = '-';
1150 }
1151 opt[0] = o;
1152 optname = opt;
1153 }
1154
1155 if (php_optarg != NULL) {
1156 /* keep the arg as binary, since the encoding is not known */
1157 ZVAL_STRING(&val, php_optarg);
1158 } else {
1159 ZVAL_FALSE(&val);
1160 }
1161
1162 /* Add this option / argument pair to the result hash. */
1163 optname_len = strlen(optname);
1164 if (!(optname_len > 1 && optname[0] == '0') && is_numeric_string(optname, optname_len, NULL, NULL, 0) == IS_LONG) {
1165 /* numeric string */
1166 int optname_int = atoi(optname);
1167 if ((args = zend_hash_index_find(Z_ARRVAL_P(return_value), optname_int)) != NULL) {
1168 if (Z_TYPE_P(args) != IS_ARRAY) {
1169 convert_to_array(args);
1170 }
1171 zend_hash_next_index_insert(Z_ARRVAL_P(args), &val);
1172 } else {
1173 zend_hash_index_update(Z_ARRVAL_P(return_value), optname_int, &val);
1174 }
1175 } else {
1176 /* other strings */
1177 if ((args = zend_hash_str_find(Z_ARRVAL_P(return_value), optname, strlen(optname))) != NULL) {
1178 if (Z_TYPE_P(args) != IS_ARRAY) {
1179 convert_to_array(args);
1180 }
1181 zend_hash_next_index_insert(Z_ARRVAL_P(args), &val);
1182 } else {
1183 zend_hash_str_add(Z_ARRVAL_P(return_value), optname, strlen(optname), &val);
1184 }
1185 }
1186
1187 php_optarg = NULL;
1188 }
1189
1190 /* Set zoptind to php_optind */
1191 if (zoptind) {
1192 ZEND_TRY_ASSIGN_REF_LONG(zoptind, php_optind);
1193 }
1194
1195 free_longopts(orig_opts);
1196 efree(orig_opts);
1197 free_argv(argv, argc);
1198 }
1199 /* }}} */
1200
1201 /* {{{ Flush the output buffer */
1202 PHP_FUNCTION(flush)
1203 {
1204 ZEND_PARSE_PARAMETERS_NONE();
1205
1206 sapi_flush();
1207 }
1208 /* }}} */
1209
1210 /* {{{ Delay for a given number of seconds */
1211 PHP_FUNCTION(sleep)
1212 {
1213 zend_long num;
1214
1215 ZEND_PARSE_PARAMETERS_START(1, 1)
1216 Z_PARAM_LONG(num)
1217 ZEND_PARSE_PARAMETERS_END();
1218
1219 if (num < 0) {
1220 zend_argument_value_error(1, "must be greater than or equal to 0");
1221 RETURN_THROWS();
1222 }
1223
1224 RETURN_LONG(php_sleep((unsigned int)num));
1225 }
1226 /* }}} */
1227
1228 /* {{{ Delay for a given number of micro seconds */
1229 PHP_FUNCTION(usleep)
1230 {
1231 zend_long num;
1232
1233 ZEND_PARSE_PARAMETERS_START(1, 1)
1234 Z_PARAM_LONG(num)
1235 ZEND_PARSE_PARAMETERS_END();
1236
1237 if (num < 0) {
1238 zend_argument_value_error(1, "must be greater than or equal to 0");
1239 RETURN_THROWS();
1240 }
1241
1242 #if HAVE_USLEEP
1243 usleep((unsigned int)num);
1244 #endif
1245 }
1246 /* }}} */
1247
1248 #if HAVE_NANOSLEEP
1249 /* {{{ Delay for a number of seconds and nano seconds */
1250 PHP_FUNCTION(time_nanosleep)
1251 {
1252 zend_long tv_sec, tv_nsec;
1253 struct timespec php_req, php_rem;
1254
1255 ZEND_PARSE_PARAMETERS_START(2, 2)
1256 Z_PARAM_LONG(tv_sec)
1257 Z_PARAM_LONG(tv_nsec)
1258 ZEND_PARSE_PARAMETERS_END();
1259
1260 if (tv_sec < 0) {
1261 zend_argument_value_error(1, "must be greater than or equal to 0");
1262 RETURN_THROWS();
1263 }
1264 if (tv_nsec < 0) {
1265 zend_argument_value_error(2, "must be greater than or equal to 0");
1266 RETURN_THROWS();
1267 }
1268
1269 php_req.tv_sec = (time_t) tv_sec;
1270 php_req.tv_nsec = (long)tv_nsec;
1271 if (!nanosleep(&php_req, &php_rem)) {
1272 RETURN_TRUE;
1273 } else if (errno == EINTR) {
1274 array_init(return_value);
1275 add_assoc_long_ex(return_value, "seconds", sizeof("seconds")-1, php_rem.tv_sec);
1276 add_assoc_long_ex(return_value, "nanoseconds", sizeof("nanoseconds")-1, php_rem.tv_nsec);
1277 return;
1278 } else if (errno == EINVAL) {
1279 zend_value_error("Nanoseconds was not in the range 0 to 999 999 999 or seconds was negative");
1280 RETURN_THROWS();
1281 }
1282
1283 RETURN_FALSE;
1284 }
1285 /* }}} */
1286
1287 /* {{{ Make the script sleep until the specified time */
1288 PHP_FUNCTION(time_sleep_until)
1289 {
1290 double target_secs;
1291 struct timeval tm;
1292 struct timespec php_req, php_rem;
1293 uint64_t current_ns, target_ns, diff_ns;
1294 const uint64_t ns_per_sec = 1000000000;
1295
1296 ZEND_PARSE_PARAMETERS_START(1, 1)
1297 Z_PARAM_DOUBLE(target_secs)
1298 ZEND_PARSE_PARAMETERS_END();
1299
1300 if (gettimeofday((struct timeval *) &tm, NULL) != 0) {
1301 RETURN_FALSE;
1302 }
1303
1304 target_ns = (uint64_t) (target_secs * ns_per_sec);
1305 current_ns = ((uint64_t) tm.tv_sec) * ns_per_sec + ((uint64_t) tm.tv_usec) * 1000;
1306 if (target_ns < current_ns) {
1307 php_error_docref(NULL, E_WARNING, "Argument #1 ($timestamp) must be greater than or equal to the current time");
1308 RETURN_FALSE;
1309 }
1310
1311 diff_ns = target_ns - current_ns;
1312 php_req.tv_sec = (time_t) (diff_ns / ns_per_sec);
1313 php_req.tv_nsec = (long) (diff_ns % ns_per_sec);
1314
1315 while (nanosleep(&php_req, &php_rem)) {
1316 if (errno == EINTR) {
1317 php_req.tv_sec = php_rem.tv_sec;
1318 php_req.tv_nsec = php_rem.tv_nsec;
1319 } else {
1320 RETURN_FALSE;
1321 }
1322 }
1323
1324 RETURN_TRUE;
1325 }
1326 /* }}} */
1327 #endif
1328
1329 /* {{{ Get the name of the owner of the current PHP script */
1330 PHP_FUNCTION(get_current_user)
1331 {
1332 ZEND_PARSE_PARAMETERS_NONE();
1333
1334 RETURN_STRING(php_get_current_user());
1335 }
1336 /* }}} */
1337
1338 #define ZVAL_SET_INI_STR(zv, val) do { \
1339 if (ZSTR_IS_INTERNED(val)) { \
1340 ZVAL_INTERNED_STR(zv, val); \
1341 } else if (ZSTR_LEN(val) == 0) { \
1342 ZVAL_EMPTY_STRING(zv); \
1343 } else if (ZSTR_LEN(val) == 1) { \
1344 ZVAL_CHAR(zv, ZSTR_VAL(val)[0]); \
1345 } else if (!(GC_FLAGS(val) & GC_PERSISTENT)) { \
1346 ZVAL_NEW_STR(zv, zend_string_copy(val)); \
1347 } else { \
1348 ZVAL_NEW_STR(zv, zend_string_init(ZSTR_VAL(val), ZSTR_LEN(val), 0)); \
1349 } \
1350 } while (0)
1351
1352 static void add_config_entries(HashTable *hash, zval *return_value);
1353
1354 /* {{{ add_config_entry */
1355 static void add_config_entry(zend_ulong h, zend_string *key, zval *entry, zval *retval)
1356 {
1357 if (Z_TYPE_P(entry) == IS_STRING) {
1358 zval str_zv;
1359 ZVAL_SET_INI_STR(&str_zv, Z_STR_P(entry));
1360 if (key) {
1361 add_assoc_zval_ex(retval, ZSTR_VAL(key), ZSTR_LEN(key), &str_zv);
1362 } else {
1363 add_index_zval(retval, h, &str_zv);
1364 }
1365 } else if (Z_TYPE_P(entry) == IS_ARRAY) {
1366 zval tmp;
1367 array_init(&tmp);
1368 add_config_entries(Z_ARRVAL_P(entry), &tmp);
1369 zend_hash_update(Z_ARRVAL_P(retval), key, &tmp);
1370 }
1371 }
1372 /* }}} */
1373
1374 /* {{{ add_config_entries */
1375 static void add_config_entries(HashTable *hash, zval *return_value) /* {{{ */
1376 {
1377 zend_ulong h;
1378 zend_string *key;
1379 zval *zv;
1380
1381 ZEND_HASH_FOREACH_KEY_VAL(hash, h, key, zv)
1382 add_config_entry(h, key, zv, return_value);
1383 ZEND_HASH_FOREACH_END();
1384 }
1385 /* }}} */
1386
1387 /* {{{ Get the value of a PHP configuration option */
1388 PHP_FUNCTION(get_cfg_var)
1389 {
1390 zend_string *varname;
1391
1392 ZEND_PARSE_PARAMETERS_START(1, 1)
1393 Z_PARAM_STR(varname)
1394 ZEND_PARSE_PARAMETERS_END();
1395
1396 zval *retval = cfg_get_entry_ex(varname);
1397
1398 if (retval) {
1399 if (Z_TYPE_P(retval) == IS_ARRAY) {
1400 array_init(return_value);
1401 add_config_entries(Z_ARRVAL_P(retval), return_value);
1402 return;
1403 } else {
1404 ZVAL_SET_INI_STR(return_value, Z_STR_P(retval));
1405 }
1406 } else {
1407 RETURN_FALSE;
1408 }
1409 }
1410 /* }}} */
1411
1412 /*
1413 1st arg = error message
1414 2nd arg = error option
1415 3rd arg = optional parameters (email address or tcp address)
1416 4th arg = used for additional headers if email
1417
1418 error options:
1419 0 = send to php_error_log (uses syslog or file depending on ini setting)
1420 1 = send via email to 3rd parameter 4th option = additional headers
1421 2 = send via tcp/ip to 3rd parameter (name or ip:port)
1422 3 = save to file in 3rd parameter
1423 4 = send to SAPI logger directly
1424 */
1425
1426 /* {{{ Send an error message somewhere */
1427 PHP_FUNCTION(error_log)
1428 {
1429 char *message, *opt = NULL, *headers = NULL;
1430 size_t message_len, opt_len = 0, headers_len = 0;
1431 zend_long erropt = 0;
1432
1433 ZEND_PARSE_PARAMETERS_START(1, 4)
1434 Z_PARAM_STRING(message, message_len)
1435 Z_PARAM_OPTIONAL
1436 Z_PARAM_LONG(erropt)
1437 Z_PARAM_PATH_OR_NULL(opt, opt_len)
1438 Z_PARAM_STRING_OR_NULL(headers, headers_len)
1439 ZEND_PARSE_PARAMETERS_END();
1440
1441 if (_php_error_log_ex((int) erropt, message, message_len, opt, headers) == FAILURE) {
1442 RETURN_FALSE;
1443 }
1444
1445 RETURN_TRUE;
1446 }
1447 /* }}} */
1448
1449 /* For BC (not binary-safe!) */
1450 PHPAPI int _php_error_log(int opt_err, const char *message, const char *opt, const char *headers) /* {{{ */
1451 {
1452 return _php_error_log_ex(opt_err, message, (opt_err == 3) ? strlen(message) : 0, opt, headers);
1453 }
1454 /* }}} */
1455
1456 PHPAPI int _php_error_log_ex(int opt_err, const char *message, size_t message_len, const char *opt, const char *headers) /* {{{ */
1457 {
1458 php_stream *stream = NULL;
1459 size_t nbytes;
1460
1461 switch (opt_err)
1462 {
1463 case 1: /*send an email */
1464 if (!php_mail(opt, "PHP error_log message", message, headers, NULL)) {
1465 return FAILURE;
1466 }
1467 break;
1468
1469 case 2: /*send to an address */
1470 zend_value_error("TCP/IP option is not available for error logging");
1471 return FAILURE;
1472
1473 case 3: /*save to a file */
1474 stream = php_stream_open_wrapper(opt, "a", REPORT_ERRORS, NULL);
1475 if (!stream) {
1476 return FAILURE;
1477 }
1478 nbytes = php_stream_write(stream, message, message_len);
1479 php_stream_close(stream);
1480 if (nbytes != message_len) {
1481 return FAILURE;
1482 }
1483 break;
1484
1485 case 4: /* send to SAPI */
1486 if (sapi_module.log_message) {
1487 sapi_module.log_message(message, -1);
1488 } else {
1489 return FAILURE;
1490 }
1491 break;
1492
1493 default:
1494 php_log_err_with_severity(message, LOG_NOTICE);
1495 break;
1496 }
1497 return SUCCESS;
1498 }
1499 /* }}} */
1500
1501 /* {{{ Get the last occurred error as associative array. Returns NULL if there hasn't been an error yet. */
1502 PHP_FUNCTION(error_get_last)
1503 {
1504 ZEND_PARSE_PARAMETERS_NONE();
1505
1506 if (PG(last_error_message)) {
1507 zval tmp;
1508 array_init(return_value);
1509
1510 ZVAL_LONG(&tmp, PG(last_error_type));
1511 zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
1512
1513 ZVAL_STR_COPY(&tmp, PG(last_error_message));
1514 zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
1515
1516 ZVAL_STR_COPY(&tmp, PG(last_error_file));
1517 zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
1518
1519 ZVAL_LONG(&tmp, PG(last_error_lineno));
1520 zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
1521 }
1522 }
1523 /* }}} */
1524
1525 /* {{{ Clear the last occurred error. */
1526 PHP_FUNCTION(error_clear_last)
1527 {
1528 ZEND_PARSE_PARAMETERS_NONE();
1529
1530 if (PG(last_error_message)) {
1531 PG(last_error_type) = 0;
1532 PG(last_error_lineno) = 0;
1533
1534 zend_string_release(PG(last_error_message));
1535 PG(last_error_message) = NULL;
1536
1537 if (PG(last_error_file)) {
1538 zend_string_release(PG(last_error_file));
1539 PG(last_error_file) = NULL;
1540 }
1541 }
1542 }
1543 /* }}} */
1544
1545 /* {{{ Call a user function which is the first parameter
1546 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1547 PHP_FUNCTION(call_user_func)
1548 {
1549 zval retval;
1550 zend_fcall_info fci;
1551 zend_fcall_info_cache fci_cache;
1552
1553 ZEND_PARSE_PARAMETERS_START(1, -1)
1554 Z_PARAM_FUNC(fci, fci_cache)
1555 Z_PARAM_VARIADIC_WITH_NAMED(fci.params, fci.param_count, fci.named_params)
1556 ZEND_PARSE_PARAMETERS_END();
1557
1558 fci.retval = &retval;
1559
1560 if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1561 if (Z_ISREF(retval)) {
1562 zend_unwrap_reference(&retval);
1563 }
1564 ZVAL_COPY_VALUE(return_value, &retval);
1565 }
1566 }
1567 /* }}} */
1568
1569 /* {{{ Call a user function which is the first parameter with the arguments contained in array
1570 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1571 PHP_FUNCTION(call_user_func_array)
1572 {
1573 zval retval;
1574 HashTable *params;
1575 zend_fcall_info fci;
1576 zend_fcall_info_cache fci_cache;
1577
1578 ZEND_PARSE_PARAMETERS_START(2, 2)
1579 Z_PARAM_FUNC(fci, fci_cache)
1580 Z_PARAM_ARRAY_HT(params)
1581 ZEND_PARSE_PARAMETERS_END();
1582
1583 fci.named_params = params;
1584 fci.retval = &retval;
1585
1586 if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1587 if (Z_ISREF(retval)) {
1588 zend_unwrap_reference(&retval);
1589 }
1590 ZVAL_COPY_VALUE(return_value, &retval);
1591 }
1592 }
1593 /* }}} */
1594
1595 /* {{{ Call a user function which is the first parameter */
1596 PHP_FUNCTION(forward_static_call)
1597 {
1598 zval retval;
1599 zend_fcall_info fci;
1600 zend_fcall_info_cache fci_cache;
1601 zend_class_entry *called_scope;
1602
1603 ZEND_PARSE_PARAMETERS_START(1, -1)
1604 Z_PARAM_FUNC(fci, fci_cache)
1605 Z_PARAM_VARIADIC('*', fci.params, fci.param_count)
1606 ZEND_PARSE_PARAMETERS_END();
1607
1608 if (!EX(prev_execute_data)->func->common.scope) {
1609 zend_throw_error(NULL, "Cannot call forward_static_call() when no class scope is active");
1610 RETURN_THROWS();
1611 }
1612
1613 fci.retval = &retval;
1614
1615 called_scope = zend_get_called_scope(execute_data);
1616 if (called_scope && fci_cache.calling_scope &&
1617 instanceof_function(called_scope, fci_cache.calling_scope)) {
1618 fci_cache.called_scope = called_scope;
1619 }
1620
1621 if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1622 if (Z_ISREF(retval)) {
1623 zend_unwrap_reference(&retval);
1624 }
1625 ZVAL_COPY_VALUE(return_value, &retval);
1626 }
1627 }
1628 /* }}} */
1629
1630 /* {{{ Call a static method which is the first parameter with the arguments contained in array */
1631 PHP_FUNCTION(forward_static_call_array)
1632 {
1633 zval *params, retval;
1634 zend_fcall_info fci;
1635 zend_fcall_info_cache fci_cache;
1636 zend_class_entry *called_scope;
1637
1638 ZEND_PARSE_PARAMETERS_START(2, 2)
1639 Z_PARAM_FUNC(fci, fci_cache)
1640 Z_PARAM_ARRAY(params)
1641 ZEND_PARSE_PARAMETERS_END();
1642
1643 zend_fcall_info_args(&fci, params);
1644 fci.retval = &retval;
1645
1646 called_scope = zend_get_called_scope(execute_data);
1647 if (called_scope && fci_cache.calling_scope &&
1648 instanceof_function(called_scope, fci_cache.calling_scope)) {
1649 fci_cache.called_scope = called_scope;
1650 }
1651
1652 if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1653 if (Z_ISREF(retval)) {
1654 zend_unwrap_reference(&retval);
1655 }
1656 ZVAL_COPY_VALUE(return_value, &retval);
1657 }
1658
1659 zend_fcall_info_args_clear(&fci, 1);
1660 }
1661 /* }}} */
1662
1663 static void fci_addref(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
1664 {
1665 Z_TRY_ADDREF(fci->function_name);
1666 if (fci_cache->object) {
1667 GC_ADDREF(fci_cache->object);
1668 }
1669 }
1670
1671 static void fci_release(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
1672 {
1673 zval_ptr_dtor(&fci->function_name);
1674 if (fci_cache->object) {
1675 zend_object_release(fci_cache->object);
1676 }
1677 }
1678
1679 void user_shutdown_function_dtor(zval *zv) /* {{{ */
1680 {
1681 php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1682
1683 zend_fcall_info_args_clear(&shutdown_function_entry->fci, true);
1684 fci_release(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache);
1685 efree(shutdown_function_entry);
1686 }
1687 /* }}} */
1688
1689 void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* {{{ */
1690 {
1691 zend_fcall_info_args_clear(&tick_function_entry->fci, true);
1692 fci_release(&tick_function_entry->fci, &tick_function_entry->fci_cache);
1693 }
1694 /* }}} */
1695
1696 static int user_shutdown_function_call(zval *zv) /* {{{ */
1697 {
1698 php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1699 zval retval;
1700 zend_result call_status;
1701
1702 /* set retval zval for FCI struct */
1703 shutdown_function_entry->fci.retval = &retval;
1704 call_status = zend_call_function(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache);
1705 ZEND_ASSERT(call_status == SUCCESS);
1706 zval_ptr_dtor(&retval);
1707
1708 return 0;
1709 }
1710 /* }}} */
1711
1712 static void user_tick_function_call(user_tick_function_entry *tick_fe) /* {{{ */
1713 {
1714 /* Prevent re-entrant calls to the same user ticks function */
1715 if (!tick_fe->calling) {
1716 zval tmp;
1717
1718 /* set tmp zval */
1719 tick_fe->fci.retval = &tmp;
1720
1721 tick_fe->calling = true;
1722 zend_call_function(&tick_fe->fci, &tick_fe->fci_cache);
1723
1724 /* Destroy return value */
1725 zval_ptr_dtor(&tmp);
1726 tick_fe->calling = false;
1727 }
1728 }
1729 /* }}} */
1730
1731 static void run_user_tick_functions(int tick_count, void *arg) /* {{{ */
1732 {
1733 zend_llist_apply(BG(user_tick_functions), (llist_apply_func_t) user_tick_function_call);
1734 }
1735 /* }}} */
1736
1737 static int user_tick_function_compare(user_tick_function_entry * tick_fe1, user_tick_function_entry * tick_fe2) /* {{{ */
1738 {
1739 zval *func1 = &tick_fe1->fci.function_name;
1740 zval *func2 = &tick_fe2->fci.function_name;
1741 int ret;
1742
1743 if (Z_TYPE_P(func1) == IS_STRING && Z_TYPE_P(func2) == IS_STRING) {
1744 ret = zend_binary_zval_strcmp(func1, func2) == 0;
1745 } else if (Z_TYPE_P(func1) == IS_ARRAY && Z_TYPE_P(func2) == IS_ARRAY) {
1746 ret = zend_compare_arrays(func1, func2) == 0;
1747 } else if (Z_TYPE_P(func1) == IS_OBJECT && Z_TYPE_P(func2) == IS_OBJECT) {
1748 ret = zend_compare_objects(func1, func2) == 0;
1749 } else {
1750 ret = 0;
1751 }
1752
1753 if (ret && tick_fe1->calling) {
1754 zend_throw_error(NULL, "Registered tick function cannot be unregistered while it is being executed");
1755 return 0;
1756 }
1757 return ret;
1758 }
1759 /* }}} */
1760
1761 PHPAPI void php_call_shutdown_functions(void) /* {{{ */
1762 {
1763 if (BG(user_shutdown_function_names)) {
1764 zend_try {
1765 zend_hash_apply(BG(user_shutdown_function_names), user_shutdown_function_call);
1766 } zend_end_try();
1767 }
1768 }
1769 /* }}} */
1770
1771 PHPAPI void php_free_shutdown_functions(void) /* {{{ */
1772 {
1773 if (BG(user_shutdown_function_names))
1774 zend_try {
1775 zend_hash_destroy(BG(user_shutdown_function_names));
1776 FREE_HASHTABLE(BG(user_shutdown_function_names));
1777 BG(user_shutdown_function_names) = NULL;
1778 } zend_catch {
1779 /* maybe shutdown method call exit, we just ignore it */
1780 FREE_HASHTABLE(BG(user_shutdown_function_names));
1781 BG(user_shutdown_function_names) = NULL;
1782 } zend_end_try();
1783 }
1784 /* }}} */
1785
1786 /* {{{ Register a user-level function to be called on request termination */
1787 PHP_FUNCTION(register_shutdown_function)
1788 {
1789 php_shutdown_function_entry entry;
1790 zval *params = NULL;
1791 uint32_t param_count = 0;
1792 bool status;
1793
1794 if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &entry.fci, &entry.fci_cache, ¶ms, ¶m_count) == FAILURE) {
1795 RETURN_THROWS();
1796 }
1797
1798 fci_addref(&entry.fci, &entry.fci_cache);
1799 zend_fcall_info_argp(&entry.fci, param_count, params);
1800
1801 status = append_user_shutdown_function(&entry);
1802 ZEND_ASSERT(status);
1803 }
1804 /* }}} */
1805
1806 PHPAPI bool register_user_shutdown_function(const char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1807 {
1808 if (!BG(user_shutdown_function_names)) {
1809 ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1810 zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1811 }
1812
1813 zend_hash_str_update_mem(BG(user_shutdown_function_names), function_name, function_len, shutdown_function_entry, sizeof(php_shutdown_function_entry));
1814 return 1;
1815 }
1816 /* }}} */
1817
1818 PHPAPI bool remove_user_shutdown_function(const char *function_name, size_t function_len) /* {{{ */
1819 {
1820 if (BG(user_shutdown_function_names)) {
1821 return zend_hash_str_del(BG(user_shutdown_function_names), function_name, function_len) != FAILURE;
1822 }
1823
1824 return 0;
1825 }
1826 /* }}} */
1827
1828 PHPAPI bool append_user_shutdown_function(php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1829 {
1830 if (!BG(user_shutdown_function_names)) {
1831 ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1832 zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1833 }
1834
1835 return zend_hash_next_index_insert_mem(BG(user_shutdown_function_names), shutdown_function_entry, sizeof(php_shutdown_function_entry)) != NULL;
1836 }
1837 /* }}} */
1838
1839 ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini) /* {{{ */
1840 {
1841 syntax_highlighter_ini->highlight_comment = INI_STR("highlight.comment");
1842 syntax_highlighter_ini->highlight_default = INI_STR("highlight.default");
1843 syntax_highlighter_ini->highlight_html = INI_STR("highlight.html");
1844 syntax_highlighter_ini->highlight_keyword = INI_STR("highlight.keyword");
1845 syntax_highlighter_ini->highlight_string = INI_STR("highlight.string");
1846 }
1847 /* }}} */
1848
1849 /* {{{ Syntax highlight a source file */
1850 PHP_FUNCTION(highlight_file)
1851 {
1852 char *filename;
1853 size_t filename_len;
1854 int ret;
1855 zend_syntax_highlighter_ini syntax_highlighter_ini;
1856 bool i = 0;
1857
1858 ZEND_PARSE_PARAMETERS_START(1, 2)
1859 Z_PARAM_PATH(filename, filename_len)
1860 Z_PARAM_OPTIONAL
1861 Z_PARAM_BOOL(i)
1862 ZEND_PARSE_PARAMETERS_END();
1863
1864 if (php_check_open_basedir(filename)) {
1865 RETURN_FALSE;
1866 }
1867
1868 if (i) {
1869 php_output_start_default();
1870 }
1871
1872 php_get_highlight_struct(&syntax_highlighter_ini);
1873
1874 ret = highlight_file(filename, &syntax_highlighter_ini);
1875
1876 if (ret == FAILURE) {
1877 if (i) {
1878 php_output_end();
1879 }
1880 RETURN_FALSE;
1881 }
1882
1883 if (i) {
1884 php_output_get_contents(return_value);
1885 php_output_discard();
1886 ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1887 } else {
1888 RETURN_TRUE;
1889 }
1890 }
1891 /* }}} */
1892
1893 /* {{{ Return source with stripped comments and whitespace */
1894 PHP_FUNCTION(php_strip_whitespace)
1895 {
1896 zend_string *filename;
1897 zend_lex_state original_lex_state;
1898 zend_file_handle file_handle;
1899
1900 ZEND_PARSE_PARAMETERS_START(1, 1)
1901 Z_PARAM_PATH_STR(filename)
1902 ZEND_PARSE_PARAMETERS_END();
1903
1904 php_output_start_default();
1905
1906 zend_stream_init_filename_ex(&file_handle, filename);
1907 zend_save_lexical_state(&original_lex_state);
1908 if (open_file_for_scanning(&file_handle) == FAILURE) {
1909 zend_restore_lexical_state(&original_lex_state);
1910 php_output_end();
1911 zend_destroy_file_handle(&file_handle);
1912 RETURN_EMPTY_STRING();
1913 }
1914
1915 zend_strip();
1916
1917 zend_restore_lexical_state(&original_lex_state);
1918
1919 php_output_get_contents(return_value);
1920 php_output_discard();
1921 zend_destroy_file_handle(&file_handle);
1922 }
1923 /* }}} */
1924
1925 /* {{{ Syntax highlight a string or optionally return it */
1926 PHP_FUNCTION(highlight_string)
1927 {
1928 zend_string *str;
1929 zend_syntax_highlighter_ini syntax_highlighter_ini;
1930 char *hicompiled_string_description;
1931 bool i = 0;
1932 int old_error_reporting = EG(error_reporting);
1933
1934 ZEND_PARSE_PARAMETERS_START(1, 2)
1935 Z_PARAM_STR(str)
1936 Z_PARAM_OPTIONAL
1937 Z_PARAM_BOOL(i)
1938 ZEND_PARSE_PARAMETERS_END();
1939
1940 if (i) {
1941 php_output_start_default();
1942 }
1943
1944 EG(error_reporting) = E_ERROR;
1945
1946 php_get_highlight_struct(&syntax_highlighter_ini);
1947
1948 hicompiled_string_description = zend_make_compiled_string_description("highlighted code");
1949
1950 highlight_string(str, &syntax_highlighter_ini, hicompiled_string_description);
1951 efree(hicompiled_string_description);
1952
1953 EG(error_reporting) = old_error_reporting;
1954
1955 if (i) {
1956 php_output_get_contents(return_value);
1957 php_output_discard();
1958 ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1959 } else {
1960 // TODO Make this function void?
1961 RETURN_TRUE;
1962 }
1963 }
1964 /* }}} */
1965
1966 /* {{{ Get a configuration option */
1967 PHP_FUNCTION(ini_get)
1968 {
1969 zend_string *varname, *val;
1970
1971 ZEND_PARSE_PARAMETERS_START(1, 1)
1972 Z_PARAM_STR(varname)
1973 ZEND_PARSE_PARAMETERS_END();
1974
1975 val = zend_ini_get_value(varname);
1976
1977 if (!val) {
1978 RETURN_FALSE;
1979 }
1980
1981 ZVAL_SET_INI_STR(return_value, val);
1982 }
1983 /* }}} */
1984
1985 /* {{{ Get all configuration options */
1986 PHP_FUNCTION(ini_get_all)
1987 {
1988 char *extname = NULL;
1989 size_t extname_len = 0, module_number = 0;
1990 zend_module_entry *module;
1991 bool details = 1;
1992 zend_string *key;
1993 zend_ini_entry *ini_entry;
1994
1995
1996 ZEND_PARSE_PARAMETERS_START(0, 2)
1997 Z_PARAM_OPTIONAL
1998 Z_PARAM_STRING_OR_NULL(extname, extname_len)
1999 Z_PARAM_BOOL(details)
2000 ZEND_PARSE_PARAMETERS_END();
2001
2002 zend_ini_sort_entries();
2003
2004 if (extname) {
2005 if ((module = zend_hash_str_find_ptr(&module_registry, extname, extname_len)) == NULL) {
2006 php_error_docref(NULL, E_WARNING, "Extension \"%s\" cannot be found", extname);
2007 RETURN_FALSE;
2008 }
2009 module_number = module->module_number;
2010 }
2011
2012 array_init(return_value);
2013 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(ini_directives), key, ini_entry) {
2014 zval option;
2015
2016 if (module_number != 0 && ini_entry->module_number != module_number) {
2017 continue;
2018 }
2019
2020 if (key == NULL || ZSTR_VAL(key)[0] != 0) {
2021 if (details) {
2022 array_init(&option);
2023
2024 if (ini_entry->orig_value) {
2025 add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->orig_value));
2026 } else if (ini_entry->value) {
2027 add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->value));
2028 } else {
2029 add_assoc_null(&option, "global_value");
2030 }
2031
2032 if (ini_entry->value) {
2033 add_assoc_str(&option, "local_value", zend_string_copy(ini_entry->value));
2034 } else {
2035 add_assoc_null(&option, "local_value");
2036 }
2037
2038 add_assoc_long(&option, "access", ini_entry->modifiable);
2039
2040 zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &option);
2041 } else {
2042 if (ini_entry->value) {
2043 zval zv;
2044
2045 ZVAL_STR_COPY(&zv, ini_entry->value);
2046 zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &zv);
2047 } else {
2048 zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &EG(uninitialized_zval));
2049 }
2050 }
2051 }
2052 } ZEND_HASH_FOREACH_END();
2053 }
2054 /* }}} */
2055
2056 static int php_ini_check_path(char *option_name, size_t option_len, char *new_option_name, size_t new_option_len) /* {{{ */
2057 {
2058 if (option_len + 1 != new_option_len) {
2059 return 0;
2060 }
2061
2062 return !strncmp(option_name, new_option_name, option_len);
2063 }
2064 /* }}} */
2065
2066 /* {{{ Set a configuration option, returns false on error and the old value of the configuration option on success */
2067 PHP_FUNCTION(ini_set)
2068 {
2069 zend_string *varname;
2070 zval *new_value;
2071 zend_string *val;
2072
2073 ZEND_PARSE_PARAMETERS_START(2, 2)
2074 Z_PARAM_STR(varname)
2075 Z_PARAM_ZVAL(new_value)
2076 ZEND_PARSE_PARAMETERS_END();
2077
2078 if (Z_TYPE_P(new_value) > IS_STRING) {
2079 zend_argument_type_error(2, "must be of type string|int|float|bool|null");
2080 RETURN_THROWS();
2081 }
2082
2083 val = zend_ini_get_value(varname);
2084
2085 if (val) {
2086 ZVAL_SET_INI_STR(return_value, val);
2087 } else {
2088 RETVAL_FALSE;
2089 }
2090
2091 zend_string *new_value_tmp_str;
2092 zend_string *new_value_str = zval_get_tmp_string(new_value, &new_value_tmp_str);
2093
2094 #define _CHECK_PATH(var, var_len, ini) php_ini_check_path(var, var_len, ini, sizeof(ini))
2095 /* open basedir check */
2096 if (PG(open_basedir)) {
2097 if (_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "error_log") ||
2098 _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.class.path") ||
2099 _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.home") ||
2100 _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "mail.log") ||
2101 _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.library.path") ||
2102 _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "vpopmail.directory")) {
2103 if (php_check_open_basedir(ZSTR_VAL(new_value_str))) {
2104 zval_ptr_dtor_str(return_value);
2105 zend_tmp_string_release(new_value_tmp_str);
2106 RETURN_FALSE;
2107 }
2108 }
2109 }
2110 #undef _CHECK_PATH
2111
2112 if (zend_alter_ini_entry_ex(varname, new_value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
2113 zval_ptr_dtor_str(return_value);
2114 RETVAL_FALSE;
2115 }
2116 zend_tmp_string_release(new_value_tmp_str);
2117 }
2118 /* }}} */
2119
2120 /* {{{ Restore the value of a configuration option specified by varname */
2121 PHP_FUNCTION(ini_restore)
2122 {
2123 zend_string *varname;
2124
2125 ZEND_PARSE_PARAMETERS_START(1, 1)
2126 Z_PARAM_STR(varname)
2127 ZEND_PARSE_PARAMETERS_END();
2128
2129 zend_restore_ini_entry(varname, PHP_INI_STAGE_RUNTIME);
2130 }
2131 /* }}} */
2132
2133 /* {{{ Sets the include_path configuration option */
2134 PHP_FUNCTION(set_include_path)
2135 {
2136 zend_string *new_value;
2137 char *old_value;
2138 zend_string *key;
2139
2140 ZEND_PARSE_PARAMETERS_START(1, 1)
2141 Z_PARAM_PATH_STR(new_value)
2142 ZEND_PARSE_PARAMETERS_END();
2143
2144 old_value = zend_ini_string("include_path", sizeof("include_path") - 1, 0);
2145 /* copy to return here, because alter might free it! */
2146 if (old_value) {
2147 RETVAL_STRING(old_value);
2148 } else {
2149 RETVAL_FALSE;
2150 }
2151
2152 key = zend_string_init("include_path", sizeof("include_path") - 1, 0);
2153 if (zend_alter_ini_entry_ex(key, new_value, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
2154 zend_string_release_ex(key, 0);
2155 zval_ptr_dtor_str(return_value);
2156 RETURN_FALSE;
2157 }
2158 zend_string_release_ex(key, 0);
2159 }
2160 /* }}} */
2161
2162 /* {{{ Get the current include_path configuration option */
2163 PHP_FUNCTION(get_include_path)
2164 {
2165 char *str;
2166
2167 ZEND_PARSE_PARAMETERS_NONE();
2168
2169 str = zend_ini_string("include_path", sizeof("include_path") - 1, 0);
2170
2171 if (str == NULL) {
2172 RETURN_FALSE;
2173 }
2174
2175 RETURN_STRING(str);
2176 }
2177 /* }}} */
2178
2179 /* {{{ Prints out or returns information about the specified variable */
2180 PHP_FUNCTION(print_r)
2181 {
2182 zval *var;
2183 bool do_return = 0;
2184
2185 ZEND_PARSE_PARAMETERS_START(1, 2)
2186 Z_PARAM_ZVAL(var)
2187 Z_PARAM_OPTIONAL
2188 Z_PARAM_BOOL(do_return)
2189 ZEND_PARSE_PARAMETERS_END();
2190
2191 if (do_return) {
2192 RETURN_STR(zend_print_zval_r_to_str(var, 0));
2193 } else {
2194 zend_print_zval_r(var, 0);
2195 RETURN_TRUE;
2196 }
2197 }
2198 /* }}} */
2199
2200 /* {{{ Returns true if client disconnected */
2201 PHP_FUNCTION(connection_aborted)
2202 {
2203 ZEND_PARSE_PARAMETERS_NONE();
2204
2205 RETURN_LONG(PG(connection_status) & PHP_CONNECTION_ABORTED);
2206 }
2207 /* }}} */
2208
2209 /* {{{ Returns the connection status bitfield */
2210 PHP_FUNCTION(connection_status)
2211 {
2212 ZEND_PARSE_PARAMETERS_NONE();
2213
2214 RETURN_LONG(PG(connection_status));
2215 }
2216 /* }}} */
2217
2218 /* {{{ Set whether we want to ignore a user abort event or not */
2219 PHP_FUNCTION(ignore_user_abort)
2220 {
2221 bool arg = 0;
2222 bool arg_is_null = 1;
2223 int old_setting;
2224
2225 ZEND_PARSE_PARAMETERS_START(0, 1)
2226 Z_PARAM_OPTIONAL
2227 Z_PARAM_BOOL_OR_NULL(arg, arg_is_null)
2228 ZEND_PARSE_PARAMETERS_END();
2229
2230 old_setting = (unsigned short)PG(ignore_user_abort);
2231
2232 if (!arg_is_null) {
2233 zend_string *key = zend_string_init("ignore_user_abort", sizeof("ignore_user_abort") - 1, 0);
2234 zend_alter_ini_entry_chars(key, arg ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
2235 zend_string_release_ex(key, 0);
2236 }
2237
2238 RETURN_LONG(old_setting);
2239 }
2240 /* }}} */
2241
2242 #if HAVE_GETSERVBYNAME
2243 /* {{{ Returns port associated with service. Protocol must be "tcp" or "udp" */
2244 PHP_FUNCTION(getservbyname)
2245 {
2246 zend_string *name;
2247 char *proto;
2248 size_t proto_len;
2249 struct servent *serv;
2250
2251 ZEND_PARSE_PARAMETERS_START(2, 2)
2252 Z_PARAM_STR(name)
2253 Z_PARAM_STRING(proto, proto_len)
2254 ZEND_PARSE_PARAMETERS_END();
2255
2256
2257 /* empty string behaves like NULL on windows implementation of
2258 getservbyname. Let be portable instead. */
2259 #ifdef PHP_WIN32
2260 if (proto_len == 0) {
2261 RETURN_FALSE;
2262 }
2263 #endif
2264
2265 serv = getservbyname(ZSTR_VAL(name), proto);
2266
2267 #if defined(_AIX)
2268 /*
2269 On AIX, imap is only known as imap2 in /etc/services, while on Linux imap is an alias for imap2.
2270 If a request for imap gives no result, we try again with imap2.
2271 */
2272 if (serv == NULL && zend_string_equals_literal(name, "imap")) {
2273 serv = getservbyname("imap2", proto);
2274 }
2275 #endif
2276 if (serv == NULL) {
2277 RETURN_FALSE;
2278 }
2279
2280 RETURN_LONG(ntohs(serv->s_port));
2281 }
2282 /* }}} */
2283 #endif
2284
2285 #if HAVE_GETSERVBYPORT
2286 /* {{{ Returns service name associated with port. Protocol must be "tcp" or "udp" */
2287 PHP_FUNCTION(getservbyport)
2288 {
2289 char *proto;
2290 size_t proto_len;
2291 zend_long port;
2292 struct servent *serv;
2293
2294 ZEND_PARSE_PARAMETERS_START(2, 2)
2295 Z_PARAM_LONG(port)
2296 Z_PARAM_STRING(proto, proto_len)
2297 ZEND_PARSE_PARAMETERS_END();
2298
2299 serv = getservbyport(htons((unsigned short) port), proto);
2300
2301 if (serv == NULL) {
2302 RETURN_FALSE;
2303 }
2304
2305 RETURN_STRING(serv->s_name);
2306 }
2307 /* }}} */
2308 #endif
2309
2310 #if HAVE_GETPROTOBYNAME
2311 /* {{{ Returns protocol number associated with name as per /etc/protocols */
2312 PHP_FUNCTION(getprotobyname)
2313 {
2314 char *name;
2315 size_t name_len;
2316 struct protoent *ent;
2317
2318 ZEND_PARSE_PARAMETERS_START(1, 1)
2319 Z_PARAM_STRING(name, name_len)
2320 ZEND_PARSE_PARAMETERS_END();
2321
2322 ent = getprotobyname(name);
2323
2324 if (ent == NULL) {
2325 RETURN_FALSE;
2326 }
2327
2328 RETURN_LONG(ent->p_proto);
2329 }
2330 /* }}} */
2331 #endif
2332
2333 #if HAVE_GETPROTOBYNUMBER
2334 /* {{{ Returns protocol name associated with protocol number proto */
2335 PHP_FUNCTION(getprotobynumber)
2336 {
2337 zend_long proto;
2338 struct protoent *ent;
2339
2340 ZEND_PARSE_PARAMETERS_START(1, 1)
2341 Z_PARAM_LONG(proto)
2342 ZEND_PARSE_PARAMETERS_END();
2343
2344 ent = getprotobynumber((int)proto);
2345
2346 if (ent == NULL) {
2347 RETURN_FALSE;
2348 }
2349
2350 RETURN_STRING(ent->p_name);
2351 }
2352 /* }}} */
2353 #endif
2354
2355 /* {{{ Registers a tick callback function */
2356 PHP_FUNCTION(register_tick_function)
2357 {
2358 user_tick_function_entry tick_fe;
2359 zval *params = NULL;
2360 uint32_t param_count = 0;
2361
2362 if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &tick_fe.fci, &tick_fe.fci_cache, ¶ms, ¶m_count) == FAILURE) {
2363 RETURN_THROWS();
2364 }
2365
2366 tick_fe.calling = false;
2367 fci_addref(&tick_fe.fci, &tick_fe.fci_cache);
2368 zend_fcall_info_argp(&tick_fe.fci, param_count, params);
2369
2370 if (!BG(user_tick_functions)) {
2371 BG(user_tick_functions) = (zend_llist *) emalloc(sizeof(zend_llist));
2372 zend_llist_init(BG(user_tick_functions),
2373 sizeof(user_tick_function_entry),
2374 (llist_dtor_func_t) user_tick_function_dtor, 0);
2375 php_add_tick_function(run_user_tick_functions, NULL);
2376 }
2377
2378 zend_llist_add_element(BG(user_tick_functions), &tick_fe);
2379
2380 RETURN_TRUE;
2381 }
2382 /* }}} */
2383
2384 /* {{{ Unregisters a tick callback function */
2385 PHP_FUNCTION(unregister_tick_function)
2386 {
2387 user_tick_function_entry tick_fe;
2388
2389 ZEND_PARSE_PARAMETERS_START(1, 1)
2390 Z_PARAM_FUNC(tick_fe.fci, tick_fe.fci_cache)
2391 ZEND_PARSE_PARAMETERS_END();
2392
2393 if (!BG(user_tick_functions)) {
2394 return;
2395 }
2396
2397 zend_llist_del_element(BG(user_tick_functions), &tick_fe, (int (*)(void *, void *)) user_tick_function_compare);
2398 }
2399 /* }}} */
2400
2401 /* {{{ Check if file was created by rfc1867 upload */
2402 PHP_FUNCTION(is_uploaded_file)
2403 {
2404 char *path;
2405 size_t path_len;
2406
2407 ZEND_PARSE_PARAMETERS_START(1, 1)
2408 Z_PARAM_PATH(path, path_len)
2409 ZEND_PARSE_PARAMETERS_END();
2410
2411 if (!SG(rfc1867_uploaded_files)) {
2412 RETURN_FALSE;
2413 }
2414
2415 if (zend_hash_str_exists(SG(rfc1867_uploaded_files), path, path_len)) {
2416 RETURN_TRUE;
2417 } else {
2418 RETURN_FALSE;
2419 }
2420 }
2421 /* }}} */
2422
2423 /* {{{ Move a file if and only if it was created by an upload */
2424 PHP_FUNCTION(move_uploaded_file)
2425 {
2426 char *path, *new_path;
2427 size_t path_len, new_path_len;
2428 bool successful = 0;
2429
2430 #ifndef PHP_WIN32
2431 int oldmask; int ret;
2432 #endif
2433
2434 ZEND_PARSE_PARAMETERS_START(2, 2)
2435 Z_PARAM_STRING(path, path_len)
2436 Z_PARAM_PATH(new_path, new_path_len)
2437 ZEND_PARSE_PARAMETERS_END();
2438
2439 if (!SG(rfc1867_uploaded_files)) {
2440 RETURN_FALSE;
2441 }
2442
2443 if (!zend_hash_str_exists(SG(rfc1867_uploaded_files), path, path_len)) {
2444 RETURN_FALSE;
2445 }
2446
2447 if (php_check_open_basedir(new_path)) {
2448 RETURN_FALSE;
2449 }
2450
2451 if (VCWD_RENAME(path, new_path) == 0) {
2452 successful = 1;
2453 #ifndef PHP_WIN32
2454 oldmask = umask(077);
2455 umask(oldmask);
2456
2457 ret = VCWD_CHMOD(new_path, 0666 & ~oldmask);
2458
2459 if (ret == -1) {
2460 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
2461 }
2462 #endif
2463 } else if (php_copy_file_ex(path, new_path, STREAM_DISABLE_OPEN_BASEDIR) == SUCCESS) {
2464 VCWD_UNLINK(path);
2465 successful = 1;
2466 }
2467
2468 if (successful) {
2469 zend_hash_str_del(SG(rfc1867_uploaded_files), path, path_len);
2470 } else {
2471 php_error_docref(NULL, E_WARNING, "Unable to move \"%s\" to \"%s\"", path, new_path);
2472 }
2473
2474 RETURN_BOOL(successful);
2475 }
2476 /* }}} */
2477
2478 /* {{{ php_simple_ini_parser_cb */
2479 static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2480 {
2481 switch (callback_type) {
2482
2483 case ZEND_INI_PARSER_ENTRY:
2484 if (!arg2) {
2485 /* bare string - nothing to do */
2486 break;
2487 }
2488 Z_TRY_ADDREF_P(arg2);
2489 zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), arg2);
2490 break;
2491
2492 case ZEND_INI_PARSER_POP_ENTRY:
2493 {
2494 zval hash, *find_hash;
2495
2496 if (!arg2) {
2497 /* bare string - nothing to do */
2498 break;
2499 }
2500
2501 if (!(Z_STRLEN_P(arg1) > 1 && Z_STRVAL_P(arg1)[0] == '0') && is_numeric_string(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), NULL, NULL, 0) == IS_LONG) {
2502 zend_ulong key = (zend_ulong) zend_atol(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1));
2503 if ((find_hash = zend_hash_index_find(Z_ARRVAL_P(arr), key)) == NULL) {
2504 array_init(&hash);
2505 find_hash = zend_hash_index_add_new(Z_ARRVAL_P(arr), key, &hash);
2506 }
2507 } else {
2508 if ((find_hash = zend_hash_find(Z_ARRVAL_P(arr), Z_STR_P(arg1))) == NULL) {
2509 array_init(&hash);
2510 find_hash = zend_hash_add_new(Z_ARRVAL_P(arr), Z_STR_P(arg1), &hash);
2511 }
2512 }
2513
2514 if (Z_TYPE_P(find_hash) != IS_ARRAY) {
2515 zval_ptr_dtor_nogc(find_hash);
2516 array_init(find_hash);
2517 }
2518
2519 if (!arg3 || (Z_TYPE_P(arg3) == IS_STRING && Z_STRLEN_P(arg3) == 0)) {
2520 Z_TRY_ADDREF_P(arg2);
2521 add_next_index_zval(find_hash, arg2);
2522 } else {
2523 array_set_zval_key(Z_ARRVAL_P(find_hash), arg3, arg2);
2524 }
2525 }
2526 break;
2527
2528 case ZEND_INI_PARSER_SECTION:
2529 break;
2530 }
2531 }
2532 /* }}} */
2533
2534 /* {{{ php_ini_parser_cb_with_sections */
2535 static void php_ini_parser_cb_with_sections(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2536 {
2537 if (callback_type == ZEND_INI_PARSER_SECTION) {
2538 array_init(&BG(active_ini_file_section));
2539 zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), &BG(active_ini_file_section));
2540 } else if (arg2) {
2541 zval *active_arr;
2542
2543 if (Z_TYPE(BG(active_ini_file_section)) != IS_UNDEF) {
2544 active_arr = &BG(active_ini_file_section);
2545 } else {
2546 active_arr = arr;
2547 }
2548
2549 php_simple_ini_parser_cb(arg1, arg2, arg3, callback_type, active_arr);
2550 }
2551 }
2552 /* }}} */
2553
2554 /* {{{ Parse configuration file */
2555 PHP_FUNCTION(parse_ini_file)
2556 {
2557 zend_string *filename = NULL;
2558 bool process_sections = 0;
2559 zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2560 zend_file_handle fh;
2561 zend_ini_parser_cb_t ini_parser_cb;
2562
2563 ZEND_PARSE_PARAMETERS_START(1, 3)
2564 Z_PARAM_PATH_STR(filename)
2565 Z_PARAM_OPTIONAL
2566 Z_PARAM_BOOL(process_sections)
2567 Z_PARAM_LONG(scanner_mode)
2568 ZEND_PARSE_PARAMETERS_END();
2569
2570 if (ZSTR_LEN(filename) == 0) {
2571 zend_argument_value_error(1, "cannot be empty");
2572 RETURN_THROWS();
2573 }
2574
2575 /* Set callback function */
2576 if (process_sections) {
2577 ZVAL_UNDEF(&BG(active_ini_file_section));
2578 ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2579 } else {
2580 ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2581 }
2582
2583 /* Setup filehandle */
2584 zend_stream_init_filename_ex(&fh, filename);
2585
2586 array_init(return_value);
2587 if (zend_parse_ini_file(&fh, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2588 zend_array_destroy(Z_ARR_P(return_value));
2589 RETVAL_FALSE;
2590 }
2591 zend_destroy_file_handle(&fh);
2592 }
2593 /* }}} */
2594
2595 /* {{{ Parse configuration string */
2596 PHP_FUNCTION(parse_ini_string)
2597 {
2598 char *string = NULL, *str = NULL;
2599 size_t str_len = 0;
2600 bool process_sections = 0;
2601 zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2602 zend_ini_parser_cb_t ini_parser_cb;
2603
2604 ZEND_PARSE_PARAMETERS_START(1, 3)
2605 Z_PARAM_STRING(str, str_len)
2606 Z_PARAM_OPTIONAL
2607 Z_PARAM_BOOL(process_sections)
2608 Z_PARAM_LONG(scanner_mode)
2609 ZEND_PARSE_PARAMETERS_END();
2610
2611 if (INT_MAX - str_len < ZEND_MMAP_AHEAD) {
2612 RETVAL_FALSE;
2613 }
2614
2615 /* Set callback function */
2616 if (process_sections) {
2617 ZVAL_UNDEF(&BG(active_ini_file_section));
2618 ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2619 } else {
2620 ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2621 }
2622
2623 /* Setup string */
2624 string = (char *) emalloc(str_len + ZEND_MMAP_AHEAD);
2625 memcpy(string, str, str_len);
2626 memset(string + str_len, 0, ZEND_MMAP_AHEAD);
2627
2628 array_init(return_value);
2629 if (zend_parse_ini_string(string, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2630 zend_array_destroy(Z_ARR_P(return_value));
2631 RETVAL_FALSE;
2632 }
2633 efree(string);
2634 }
2635 /* }}} */
2636
2637 #if ZEND_DEBUG
2638 /* This function returns an array of ALL valid ini options with values and
2639 * is not the same as ini_get_all() which returns only registered ini options. Only useful for devs to debug php.ini scanner/parser! */
2640 PHP_FUNCTION(config_get_hash) /* {{{ */
2641 {
2642 ZEND_PARSE_PARAMETERS_NONE();
2643
2644 HashTable *hash = php_ini_get_configuration_hash();
2645
2646 array_init(return_value);
2647 add_config_entries(hash, return_value);
2648 }
2649 /* }}} */
2650 #endif
2651
2652 #ifdef HAVE_GETLOADAVG
2653 /* {{{ */
2654 PHP_FUNCTION(sys_getloadavg)
2655 {
2656 double load[3];
2657
2658 ZEND_PARSE_PARAMETERS_NONE();
2659
2660 if (getloadavg(load, 3) == -1) {
2661 RETURN_FALSE;
2662 } else {
2663 array_init(return_value);
2664 add_index_double(return_value, 0, load[0]);
2665 add_index_double(return_value, 1, load[1]);
2666 add_index_double(return_value, 2, load[2]);
2667 }
2668 }
2669 /* }}} */
2670 #endif
2671