summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJani Taskinen <jani@php.net>2007-09-28 02:05:10 +0000
committerJani Taskinen <jani@php.net>2007-09-28 02:05:10 +0000
commit09b6f37f20b239dd021c21a1756629c4a64dc2da (patch)
tree635d42eb3591448faedff41f62ce0fff087ea467 /main
parent0d3bdf23d24ede05b07d613d030514861ab475e5 (diff)
downloadphp-git-09b6f37f20b239dd021c21a1756629c4a64dc2da.tar.gz
MFH:
- Added ".htaccess" style user-defined php.ini files support for CGI/FastCGI. - Added support for special [PATH=/opt/httpd/www.example.com/] sections in php.ini. All directives set in these sections will not be able to be overridden in user-defined ini-files or during runtime in the specified path. - Improved php.ini handling: . Added better error reporting for syntax errors in php.ini files . Allowed "ini-variables" to be used almost everywhere ini php.ini files . Allowed using alphanumeric/variable indexes in "array" ini options . Fixed get_cfg_var() to be able to return "array" ini options - Fixed bug #27372 (parse error loading browscap.ini at apache startup) - Fixed bug #42069 (parse_ini_file() allows using some non-alpha numeric characters)
Diffstat (limited to 'main')
-rw-r--r--main/main.c9
-rw-r--r--main/php_globals.h3
-rw-r--r--main/php_ini.c300
-rw-r--r--main/php_ini.h7
4 files changed, 255 insertions, 64 deletions
diff --git a/main/main.c b/main/main.c
index bb63051181..b08fb65634 100644
--- a/main/main.c
+++ b/main/main.c
@@ -447,12 +447,15 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
- STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
+ STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
+ STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("always_populate_raw_post_data", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, always_populate_raw_post_data, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
+
+ STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
+ STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
PHP_INI_END()
/* }}} */
@@ -1025,7 +1028,7 @@ PHP_FUNCTION(set_time_limit)
}
convert_to_string_ex(new_timeout);
- if (zend_alter_ini_entry("max_execution_time", sizeof("max_execution_time"), Z_STRVAL_PP(new_timeout), Z_STRLEN_PP(new_timeout), PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) {
+ if (zend_alter_ini_entry_ex("max_execution_time", sizeof("max_execution_time"), Z_STRVAL_PP(new_timeout), Z_STRLEN_PP(new_timeout), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC) == SUCCESS) {
RETURN_TRUE;
} else {
RETURN_FALSE;
diff --git a/main/php_globals.h b/main/php_globals.h
index 6c796d2c76..889072bc11 100644
--- a/main/php_globals.h
+++ b/main/php_globals.h
@@ -161,6 +161,9 @@ struct _php_core_globals {
#endif
long max_input_nesting_level;
zend_bool in_user_include;
+
+ char *user_ini_filename;
+ long user_ini_cache_ttl;
};
diff --git a/main/php_ini.c b/main/php_ini.c
index 390883da45..fd0e560de1 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -21,6 +21,7 @@
#include "php.h"
#include "ext/standard/info.h"
#include "zend_ini.h"
+#include "zend_ini_scanner.h"
#include "php_ini.h"
#include "ext/standard/dl.h"
#include "zend_extensions.h"
@@ -45,8 +46,8 @@ typedef struct _php_extension_lists {
zend_llist functions;
} php_extension_lists;
-
/* True globals */
+static HashTable *active_ini_hash;
static HashTable configuration_hash;
PHPAPI char *php_ini_opened_path=NULL;
static php_extension_lists extension_lists;
@@ -54,14 +55,13 @@ PHPAPI char *php_ini_scanned_files=NULL;
/* {{{ php_ini_displayer_cb
*/
-static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type)
+static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type TSRMLS_DC)
{
if (ini_entry->displayer) {
ini_entry->displayer(ini_entry, type);
} else {
char *display_string;
uint display_string_length, esc_html=0;
- TSRMLS_FETCH();
if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
if (ini_entry->orig_value && ini_entry->orig_value[0]) {
@@ -112,16 +112,16 @@ static int php_ini_displayer(zend_ini_entry *ini_entry, int module_number TSRMLS
PUTS("<td class=\"e\">");
PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
PUTS("</td><td class=\"v\">");
- php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE);
+ php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
PUTS("</td><td class=\"v\">");
- php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG);
+ php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
PUTS("</td></tr>\n");
} else {
PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
PUTS(" => ");
- php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE);
+ php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
PUTS(" => ");
- php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG);
+ php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
PUTS("\n");
}
return 0;
@@ -148,7 +148,6 @@ PHPAPI void display_ini_entries(zend_module_entry *module)
/* }}} */
/* php.ini support */
-
#ifdef ZTS
# if (ZEND_DEBUG)
# define ZEND_EXTENSION_TOKEN "zend_extension_debug_ts"
@@ -163,17 +162,46 @@ PHPAPI void display_ini_entries(zend_module_entry *module)
# endif
#endif
-/* {{{ php_config_ini_parser_cb
+/* {{{ config_zval_dtor
*/
-static void php_config_ini_parser_cb(zval *arg1, zval *arg2, int callback_type, void *arg)
+void config_zval_dtor(zval *zvalue)
{
+ if (Z_TYPE_P(zvalue) == IS_ARRAY) {
+ zend_hash_destroy(Z_ARRVAL_P(zvalue));
+ free(Z_ARRVAL_P(zvalue));
+ } else if (Z_TYPE_P(zvalue) == IS_STRING) {
+ free(Z_STRVAL_P(zvalue));
+ }
+}
+/* Reset / free active_ini_sectin global */
+#define RESET_ACTIVE_INI_HASH() do { \
+ active_ini_hash = NULL; \
+} while (0)
+/* }}} */
+
+/* {{{ php_ini_parser_cb
+ */
+static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, HashTable *target_hash)
+{
+ zval *entry;
+ HashTable *active_hash;
+
+ if (active_ini_hash) {
+ active_hash = active_ini_hash;
+ } else {
+ active_hash = target_hash;
+ }
+
switch (callback_type) {
case ZEND_INI_PARSER_ENTRY: {
- zval *entry;
-
if (!arg2) {
+ /* bare string - nothing to do */
break;
}
+
+/* FIXME: Should the extension loading be disabled for PATH sections? */
+
+ /* PHP and Zend extensions are not added into configuration hash! */
if (!strcasecmp(Z_STRVAL_P(arg1), "extension")) { /* load function module */
zval copy;
@@ -185,41 +213,101 @@ static void php_config_ini_parser_cb(zval *arg1, zval *arg2, int callback_type,
char *extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
zend_llist_add_element(&extension_lists.engine, &extension_name);
+
+ /* All other entries are added into either configuration_hash or active ini section array */
} else {
- zend_hash_update(&configuration_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, arg2, sizeof(zval), (void **) &entry);
+ /* Store in active hash */
+ zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, arg2, sizeof(zval), (void **) &entry);
Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
}
}
break;
case ZEND_INI_PARSER_POP_ENTRY: {
- zval *hash;
- zval **find_hash;
- zval *element;
+ zval *option_arr;
+ zval *find_arr;
if (!arg2) {
/* bare string - nothing to do */
break;
}
- if (zend_hash_find(&configuration_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, (void **) &find_hash) == FAILURE) {
- ALLOC_ZVAL(hash);
- array_init(hash);
+/* fprintf(stdout, "ZEND_INI_PARSER_POP_ENTRY: %s[%s] = %s\n",Z_STRVAL_P(arg1), Z_STRVAL_P(arg3), Z_STRVAL_P(arg2)); */
+
+ /* If option not found in hash or is not an array -> create array, otherwise add to existing array */
+ 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) {
+ option_arr = (zval *) pemalloc(sizeof(zval), 1);
+ INIT_PZVAL(option_arr);
+ Z_TYPE_P(option_arr) = IS_ARRAY;
+ Z_ARRVAL_P(option_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(Z_ARRVAL_P(option_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
+ zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, option_arr, sizeof(zval), (void **) &find_arr);
+ free(option_arr);
+ }
- zend_hash_update(&configuration_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, &hash, sizeof(zval *), NULL);
+ /* arg3 is possible option offset name */
+ if (arg3 && Z_STRLEN_P(arg3) > 0) {
+ zend_symtable_update(Z_ARRVAL_P(find_arr), Z_STRVAL_P(arg3), Z_STRLEN_P(arg3) + 1, arg2, sizeof(zval), (void **) &entry);
} else {
- hash = *find_hash;
+ zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2, sizeof(zval), (void **) &entry);
}
-
- ALLOC_ZVAL(element);
- *element = *arg2;
- zval_copy_ctor(element);
- INIT_PZVAL(element);
- add_next_index_zval(hash, element);
+ Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
}
break;
- case ZEND_INI_PARSER_SECTION:
+ case ZEND_INI_PARSER_SECTION: { /* Create an array of entries of each section */
+
+/* fprintf(stdout, "ZEND_INI_PARSER_SECTION: %s\n",Z_STRVAL_P(arg1)); */
+
+ char *key = NULL;
+ uint key_len;
+
+ /* Only PATH sections are handled here! */
+ if (!strncasecmp(Z_STRVAL_P(arg1), "PATH", sizeof("PATH") - 1)) {
+ key = Z_STRVAL_P(arg1);
+ key = key + sizeof("PATH") - 1;
+ key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1;
+
+#if 0 /* Disable HOST sections for now. If someone can come up with some good usage case, then I can reconsider :) */
+ } else if (!strncasecmp(Z_STRVAL_P(arg1), "HOST", sizeof("HOST") - 1)) {
+ key = Z_STRVAL_P(arg1);
+ key = key + sizeof("HOST") - 1;
+ key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1;
+#endif
+ }
+
+ if (key && key_len > 0) {
+ /* Strip any trailing slashes */
+ while (key_len > 0 && (key[key_len - 1] == '/' || key[key_len - 1] == '\\')) {
+ key_len--;
+ key[key_len] = 0;
+ }
+
+ /* Strip any leading whitespace and '=' */
+ while (*key && (
+ *key == '=' ||
+ *key == ' ' ||
+ *key == '\t'
+ )) {
+ key++;
+ key_len--;
+ }
+
+ /* Search for existing entry and if it does not exist create one */
+ if (zend_hash_find(target_hash, key, key_len + 1, (void **) &entry) == FAILURE) {
+ zval *section_arr;
+
+ section_arr = (zval *) pemalloc(sizeof(zval), 1);
+ INIT_PZVAL(section_arr);
+ Z_TYPE_P(section_arr) = IS_ARRAY;
+ Z_ARRVAL_P(section_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(Z_ARRVAL_P(section_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
+ zend_hash_update(target_hash, key, key_len + 1, section_arr, sizeof(zval), (void **) &entry);
+ free(section_arr);
+ }
+ active_ini_hash = Z_ARRVAL_P(entry);
+ }
+ }
break;
}
}
@@ -244,16 +332,6 @@ static void php_load_zend_extension_cb(void *arg TSRMLS_DC)
}
/* }}} */
-/* {{{ pvalue_config_destructor
- */
-static void pvalue_config_destructor(zval *pvalue)
-{
- if (Z_TYPE_P(pvalue) == IS_STRING) {
- free(Z_STRVAL_P(pvalue));
- }
-}
-/* }}} */
-
/* {{{ php_init_config
*/
int php_init_config(TSRMLS_D)
@@ -264,14 +342,8 @@ int php_init_config(TSRMLS_D)
char *open_basedir;
int free_ini_search_path = 0;
zend_file_handle fh;
- struct stat sb;
- char ini_file[MAXPATHLEN];
- char *p;
- zend_llist scanned_ini_list;
- int l, total_l=0;
- zend_llist_element *element;
- if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) pvalue_config_destructor, 1) == FAILURE) {
+ if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) config_zval_dtor, 1) == FAILURE) {
return FAILURE;
}
@@ -281,7 +353,6 @@ int php_init_config(TSRMLS_D)
zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
zend_llist_init(&extension_lists.functions, sizeof(zval), (llist_dtor_func_t) ZVAL_DESTRUCTOR, 1);
- zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
safe_mode_state = PG(safe_mode);
open_basedir = PG(open_basedir);
@@ -492,8 +563,9 @@ int php_init_config(TSRMLS_D)
if (fh.handle.fp) {
fh.type = ZEND_HANDLE_FP;
+ RESET_ACTIVE_INI_HASH();
- zend_parse_ini_file(&fh, 1, php_config_ini_parser_cb, &extension_lists);
+ zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
{
zval tmp;
@@ -501,6 +573,8 @@ int php_init_config(TSRMLS_D)
Z_STRLEN(tmp) = strlen(fh.filename);
Z_STRVAL(tmp) = zend_strndup(fh.filename, Z_STRLEN(tmp));
Z_TYPE(tmp) = IS_STRING;
+ tmp.refcount = 0;
+
zend_hash_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path"), (void *) &tmp, sizeof(zval), NULL);
if (php_ini_opened_path) {
efree(php_ini_opened_path);
@@ -514,10 +588,24 @@ int php_init_config(TSRMLS_D)
if (!sapi_module.php_ini_ignore && strlen(PHP_CONFIG_FILE_SCAN_DIR)) {
struct dirent **namelist;
int ndir, i;
+ struct stat sb;
+ char ini_file[MAXPATHLEN];
+ char *p;
+ zend_file_handle fh;
+ zend_llist scanned_ini_list;
+ zend_llist_element *element;
+ int l, total_l = 0;
+
+ /* Reset active ini section */
+ RESET_ACTIVE_INI_HASH();
if ((ndir = php_scandir(PHP_CONFIG_FILE_SCAN_DIR, &namelist, 0, php_alphasort)) > 0) {
+ zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
+ memset(&fh, 0, sizeof(fh));
+
for (i = 0; i < ndir; i++) {
- /* check for a .ini extension */
+
+ /* check for any file with .ini extension */
if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) {
free(namelist[i]);
continue;
@@ -528,12 +616,14 @@ int php_init_config(TSRMLS_D)
if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
fh.filename = ini_file;
fh.type = ZEND_HANDLE_FP;
- zend_parse_ini_file(&fh, 1, php_config_ini_parser_cb, &extension_lists);
- /* Here, add it to the list of ini files read */
- l = strlen(ini_file);
- total_l += l + 2;
- p = estrndup(ini_file, l);
- zend_llist_add_element(&scanned_ini_list, &p);
+
+ if (zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) {
+ /* Here, add it to the list of ini files read */
+ l = strlen(ini_file);
+ total_l += l + 2;
+ p = estrndup(ini_file, l);
+ zend_llist_add_element(&scanned_ini_list, &p);
+ }
}
}
}
@@ -541,14 +631,17 @@ int php_init_config(TSRMLS_D)
}
free(namelist);
- /*
- * Don't need an extra byte for the \0 in this malloc as the last
- * element will not get a trailing , which gives us the byte for the \0
- */
if (total_l) {
- php_ini_scanned_files = (char *) malloc(total_l);
- *php_ini_scanned_files = '\0';
+ int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0;
+ php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
+ if (!php_ini_scanned_files_len) {
+ *php_ini_scanned_files = '\0';
+ }
+ total_l += php_ini_scanned_files_len;
for (element = scanned_ini_list.head; element; element = element->next) {
+ if (php_ini_scanned_files_len) {
+ strlcat(php_ini_scanned_files, ",\n", total_l);
+ }
strlcat(php_ini_scanned_files, *(char **)element->data, total_l);
strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l);
}
@@ -558,7 +651,9 @@ int php_init_config(TSRMLS_D)
}
if (sapi_module.ini_entries) {
- zend_parse_ini_string(sapi_module.ini_entries, 1, php_config_ini_parser_cb, &extension_lists);
+ /* Reset active ini section */
+ RESET_ACTIVE_INI_HASH();
+ 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);
}
return SUCCESS;
@@ -594,6 +689,81 @@ void php_ini_register_extensions(TSRMLS_D)
}
/* }}} */
+/* {{{ php_parse_user_ini_file
+ */
+PHPAPI int php_parse_user_ini_file(char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC)
+{
+ struct stat sb;
+ char ini_file[MAXPATHLEN];
+ zend_file_handle fh;
+
+ snprintf(ini_file, MAXPATHLEN, "%s%c%s", dirname, DEFAULT_SLASH, ini_filename);
+
+ if (VCWD_STAT(ini_file, &sb) == 0) {
+ if (S_ISREG(sb.st_mode)) {
+ memset(&fh, 0, sizeof(fh));
+ if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
+ fh.filename = ini_file;
+ fh.type = ZEND_HANDLE_FP;
+
+ /* Reset active ini section */
+ RESET_ACTIVE_INI_HASH();
+
+ 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) {
+ /* FIXME: Add parsed file to the list of user files read? */
+ return SUCCESS;
+ }
+ return FAILURE;
+ }
+ }
+ }
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ php_ini_activate_config
+ */
+PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC)
+{
+ char *str;
+ zval *data;
+ uint str_len;
+ ulong num_index;
+
+ /* Walk through config hash and alter matching ini entries using the values found in the hash */
+ for (zend_hash_internal_pointer_reset(source_hash);
+ zend_hash_get_current_key_ex(source_hash, &str, &str_len, &num_index, 0, NULL) == HASH_KEY_IS_STRING;
+ zend_hash_move_forward(source_hash)
+ ) {
+ zend_hash_get_current_data(source_hash, (void **) &data);
+ zend_alter_ini_entry_ex(str, str_len, Z_STRVAL_P(data), Z_STRLEN_P(data), modify_type, stage, 0 TSRMLS_CC);
+ }
+}
+/* }}} */
+
+/* {{{ php_ini_activate_per_dir_config
+ */
+PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC)
+{
+ zval *tmp;
+ char *ptr;
+
+ /* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
+ if (path && path_len) {
+ ptr = path + 1;
+ while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) {
+ *ptr = 0;
+ /* Search for source array matching the path from configuration_hash */
+ if (zend_hash_find(&configuration_hash, path, path_len, (void **) &tmp) == SUCCESS) {
+ php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
+ }
+ *ptr = '/';
+ ptr++;
+ }
+ }
+}
+/* }}} */
+
/* {{{ cfg_get_entry
*/
PHPAPI zval *cfg_get_entry(char *name, uint name_length)
@@ -659,6 +829,14 @@ PHPAPI int cfg_get_string(char *varname, char **result)
}
/* }}} */
+#if ZEND_DEBUG
+#include "php_ini.h"
+PHPAPI HashTable get_configuration_hash(void)
+{
+ return configuration_hash;
+}
+#endif
+
/*
* Local variables:
* tab-width: 4
diff --git a/main/php_ini.h b/main/php_ini.h
index a2b3125c3a..9034a9cce2 100644
--- a/main/php_ini.h
+++ b/main/php_ini.h
@@ -24,6 +24,7 @@
#include "zend_ini.h"
BEGIN_EXTERN_C()
+void config_zval_dtor(zval *zvalue);
int php_init_config(TSRMLS_D);
int php_shutdown_config(void);
void php_ini_register_extensions(TSRMLS_D);
@@ -31,6 +32,12 @@ PHPAPI zval *cfg_get_entry(char *name, uint name_length);
PHPAPI int cfg_get_long(char *varname, long *result);
PHPAPI int cfg_get_double(char *varname, double *result);
PHPAPI int cfg_get_string(char *varname, char **result);
+PHPAPI int php_parse_user_ini_file(char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC);
+PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC);
+PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC);
+#if ZEND_DEBUG
+PHPAPI HashTable get_configuration_hash(void);
+#endif
END_EXTERN_C()
#define PHP_INI_USER ZEND_INI_USER