File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / main / php_ini.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:35 2012 UTC (12 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2012 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: php_ini.c,v 1.1.1.2 2012/05/29 12:34:35 misho Exp $ */
   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:  */
   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:  */
  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:  */
  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:  */
  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:  */
  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:  */
  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 insensitivty. Does nothign 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:  */
  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:  */
  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:  */
  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:  */
  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:  */
  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:  */
  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:  */
  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:  */
  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:  */
  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 (path_len > MAXPATHLEN) {
  789: 		return;
  790: 	}
  791: 
  792: #if PHP_WIN32
  793: 	memcpy(path_bak, path, path_len);
  794: 	path_bak[path_len] = 0;
  795: 	TRANSLATE_SLASHES_LOWER(path_bak);
  796: 	path = path_bak;
  797: #endif
  798: 
  799: 	/* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
  800: 	if (has_per_dir_config && path && path_len) {
  801: 		ptr = path + 1;
  802: 		while ((ptr = strchr(ptr, '/')) != NULL) {
  803: 			*ptr = 0;
  804: 			/* Search for source array matching the path from configuration_hash */
  805: 			if (zend_hash_find(&configuration_hash, path, strlen(path) + 1, (void **) &tmp2) == SUCCESS) {
  806: 				php_ini_activate_config(Z_ARRVAL_P(tmp2), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
  807: 			}
  808: 			*ptr = '/';
  809: 			ptr++;
  810: 		}
  811: 	}
  812: }
  813: /* }}} */
  814: 
  815: /* {{{ php_ini_has_per_host_config
  816:  */
  817: PHPAPI int php_ini_has_per_host_config(void)
  818: {
  819: 	return has_per_host_config;
  820: }
  821: /* }}} */
  822: 
  823: /* {{{ php_ini_activate_per_host_config
  824:  */
  825: PHPAPI void php_ini_activate_per_host_config(const char *host, uint host_len TSRMLS_DC)
  826: {
  827: 	zval *tmp;
  828: 
  829: 	if (has_per_host_config && host && host_len) {
  830: 		/* Search for source array matching the host from configuration_hash */
  831: 		if (zend_hash_find(&configuration_hash, host, host_len, (void **) &tmp) == SUCCESS) {
  832: 			php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
  833: 		}
  834: 	}
  835: }
  836: /* }}} */
  837: 
  838: /* {{{ cfg_get_entry
  839:  */
  840: PHPAPI zval *cfg_get_entry(const char *name, uint name_length)
  841: {
  842: 	zval *tmp;
  843: 
  844: 	if (zend_hash_find(&configuration_hash, name, name_length, (void **) &tmp) == SUCCESS) {
  845: 		return tmp;
  846: 	} else {
  847: 		return NULL;
  848: 	}
  849: }
  850: /* }}} */
  851: 
  852: /* {{{ cfg_get_long
  853:  */
  854: PHPAPI int cfg_get_long(const char *varname, long *result)
  855: {
  856: 	zval *tmp, var;
  857: 
  858: 	if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
  859: 		*result = 0;
  860: 		return FAILURE;
  861: 	}
  862: 	var = *tmp;
  863: 	zval_copy_ctor(&var);
  864: 	convert_to_long(&var);
  865: 	*result = Z_LVAL(var);
  866: 	return SUCCESS;
  867: }
  868: /* }}} */
  869: 
  870: /* {{{ cfg_get_double
  871:  */
  872: PHPAPI int cfg_get_double(const char *varname, double *result)
  873: {
  874: 	zval *tmp, var;
  875: 
  876: 	if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
  877: 		*result = (double) 0;
  878: 		return FAILURE;
  879: 	}
  880: 	var = *tmp;
  881: 	zval_copy_ctor(&var);
  882: 	convert_to_double(&var);
  883: 	*result = Z_DVAL(var);
  884: 	return SUCCESS;
  885: }
  886: /* }}} */
  887: 
  888: /* {{{ cfg_get_string
  889:  */
  890: PHPAPI int cfg_get_string(const char *varname, char **result)
  891: {
  892: 	zval *tmp;
  893: 
  894: 	if (zend_hash_find(&configuration_hash, varname, strlen(varname)+1, (void **) &tmp) == FAILURE) {
  895: 		*result = NULL;
  896: 		return FAILURE;
  897: 	}
  898: 	*result = Z_STRVAL_P(tmp);
  899: 	return SUCCESS;
  900: }
  901: /* }}} */
  902: 
  903: PHPAPI HashTable* php_ini_get_configuration_hash(void) /* {{{ */
  904: {
  905: 	return &configuration_hash;
  906: } /* }}} */
  907: 
  908: /*
  909:  * Local variables:
  910:  * tab-width: 4
  911:  * c-basic-offset: 4
  912:  * indent-tabs-mode: t
  913:  * End:
  914:  * vim600: sw=4 ts=4 fdm=marker
  915:  * vim<600: sw=4 ts=4
  916:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>