1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2017 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Zeev Suraski <zeev@zend.com> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #include "php.h"
22 #include "ext/standard/info.h"
23 #include "zend_ini.h"
24 #include "zend_ini_scanner.h"
25 #include "php_ini.h"
26 #include "ext/standard/dl.h"
27 #include "zend_extensions.h"
28 #include "zend_highlight.h"
29 #include "SAPI.h"
30 #include "php_main.h"
31 #include "php_scandir.h"
32 #ifdef PHP_WIN32
33 #include "win32/php_registry.h"
34 #endif
35
36 #if HAVE_SCANDIR && HAVE_ALPHASORT && HAVE_DIRENT_H
37 #include <dirent.h>
38 #endif
39
40 #ifdef PHP_WIN32
41 #define TRANSLATE_SLASHES_LOWER(path) \
42 { \
43 char *tmp = path; \
44 while (*tmp) { \
45 if (*tmp == '\\') *tmp = '/'; \
46 else *tmp = tolower(*tmp); \
47 tmp++; \
48 } \
49 }
50 #else
51 #define TRANSLATE_SLASHES_LOWER(path)
52 #endif
53
54
55 typedef struct _php_extension_lists {
56 zend_llist engine;
57 zend_llist functions;
58 } php_extension_lists;
59
60 /* True globals */
61 static int is_special_section = 0;
62 static HashTable *active_ini_hash;
63 static HashTable configuration_hash;
64 static int has_per_dir_config = 0;
65 static int has_per_host_config = 0;
66 PHPAPI char *php_ini_opened_path=NULL;
67 static php_extension_lists extension_lists;
68 PHPAPI char *php_ini_scanned_path=NULL;
69 PHPAPI char *php_ini_scanned_files=NULL;
70
71 /* {{{ php_ini_displayer_cb
72 */
php_ini_displayer_cb(zend_ini_entry * ini_entry,int type)73 static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type)
74 {
75 if (ini_entry->displayer) {
76 ini_entry->displayer(ini_entry, type);
77 } else {
78 char *display_string;
79 size_t display_string_length;
80 int esc_html=0;
81
82 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
83 if (ini_entry->orig_value && ZSTR_VAL(ini_entry->orig_value)[0]) {
84 display_string = ZSTR_VAL(ini_entry->orig_value);
85 display_string_length = ZSTR_LEN(ini_entry->orig_value);
86 esc_html = !sapi_module.phpinfo_as_text;
87 } else {
88 if (!sapi_module.phpinfo_as_text) {
89 display_string = "<i>no value</i>";
90 display_string_length = sizeof("<i>no value</i>") - 1;
91 } else {
92 display_string = "no value";
93 display_string_length = sizeof("no value") - 1;
94 }
95 }
96 } else if (ini_entry->value && ZSTR_VAL(ini_entry->value)[0]) {
97 display_string = ZSTR_VAL(ini_entry->value);
98 display_string_length = ZSTR_LEN(ini_entry->value);
99 esc_html = !sapi_module.phpinfo_as_text;
100 } else {
101 if (!sapi_module.phpinfo_as_text) {
102 display_string = "<i>no value</i>";
103 display_string_length = sizeof("<i>no value</i>") - 1;
104 } else {
105 display_string = "no value";
106 display_string_length = sizeof("no value") - 1;
107 }
108 }
109
110 if (esc_html) {
111 php_html_puts(display_string, display_string_length);
112 } else {
113 PHPWRITE(display_string, display_string_length);
114 }
115 }
116 }
117 /* }}} */
118
119 /* {{{ php_ini_displayer
120 */
php_ini_displayer(zval * el,void * arg)121 static int php_ini_displayer(zval *el, void *arg)
122 {
123 zend_ini_entry *ini_entry = (zend_ini_entry*)Z_PTR_P(el);
124 int module_number = *(int *)arg;
125
126 if (ini_entry->module_number != module_number) {
127 return 0;
128 }
129 if (!sapi_module.phpinfo_as_text) {
130 PUTS("<tr>");
131 PUTS("<td class=\"e\">");
132 PHPWRITE(ZSTR_VAL(ini_entry->name), ZSTR_LEN(ini_entry->name));
133 PUTS("</td><td class=\"v\">");
134 php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE);
135 PUTS("</td><td class=\"v\">");
136 php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG);
137 PUTS("</td></tr>\n");
138 } else {
139 PHPWRITE(ZSTR_VAL(ini_entry->name), ZSTR_LEN(ini_entry->name));
140 PUTS(" => ");
141 php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE);
142 PUTS(" => ");
143 php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG);
144 PUTS("\n");
145 }
146 return 0;
147 }
148 /* }}} */
149
150 /* {{{ php_ini_available
151 */
php_ini_available(zval * el,void * arg)152 static int php_ini_available(zval *el, void *arg)
153 {
154 zend_ini_entry *ini_entry = (zend_ini_entry *)Z_PTR_P(el);
155 int *module_number_available = (int *)arg;
156 if (ini_entry->module_number == *(int *)module_number_available) {
157 *(int *)module_number_available = -1;
158 return ZEND_HASH_APPLY_STOP;
159 } else {
160 return ZEND_HASH_APPLY_KEEP;
161 }
162 }
163 /* }}} */
164
165 /* {{{ display_ini_entries
166 */
display_ini_entries(zend_module_entry * module)167 PHPAPI void display_ini_entries(zend_module_entry *module)
168 {
169 int module_number, module_number_available;
170
171 if (module) {
172 module_number = module->module_number;
173 } else {
174 module_number = 0;
175 }
176 module_number_available = module_number;
177 zend_hash_apply_with_argument(EG(ini_directives), php_ini_available, &module_number_available);
178 if (module_number_available == -1) {
179 php_info_print_table_start();
180 php_info_print_table_header(3, "Directive", "Local Value", "Master Value");
181 zend_hash_apply_with_argument(EG(ini_directives), php_ini_displayer, (void *)&module_number);
182 php_info_print_table_end();
183 }
184 }
185 /* }}} */
186
187 /* php.ini support */
188 #define PHP_EXTENSION_TOKEN "extension"
189 #define ZEND_EXTENSION_TOKEN "zend_extension"
190
191 /* {{{ config_zval_dtor
192 */
config_zval_dtor(zval * zvalue)193 PHPAPI void config_zval_dtor(zval *zvalue)
194 {
195 if (Z_TYPE_P(zvalue) == IS_ARRAY) {
196 zend_hash_destroy(Z_ARRVAL_P(zvalue));
197 free(Z_ARR_P(zvalue));
198 } else if (Z_TYPE_P(zvalue) == IS_STRING) {
199 zend_string_release(Z_STR_P(zvalue));
200 }
201 }
202 /* Reset / free active_ini_sectin global */
203 #define RESET_ACTIVE_INI_HASH() do { \
204 active_ini_hash = NULL; \
205 is_special_section = 0; \
206 } while (0)
207 /* }}} */
208
209 /* {{{ php_ini_parser_cb
210 */
php_ini_parser_cb(zval * arg1,zval * arg2,zval * arg3,int callback_type,HashTable * target_hash)211 static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, HashTable *target_hash)
212 {
213 zval *entry;
214 HashTable *active_hash;
215 char *extension_name;
216
217 if (active_ini_hash) {
218 active_hash = active_ini_hash;
219 } else {
220 active_hash = target_hash;
221 }
222
223 switch (callback_type) {
224 case ZEND_INI_PARSER_ENTRY: {
225 if (!arg2) {
226 /* bare string - nothing to do */
227 break;
228 }
229
230 /* PHP and Zend extensions are not added into configuration hash! */
231 if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), PHP_EXTENSION_TOKEN)) { /* load PHP extension */
232 extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
233 zend_llist_add_element(&extension_lists.functions, &extension_name);
234 } else if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), ZEND_EXTENSION_TOKEN)) { /* load Zend extension */
235 extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
236 zend_llist_add_element(&extension_lists.engine, &extension_name);
237
238 /* All other entries are added into either configuration_hash or active ini section array */
239 } else {
240 /* Store in active hash */
241 entry = zend_hash_update(active_hash, Z_STR_P(arg1), arg2);
242 Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), 1);
243 }
244 }
245 break;
246
247 case ZEND_INI_PARSER_POP_ENTRY: {
248 zval option_arr;
249 zval *find_arr;
250
251 if (!arg2) {
252 /* bare string - nothing to do */
253 break;
254 }
255
256 /* fprintf(stdout, "ZEND_INI_PARSER_POP_ENTRY: %s[%s] = %s\n",Z_STRVAL_P(arg1), Z_STRVAL_P(arg3), Z_STRVAL_P(arg2)); */
257
258 /* If option not found in hash or is not an array -> create array, otherwise add to existing array */
259 if ((find_arr = zend_hash_find(active_hash, Z_STR_P(arg1))) == NULL || Z_TYPE_P(find_arr) != IS_ARRAY) {
260 ZVAL_NEW_PERSISTENT_ARR(&option_arr);
261 zend_hash_init(Z_ARRVAL(option_arr), 8, NULL, config_zval_dtor, 1);
262 find_arr = zend_hash_update(active_hash, Z_STR_P(arg1), &option_arr);
263 }
264
265 /* arg3 is possible option offset name */
266 if (arg3 && Z_STRLEN_P(arg3) > 0) {
267 entry = zend_symtable_update(Z_ARRVAL_P(find_arr), Z_STR_P(arg3), arg2);
268 } else {
269 entry = zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2);
270 }
271 Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), 1);
272 }
273 break;
274
275 case ZEND_INI_PARSER_SECTION: { /* Create an array of entries of each section */
276
277 /* fprintf(stdout, "ZEND_INI_PARSER_SECTION: %s\n",Z_STRVAL_P(arg1)); */
278
279 char *key = NULL;
280 size_t key_len;
281
282 /* PATH sections */
283 if (!zend_binary_strncasecmp(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), "PATH", sizeof("PATH") - 1, sizeof("PATH") - 1)) {
284 key = Z_STRVAL_P(arg1);
285 key = key + sizeof("PATH") - 1;
286 key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1;
287 is_special_section = 1;
288 has_per_dir_config = 1;
289
290 /* make the path lowercase on Windows, for case insensitivity. Does nothing for other platforms */
291 TRANSLATE_SLASHES_LOWER(key);
292
293 /* HOST sections */
294 } else if (!zend_binary_strncasecmp(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), "HOST", sizeof("HOST") - 1, sizeof("HOST") - 1)) {
295 key = Z_STRVAL_P(arg1);
296 key = key + sizeof("HOST") - 1;
297 key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1;
298 is_special_section = 1;
299 has_per_host_config = 1;
300 zend_str_tolower(key, key_len); /* host names are case-insensitive. */
301
302 } else {
303 is_special_section = 0;
304 }
305
306 if (key && key_len > 0) {
307 /* Strip any trailing slashes */
308 while (key_len > 0 && (key[key_len - 1] == '/' || key[key_len - 1] == '\\')) {
309 key_len--;
310 key[key_len] = 0;
311 }
312
313 /* Strip any leading whitespace and '=' */
314 while (*key && (
315 *key == '=' ||
316 *key == ' ' ||
317 *key == '\t'
318 )) {
319 key++;
320 key_len--;
321 }
322
323 /* Search for existing entry and if it does not exist create one */
324 if ((entry = zend_hash_str_find(target_hash, key, key_len)) == NULL) {
325 zval section_arr;
326
327 ZVAL_NEW_PERSISTENT_ARR(§ion_arr);
328 zend_hash_init(Z_ARRVAL(section_arr), 8, NULL, (dtor_func_t) config_zval_dtor, 1);
329 entry = zend_hash_str_update(target_hash, key, key_len, §ion_arr);
330 }
331 if (Z_TYPE_P(entry) == IS_ARRAY) {
332 active_ini_hash = Z_ARRVAL_P(entry);
333 }
334 }
335 }
336 break;
337 }
338 }
339 /* }}} */
340
341 /* {{{ php_load_php_extension_cb
342 */
php_load_php_extension_cb(void * arg)343 static void php_load_php_extension_cb(void *arg)
344 {
345 #ifdef HAVE_LIBDL
346 php_load_extension(*((char **) arg), MODULE_PERSISTENT, 0);
347 #endif
348 }
349 /* }}} */
350
351 /* {{{ php_load_zend_extension_cb
352 */
php_load_zend_extension_cb(void * arg)353 static void php_load_zend_extension_cb(void *arg)
354 {
355 char *filename = *((char **) arg);
356 const int length = (int)strlen(filename);
357
358 #ifndef PHP_WIN32
359 (void) length;
360 #endif
361
362 if (IS_ABSOLUTE_PATH(filename, length)) {
363 zend_load_extension(filename);
364 } else {
365 char *libpath;
366 char *extension_dir = INI_STR("extension_dir");
367 int extension_dir_len = (int)strlen(extension_dir);
368
369 if (IS_SLASH(extension_dir[extension_dir_len-1])) {
370 spprintf(&libpath, 0, "%s%s", extension_dir, filename);
371 } else {
372 spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename);
373 }
374 zend_load_extension(libpath);
375 efree(libpath);
376 }
377 }
378 /* }}} */
379
380 /* {{{ php_init_config
381 */
php_init_config(void)382 int php_init_config(void)
383 {
384 char *php_ini_file_name = NULL;
385 char *php_ini_search_path = NULL;
386 int php_ini_scanned_path_len;
387 char *open_basedir;
388 int free_ini_search_path = 0;
389 zend_file_handle fh;
390 zend_string *opened_path = NULL;
391
392 zend_hash_init(&configuration_hash, 8, NULL, config_zval_dtor, 1);
393
394 if (sapi_module.ini_defaults) {
395 sapi_module.ini_defaults(&configuration_hash);
396 }
397
398 zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
399 zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
400
401 open_basedir = PG(open_basedir);
402
403 if (sapi_module.php_ini_path_override) {
404 php_ini_file_name = sapi_module.php_ini_path_override;
405 php_ini_search_path = sapi_module.php_ini_path_override;
406 free_ini_search_path = 0;
407 } else if (!sapi_module.php_ini_ignore) {
408 int search_path_size;
409 char *default_location;
410 char *env_location;
411 static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 };
412 #ifdef PHP_WIN32
413 char *reg_location;
414 char phprc_path[MAXPATHLEN];
415 #endif
416
417 env_location = getenv("PHPRC");
418
419 #ifdef PHP_WIN32
420 if (!env_location) {
421 char dummybuf;
422 int size;
423
424 SetLastError(0);
425
426 /*If the given buffer is not large enough to hold the data, the return value is
427 the buffer size, in characters, required to hold the string and its terminating
428 null character. We use this return value to alloc the final buffer. */
429 size = GetEnvironmentVariableA("PHPRC", &dummybuf, 0);
430 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
431 /* The environment variable doesn't exist. */
432 env_location = "";
433 } else {
434 if (size == 0) {
435 env_location = "";
436 } else {
437 size = GetEnvironmentVariableA("PHPRC", phprc_path, size);
438 if (size == 0) {
439 env_location = "";
440 } else {
441 env_location = phprc_path;
442 }
443 }
444 }
445 }
446 #else
447 if (!env_location) {
448 env_location = "";
449 }
450 #endif
451 /*
452 * Prepare search path
453 */
454
455 search_path_size = MAXPATHLEN * 4 + (int)strlen(env_location) + 3 + 1;
456 php_ini_search_path = (char *) emalloc(search_path_size);
457 free_ini_search_path = 1;
458 php_ini_search_path[0] = 0;
459
460 /* Add environment location */
461 if (env_location[0]) {
462 if (*php_ini_search_path) {
463 strlcat(php_ini_search_path, paths_separator, search_path_size);
464 }
465 strlcat(php_ini_search_path, env_location, search_path_size);
466 php_ini_file_name = env_location;
467 }
468
469 #ifdef PHP_WIN32
470 /* Add registry location */
471 reg_location = GetIniPathFromRegistry();
472 if (reg_location != NULL) {
473 if (*php_ini_search_path) {
474 strlcat(php_ini_search_path, paths_separator, search_path_size);
475 }
476 strlcat(php_ini_search_path, reg_location, search_path_size);
477 efree(reg_location);
478 }
479 #endif
480
481 /* Add cwd (not with CLI) */
482 if (!sapi_module.php_ini_ignore_cwd) {
483 if (*php_ini_search_path) {
484 strlcat(php_ini_search_path, paths_separator, search_path_size);
485 }
486 strlcat(php_ini_search_path, ".", search_path_size);
487 }
488
489 if (PG(php_binary)) {
490 char *separator_location, *binary_location;
491
492 binary_location = estrdup(PG(php_binary));
493 separator_location = strrchr(binary_location, DEFAULT_SLASH);
494
495 if (separator_location && separator_location != binary_location) {
496 *(separator_location) = 0;
497 }
498 if (*php_ini_search_path) {
499 strlcat(php_ini_search_path, paths_separator, search_path_size);
500 }
501 strlcat(php_ini_search_path, binary_location, search_path_size);
502 efree(binary_location);
503 }
504
505 /* Add default location */
506 #ifdef PHP_WIN32
507 default_location = (char *) emalloc(MAXPATHLEN + 1);
508
509 if (0 < GetWindowsDirectory(default_location, MAXPATHLEN)) {
510 if (*php_ini_search_path) {
511 strlcat(php_ini_search_path, paths_separator, search_path_size);
512 }
513 strlcat(php_ini_search_path, default_location, search_path_size);
514 }
515
516 /* For people running under terminal services, GetWindowsDirectory will
517 * return their personal Windows directory, so lets add the system
518 * windows directory too */
519 if (0 < GetSystemWindowsDirectory(default_location, MAXPATHLEN)) {
520 if (*php_ini_search_path) {
521 strlcat(php_ini_search_path, paths_separator, search_path_size);
522 }
523 strlcat(php_ini_search_path, default_location, search_path_size);
524 }
525 efree(default_location);
526
527 #else
528 default_location = PHP_CONFIG_FILE_PATH;
529 if (*php_ini_search_path) {
530 strlcat(php_ini_search_path, paths_separator, search_path_size);
531 }
532 strlcat(php_ini_search_path, default_location, search_path_size);
533 #endif
534 }
535
536 PG(open_basedir) = NULL;
537
538 /*
539 * Find and open actual ini file
540 */
541
542 memset(&fh, 0, sizeof(fh));
543
544 /* If SAPI does not want to ignore all ini files OR an overriding file/path is given.
545 * This allows disabling scanning for ini files in the PHP_CONFIG_FILE_SCAN_DIR but still
546 * load an optional ini file. */
547 if (!sapi_module.php_ini_ignore || sapi_module.php_ini_path_override) {
548
549 /* Check if php_ini_file_name is a file and can be opened */
550 if (php_ini_file_name && php_ini_file_name[0]) {
551 zend_stat_t statbuf;
552
553 if (!VCWD_STAT(php_ini_file_name, &statbuf)) {
554 if (!((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
555 fh.handle.fp = VCWD_FOPEN(php_ini_file_name, "r");
556 if (fh.handle.fp) {
557 fh.filename = expand_filepath(php_ini_file_name, NULL);
558 }
559 }
560 }
561 }
562
563 /* Otherwise search for php-%sapi-module-name%.ini file in search path */
564 if (!fh.handle.fp) {
565 const char *fmt = "php-%s.ini";
566 char *ini_fname;
567 spprintf(&ini_fname, 0, fmt, sapi_module.name);
568 fh.handle.fp = php_fopen_with_path(ini_fname, "r", php_ini_search_path, &opened_path);
569 efree(ini_fname);
570 if (fh.handle.fp) {
571 fh.filename = ZSTR_VAL(opened_path);
572 }
573 }
574
575 /* If still no ini file found, search for php.ini file in search path */
576 if (!fh.handle.fp) {
577 fh.handle.fp = php_fopen_with_path("php.ini", "r", php_ini_search_path, &opened_path);
578 if (fh.handle.fp) {
579 fh.filename = ZSTR_VAL(opened_path);
580 }
581 }
582 }
583
584 if (free_ini_search_path) {
585 efree(php_ini_search_path);
586 }
587
588 PG(open_basedir) = open_basedir;
589
590 if (fh.handle.fp) {
591 fh.type = ZEND_HANDLE_FP;
592 RESET_ACTIVE_INI_HASH();
593
594 zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash);
595
596 {
597 zval tmp;
598
599 ZVAL_NEW_STR(&tmp, zend_string_init(fh.filename, strlen(fh.filename), 1));
600 zend_hash_str_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path")-1, &tmp);
601 if (opened_path) {
602 zend_string_release(opened_path);
603 } else {
604 efree((char *)fh.filename);
605 }
606 php_ini_opened_path = zend_strndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
607 }
608 }
609
610 /* Check for PHP_INI_SCAN_DIR environment variable to override/set config file scan directory */
611 php_ini_scanned_path = getenv("PHP_INI_SCAN_DIR");
612 if (!php_ini_scanned_path) {
613 /* Or fall back using possible --with-config-file-scan-dir setting (defaults to empty string!) */
614 php_ini_scanned_path = PHP_CONFIG_FILE_SCAN_DIR;
615 }
616 php_ini_scanned_path_len = (int)strlen(php_ini_scanned_path);
617
618 /* Scan and parse any .ini files found in scan path if path not empty. */
619 if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) {
620 struct dirent **namelist;
621 int ndir, i;
622 zend_stat_t sb;
623 char ini_file[MAXPATHLEN];
624 char *p;
625 zend_file_handle fh2;
626 zend_llist scanned_ini_list;
627 zend_llist_element *element;
628 int l, total_l = 0;
629 char *bufpath, *debpath, *endpath;
630 int lenpath;
631
632 zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
633 memset(&fh2, 0, sizeof(fh2));
634
635 bufpath = estrdup(php_ini_scanned_path);
636 for (debpath = bufpath ; debpath ; debpath=endpath) {
637 endpath = strchr(debpath, DEFAULT_DIR_SEPARATOR);
638 if (endpath) {
639 *(endpath++) = 0;
640 }
641 if (!debpath[0]) {
642 /* empty string means default builtin value
643 to allow "/foo/phd.d:" or ":/foo/php.d" */
644 debpath = PHP_CONFIG_FILE_SCAN_DIR;
645 }
646 lenpath = (int)strlen(debpath);
647
648 if (lenpath > 0 && (ndir = php_scandir(debpath, &namelist, 0, php_alphasort)) > 0) {
649
650 for (i = 0; i < ndir; i++) {
651
652 /* check for any file with .ini extension */
653 if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) {
654 free(namelist[i]);
655 continue;
656 }
657 /* Reset active ini section */
658 RESET_ACTIVE_INI_HASH();
659
660 if (IS_SLASH(debpath[lenpath - 1])) {
661 snprintf(ini_file, MAXPATHLEN, "%s%s", debpath, namelist[i]->d_name);
662 } else {
663 snprintf(ini_file, MAXPATHLEN, "%s%c%s", debpath, DEFAULT_SLASH, namelist[i]->d_name);
664 }
665 if (VCWD_STAT(ini_file, &sb) == 0) {
666 if (S_ISREG(sb.st_mode)) {
667 if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
668 fh2.filename = ini_file;
669 fh2.type = ZEND_HANDLE_FP;
670
671 if (zend_parse_ini_file(&fh2, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash) == SUCCESS) {
672 /* Here, add it to the list of ini files read */
673 l = (int)strlen(ini_file);
674 total_l += l + 2;
675 p = estrndup(ini_file, l);
676 zend_llist_add_element(&scanned_ini_list, &p);
677 }
678 }
679 }
680 }
681 free(namelist[i]);
682 }
683 free(namelist);
684 }
685 }
686 efree(bufpath);
687
688 if (total_l) {
689 int php_ini_scanned_files_len = (php_ini_scanned_files) ? (int)strlen(php_ini_scanned_files) + 1 : 0;
690 php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
691 if (!php_ini_scanned_files_len) {
692 *php_ini_scanned_files = '\0';
693 }
694 total_l += php_ini_scanned_files_len;
695 for (element = scanned_ini_list.head; element; element = element->next) {
696 if (php_ini_scanned_files_len) {
697 strlcat(php_ini_scanned_files, ",\n", total_l);
698 }
699 strlcat(php_ini_scanned_files, *(char **)element->data, total_l);
700 strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l);
701 }
702 }
703 zend_llist_destroy(&scanned_ini_list);
704 } else {
705 /* Make sure an empty php_ini_scanned_path ends up as NULL */
706 php_ini_scanned_path = NULL;
707 }
708
709 if (sapi_module.ini_entries) {
710 /* Reset active ini section */
711 RESET_ACTIVE_INI_HASH();
712 zend_parse_ini_string(sapi_module.ini_entries, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash);
713 }
714
715 return SUCCESS;
716 }
717 /* }}} */
718
719 /* {{{ php_shutdown_config
720 */
php_shutdown_config(void)721 int php_shutdown_config(void)
722 {
723 zend_hash_destroy(&configuration_hash);
724 if (php_ini_opened_path) {
725 free(php_ini_opened_path);
726 php_ini_opened_path = NULL;
727 }
728 if (php_ini_scanned_files) {
729 free(php_ini_scanned_files);
730 php_ini_scanned_files = NULL;
731 }
732 return SUCCESS;
733 }
734 /* }}} */
735
736 /* {{{ php_ini_register_extensions
737 */
php_ini_register_extensions(void)738 void php_ini_register_extensions(void)
739 {
740 zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb);
741 zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb);
742
743 zend_llist_destroy(&extension_lists.engine);
744 zend_llist_destroy(&extension_lists.functions);
745 }
746 /* }}} */
747
748 /* {{{ php_parse_user_ini_file
749 */
php_parse_user_ini_file(const char * dirname,char * ini_filename,HashTable * target_hash)750 PHPAPI int php_parse_user_ini_file(const char *dirname, char *ini_filename, HashTable *target_hash)
751 {
752 zend_stat_t sb;
753 char ini_file[MAXPATHLEN];
754 zend_file_handle fh;
755
756 snprintf(ini_file, MAXPATHLEN, "%s%c%s", dirname, DEFAULT_SLASH, ini_filename);
757
758 if (VCWD_STAT(ini_file, &sb) == 0) {
759 if (S_ISREG(sb.st_mode)) {
760 memset(&fh, 0, sizeof(fh));
761 if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
762 fh.filename = ini_file;
763 fh.type = ZEND_HANDLE_FP;
764
765 /* Reset active ini section */
766 RESET_ACTIVE_INI_HASH();
767
768 if (zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, target_hash) == SUCCESS) {
769 /* FIXME: Add parsed file to the list of user files read? */
770 return SUCCESS;
771 }
772 return FAILURE;
773 }
774 }
775 }
776 return FAILURE;
777 }
778 /* }}} */
779
780 /* {{{ php_ini_activate_config
781 */
php_ini_activate_config(HashTable * source_hash,int modify_type,int stage)782 PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage)
783 {
784 zend_string *str;
785 zval *data;
786
787 /* Walk through config hash and alter matching ini entries using the values found in the hash */
788 ZEND_HASH_FOREACH_STR_KEY_VAL(source_hash, str, data) {
789 zend_alter_ini_entry_ex(str, Z_STR_P(data), modify_type, stage, 0);
790 } ZEND_HASH_FOREACH_END();
791 }
792 /* }}} */
793
794 /* {{{ php_ini_has_per_dir_config
795 */
php_ini_has_per_dir_config(void)796 PHPAPI int php_ini_has_per_dir_config(void)
797 {
798 return has_per_dir_config;
799 }
800 /* }}} */
801
802 /* {{{ php_ini_activate_per_dir_config
803 */
php_ini_activate_per_dir_config(char * path,size_t path_len)804 PHPAPI void php_ini_activate_per_dir_config(char *path, size_t path_len)
805 {
806 zval *tmp2;
807 char *ptr;
808
809 #ifdef PHP_WIN32
810 char path_bak[MAXPATHLEN];
811 #endif
812
813 #ifdef PHP_WIN32
814 /* MAX_PATH is \0-terminated, path_len == MAXPATHLEN would overrun path_bak */
815 if (path_len >= MAXPATHLEN) {
816 #else
817 if (path_len > MAXPATHLEN) {
818 #endif
819 return;
820 }
821
822 #ifdef PHP_WIN32
823 memcpy(path_bak, path, path_len);
824 path_bak[path_len] = 0;
825 TRANSLATE_SLASHES_LOWER(path_bak);
826 path = path_bak;
827 #endif
828
829 /* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
830 if (has_per_dir_config && path && path_len) {
831 ptr = path + 1;
832 while ((ptr = strchr(ptr, '/')) != NULL) {
833 *ptr = 0;
834 /* Search for source array matching the path from configuration_hash */
835 if ((tmp2 = zend_hash_str_find(&configuration_hash, path, strlen(path))) != NULL) {
836 php_ini_activate_config(Z_ARRVAL_P(tmp2), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
837 }
838 *ptr = '/';
839 ptr++;
840 }
841 }
842 }
843 /* }}} */
844
845 /* {{{ php_ini_has_per_host_config
846 */
847 PHPAPI int php_ini_has_per_host_config(void)
848 {
849 return has_per_host_config;
850 }
851 /* }}} */
852
853 /* {{{ php_ini_activate_per_host_config
854 */
855 PHPAPI void php_ini_activate_per_host_config(const char *host, size_t host_len)
856 {
857 zval *tmp;
858
859 if (has_per_host_config && host && host_len) {
860 /* Search for source array matching the host from configuration_hash */
861 if ((tmp = zend_hash_str_find(&configuration_hash, host, host_len)) != NULL) {
862 php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
863 }
864 }
865 }
866 /* }}} */
867
868 /* {{{ cfg_get_entry
869 */
870 PHPAPI zval *cfg_get_entry_ex(zend_string *name)
871 {
872 return zend_hash_find(&configuration_hash, name);
873 }
874 /* }}} */
875
876 /* {{{ cfg_get_entry
877 */
878 PHPAPI zval *cfg_get_entry(const char *name, size_t name_length)
879 {
880 return zend_hash_str_find(&configuration_hash, name, name_length);
881 }
882 /* }}} */
883
884 /* {{{ cfg_get_long
885 */
886 PHPAPI int cfg_get_long(const char *varname, zend_long *result)
887 {
888 zval *tmp;
889
890 if ((tmp = zend_hash_str_find(&configuration_hash, varname, strlen(varname))) == NULL) {
891 *result = 0;
892 return FAILURE;
893 }
894 *result = zval_get_long(tmp);
895 return SUCCESS;
896 }
897 /* }}} */
898
899 /* {{{ cfg_get_double
900 */
901 PHPAPI int cfg_get_double(const char *varname, double *result)
902 {
903 zval *tmp;
904
905 if ((tmp = zend_hash_str_find(&configuration_hash, varname, strlen(varname))) == NULL) {
906 *result = (double) 0;
907 return FAILURE;
908 }
909 *result = zval_get_double(tmp);
910 return SUCCESS;
911 }
912 /* }}} */
913
914 /* {{{ cfg_get_string
915 */
916 PHPAPI int cfg_get_string(const char *varname, char **result)
917 {
918 zval *tmp;
919
920 if ((tmp = zend_hash_str_find(&configuration_hash, varname, strlen(varname))) == NULL) {
921 *result = NULL;
922 return FAILURE;
923 }
924 *result = Z_STRVAL_P(tmp);
925 return SUCCESS;
926 }
927 /* }}} */
928
929 PHPAPI HashTable* php_ini_get_configuration_hash(void) /* {{{ */
930 {
931 return &configuration_hash;
932 } /* }}} */
933
934 /*
935 * Local variables:
936 * tab-width: 4
937 * c-basic-offset: 4
938 * indent-tabs-mode: t
939 * End:
940 * vim600: sw=4 ts=4 fdm=marker
941 * vim<600: sw=4 ts=4
942 */
943