Coverage Report

Created: 2026-01-18 06:47

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