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