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