Index: php.ini-dist =================================================================== RCS file: /repository/php-src/php.ini-dist,v retrieving revision 1.231.2.10.2.22 diff -u -a -r1.231.2.10.2.22 php.ini-dist --- php.ini-dist 21 Aug 2007 23:24:18 -0000 1.231.2.10.2.22 +++ php.ini-dist 18 Sep 2007 15:36:40 -0000 @@ -63,6 +63,17 @@ ; defaults (that is, if no php.ini is used, or if you delete these lines, ; the builtin defaults will be identical). +;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is "user.ini" +;user_ini.filename = "user.ini" + +; To disable this feature set this option to empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +;user_ini.cache_ttl = 300 ;;;;;;;;;;;;;;;;;;;; ; Language Options ; Index: php.ini-recommended =================================================================== RCS file: /repository/php-src/php.ini-recommended,v retrieving revision 1.179.2.11.2.23 diff -u -a -r1.179.2.11.2.23 php.ini-recommended --- php.ini-recommended 21 Aug 2007 23:24:18 -0000 1.179.2.11.2.23 +++ php.ini-recommended 18 Sep 2007 15:36:40 -0000 @@ -113,6 +113,18 @@ ; since short tags may not be supported on the target server. ;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is "user.ini" +;user_ini.filename = "user.ini" + +; To disable this feature set this option to empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +;user_ini.cache_ttl = 300 + +;;;;;;;;;;;;;;;;;;;; ; Language Options ; ;;;;;;;;;;;;;;;;;;;; Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.277.2.12.2.25 diff -u -a -r1.277.2.12.2.25 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 30 Aug 2007 07:43:21 -0000 1.277.2.12.2.25 +++ Zend/zend_builtin_functions.c 18 Sep 2007 15:36:40 -0000 @@ -438,7 +438,7 @@ RETURN_FALSE; } convert_to_string_ex(arg); - zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); + zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME TSRMLS_CC); break; default: ZEND_WRONG_PARAM_COUNT(); Index: Zend/zend_globals.h =================================================================== RCS file: /repository/ZendEngine2/zend_globals.h,v retrieving revision 1.141.2.3.2.7 diff -u -a -r1.141.2.3.2.7 zend_globals.h --- Zend/zend_globals.h 1 Jan 2007 09:35:46 -0000 1.141.2.3.2.7 +++ Zend/zend_globals.h 18 Sep 2007 15:36:40 -0000 @@ -265,6 +265,9 @@ int yy_start_stack_depth; int *yy_start_stack; + /* For ini scanner. Modes are: ZEND_INI_SCANNER_NORMAL, ZEND_INI_SCANNER_RAW */ + int scanner_mode; + #ifdef ZEND_MULTIBYTE /* original (unfiltered) script */ char *script_org; Index: Zend/zend_ini.c =================================================================== RCS file: /repository/ZendEngine2/zend_ini.c,v retrieving revision 1.39.2.2.2.17 diff -u -a -r1.39.2.2.2.17 zend_ini.c --- Zend/zend_ini.c 7 Sep 2007 14:15:17 -0000 1.39.2.2.2.17 +++ Zend/zend_ini.c 18 Sep 2007 15:36:40 -0000 @@ -234,18 +234,17 @@ /* }}} */ #endif -ZEND_API int zend_alter_ini_entry(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage) /* {{{ */ +ZEND_API int zend_alter_ini_entry(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage TSRMLS_DC) /* {{{ */ { - return zend_alter_ini_entry_ex(name, name_length, new_value, new_value_length, modify_type, stage, 0); + return zend_alter_ini_entry_ex(name, name_length, new_value, new_value_length, modify_type, stage, 0 TSRMLS_CC); } /* }}} */ -ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage, int force_change) /* {{{ */ +ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC) /* {{{ */ { zend_ini_entry *ini_entry; char *duplicate; zend_bool modified; - TSRMLS_FETCH(); if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE) { return FAILURE; @@ -291,10 +290,9 @@ } /* }}} */ -ZEND_API int zend_restore_ini_entry(char *name, uint name_length, int stage) /* {{{ */ +ZEND_API int zend_restore_ini_entry(char *name, uint name_length, int stage TSRMLS_DC) /* {{{ */ { zend_ini_entry *ini_entry; - TSRMLS_FETCH(); if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE || (stage == ZEND_INI_STAGE_RUNTIME && (ini_entry->modifiable & ZEND_INI_USER) == 0)) { @@ -327,16 +325,15 @@ * Data retrieval */ -ZEND_API long zend_ini_long(char *name, uint name_length, int orig) /* {{{ */ +ZEND_API long zend_ini_long(char *name, uint name_length, int orig TSRMLS_DC) /* {{{ */ { zend_ini_entry *ini_entry; - TSRMLS_FETCH(); - if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == SUCCESS) { if (orig && ini_entry->modified) { return (ini_entry->orig_value ? strtol(ini_entry->orig_value, NULL, 0) : 0); - } else if (ini_entry->value) { - return strtol(ini_entry->value, NULL, 0); + } else { + return (ini_entry->value ? strtol(ini_entry->value, NULL, 0) : 0); } } @@ -344,16 +341,15 @@ } /* }}} */ -ZEND_API double zend_ini_double(char *name, uint name_length, int orig) /* {{{ */ +ZEND_API double zend_ini_double(char *name, uint name_length, int orig TSRMLS_DC) /* {{{ */ { zend_ini_entry *ini_entry; - TSRMLS_FETCH(); - if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == SUCCESS) { if (orig && ini_entry->modified) { return (double) (ini_entry->orig_value ? zend_strtod(ini_entry->orig_value, NULL) : 0.0); - } else if (ini_entry->value) { - return (double) zend_strtod(ini_entry->value, NULL); + } else { + return (double) (ini_entry->value ? zend_strtod(ini_entry->value, NULL) : 0.0); } } @@ -361,17 +357,18 @@ } /* }}} */ -ZEND_API char *zend_ini_string(char *name, uint name_length, int orig) /* {{{ */ +ZEND_API char *zend_ini_string(char *name, uint name_length, int orig TSRMLS_DC) /* {{{ */ { zend_ini_entry *ini_entry; - TSRMLS_FETCH(); - if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == SUCCESS) { if (orig && ini_entry->modified) { - return ini_entry->orig_value; + return ini_entry->orig_value ? ini_entry->orig_value : ""; } else { - return ini_entry->value; + return ini_entry->value ? ini_entry->value : ""; } + } else { + return NULL; } return ""; Index: Zend/zend_ini.h =================================================================== RCS file: /repository/ZendEngine2/zend_ini.h,v retrieving revision 1.34.2.1.2.6 diff -u -a -r1.34.2.1.2.6 zend_ini.h --- Zend/zend_ini.h 7 Sep 2007 09:55:37 -0000 1.34.2.1.2.6 +++ Zend/zend_ini.h 18 Sep 2007 15:36:40 -0000 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_ini.h,v 1.34.2.1.2.6 2007/09/07 09:55:37 jani Exp $ */ +/* $Id: zend_ini.h,v 1.34.2.1.2.4 2007/08/02 23:57:21 stas Exp $ */ #ifndef ZEND_INI_H #define ZEND_INI_H @@ -95,17 +95,17 @@ ZEND_API int zend_register_ini_entries(zend_ini_entry *ini_entry, int module_number TSRMLS_DC); ZEND_API void zend_unregister_ini_entries(int module_number TSRMLS_DC); ZEND_API void zend_ini_refresh_caches(int stage TSRMLS_DC); -ZEND_API int zend_alter_ini_entry(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage); -ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage, int force_change); -ZEND_API int zend_restore_ini_entry(char *name, uint name_length, int stage); -ZEND_API void display_ini_entries(zend_module_entry *module); - -ZEND_API long zend_ini_long(char *name, uint name_length, int orig); -ZEND_API double zend_ini_double(char *name, uint name_length, int orig); -ZEND_API char *zend_ini_string(char *name, uint name_length, int orig); +ZEND_API int zend_alter_ini_entry(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage TSRMLS_DC); +ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC); +ZEND_API int zend_restore_ini_entry(char *name, uint name_length, int stage TSRMLS_DC); +ZEND_API void display_ini_entries(zend_module_entry *module TSRMLS_DC); + +ZEND_API long zend_ini_long(char *name, uint name_length, int orig TSRMLS_DC); +ZEND_API double zend_ini_double(char *name, uint name_length, int orig TSRMLS_DC); +ZEND_API char *zend_ini_string(char *name, uint name_length, int orig TSRMLS_DC); ZEND_API int zend_ini_register_displayer(char *name, uint name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)); - + ZEND_API ZEND_INI_DISP(zend_ini_boolean_displayer_cb); ZEND_API ZEND_INI_DISP(zend_ini_color_displayer_cb); ZEND_API ZEND_INI_DISP(display_link_numbers); @@ -154,20 +154,19 @@ ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr, NULL, zend_ini_boolean_displayer_cb) #endif -#define INI_INT(name) zend_ini_long((name), sizeof(name), 0) -#define INI_FLT(name) zend_ini_double((name), sizeof(name), 0) -#define INI_STR(name) zend_ini_string((name), sizeof(name), 0) +#define INI_INT(name) zend_ini_long((name), sizeof(name), 0 TSRMLS_CC) +#define INI_FLT(name) zend_ini_double((name), sizeof(name), 0 TSRMLS_CC) +#define INI_STR(name) zend_ini_string((name), sizeof(name), 0 TSRMLS_CC) #define INI_BOOL(name) ((zend_bool) INI_INT(name)) -#define INI_ORIG_INT(name) zend_ini_long((name), sizeof(name), 1) -#define INI_ORIG_FLT(name) zend_ini_double((name), sizeof(name), 1) -#define INI_ORIG_STR(name) zend_ini_string((name), sizeof(name), 1) +#define INI_ORIG_INT(name) zend_ini_long((name), sizeof(name), 1 TSRMLS_CC) +#define INI_ORIG_FLT(name) zend_ini_double((name), sizeof(name), 1 TSRMLS_CC) +#define INI_ORIG_STR(name) zend_ini_string((name), sizeof(name), 1 TSRMLS_CC) #define INI_ORIG_BOOL(name) ((zend_bool) INI_ORIG_INT(name)) - #define REGISTER_INI_ENTRIES() zend_register_ini_entries(ini_entries, module_number TSRMLS_CC) #define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries(module_number TSRMLS_CC) -#define DISPLAY_INI_ENTRIES() display_ini_entries(zend_module) +#define DISPLAY_INI_ENTRIES() display_ini_entries(zend_module TSRMLS_CC) #define REGISTER_INI_DISPLAYER(name, displayer) zend_ini_register_displayer((name), sizeof(name), displayer) #define REGISTER_INI_BOOLEAN(name) REGISTER_INI_DISPLAYER(name, zend_ini_boolean_displayer_cb) @@ -193,15 +192,16 @@ #define ZEND_INI_STAGE_HTACCESS (1<<5) /* INI parsing engine */ -typedef void (*zend_ini_parser_cb_t)(zval *arg1, zval *arg2, int callback_type, void *arg); +typedef void (*zend_ini_parser_cb_t)(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg TSRMLS_DC); BEGIN_EXTERN_C() -ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg); -ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg); +ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, int scanner_mode, zend_ini_parser_cb_t ini_parser_cb, void *arg TSRMLS_DC); +ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg TSRMLS_DC); END_EXTERN_C() -#define ZEND_INI_PARSER_ENTRY 1 -#define ZEND_INI_PARSER_SECTION 2 -#define ZEND_INI_PARSER_POP_ENTRY 3 +/* INI entries */ +#define ZEND_INI_PARSER_ENTRY 1 /* Normal entry: foo = bar */ +#define ZEND_INI_PARSER_SECTION 2 /* Section: [foobar] */ +#define ZEND_INI_PARSER_POP_ENTRY 3 /* Offset entry: foo[] = bar */ typedef struct _zend_ini_parser_param { zend_ini_parser_cb_t ini_parser_cb; Index: Zend/zend_ini_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_ini_parser.y,v retrieving revision 1.41.2.2.2.2 diff -u -a -r1.41.2.2.2.2 zend_ini_parser.y --- Zend/zend_ini_parser.y 23 Jul 2007 16:17:10 -0000 1.41.2.2.2.2 +++ Zend/zend_ini_parser.y 18 Sep 2007 15:36:40 -0000 @@ -13,13 +13,15 @@ | obtain it through the world-wide-web, please send a note to | | license@zend.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Zeev Suraski | + | Authors: Zeev Suraski | + | Jani Taskinen | +----------------------------------------------------------------------+ */ /* $Id: zend_ini_parser.y,v 1.41.2.2.2.2 2007/07/23 16:17:10 jani Exp $ */ #define DEBUG_CFG_PARSER 0 + #include "zend.h" #include "zend_API.h" #include "zend_ini.h" @@ -27,6 +29,7 @@ #include "zend_ini_scanner.h" #include "zend_extensions.h" +#define YYERROR_VERBOSE #define YYSTYPE zval #ifdef ZTS @@ -111,11 +114,11 @@ Z_TYPE_P(result) = IS_STRING; } -void zend_ini_get_constant(zval *result, zval *name) +void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC) { zval z_constant; - TSRMLS_FETCH(); + /* If name contains ':' it is not a constant. Bug #26893. */ if (!memchr(Z_STRVAL_P(name), ':', Z_STRLEN_P(name)) && zend_get_constant(Z_STRVAL_P(name), Z_STRLEN_P(name), &z_constant TSRMLS_CC)) { /* z_constant is emalloc()'d */ @@ -130,15 +133,16 @@ } } -void zend_ini_get_var(zval *result, zval *name) +void zend_ini_get_var(zval *result, zval *name TSRMLS_DC) { zval curval; char *envvar; - TSRMLS_FETCH(); + /* Fetch configuration option value */ if (zend_get_configuration_directive(Z_STRVAL_P(name), Z_STRLEN_P(name)+1, &curval) == SUCCESS) { Z_STRVAL_P(result) = zend_strndup(Z_STRVAL(curval), Z_STRLEN(curval)); Z_STRLEN_P(result) = Z_STRLEN(curval); + /* ..or if not found, try ENV */ } else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name) TSRMLS_CC)) != NULL || (envvar = getenv(Z_STRVAL_P(name))) != NULL) { Z_STRVAL_P(result) = strdup(envvar); @@ -148,8 +152,7 @@ } } - -static void ini_error(char *str) +static void ini_error(char *msg) { char *error_buf; int error_buf_len; @@ -158,10 +161,10 @@ currently_parsed_filename = zend_ini_scanner_get_filename(TSRMLS_C); if (currently_parsed_filename) { - error_buf_len = 128+strlen(currently_parsed_filename); /* should be more than enough */ + error_buf_len = 128 + strlen(msg) + strlen(currently_parsed_filename); /* should be more than enough */ error_buf = (char *) emalloc(error_buf_len); - sprintf(error_buf, "Error parsing %s on line %d\n", currently_parsed_filename, zend_ini_scanner_get_lineno(TSRMLS_C)); + sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno(TSRMLS_C)); } else { error_buf = estrdup("Invalid configuration directive\n"); } @@ -178,70 +181,79 @@ efree(error_buf); } - -ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg) +ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, int scanner_mode, zend_ini_parser_cb_t ini_parser_cb, void *arg TSRMLS_DC) { int retval; zend_ini_parser_param ini_parser_param; - TSRMLS_FETCH(); ini_parser_param.ini_parser_cb = ini_parser_cb; ini_parser_param.arg = arg; - CG(ini_parser_param) = &ini_parser_param; - if (zend_ini_open_file_for_scanning(fh TSRMLS_CC)==FAILURE) { + + if (zend_ini_open_file_for_scanning(fh, scanner_mode TSRMLS_CC) == FAILURE) { return FAILURE; } CG(ini_parser_unbuffered_errors) = unbuffered_errors; retval = ini_parse(TSRMLS_C); - zend_ini_close_file(fh TSRMLS_CC); - if (retval==0) { + shutdown_ini_scanner(TSRMLS_C); + + if (retval == 0) { return SUCCESS; } else { return FAILURE; } } - -ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg) +ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg TSRMLS_DC) { + int retval; zend_ini_parser_param ini_parser_param; - TSRMLS_FETCH(); ini_parser_param.ini_parser_cb = ini_parser_cb; ini_parser_param.arg = arg; - CG(ini_parser_param) = &ini_parser_param; + if (zend_ini_prepare_string_for_scanning(str TSRMLS_CC)==FAILURE) { return FAILURE; } CG(ini_parser_unbuffered_errors) = unbuffered_errors; + retval = ini_parse(TSRMLS_C); + + shutdown_ini_scanner(TSRMLS_C); - if (ini_parse(TSRMLS_C)) { + if (retval == 0) { return SUCCESS; } else { return FAILURE; } } - %} +%expect 1 %pure_parser + +%token TC_SECTION +%token TC_RAW +%token TC_NUMBER %token TC_STRING -%token TC_ENCAPSULATED_STRING -%token BRACK -%token SECTION -%token CFG_TRUE -%token CFG_FALSE +%token TC_OFFSET %token TC_DOLLAR_CURLY +%token TC_VARNAME +%token TC_QUOTED_STRING +%token BOOL_TRUE +%token BOOL_FALSE +%token END_OF_LINE +%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' %left '|' '&' %right '~' '!' +%destructor { free(Z_STRVAL($$)); } TC_RAW TC_NUMBER TC_STRING TC_OFFSET TC_VARNAME TC_QUOTED_STRING BOOL_TRUE BOOL_FALSE + %% statement_list: @@ -250,61 +262,94 @@ ; statement: - TC_STRING '=' string_or_value { + TC_SECTION section_string_or_value ']' { +#if DEBUG_CFG_PARSER + printf("SECTION: [%s]\n", Z_STRVAL($2)); +#endif + ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC); + free(Z_STRVAL($2)); + } + | TC_STRING '=' string_or_value { #if DEBUG_CFG_PARSER - printf("'%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3)); + printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3)); #endif - ZEND_INI_PARSER_CB(&$1, &$3, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG); + ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); free(Z_STRVAL($3)); } - | TC_STRING BRACK '=' string_or_value { + | TC_OFFSET option_offset ']' '=' string_or_value { #if DEBUG_CFG_PARSER - printf("'%s'[ ] = '%s'\n", Z_STRVAL($1), Z_STRVAL($4)); + printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5)); #endif - ZEND_INI_PARSER_CB(&$1, &$4, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG); + ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); - free(Z_STRVAL($4)); + free(Z_STRVAL($2)); + free(Z_STRVAL($5)); } - | TC_STRING { ZEND_INI_PARSER_CB(&$1, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG); free(Z_STRVAL($1)); } - | SECTION { ZEND_INI_PARSER_CB(&$1, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG); free(Z_STRVAL($1)); } - | '\n' + | TC_STRING { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); } + | END_OF_LINE ; +section_string_or_value: + TC_RAW { $$ = $1; } + | section_var_list { $$ = $1; } + | '"' encapsed_list '"' { $$ = $2; } + | /* empty */ { zend_ini_init_string(&$$); } +; string_or_value: - expr { $$ = $1; } - | CFG_TRUE { $$ = $1; } - | CFG_FALSE { $$ = $1; } - | '\n' { zend_ini_init_string(&$$); } - | /* empty */ { zend_ini_init_string(&$$); } + expr { $$ = $1; } + | TC_RAW { $$ = $1; } + | TC_NUMBER { $$ = $1; } + | BOOL_TRUE { $$ = $1; } + | BOOL_FALSE { $$ = $1; } + | '"' encapsed_list '"' { $$ = $2; } + | END_OF_LINE { zend_ini_init_string(&$$); } +; + +option_offset: + TC_NUMBER { $$ = $1; } + | TC_RAW { $$ = $1; } + | var_string_list { $$ = $1; } + | '"' encapsed_list '"' { $$ = $2; } + | /* empty */ { zend_ini_init_string(&$$); } ; +encapsed_list: + encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); } + | encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); } + | /* empty */ { zend_ini_init_string(&$$); } +; -var_string_list: - cfg_var_ref { $$ = $1; } - | TC_ENCAPSULATED_STRING { $$ = $1; } - | constant_string { $$ = $1; } - | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free($2.value.str.val); } - | var_string_list TC_ENCAPSULATED_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); } - | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); free($2.value.str.val); } +section_var_list: + cfg_var_ref { $$ = $1; } + | TC_STRING { $$ = $1; } + | section_var_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); } + | section_var_list TC_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); } ; -cfg_var_ref: - TC_DOLLAR_CURLY TC_STRING '}' { zend_ini_get_var(&$$, &$2); free($2.value.str.val); } +var_string_list: + cfg_var_ref { $$ = $1; } + | constant_string { $$ = $1; } + | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); } + | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); } ; expr: - var_string_list { $$ = $1; } - | expr '|' expr { zend_ini_do_op('|', &$$, &$1, &$3); } - | expr '&' expr { zend_ini_do_op('&', &$$, &$1, &$3); } - | '~' expr { zend_ini_do_op('~', &$$, &$2, NULL); } - | '!' expr { zend_ini_do_op('!', &$$, &$2, NULL); } - | '(' expr ')' { $$ = $2; } + var_string_list { $$ = $1; } + | expr '|' expr { zend_ini_do_op('|', &$$, &$1, &$3); } + | expr '&' expr { zend_ini_do_op('&', &$$, &$1, &$3); } + | '~' expr { zend_ini_do_op('~', &$$, &$2, NULL); } + | '!' expr { zend_ini_do_op('!', &$$, &$2, NULL); } + | '(' expr ')' { $$ = $2; } +; + +cfg_var_ref: + TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2 TSRMLS_CC); free(Z_STRVAL($2)); } ; constant_string: - TC_STRING { zend_ini_get_constant(&$$, &$1); } + TC_STRING { zend_ini_get_constant(&$$, &$1 TSRMLS_CC); } ; /* Index: Zend/zend_ini_scanner.h =================================================================== RCS file: /repository/ZendEngine2/zend_ini_scanner.h,v retrieving revision 1.14.2.1.2.2 diff -u -a -r1.14.2.1.2.2 zend_ini_scanner.h --- Zend/zend_ini_scanner.h 1 Jan 2007 09:35:46 -0000 1.14.2.1.2.2 +++ Zend/zend_ini_scanner.h 18 Sep 2007 15:36:40 -0000 @@ -22,13 +22,18 @@ #ifndef _ZEND_INI_SCANNER_H #define _ZEND_INI_SCANNER_H +/* Scanner modes */ +#define ZEND_INI_SCANNER_NORMAL 0 /* Normal mode. [DEFAULT] */ +#define ZEND_INI_SCANNER_RAW 1 /* Raw mode. Option values are not parsed */ + BEGIN_EXTERN_C() int zend_ini_scanner_get_lineno(TSRMLS_D); char *zend_ini_scanner_get_filename(TSRMLS_D); -int zend_ini_open_file_for_scanning(zend_file_handle *fh TSRMLS_DC); +int zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode TSRMLS_DC); int zend_ini_prepare_string_for_scanning(char *str TSRMLS_DC); void zend_ini_close_file(zend_file_handle *fh TSRMLS_DC); int ini_lex(zval *ini_lval TSRMLS_DC); +void shutdown_ini_scanner(TSRMLS_D); END_EXTERN_C() #endif /* _ZEND_INI_SCANNER_H */ Index: Zend/zend_ini_scanner.l =================================================================== RCS file: /repository/ZendEngine2/zend_ini_scanner.l,v retrieving revision 1.41.2.2.2.2 diff -u -a -r1.41.2.2.2.2 zend_ini_scanner.l --- Zend/zend_ini_scanner.l 23 Jul 2007 16:17:10 -0000 1.41.2.2.2.2 +++ Zend/zend_ini_scanner.l 18 Sep 2007 15:36:40 -0000 @@ -13,21 +13,71 @@ | obtain it through the world-wide-web, please send a note to | | license@zend.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Zeev Suraski | + | Authors: Zeev Suraski | + | Jani Taskinen | +----------------------------------------------------------------------+ */ /* $Id: zend_ini_scanner.l,v 1.41.2.2.2.2 2007/07/23 16:17:10 jani Exp $ */ +#define DEBUG_CFG_SCANNER 0 + #define yyleng SCNG(yy_leng) #define yytext SCNG(yy_text) #define yytext_ptr SCNG(yy_text) #define yyin SCNG(yy_in) #define yyout SCNG(yy_out) + +/* How it works (for the core ini directives): + * =========================================== + * + * 1. Scanner scans file for tokens and passes them to parser. + * 2. Parser parses the tokens and passes the name/value pairs to the callback + * function which stores them in the configuration hash table. + * 3. Later REGISTER_INI_ENTRIES() is called which triggers the actual + * registering of ini entries and uses zend_get_configuration_directive() + * to fetch the previously stored name/value pair from configuration hash table + * and registers the static ini entries which match the name to the value + * into EG(ini_directives) hash table. + * 4. PATH section entries are used per-request from down to top, each overriding + * previous if one exists. zend_alter_ini_entry() is called for each entry. + * Settings in PATH section are ZEND_INI_SYSTEM accessible and thus mimics the + * php_admin_* directives used within Apache httpd.conf when PHP is compiled as + * module for Apache. + * 5. User defined ini files (like .htaccess for apache) are parsed for each request and + * stored in separate hash defined by SAPI. + */ + +/* TODO: (ordered by importance :-) + * =============================================================================== + * + * - Separate constant lookup totally from plain strings (using CONSTANT pattern) + * - Add #if .. #else .. #endif and ==, !=, <, > , <=, >= operators + * - Add #include "some.ini" + * - Allow variables to refer to options also when using parse_ini_file() + * + */ + +/* These are not needed when yymore() is not used */ +/* #define yy_last_accepting_state SCNG(_yy_last_accepting_state) #define yy_last_accepting_cpos SCNG(_yy_last_accepting_cpos) #define yy_more_flag SCNG(_yy_more_flag) #define yy_more_len SCNG(_yy_more_len) +*/ + +%} + +%x ST_DOUBLE_QUOTES +%x ST_OFFSET +%x ST_RAW +%x ST_SECTION_RAW +%x ST_SECTION_VALUE +%x ST_VALUE +%x ST_VARNAME +%option stack + +%{ #include #include "zend.h" @@ -48,16 +98,59 @@ ZEND_API zend_scanner_globals ini_scanner_globals; #endif -# define YY_INPUT(buf, result, max_size) \ +/* Eat trailing whitespace + extra char */ +#define EAT_TRAILING_WHITESPACE_EX(ch) \ + while (yyleng > 0 && ( \ + (ch != 'X' && yytext[yyleng - 1] == ch) || \ + yytext[yyleng - 1] == '\n' || \ + yytext[yyleng - 1] == '\r' || \ + yytext[yyleng - 1] == '\t' || \ + yytext[yyleng - 1] == ' ') \ + ) { \ + yyleng--; \ + yytext[yyleng]=0; \ + } + +/* Eat trailing whitespace */ +#define EAT_TRAILING_WHITESPACE() EAT_TRAILING_WHITESPACE_EX('X') + +#define zend_ini_copy_value(retval, str, len) { \ + Z_STRVAL_P(retval) = zend_strndup(str, len); \ + Z_STRLEN_P(retval) = len; \ + Z_TYPE_P(retval) = IS_STRING; \ +} + +#define RETURN_TOKEN(type, str, len) { \ + zend_ini_copy_value(ini_lval, str, len); \ + return type; \ +} + +#define YY_INPUT(buf, result, max_size) \ if ( ((result = zend_stream_read(yyin, buf, max_size TSRMLS_CC)) == 0) \ - && zend_stream_ferror( yyin TSRMLS_CC) ) \ + && zend_stream_ferror( yyin TSRMLS_CC) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); static char *ini_filename; -void init_ini_scanner(TSRMLS_D) +static void init_ini_scanner(TSRMLS_D) { - SCNG(lineno)=1; + SCNG(lineno) = 1; + SCNG(scanner_mode) = ZEND_INI_SCANNER_NORMAL; + SCNG(yy_start_stack_ptr) = 0; + SCNG(yy_start_stack_depth) = 0; + SCNG(current_buffer) = NULL; +} + +void shutdown_ini_scanner(TSRMLS_D) +{ + if (SCNG(yy_start_stack)) { + yy_flex_free(SCNG(yy_start_stack)); + SCNG(yy_start_stack) = NULL; + } + yy_delete_buffer(SCNG(current_buffer) TSRMLS_CC); + if (ini_filename) { + free(ini_filename); + } } int zend_ini_scanner_get_lineno(TSRMLS_D) @@ -70,16 +163,17 @@ return ini_filename; } -int zend_ini_open_file_for_scanning(zend_file_handle *fh TSRMLS_DC) +int zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode TSRMLS_DC) { if (FAILURE == zend_stream_fixup(fh TSRMLS_CC)) { return FAILURE; } init_ini_scanner(TSRMLS_C); + SCNG(scanner_mode) = scanner_mode; yyin = fh; yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC); - ini_filename = fh->filename; + ini_filename = zend_strndup(fh->filename, strlen(fh->filename)); return SUCCESS; } @@ -87,6 +181,7 @@ { int len = strlen(str); + init_ini_scanner(TSRMLS_C); yyin = NULL; yy_scan_buffer(str, len + 2 TSRMLS_CC); ini_filename = NULL; @@ -98,154 +193,307 @@ zend_stream_close(fh); } +/* {{{ zend_ini_escape_string() + */ +static void zend_ini_escape_string(zval *lval, char *str, int len, char quote_type TSRMLS_DC) +{ + register char *s, *t; + char *end; + + zend_ini_copy_value(lval, str, len); + + /* convert escape sequences */ + s = t = Z_STRVAL_P(lval); + end = s + Z_STRLEN_P(lval); + + while (s < end) { + if (*s == '\\') { + s++; + if (s >= end) { + continue; + } + switch (*s) { + case 'n': + *t++ = '\n'; + Z_STRLEN_P(lval)--; + break; + case 'r': + *t++ = '\r'; + Z_STRLEN_P(lval)--; + break; + case 't': + *t++ = '\t'; + Z_STRLEN_P(lval)--; + break; + case '"': + if (*s != quote_type) { + *t++ = '\\'; + *t++ = *s; + break; + } + case '\\': + case '$': + *t++ = *s; + Z_STRLEN_P(lval)--; + break; + default: + *t++ = '\\'; + *t++ = *s; + break; + } + } else { + *t++ = *s; + } + + if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) { + SCNG(lineno)++; + } + s++; + } + *t = 0; +} +/* }}} */ + %} -NEWLINE ("\r"|"\n"|"\r\n") +LNUM [0-9]+ +DNUM ([0-9]*[\.][0-9]+)|([0-9]+[\.][0-9]*) +NUMBER {LNUM}|{DNUM} +ANY_CHAR (.|[\n]) +NEWLINE ("\r"|"\n"|"\r\n") +TABS_AND_SPACES [ \t] +CONSTANT [a-zA-Z][a-zA-Z0-9_]* +LABEL [a-zA-Z0-9][a-zA-Z0-9._]* +TOKENS [:,.\[\]"'()|^&+-/*=%$!~<>?@] +OPERATORS [&|~()!] + +LITERAL_DOLLAR ("$"+([^a-zA-Z0-9$"'\\{]|("\\"{ANY_CHAR}))) +VALUE_CHARS ("{"*([^=\n\r;&|~()!$"'\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR}) +RAW_VALUE_CHARS [^=\n\r;] +SINGLE_QUOTED_CHARS [^'] + +SECTION_VALUE_CHARS ("{"*([^\n\r;$"'\\{\]]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR}) +SECTION_RAW_CHARS [^\]\n\r] +/* Allow using ${foobar} inside quoted strings */ +DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR}) + +/* " */ + +%option nounput %option noyywrap +%option noyylineno +%option noyy_top_state %option never-interactive %% -[ ]*[\[][ ]*[\]][ ]* { - return BRACK; +"[" { /* Section start */ + /* Enter section data lookup state */ + if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) { + yy_push_state(ST_SECTION_RAW TSRMLS_CC); + } else { + yy_push_state(ST_SECTION_VALUE TSRMLS_CC); + } + return TC_SECTION; +} + +"'"{SINGLE_QUOTED_CHARS}+"'" { /* Raw string */ + /* Eat leading and trailing single quotes */ + if (yytext[0] == '\'' && yytext[yyleng - 1] == '\'') { + yytext++; + yyleng = yyleng - 2; + yytext[yyleng] = 0; + } + RETURN_TOKEN(TC_RAW, yytext, yyleng); } -[ ]*("true"|"on"|"yes")[ ]* { - Z_STRVAL_P(ini_lval) = zend_strndup("1", 1); - Z_STRLEN_P(ini_lval) = 1; - Z_TYPE_P(ini_lval) = IS_STRING; - return CFG_TRUE; +"]"{TABS_AND_SPACES}*{NEWLINE}? { /* End of section */ + BEGIN(INITIAL); + SCNG(lineno)++; + return ']'; } +{LABEL}"["{TABS_AND_SPACES}* { /* Start of option with offset */ + /* Eat trailing whitespace and [ */ + EAT_TRAILING_WHITESPACE_EX('['); + + /* Enter offset lookup state */ + yy_push_state(ST_OFFSET TSRMLS_CC); + + RETURN_TOKEN(TC_OFFSET, yytext, yyleng); +} -[ ]*("false"|"off"|"no"|"none"|"null")[ ]* { - Z_STRVAL_P(ini_lval) = zend_strndup("", 0); - Z_STRLEN_P(ini_lval) = 0; - Z_TYPE_P(ini_lval) = IS_STRING; - return CFG_FALSE; +{TABS_AND_SPACES}*"]" { /* End of section or an option offset */ + BEGIN(INITIAL); + return ']'; } -[[][^\]\n]+[\]][ ]*{NEWLINE}? { - /* SECTION */ +"${" { /* Variable start */ + yy_push_state(ST_VARNAME TSRMLS_CC); + return TC_DOLLAR_CURLY; +} - /* eat trailing ] and spaces */ - while (yyleng>0 && (yytext[yyleng-1]=='\n' || yytext[yyleng-1]=='\r' || yytext[yyleng-1]==']' || yytext[yyleng-1]==' ')) { - yyleng--; - yytext[yyleng]=0; - } +{LABEL} { /* Variable name */ + RETURN_TOKEN(TC_VARNAME, yytext, yyleng); +} - SCNG(lineno)++; +"}" { /* Variable end */ + yy_pop_state(TSRMLS_C); + return '}'; +} - /* eat leading [ */ - yytext++; - yyleng--; +("true"|"on"|"yes"){TABS_AND_SPACES}* { /* TRUE value (when used outside option value/offset this causes parse error!) */ + RETURN_TOKEN(BOOL_TRUE, "1", 1); +} - Z_STRVAL_P(ini_lval) = zend_strndup(yytext, yyleng); - Z_STRLEN_P(ini_lval) = yyleng; - Z_TYPE_P(ini_lval) = IS_STRING; - return SECTION; +("false"|"off"|"no"|"none"|"null"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/ + RETURN_TOKEN(BOOL_FALSE, "", 0); } -["][^"]*["] { - char *p = yytext; +{LABEL} { /* Get option name or option offset value */ + RETURN_TOKEN(TC_STRING, yytext, yyleng); +} - /* ENCAPSULATED TC_STRING */ +{TABS_AND_SPACES}*[=]{TABS_AND_SPACES}* { /* Start option value */ + if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) { + yy_push_state(ST_RAW TSRMLS_CC); + } else { + yy_push_state(ST_VALUE TSRMLS_CC); + } + return '='; +} - while ((p = strpbrk(p, "\r\n"))) { - if (*p == '\r' && *(p + 1) == '\n') { - p++; - } - SCNG(lineno)++; - p++; +{RAW_VALUE_CHARS}+ { /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */ + /* Eat leading and trailing double quotes */ + if (yytext[0] == '"' && yytext[yyleng - 1] == '"') { + yytext++; + yyleng = yyleng - 2; + yytext[yyleng] = 0; } + RETURN_TOKEN(TC_RAW, yytext, yyleng); +} - /* eat trailing " */ - yytext[yyleng-1]=0; +{SECTION_RAW_CHARS}+ { /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */ + RETURN_TOKEN(TC_RAW, yytext, yyleng); +} - /* eat leading " */ - yytext++; +{NEWLINE} { /* End of option value */ + BEGIN(INITIAL); + SCNG(lineno)++; + return END_OF_LINE; +} - Z_STRVAL_P(ini_lval) = zend_strndup(yytext, yyleng - 2); - Z_STRLEN_P(ini_lval) = yyleng - 2; - Z_TYPE_P(ini_lval) = IS_STRING; - return TC_ENCAPSULATED_STRING; +{CONSTANT} { /* Get constant option value */ + RETURN_TOKEN(TC_STRING, yytext, yyleng); } -"${" { - return TC_DOLLAR_CURLY; +{NUMBER} { /* Get number option value as string */ + RETURN_TOKEN(TC_NUMBER, yytext, yyleng); } -"}" { - Z_LVAL_P(ini_lval) = (long) yytext[0]; +{TOKENS} { /* Disallow these chars outside option values */ return yytext[0]; } -[&|~$(){}!] { +{OPERATORS}{TABS_AND_SPACES}* { /* Boolean operators */ return yytext[0]; } -[^=\n\r\t;|&$~(){}!"\[]+ { - /* STRING */ - register int i; - - /* eat trailing whitespace */ - for (i=yyleng-1; i>=0; i--) { - if (yytext[i]==' ' || yytext[i]=='\t') { - yytext[i]=0; - yyleng--; - } else { - break; - } - } - /* eat leading whitespace */ - while (yytext[0]) { - if (yytext[0]==' ' || yytext[0]=='\t') { - yytext++; - yyleng--; - } else { - break; - } - } - if (yyleng!=0) { - Z_STRVAL_P(ini_lval) = zend_strndup(yytext, yyleng); - Z_STRLEN_P(ini_lval) = yyleng; - Z_TYPE_P(ini_lval) = IS_STRING; - return TC_STRING; - } else { - /* whitespace */ - } +[=] { /* Make = used in option value to trigger error */ + yyless(yyleng - 1); + yy_pop_state(TSRMLS_C); + return END_OF_LINE; } -[=\n] { - if (yytext[0] == '\n') { - SCNG(lineno)++; - } - return yytext[0]; +{VALUE_CHARS}+ { /* Get everything else as option/offset value */ + /* Eat trailing tabs and spaces */ + EAT_TRAILING_WHITESPACE(); + RETURN_TOKEN(TC_STRING, yytext, yyleng); } -{NEWLINE} { - SCNG(lineno)++; - return '\n'; +{SECTION_VALUE_CHARS}+ { /* Get rest as section/offset value */ + RETURN_TOKEN(TC_STRING, yytext, yyleng); } -[;][^\r\n]*{NEWLINE}? { - /* comment */ - SCNG(lineno)++; - return '\n'; +["] { /* Double quoted '"' string start */ + yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC); + return '"'; } -[ \t] { +{DOUBLE_QUOTES_CHARS}+ { /* Escape double quoted string contents */ + zend_ini_escape_string(ini_lval, yytext, yyleng, '"' TSRMLS_CC); + return TC_QUOTED_STRING; +} + +["] { /* Double quoted '"' string ends */ + yy_pop_state(TSRMLS_C); + return '"'; +} + +{TABS_AND_SPACES} { /* eat whitespace */ } -. { -#if DEBUG - php_error(E_NOTICE,"Unexpected character on line %d: '%s' (ASCII %d)\n", yylineno, yytext, yytext[0]); -#endif +{NEWLINE} { + SCNG(lineno)++; + return END_OF_LINE; +} + +[;][^\r\n]*{NEWLINE} { /* Comment */ + if (YYSTATE == ST_VALUE || YYSTATE == ST_RAW) { + yy_pop_state(TSRMLS_C); + } + SCNG(lineno)++; + return END_OF_LINE; +} + +<> { /* End of option value (if EOF is reached before EOL */ + yy_pop_state(TSRMLS_C); + return END_OF_LINE; } <> { - yy_delete_buffer(YY_CURRENT_BUFFER TSRMLS_CC); +#if DEBUG_CFG_SCANNER + while (YYSTATE != INITIAL) { + switch (YYSTATE) { + case INITIAL: + break; + + case ST_DOUBLE_QUOTES: + fprintf(stderr, "ERROR: Unterminated ini option value double quotes\n"); + break; + + case ST_OFFSET: + fprintf(stderr, "ERROR: Unterminated ini option offset\n"); + break; + + case ST_RAW: + fprintf(stderr, "ERROR: Unterminated raw ini option value\n"); + break; + + case ST_SECTION_RAW: + fprintf(stderr, "ERROR: Unterminated raw ini section value\n"); + break; + + case ST_SECTION_VALUE: + fprintf(stderr, "ERROR: Unterminated ini section value\n"); + break; + + case ST_VALUE: + fprintf(stderr, "ERROR: Unterminated ini option value\n"); + break; + + case ST_VARNAME: + fprintf(stderr, "ERROR: Unterminated ini variable\n"); + break; + + default: + fprintf(stderr, "BUG: Unknown state (%d)\n", YYSTATE); + break; + } + yy_pop_state(TSRMLS_C); + } +#endif yyterminate(); } Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.59.2.29.2.48 diff -u -a -r1.59.2.29.2.48 zend_vm_def.h --- Zend/zend_vm_def.h 7 Sep 2007 09:37:37 -0000 1.59.2.29.2.48 +++ Zend/zend_vm_def.h 18 Sep 2007 15:36:40 -0000 @@ -3599,7 +3599,7 @@ } if (EG(error_reporting)) { - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1); + zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); } ZEND_VM_NEXT_OPCODE(); } @@ -3619,7 +3619,7 @@ Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.u.var).tmp_var); convert_to_string(&restored_error_reporting); - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1); + zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); zendi_zval_dtor(restored_error_reporting); } if (EX(old_error_reporting) == &EX_T(opline->op1.u.var).tmp_var) { @@ -3811,7 +3811,7 @@ Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL_P(EX(old_error_reporting)); convert_to_string(&restored_error_reporting); - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1); + zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); zendi_zval_dtor(restored_error_reporting); } EX(old_error_reporting) = NULL; Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.62.2.30.2.49 diff -u -a -r1.62.2.30.2.49 zend_vm_execute.h --- Zend/zend_vm_execute.h 7 Sep 2007 09:37:38 -0000 1.62.2.30.2.49 +++ Zend/zend_vm_execute.h 18 Sep 2007 15:36:41 -0000 @@ -442,7 +442,7 @@ } if (EG(error_reporting)) { - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1); + zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); } ZEND_VM_NEXT_OPCODE(); } @@ -592,7 +592,7 @@ Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL_P(EX(old_error_reporting)); convert_to_string(&restored_error_reporting); - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1); + zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); zendi_zval_dtor(restored_error_reporting); } EX(old_error_reporting) = NULL; @@ -4922,7 +4922,7 @@ Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.u.var).tmp_var); convert_to_string(&restored_error_reporting); - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1); + zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); zendi_zval_dtor(restored_error_reporting); } if (EX(old_error_reporting) == &EX_T(opline->op1.u.var).tmp_var) { Index: ext/iconv/iconv.c =================================================================== RCS file: /repository/php-src/ext/iconv/iconv.c,v retrieving revision 1.124.2.8.2.16 diff -u -a -r1.124.2.8.2.16 iconv.c --- ext/iconv/iconv.c 19 May 2007 17:52:30 -0000 1.124.2.8.2.16 +++ ext/iconv/iconv.c 18 Sep 2007 15:36:41 -0000 @@ -2336,11 +2336,11 @@ return; if(!strcasecmp("input_encoding", type)) { - retval = zend_alter_ini_entry("iconv.input_encoding", sizeof("iconv.input_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + retval = zend_alter_ini_entry("iconv.input_encoding", sizeof("iconv.input_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } else if(!strcasecmp("output_encoding", type)) { - retval = zend_alter_ini_entry("iconv.output_encoding", sizeof("iconv.output_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + retval = zend_alter_ini_entry("iconv.output_encoding", sizeof("iconv.output_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } else if(!strcasecmp("internal_encoding", type)) { - retval = zend_alter_ini_entry("iconv.internal_encoding", sizeof("iconv.internal_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + retval = zend_alter_ini_entry("iconv.internal_encoding", sizeof("iconv.internal_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } else { RETURN_FALSE; } Index: ext/mbstring/mb_gpc.c =================================================================== RCS file: /repository/php-src/ext/mbstring/mb_gpc.c,v retrieving revision 1.17.2.2.2.3 diff -u -a -r1.17.2.2.2.3 mb_gpc.c --- ext/mbstring/mb_gpc.c 18 Mar 2007 16:36:13 -0000 1.17.2.2.2.3 +++ ext/mbstring/mb_gpc.c 18 Sep 2007 15:36:41 -0000 @@ -209,7 +209,7 @@ * XXX: this feature is going to be deprecated? */ if (info->force_register_globals && !(prev_rg_state = PG(register_globals))) { - zend_alter_ini_entry("register_globals", sizeof("register_globals"), "1", sizeof("1")-1, PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("register_globals", sizeof("register_globals"), "1", sizeof("1")-1, PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } if (!res || *res == '\0') { @@ -343,7 +343,7 @@ out: /* register_global stuff */ if (info->force_register_globals && !prev_rg_state) { - zend_alter_ini_entry("register_globals", sizeof("register_globals"), "0", sizeof("0")-1, PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("register_globals", sizeof("register_globals"), "0", sizeof("0")-1, PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } if (convd != NULL) { Index: ext/mbstring/mbstring.c =================================================================== RCS file: /repository/php-src/ext/mbstring/mbstring.c,v retrieving revision 1.224.2.22.2.24 diff -u -a -r1.224.2.22.2.24 mbstring.c --- ext/mbstring/mbstring.c 12 Jul 2007 15:31:54 -0000 1.224.2.22.2.24 +++ ext/mbstring/mbstring.c 18 Sep 2007 15:36:41 -0000 @@ -925,7 +925,7 @@ zend_alter_ini_entry("mbstring.internal_encoding", sizeof("mbstring.internal_encoding"), default_enc, strlen(default_enc), - PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME); + PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } } Index: ext/session/session.c =================================================================== RCS file: /repository/php-src/ext/session/session.c,v retrieving revision 1.417.2.8.2.40 diff -u -a -r1.417.2.8.2.40 session.c --- ext/session/session.c 3 Aug 2007 01:16:40 -0000 1.417.2.8.2.40 +++ ext/session/session.c 18 Sep 2007 15:36:41 -0000 @@ -1225,7 +1225,7 @@ if (PS(session_status) == php_session_disabled) { char *value; - value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); + value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0 TSRMLS_CC); if (value) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find save handler %s", value); @@ -1385,22 +1385,22 @@ WRONG_PARAM_COUNT; convert_to_string_ex(lifetime); - zend_alter_ini_entry("session.cookie_lifetime", sizeof("session.cookie_lifetime"), Z_STRVAL_PP(lifetime), Z_STRLEN_PP(lifetime), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.cookie_lifetime", sizeof("session.cookie_lifetime"), Z_STRVAL_PP(lifetime), Z_STRLEN_PP(lifetime), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); if (ZEND_NUM_ARGS() > 1) { convert_to_string_ex(path); - zend_alter_ini_entry("session.cookie_path", sizeof("session.cookie_path"), Z_STRVAL_PP(path), Z_STRLEN_PP(path), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.cookie_path", sizeof("session.cookie_path"), Z_STRVAL_PP(path), Z_STRLEN_PP(path), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); if (ZEND_NUM_ARGS() > 2) { convert_to_string_ex(domain); - zend_alter_ini_entry("session.cookie_domain", sizeof("session.cookie_domain"), Z_STRVAL_PP(domain), Z_STRLEN_PP(domain), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.cookie_domain", sizeof("session.cookie_domain"), Z_STRVAL_PP(domain), Z_STRLEN_PP(domain), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); if (ZEND_NUM_ARGS() > 3) { convert_to_long_ex(secure); - zend_alter_ini_entry("session.cookie_secure", sizeof("session.cookie_secure"), Z_BVAL_PP(secure)?"1":"0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.cookie_secure", sizeof("session.cookie_secure"), Z_BVAL_PP(secure)?"1":"0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } if (ZEND_NUM_ARGS() > 4) { convert_to_long_ex(httponly); - zend_alter_ini_entry("session.cookie_httponly", sizeof("session.cookie_httponly"), Z_BVAL_PP(httponly)?"1":"0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.cookie_httponly", sizeof("session.cookie_httponly"), Z_BVAL_PP(httponly)?"1":"0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } } } @@ -1440,7 +1440,7 @@ if (ac == 1) { convert_to_string_ex(p_name); - zend_alter_ini_entry("session.name", sizeof("session.name"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.name", sizeof("session.name"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } RETVAL_STRING(old, 0); @@ -1478,7 +1478,7 @@ } PS(mod_data) = NULL; - zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } } /* }}} */ @@ -1507,7 +1507,7 @@ efree(name); } - zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); mdata = emalloc(sizeof(*mdata)); @@ -1537,7 +1537,7 @@ if (ac == 1) { convert_to_string_ex(p_name); - zend_alter_ini_entry("session.save_path", sizeof("session.save_path"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.save_path", sizeof("session.save_path"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } RETVAL_STRING(old, 0); @@ -1622,7 +1622,7 @@ if (ac == 1) { convert_to_string_ex(p_cache_limiter); - zend_alter_ini_entry("session.cache_limiter", sizeof("session.cache_limiter"), Z_STRVAL_PP(p_cache_limiter), Z_STRLEN_PP(p_cache_limiter), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.cache_limiter", sizeof("session.cache_limiter"), Z_STRVAL_PP(p_cache_limiter), Z_STRLEN_PP(p_cache_limiter), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } RETVAL_STRING(old, 0); @@ -1644,7 +1644,7 @@ if (ac == 1) { convert_to_string_ex(p_cache_expire); - zend_alter_ini_entry("session.cache_expire", sizeof("session.cache_expire"), Z_STRVAL_PP(p_cache_expire), Z_STRLEN_PP(p_cache_expire), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); + zend_alter_ini_entry("session.cache_expire", sizeof("session.cache_expire"), Z_STRVAL_PP(p_cache_expire), Z_STRLEN_PP(p_cache_expire), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME TSRMLS_CC); } RETVAL_LONG(old); @@ -1897,7 +1897,7 @@ if (PS(mod) == NULL) { char *value; - value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); + value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0 TSRMLS_CC); if (value) { PS(mod) = _php_find_ps_module(value TSRMLS_CC); } Index: ext/soap/soap.c =================================================================== RCS file: /repository/php-src/ext/soap/soap.c,v retrieving revision 1.156.2.28.2.30 diff -u -a -r1.156.2.28.2.30 soap.c --- ext/soap/soap.c 5 Sep 2007 11:20:45 -0000 1.156.2.28.2.30 +++ ext/soap/soap.c 18 Sep 2007 15:36:41 -0000 @@ -1878,7 +1878,7 @@ params[1] = &mode; if (call_user_function(CG(function_table), NULL, &nm_ob_gzhandler, &result, 2, params TSRMLS_CC) != FAILURE && Z_TYPE(result) == IS_STRING && - zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) { + zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC) == SUCCESS) { xmlFree(buf); buf = NULL; snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", Z_STRLEN(result)); Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.725.2.31.2.64 diff -u -a -r1.725.2.31.2.64 basic_functions.c --- ext/standard/basic_functions.c 6 Sep 2007 13:28:05 -0000 1.725.2.31.2.64 +++ ext/standard/basic_functions.c 18 Sep 2007 15:36:41 -0000 @@ -41,6 +41,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; #include "zend.h" +#include "zend_ini_scanner.h" #include "zend_language_scanner.h" #include @@ -947,8 +948,15 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_parse_ini_file, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, process_sections) + ZEND_ARG_INFO(0, scanner_mode) ZEND_END_ARG_INFO() +#if ZEND_DEBUG +static +ZEND_BEGIN_ARG_INFO(arginfo_dump_config_hash, 0) +ZEND_END_ARG_INFO() +#endif + static ZEND_BEGIN_ARG_INFO_EX(arginfo_import_request_variables, 0, 0, 1) ZEND_ARG_INFO(0, types) @@ -3430,6 +3438,9 @@ PHP_FE(connection_status, arginfo_connection_status) PHP_FE(ignore_user_abort, arginfo_ignore_user_abort) PHP_FE(parse_ini_file, arginfo_parse_ini_file) +#if ZEND_DEBUG + PHP_FE(dump_config_hash, arginfo_dump_config_hash) +#endif PHP_FE(is_uploaded_file, arginfo_is_uploaded_file) PHP_FE(move_uploaded_file, arginfo_move_uploaded_file) @@ -3988,6 +3999,9 @@ REGISTER_LONG_CONSTANT("INI_SYSTEM", ZEND_INI_SYSTEM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INI_ALL", ZEND_INI_ALL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("INI_SCANNER_NORMAL", ZEND_INI_SCANNER_NORMAL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("INI_SCANNER_RAW", ZEND_INI_SCANNER_RAW, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHP_URL_SCHEME", PHP_URL_SCHEME, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_URL_HOST", PHP_URL_HOST, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_URL_PORT", PHP_URL_PORT, CONST_CS | CONST_PERSISTENT); @@ -4847,12 +4861,34 @@ } /* }}} */ -/* {{{ proto string get_cfg_var(string option_name) +/* {{{ add_config_entry_cb + */ +static int add_config_entry_cb(zval *entry, int num_args, va_list args, zend_hash_key *hash_key TSRMLS_DC) +{ + zval *retval = (zval *) va_arg(args, int); + zval *tmp; + + if (Z_TYPE_P(entry) == IS_STRING) { + if (hash_key->nKeyLength > 0) { + add_assoc_stringl_ex(retval, hash_key->arKey, hash_key->nKeyLength, Z_STRVAL_P(entry), Z_STRLEN_P(entry), 1); + } else { + add_index_stringl(retval, hash_key->h, Z_STRVAL_P(entry), Z_STRLEN_P(entry), 1); + } + } else if (Z_TYPE_P(entry) == IS_ARRAY) { + MAKE_STD_ZVAL(tmp); + array_init(tmp); + zend_hash_apply_with_arguments(Z_ARRVAL_P(entry), (apply_func_args_t) add_config_entry_cb, 1, tmp TSRMLS_CC); + add_assoc_zval_ex(retval, hash_key->arKey, hash_key->nKeyLength, tmp); + } + return 0; +} +/* }}} */ + +/* {{{ proto mixed get_cfg_var(string option_name) Get the value of a PHP configuration option */ PHP_FUNCTION(get_cfg_var) { - zval **varname; - char *value; + zval **varname, *retval; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &varname) == FAILURE) { WRONG_PARAM_COUNT; @@ -4860,10 +4896,19 @@ convert_to_string_ex(varname); - if (cfg_get_string(Z_STRVAL_PP(varname), &value) == FAILURE) { + retval = cfg_get_entry(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) + 1); + + if (retval) { + if (Z_TYPE_P(retval) == IS_ARRAY) { + array_init(return_value); + zend_hash_apply_with_arguments(Z_ARRVAL_P(retval), (apply_func_args_t) add_config_entry_cb, 1, return_value TSRMLS_CC); + return; + } else { + RETURN_STRING(Z_STRVAL_P(retval), 1); + } + } else { RETURN_FALSE; } - RETURN_STRING(value, 1); } /* }}} */ @@ -5417,7 +5462,7 @@ /* }}} */ -ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini) +ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC) { syntax_highlighter_ini->highlight_comment = INI_STR("highlight.comment"); syntax_highlighter_ini->highlight_default = INI_STR("highlight.default"); @@ -5451,7 +5496,7 @@ php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC); } - php_get_highlight_struct(&syntax_highlighter_ini); + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); if (highlight_file(filename, &syntax_highlighter_ini TSRMLS_CC) == FAILURE) { if (i) { @@ -5538,7 +5583,7 @@ EG(error_reporting) = E_ERROR; - php_get_highlight_struct(&syntax_highlighter_ini); + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); hicompiled_string_description = zend_make_compiled_string_description("highlighted code" TSRMLS_CC); @@ -5576,7 +5621,7 @@ convert_to_string_ex(varname); - str = zend_ini_string(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, 0); + str = zend_ini_string(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) + 1, 0 TSRMLS_CC); if (!str) { RETURN_FALSE; @@ -5673,7 +5718,7 @@ convert_to_string_ex(varname); convert_to_string_ex(new_value); - old_value = zend_ini_string(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, 0); + old_value = zend_ini_string(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, 0 TSRMLS_CC); /* copy to return here, because alter might free it! */ if (old_value) { @@ -5713,8 +5758,7 @@ } } - if (zend_alter_ini_entry(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, Z_STRVAL_PP(new_value), Z_STRLEN_PP(new_value), - PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) { + if (zend_alter_ini_entry(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) + 1, Z_STRVAL_PP(new_value), Z_STRLEN_PP(new_value), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC) == FAILURE) { zval_dtor(return_value); RETURN_FALSE; } @@ -5733,7 +5777,7 @@ convert_to_string_ex(varname); - zend_restore_ini_entry(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, PHP_INI_STAGE_RUNTIME); + zend_restore_ini_entry(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } /* }}} */ @@ -5749,16 +5793,14 @@ WRONG_PARAM_COUNT; } convert_to_string_ex(new_value); - old_value = zend_ini_string("include_path", sizeof("include_path"), 0); + old_value = zend_ini_string("include_path", sizeof("include_path"), 0 TSRMLS_CC); /* copy to return here, because alter might free it! */ if (old_value) { RETVAL_STRING(old_value, 1); } else { RETVAL_FALSE; } - if (zend_alter_ini_entry("include_path", sizeof("include_path"), - Z_STRVAL_PP(new_value), Z_STRLEN_PP(new_value), - PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) { + if (zend_alter_ini_entry("include_path", sizeof("include_path"), Z_STRVAL_PP(new_value), Z_STRLEN_PP(new_value), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC) == FAILURE) { zval_dtor(return_value); RETURN_FALSE; } @@ -5775,7 +5817,7 @@ if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; } - str = zend_ini_string("include_path", sizeof("include_path"), 0); + str = zend_ini_string("include_path", sizeof("include_path"), 0 TSRMLS_CC); if (str == NULL) { RETURN_FALSE; } @@ -5793,8 +5835,7 @@ WRONG_PARAM_COUNT; } - zend_restore_ini_entry("include_path", sizeof("include_path"), - PHP_INI_STAGE_RUNTIME); + zend_restore_ini_entry("include_path", sizeof("include_path"), PHP_INI_STAGE_RUNTIME TSRMLS_CC); } /* }}} */ @@ -5861,7 +5902,7 @@ RETURN_FALSE; } convert_to_string_ex(arg); - zend_alter_ini_entry("ignore_user_abort", sizeof("ignore_user_abort"), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("ignore_user_abort", sizeof("ignore_user_abort"), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); break; default: @@ -6116,7 +6157,7 @@ /* {{{ php_simple_ini_parser_cb */ -static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, int callback_type, zval *arr) +static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr) { zval *element; @@ -6146,11 +6187,11 @@ if (!(Z_STRLEN_P(arg1) > 1 && Z_STRVAL_P(arg1)[0] == '0') && is_numeric_string(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), NULL, NULL, 0) == IS_LONG) { ulong key = (ulong) zend_atoi(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1)); if (zend_hash_index_find(Z_ARRVAL_P(arr), key, (void **) &find_hash) == FAILURE) { - ALLOC_ZVAL(hash); - INIT_PZVAL(hash); - array_init(hash); + ALLOC_ZVAL(hash); + INIT_PZVAL(hash); + array_init(hash); - zend_hash_index_update(Z_ARRVAL_P(arr), key, &hash, sizeof(zval *), NULL); + zend_hash_index_update(Z_ARRVAL_P(arr), key, &hash, sizeof(zval *), NULL); } else { hash = *find_hash; } @@ -6176,7 +6217,12 @@ *element = *arg2; zval_copy_ctor(element); INIT_PZVAL(element); - add_next_index_zval(hash, element); + + if (arg3 && Z_STRLEN_P(arg3) > 0) { + add_assoc_zval_ex(hash, Z_STRVAL_P(arg3), Z_STRLEN_P(arg3) + 1, element); + } else { + add_next_index_zval(hash, element); + } } break; @@ -6188,7 +6234,7 @@ /* {{{ php_ini_parser_cb_with_sections */ -static void php_ini_parser_cb_with_sections(zval *arg1, zval *arg2, int callback_type, zval *arr) +static void php_ini_parser_cb_with_sections(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr) { TSRMLS_FETCH(); @@ -6205,58 +6251,61 @@ active_arr = arr; } - php_simple_ini_parser_cb(arg1, arg2, callback_type, active_arr); + php_simple_ini_parser_cb(arg1, arg2, arg3, callback_type, active_arr); } } /* }}} */ -/* {{{ proto array parse_ini_file(string filename [, bool process_sections]) +/* {{{ proto array parse_ini_file(string filename [, bool process_sections [, int scanner_mode]]) Parse configuration file */ PHP_FUNCTION(parse_ini_file) { - zval **filename, **process_sections; + char *filename = NULL; + int filename_len = 0; + zend_bool process_sections = 0; + long scanner_mode = ZEND_INI_SCANNER_NORMAL; zend_file_handle fh; zend_ini_parser_cb_t ini_parser_cb; - switch (ZEND_NUM_ARGS()) { - - case 1: - if (zend_get_parameters_ex(1, &filename) == FAILURE) { - RETURN_FALSE; - } - ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb; - break; - - case 2: - if (zend_get_parameters_ex(2, &filename, &process_sections) == FAILURE) { - RETURN_FALSE; - } - - convert_to_boolean_ex(process_sections); - - if (Z_BVAL_PP(process_sections)) { - BG(active_ini_file_section) = NULL; - ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections; - } else { - ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb; - } - break; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &filename, &filename_len, &process_sections, &scanner_mode) == FAILURE) { + RETURN_FALSE; + } - default: - ZEND_WRONG_PARAM_COUNT(); - break; + if (filename_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename can not be empty!"); + RETURN_FALSE; } - convert_to_string_ex(filename); + /* Set callback function */ + if (process_sections) { + BG(active_ini_file_section) = NULL; + ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections; + } else { + ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb; + } + /* Setup filehandle */ memset(&fh, 0, sizeof(fh)); - fh.filename = Z_STRVAL_PP(filename); + fh.filename = filename; Z_TYPE(fh) = ZEND_HANDLE_FILENAME; array_init(return_value); - zend_parse_ini_file(&fh, 0, ini_parser_cb, return_value); + zend_parse_ini_file(&fh, 0, scanner_mode, ini_parser_cb, return_value TSRMLS_CC); +} +/* }}} */ + +#if ZEND_DEBUG +/* {{{ proto void dump_config_hash(void) + */ +PHP_FUNCTION(dump_config_hash) +{ + HashTable hash = get_configuration_hash(); + + array_init(return_value); + zend_hash_apply_with_arguments(&hash, (apply_func_args_t) add_config_entry_cb, 1, return_value TSRMLS_CC); } /* }}} */ +#endif static int copy_request_variable(void *pDest, int num_args, va_list args, zend_hash_key *hash_key) { Index: ext/standard/basic_functions.h =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.h,v retrieving revision 1.139.2.4.2.6 diff -u -a -r1.139.2.4.2.6 basic_functions.h --- ext/standard/basic_functions.h 21 Jul 2007 01:24:26 -0000 1.139.2.4.2.6 +++ ext/standard/basic_functions.h 18 Sep 2007 15:36:41 -0000 @@ -89,7 +89,7 @@ PHP_FUNCTION(highlight_file); PHP_FUNCTION(highlight_string); PHP_FUNCTION(php_strip_whitespace); -ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini); +ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC); PHP_FUNCTION(ini_get); PHP_FUNCTION(ini_get_all); @@ -125,6 +125,9 @@ /* From the INI parser */ PHP_FUNCTION(parse_ini_file); +#if ZEND_DEBUG +PHP_FUNCTION(dump_config_hash); +#endif PHP_FUNCTION(str_rot13); PHP_FUNCTION(stream_get_filters); Index: ext/standard/browscap.c =================================================================== RCS file: /repository/php-src/ext/standard/browscap.c,v retrieving revision 1.85.2.2.2.3 diff -u -a -r1.85.2.2.2.3 browscap.c --- ext/standard/browscap.c 7 Mar 2007 00:52:40 -0000 1.85.2.2.2.3 +++ ext/standard/browscap.c 18 Sep 2007 15:36:41 -0000 @@ -23,11 +23,12 @@ #include "php_browscap.h" #include "php_ini.h" #include "php_string.h" - +#include "zend_ini_scanner.h" #include "zend_globals.h" static HashTable browser_hash; static zval *current_section; +static char *current_section_name; #define DEFAULT_SECTION_NAME "Default Browser Capability Settings" @@ -88,7 +89,7 @@ /* {{{ php_browscap_parser_cb */ -static void php_browscap_parser_cb(zval *arg1, zval *arg2, int callback_type, void *arg) +static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg TSRMLS_DC) { if (!arg1) { return; @@ -100,12 +101,37 @@ zval *new_property; char *new_key; + /* parent entry can not be same as current section -> causes infinite loop! */ + if (!strcasecmp(Z_STRVAL_P(arg1), "parent") && + !strcasecmp(current_section_name, Z_STRVAL_P(arg2)) + ) { + zend_error(E_CORE_ERROR, "Invalid browscap ini file: 'Parent' value can not be same as the section name: %s (in file %s)", current_section_name, INI_STR("browscap")); + return; + } + new_property = (zval *) pemalloc(sizeof(zval), 1); INIT_PZVAL(new_property); - Z_STRVAL_P(new_property) = zend_strndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2)); - Z_STRLEN_P(new_property) = Z_STRLEN_P(arg2); Z_TYPE_P(new_property) = IS_STRING; + /* Set proper value for true/false settings */ + if ((Z_STRLEN_P(arg2) == 2 && !strncasecmp(Z_STRVAL_P(arg2), "on", sizeof("on") - 1)) || + (Z_STRLEN_P(arg2) == 3 && !strncasecmp(Z_STRVAL_P(arg2), "yes", sizeof("yes") - 1)) || + (Z_STRLEN_P(arg2) == 4 && !strncasecmp(Z_STRVAL_P(arg2), "true", sizeof("true") - 1)) + ) { + Z_STRVAL_P(new_property) = zend_strndup("1", 1); + Z_STRLEN_P(new_property) = 1; + } else if ( + (Z_STRLEN_P(arg2) == 2 && !strncasecmp(Z_STRVAL_P(arg2), "no", sizeof("no") - 1)) || + (Z_STRLEN_P(arg2) == 3 && !strncasecmp(Z_STRVAL_P(arg2), "off", sizeof("off") - 1)) || + (Z_STRLEN_P(arg2) == 4 && !strncasecmp(Z_STRVAL_P(arg2), "none", sizeof("none") - 1)) || + (Z_STRLEN_P(arg2) == 5 && !strncasecmp(Z_STRVAL_P(arg2), "false", sizeof("false") - 1)) + ) { + Z_STRVAL_P(new_property) = zend_strndup("", 0); + Z_STRLEN_P(new_property) = 0; + } else { /* Other than true/false setting */ + Z_STRVAL_P(new_property) = zend_strndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2)); + Z_STRLEN_P(new_property) = Z_STRLEN_P(arg2); + } new_key = zend_strndup(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1)); zend_str_tolower(new_key, Z_STRLEN_P(arg1)); zend_hash_update(Z_ARRVAL_P(current_section), new_key, Z_STRLEN_P(arg1)+1, &new_property, sizeof(zval *), NULL); @@ -127,8 +153,10 @@ section_properties = (HashTable *) pemalloc(sizeof(HashTable), 1); zend_hash_init(section_properties, 0, NULL, (dtor_func_t) browscap_entry_dtor, 1); - current_section->value.ht = section_properties; - current_section->type = IS_ARRAY; + Z_ARRVAL_P(current_section) = section_properties; + Z_TYPE_P(current_section) = IS_ARRAY; + current_section_name = zend_strndup(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1)); + zend_hash_update(&browser_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1)+1, (void *) ¤t_section, sizeof(zval *), NULL); Z_STRVAL_P(processed) = Z_STRVAL_P(arg1); @@ -171,7 +199,7 @@ } fh.filename = browscap; Z_TYPE(fh) = ZEND_HANDLE_FP; - zend_parse_ini_file(&fh, 1, (zend_ini_parser_cb_t) php_browscap_parser_cb, &browser_hash); + zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_RAW, (zend_ini_parser_cb_t) php_browscap_parser_cb, &browser_hash TSRMLS_CC); } return SUCCESS; Index: ext/standard/ftp_fopen_wrapper.c =================================================================== RCS file: /repository/php-src/ext/standard/ftp_fopen_wrapper.c,v retrieving revision 1.85.2.4.2.3 diff -u -a -r1.85.2.4.2.3 ftp_fopen_wrapper.c --- ext/standard/ftp_fopen_wrapper.c 31 Aug 2007 07:42:00 -0000 1.85.2.4.2.3 +++ ext/standard/ftp_fopen_wrapper.c 18 Sep 2007 15:36:41 -0000 @@ -69,7 +69,11 @@ #include "php_fopen_wrappers.h" +#define FTPS_ENCRYPT_DATA 1 +#define GET_FTP_RESULT(stream) get_ftp_result((stream), tmp_line, sizeof(tmp_line) TSRMLS_CC) +/* {{{ get_ftp_result + */ static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer_size TSRMLS_DC) { while (php_stream_gets(stream, buffer, buffer_size-1) && @@ -77,24 +81,21 @@ isdigit((int) buffer[2]) && buffer[3] == ' ')); return strtol(buffer, NULL, 10); } -#define GET_FTP_RESULT(stream) get_ftp_result((stream), tmp_line, sizeof(tmp_line) TSRMLS_CC) - -#define FTPS_ENCRYPT_DATA 1 +/* }}} */ -static int php_stream_ftp_stream_stat(php_stream_wrapper *wrapper, - php_stream *stream, - php_stream_statbuf *ssb - TSRMLS_DC) +/* {{{ php_stream_ftp_stream_stat + */ +static int php_stream_ftp_stream_stat(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) { /* For now, we return with a failure code to prevent the underlying * file's details from being used instead. */ return -1; } +/* }}} */ - -static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper, - php_stream *stream - TSRMLS_DC) +/* {{{ php_stream_ftp_stream_close + */ +static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC) { php_stream *controlstream = (php_stream *)stream->wrapperdata; @@ -105,6 +106,7 @@ } return 0; } +/* }}} */ /* {{{ php_ftp_fopen_connect */ @@ -564,7 +566,7 @@ php_url_free(resource); return datastream; - errexit: +errexit: if (resource) { php_url_free(resource); } @@ -726,7 +728,7 @@ php_url_free(resource); return php_stream_alloc(&php_ftp_dirstream_ops, datastream, 0, mode); - opendir_errexit: +opendir_errexit: if (resource) { php_url_free(resource); } @@ -825,7 +827,7 @@ #endif } else { /* error or unsupported command */ - mdtm_error: +mdtm_error: #ifdef NETWARE ssb->sb.st_mtime.tv_sec = -1; #else @@ -857,7 +859,7 @@ php_url_free(resource); return 0; - stat_errexit: +stat_errexit: if (resource) { php_url_free(resource); } @@ -907,7 +909,7 @@ php_stream_close(stream); return 1; - unlink_errexit: +unlink_errexit: if (resource) { php_url_free(resource); } @@ -983,7 +985,7 @@ php_stream_close(stream); return 1; - rename_errexit: +rename_errexit: if (resource_from) { php_url_free(resource_from); } @@ -1080,7 +1082,7 @@ return 1; - mkdir_errexit: +mkdir_errexit: if (resource) { php_url_free(resource); } @@ -1130,7 +1132,7 @@ return 1; - rmdir_errexit: +rmdir_errexit: if (resource) { php_url_free(resource); } Index: ext/standard/info.c =================================================================== RCS file: /repository/php-src/ext/standard/info.c,v retrieving revision 1.249.2.10.2.14 diff -u -a -r1.249.2.10.2.14 info.c --- ext/standard/info.c 21 Jul 2007 01:24:26 -0000 1.249.2.10.2.14 +++ ext/standard/info.c 18 Sep 2007 15:36:41 -0000 @@ -672,7 +672,7 @@ SECTION("Configuration"); } SECTION("PHP Core"); - display_ini_entries(NULL); + display_ini_entries(NULL TSRMLS_CC); } if (flag & PHP_INFO_MODULES) { Index: ext/standard/tests/general_functions/parse_ini_basic.data =================================================================== RCS file: ext/standard/tests/general_functions/parse_ini_basic.data diff -N ext/standard/tests/general_functions/parse_ini_basic.data --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/standard/tests/general_functions/parse_ini_basic.data 18 Sep 2007 15:36:42 -0000 @@ -0,0 +1,106 @@ +[basic] +basicval = bar +longval = 12345 +with.dot = fooobar +boolon = on +booltrue = true +boolyes = yes +booloff = off +boolfalse = false +boolnone = none +boolno = no +string = asdadfsdjkslkj ¡@£$$ { }[ ]/%#¤ +sqstring = 'adsasdadasdasd' +dqstring = "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #" +php_constant = E_ALL + +[basic with whitespace] +basicval = bar +longval = 12345 +with.dot = fooobar +boolon = on +booltrue = true +boolyes = yes +booloff = off +boolfalse = false +boolnone = none +boolno = no +sqstring = 'adsasdadasdasd' +dqstring = "asdadfsdjkslkj ¡@£$$€¥¥{[()/)&/%#¤" +php_constant = E_ALL + +[comments] +; some comment + ; some comment with whitespace +somecomment = comment follows;aaa@bbb ; comment here +; + +[variables] +var1 = ${basicval} +var2 = ${basicval}/foo +var3 = foo/${basicval} +var4 = foo/${basicval}/foo +quoted_var1 = "${basicqval}" +quoted_var2 = "${basicqval}/foo" +quoted_var3 = "foo/${basicqval}" +quoted_var4 = "foo/${basicqval}/foo" + +[offset values] +foo1[] = "basic offset 1" +foo1[ ] = "basic offset 2" +foo2[123] = "long offset" +foo3[abc] = "string offset" +foo4[""] = "quoted offset 1" +foo4[" "] = "quoted offset 2" +foo4["sqfoobar"] = "quoted string offset" +foo4['dqfoobar'] = "single quoted offset" +foo6[${basicval}] = "variable" +foo6[${basicval}/foo] = "variable with string 1" +foo6[foo/${basicval}] = "variable with string 2" +foo6[foo/${basicval}/foo] = "variable with string 3" +foo7["${basicqval}"] = "quoted variable 1" +foo7["${basicqval}/foo"] = "quoted variable 2" +foo7["foo/${basicqval}"] = "quoted variable 3" +foo7[ "foo/${basicqval}/foo" ] = "quoted variable 4" + +[non value] +novalue_option1 = +novalue_option2= +novalue_option3 = +novalue_option4= +novalue_option4[] = +novalue_option4[]= +novalue_option4[]= + +["Quoted strings and variables in sections"] + +[${basicval}] +[${basicval}/foo] +[foo/${basicval}] +[foo/${basicval}/foo] + +["${basicqval}"] +["${basicqval}/foo"] +["foo/${basicqval}"] +["foo/${basicqval}/foo"] + +[PATH=${basicval}/no/quotes] +; Invalid! +;[PATH="${basicval}/path/quoted"] +["PATH=${basicval}/all/quoted"] + +; The rest is from bug #29306 +[01] +e=e +f=f +[02] +g=g +h=h +[1] +a=a +b=b +[2] +c=c +d=d +[0815] +bla=bla Index: ext/standard/tests/general_functions/parse_ini_basic.phpt =================================================================== RCS file: ext/standard/tests/general_functions/parse_ini_basic.phpt diff -N ext/standard/tests/general_functions/parse_ini_basic.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/standard/tests/general_functions/parse_ini_basic.phpt 18 Sep 2007 15:36:42 -0000 @@ -0,0 +1,239 @@ +--TEST-- +parse_ini_file() tests +--ENV-- +basicval=FUBAR_VARIABLE +basicqval=FUBAR_QUOTES_VARIABLE +--FILE-- + +--EXPECTF-- +array(22) { + ["basic"]=> + array(14) { + ["basicval"]=> + string(3) "bar" + ["longval"]=> + string(5) "12345" + ["with.dot"]=> + string(7) "fooobar" + ["boolon"]=> + string(1) "1" + ["booltrue"]=> + string(1) "1" + ["boolyes"]=> + string(1) "1" + ["booloff"]=> + string(0) "" + ["boolfalse"]=> + string(0) "" + ["boolnone"]=> + string(0) "" + ["boolno"]=> + string(0) "" + ["string"]=> + string(34) "asdadfsdjkslkj ¡@£$$ { }[ ]/%#¤" + ["sqstring"]=> + string(14) "adsasdadasdasd" + ["dqstring"]=> + string(51) "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #" + ["php_constant"]=> + string(4) "6143" + } + ["basic with whitespace"]=> + array(13) { + ["basicval"]=> + string(3) "bar" + ["longval"]=> + string(5) "12345" + ["with.dot"]=> + string(7) "fooobar" + ["boolon"]=> + string(1) "1" + ["booltrue"]=> + string(1) "1" + ["boolyes"]=> + string(1) "1" + ["booloff"]=> + string(0) "" + ["boolfalse"]=> + string(0) "" + ["boolnone"]=> + string(0) "" + ["boolno"]=> + string(0) "" + ["sqstring"]=> + string(14) "adsasdadasdasd" + ["dqstring"]=> + string(41) "asdadfsdjkslkj ¡@£$$€¥¥{[()/)&/%#¤" + ["php_constant"]=> + string(4) "6143" + } + ["comments"]=> + array(1) { + ["somecomment"]=> + string(15) "comment follows" + } + ["variables"]=> + array(8) { + ["var1"]=> + string(14) "FUBAR_VARIABLE" + ["var2"]=> + string(18) "FUBAR_VARIABLE/foo" + ["var3"]=> + string(18) "foo/FUBAR_VARIABLE" + ["var4"]=> + string(22) "foo/FUBAR_VARIABLE/foo" + ["quoted_var1"]=> + string(21) "FUBAR_QUOTES_VARIABLE" + ["quoted_var2"]=> + string(25) "FUBAR_QUOTES_VARIABLE/foo" + ["quoted_var3"]=> + string(25) "foo/FUBAR_QUOTES_VARIABLE" + ["quoted_var4"]=> + string(29) "foo/FUBAR_QUOTES_VARIABLE/foo" + } + ["offset values"]=> + array(6) { + ["foo1"]=> + array(2) { + [0]=> + string(14) "basic offset 1" + [1]=> + string(14) "basic offset 2" + } + ["foo2"]=> + array(1) { + [123]=> + string(11) "long offset" + } + ["foo3"]=> + array(1) { + ["abc"]=> + string(13) "string offset" + } + ["foo4"]=> + array(4) { + [0]=> + string(15) "quoted offset 1" + [" "]=> + string(15) "quoted offset 2" + ["sqfoobar"]=> + string(20) "quoted string offset" + ["dqfoobar"]=> + string(20) "single quoted offset" + } + ["foo6"]=> + array(4) { + ["FUBAR_VARIABLE"]=> + string(8) "variable" + ["FUBAR_VARIABLE/foo"]=> + string(22) "variable with string 1" + ["foo/FUBAR_VARIABLE"]=> + string(22) "variable with string 2" + ["foo/FUBAR_VARIABLE/foo"]=> + string(22) "variable with string 3" + } + ["foo7"]=> + array(4) { + ["FUBAR_QUOTES_VARIABLE"]=> + string(17) "quoted variable 1" + ["FUBAR_QUOTES_VARIABLE/foo"]=> + string(17) "quoted variable 2" + ["foo/FUBAR_QUOTES_VARIABLE"]=> + string(17) "quoted variable 3" + ["foo/FUBAR_QUOTES_VARIABLE/foo"]=> + string(17) "quoted variable 4" + } + } + ["non value"]=> + array(4) { + ["novalue_option1"]=> + string(0) "" + ["novalue_option2"]=> + string(0) "" + ["novalue_option3"]=> + string(0) "" + ["novalue_option4"]=> + array(3) { + [0]=> + string(0) "" + [1]=> + string(0) "" + [2]=> + string(0) "" + } + } + ["Quoted strings and variables in sections"]=> + array(0) { + } + ["FUBAR_VARIABLE"]=> + array(0) { + } + ["FUBAR_VARIABLE/foo"]=> + array(0) { + } + ["foo/FUBAR_VARIABLE"]=> + array(0) { + } + ["foo/FUBAR_VARIABLE/foo"]=> + array(0) { + } + ["FUBAR_QUOTES_VARIABLE"]=> + array(0) { + } + ["FUBAR_QUOTES_VARIABLE/foo"]=> + array(0) { + } + ["foo/FUBAR_QUOTES_VARIABLE"]=> + array(0) { + } + ["foo/FUBAR_QUOTES_VARIABLE/foo"]=> + array(0) { + } + ["PATH=FUBAR_VARIABLE/no/quotes"]=> + array(0) { + } + ["PATH=FUBAR_VARIABLE/all/quoted"]=> + array(0) { + } + ["01"]=> + array(2) { + ["e"]=> + string(1) "e" + ["f"]=> + string(1) "f" + } + ["02"]=> + array(2) { + ["g"]=> + string(1) "g" + ["h"]=> + string(1) "h" + } + [1]=> + array(2) { + ["a"]=> + string(1) "a" + ["b"]=> + string(1) "b" + } + [2]=> + array(2) { + ["c"]=> + string(1) "c" + ["d"]=> + string(1) "d" + } + ["0815"]=> + array(1) { + ["bla"]=> + string(3) "bla" + } +} +Done. Index: ext/standard/tests/general_functions/parse_ini_booleans.data =================================================================== RCS file: ext/standard/tests/general_functions/parse_ini_booleans.data diff -N ext/standard/tests/general_functions/parse_ini_booleans.data --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/standard/tests/general_functions/parse_ini_booleans.data 18 Sep 2007 15:36:42 -0000 @@ -0,0 +1,27 @@ +[error_reporting values] +foo = E_ALL E_NOTICE +error_reporting = E_ALL +error_reporting1 = E_COMPILE_ERROR|E_RECOVERABLE_ERROR |E_ERROR|E_CORE_ERROR +error_reporting2 = E_ALL&~E_NOTICE +error_reporting3 = E_ALL & ~E_NOTICE +error_reporting4 = E_ALL & ~E_NOTICE | E_STRICT + +[true or false] +bool_true = true +bool_yes = yes +bool_on = on +bool_false=false +bool_off =Off +bool_no=No +bool_none= NoNe +bool_null = NULl + +[strings] +string_true = "true" +string_yes = " yes" +string_on = " on " +string_false="false" +string_off ="Off " +string_no="No " +string_none=" NoNe" +string_null = "NULl" Index: ext/standard/tests/general_functions/parse_ini_booleans.phpt =================================================================== RCS file: ext/standard/tests/general_functions/parse_ini_booleans.phpt diff -N ext/standard/tests/general_functions/parse_ini_booleans.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/standard/tests/general_functions/parse_ini_booleans.phpt 18 Sep 2007 15:36:42 -0000 @@ -0,0 +1,69 @@ +--TEST-- +parse_ini_file() boolean operators +--FILE-- + +--EXPECTF-- +array(3) { + ["error_reporting values"]=> + array(6) { + ["foo"]=> + string(14) "E_ALL E_NOTICE" + ["error_reporting"]=> + string(4) "6143" + ["error_reporting1"]=> + string(4) "4177" + ["error_reporting2"]=> + string(4) "6135" + ["error_reporting3"]=> + string(4) "6135" + ["error_reporting4"]=> + string(4) "8183" + } + ["true or false"]=> + array(8) { + ["bool_true"]=> + string(1) "1" + ["bool_yes"]=> + string(1) "1" + ["bool_on"]=> + string(1) "1" + ["bool_false"]=> + string(0) "" + ["bool_off"]=> + string(0) "" + ["bool_no"]=> + string(0) "" + ["bool_none"]=> + string(0) "" + ["bool_null"]=> + string(0) "" + } + ["strings"]=> + array(8) { + ["string_true"]=> + string(4) "true" + ["string_yes"]=> + string(4) " yes" + ["string_on"]=> + string(5) " on " + ["string_false"]=> + string(5) "false" + ["string_off"]=> + string(4) "Off " + ["string_no"]=> + string(4) "No " + ["string_none"]=> + string(5) " NoNe" + ["string_null"]=> + string(4) "NULl" + } +} +Done. Index: ext/standard/tests/general_functions/parse_ini_file.phpt =================================================================== RCS file: /repository/php-src/ext/standard/tests/general_functions/parse_ini_file.phpt,v retrieving revision 1.1.2.2 diff -u -a -r1.1.2.2 parse_ini_file.phpt --- ext/standard/tests/general_functions/parse_ini_file.phpt 16 Nov 2006 13:01:23 -0000 1.1.2.2 +++ ext/standard/tests/general_functions/parse_ini_file.phpt 18 Sep 2007 15:36:42 -0000 @@ -1,12 +1,13 @@ --TEST-- -parse_ini_file() tests +parse_ini_file() multiple calls --FILE-- --EXPECTF-- -Warning: Wrong parameter count for parse_ini_file() in %s on line %d -NULL +Warning: parse_ini_file() expects at least 1 parameter, 0 given in %sparse_ini_file.php on line 6 +bool(false) -Warning: Wrong parameter count for parse_ini_file() in %s on line %d -NULL +Warning: parse_ini_file() expects at most 3 parameters, 4 given in %sparse_ini_file.php on line 7 +bool(false) -Warning: parse_ini_file(%sparse_ini_file.dat): failed to open stream: No such file or directory in %s on line %d +Warning: parse_ini_file(%sparse_ini_file.dat): failed to open stream: No such file or directory in %sparse_ini_file.php on line 8 array(0) { } -Warning: parse_ini_file(%sparse_ini_file.dat): failed to open stream: No such file or directory in %s on line %d +Warning: parse_ini_file(%sparse_ini_file.dat): failed to open stream: No such file or directory in %sparse_ini_file.php on line 9 array(0) { } array(1) { @@ -113,15 +111,15 @@ string(0) "" } -Warning: Error parsing %sparse_ini_file.dat on line 2 - in %s on line %d +Warning: syntax error, unexpected '=' in %sparse_ini_file.dat on line 2 + in %sparse_ini_file.php on line 20 array(1) { ["test"]=> string(0) "" } -Warning: Error parsing %sparse_ini_file.dat on line 2 - in %s on line %d +Warning: syntax error, unexpected '=' in %sparse_ini_file.dat on line 2 + in %sparse_ini_file.php on line 26 array(1) { ["test"]=> string(4) "test" Index: ext/zlib/zlib.c =================================================================== RCS file: /repository/php-src/ext/zlib/zlib.c,v retrieving revision 1.183.2.6.2.5 diff -u -a -r1.183.2.6.2.5 zlib.c --- ext/zlib/zlib.c 1 Jan 2007 09:36:10 -0000 1.183.2.6.2.5 +++ ext/zlib/zlib.c 18 Sep 2007 15:36:42 -0000 @@ -173,7 +173,7 @@ new_value_length = sizeof("1"); } - ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0); + ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0 TSRMLS_CC); if (ini_value != NULL && strlen(ini_value) != 0 && zend_atoi(new_value, new_value_length) != 0) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!"); return FAILURE; Index: main/SAPI.c =================================================================== RCS file: /repository/php-src/main/SAPI.c,v retrieving revision 1.202.2.7.2.15 diff -u -a -r1.202.2.7.2.15 SAPI.c --- main/SAPI.c 25 May 2007 09:20:01 -0000 1.202.2.7.2.15 +++ main/SAPI.c 18 Sep 2007 15:36:42 -0000 @@ -606,7 +606,7 @@ } #if HAVE_ZLIB if(!strncmp(ptr, "image/", sizeof("image/")-1)) { - zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC); } #endif mimetype = estrdup(ptr); @@ -762,7 +762,7 @@ /* Add output compression headers at this late stage in order to make it possible to switch it off inside the script. */ - if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) { + if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0 TSRMLS_CC)) { zval nm_zlib_get_coding_type; zval *uf_result = NULL; Index: main/main.c =================================================================== RCS file: /repository/php-src/main/main.c,v retrieving revision 1.640.2.23.2.55 diff -u -a -r1.640.2.23.2.55 main.c --- main/main.c 13 Sep 2007 20:04:22 -0000 1.640.2.23.2.55 +++ main/main.c 18 Sep 2007 15:36:42 -0000 @@ -445,12 +445,15 @@ 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() /* }}} */ @@ -1023,7 +1026,7 @@ } 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("max_execution_time", sizeof("max_execution_time"), Z_STRVAL_PP(new_timeout), Z_STRLEN_PP(new_timeout), PHP_INI_USER, PHP_INI_STAGE_RUNTIME TSRMLS_CC) == SUCCESS) { RETURN_TRUE; } else { RETURN_FALSE; Index: main/php_globals.h =================================================================== RCS file: /repository/php-src/main/php_globals.h,v retrieving revision 1.98.2.1.2.7 diff -u -a -r1.98.2.1.2.7 php_globals.h --- main/php_globals.h 24 Jul 2007 14:21:36 -0000 1.98.2.1.2.7 +++ main/php_globals.h 18 Sep 2007 15:36:42 -0000 @@ -161,6 +161,9 @@ #endif long max_input_nesting_level; zend_bool in_user_include; + + char *user_ini_filename; + long user_ini_cache_ttl; }; Index: main/php_ini.c =================================================================== RCS file: /repository/php-src/main/php_ini.c,v retrieving revision 1.136.2.4.2.15 diff -u -a -r1.136.2.4.2.15 php_ini.c --- main/php_ini.c 31 Aug 2007 08:16:13 -0000 1.136.2.4.2.15 +++ main/php_ini.c 18 Sep 2007 15:36:42 -0000 @@ -16,11 +16,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_ini.c,v 1.136.2.4.2.15 2007/08/31 08:16:13 jani Exp $ */ +/* $Id: php_ini.c,v 1.136.2.4.2.13 2007/05/19 12:53:06 tony2001 Exp $ */ #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 @@ 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 @@ /* {{{ 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 @@ PUTS(""); 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"); } 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; @@ -130,10 +130,9 @@ /* {{{ display_ini_entries */ -PHPAPI void display_ini_entries(zend_module_entry *module) +PHPAPI void display_ini_entries(zend_module_entry *module TSRMLS_DC) { int module_number; - TSRMLS_FETCH(); if (module) { module_number = module->module_number; @@ -148,7 +147,6 @@ /* }}} */ /* php.ini support */ - #ifdef ZTS # if (ZEND_DEBUG) # define ZEND_EXTENSION_TOKEN "zend_extension_debug_ts" @@ -163,17 +161,46 @@ # 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 +212,101 @@ 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)); */ - zend_hash_update(&configuration_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, &hash, sizeof(zval *), NULL); + /* 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); + } + + /* 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 +331,6 @@ } /* }}} */ -/* {{{ 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 +341,8 @@ 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 +352,6 @@ 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 +562,9 @@ 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 +572,8 @@ 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 +587,24 @@ 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 +615,14 @@ 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 +630,17 @@ } 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 +650,9 @@ } 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_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC); } return SUCCESS; @@ -594,6 +688,81 @@ } /* }}} */ +/* {{{ 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(str, str_len, Z_STRVAL_P(data), Z_STRLEN_P(data), modify_type, stage 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 +828,14 @@ } /* }}} */ +#if ZEND_DEBUG +#include "php_ini.h" +PHPAPI HashTable get_configuration_hash(void) +{ + return configuration_hash; +} +#endif + /* * Local variables: * tab-width: 4 Index: main/php_ini.h =================================================================== RCS file: /repository/php-src/main/php_ini.h,v retrieving revision 1.45.2.3.2.3 diff -u -a -r1.45.2.3.2.3 php_ini.h --- main/php_ini.h 31 Aug 2007 07:48:05 -0000 1.45.2.3.2.3 +++ main/php_ini.h 18 Sep 2007 15:36:42 -0000 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_ini.h,v 1.45.2.3.2.3 2007/08/31 07:48:05 jani Exp $ */ +/* $Id: php_ini.h,v 1.45.2.3.2.2 2007/08/02 23:57:52 stas Exp $ */ #ifndef PHP_INI_H #define 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 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 Index: sapi/aolserver/aolserver.c =================================================================== RCS file: /repository/php-src/sapi/aolserver/aolserver.c,v retrieving revision 1.81.2.2.2.1 diff -u -a -r1.81.2.2.2.1 aolserver.c --- sapi/aolserver/aolserver.c 1 Jan 2007 09:36:12 -0000 1.81.2.2.2.1 +++ sapi/aolserver/aolserver.c 18 Sep 2007 15:36:42 -0000 @@ -539,6 +539,7 @@ Ns_Log(Notice, "php_value has been deactivated temporarily. Please use a php.ini file to pass directives to PHP. Thanks."); #if 0 char *val; + TSRMLS_FETCH(); val = strchr(value, ' '); if (val) { @@ -551,8 +552,7 @@ } while(*val == ' '); Ns_Log(Debug, "PHP configuration option '%s=%s'", new_key, val); - zend_alter_ini_entry(new_key, strlen(new_key) + 1, val, - strlen(val) + 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry(new_key, strlen(new_key) + 1, val, strlen(val) + 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); efree(new_key); } Index: sapi/apache/mod_php5.c =================================================================== RCS file: /repository/php-src/sapi/apache/Attic/mod_php5.c,v retrieving revision 1.19.2.7.2.13 diff -u -a -r1.19.2.7.2.13 mod_php5.c --- sapi/apache/mod_php5.c 6 Aug 2007 12:54:57 -0000 1.19.2.7.2.13 +++ sapi/apache/mod_php5.c 18 Sep 2007 15:36:42 -0000 @@ -548,7 +548,7 @@ */ static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC) { - zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, per_dir_entry->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, (per_dir_entry->htaccess ? PHP_INI_STAGE_HTACCESS : PHP_INI_STAGE_ACTIVATE) TSRMLS_CC); return 0; } /* }}} */ Index: sapi/apache/sapi_apache.c =================================================================== RCS file: /repository/php-src/sapi/apache/sapi_apache.c,v retrieving revision 1.47.2.1.2.1 diff -u -a -r1.47.2.1.2.1 sapi_apache.c --- sapi/apache/sapi_apache.c 1 Jan 2007 09:36:12 -0000 1.47.2.1.2.1 +++ sapi/apache/sapi_apache.c 18 Sep 2007 15:36:42 -0000 @@ -39,7 +39,7 @@ if (display_source_mode) { zend_syntax_highlighter_ini syntax_highlighter_ini; - php_get_highlight_struct(&syntax_highlighter_ini); + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); if (highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC) != SUCCESS) { retval = NOT_FOUND; } Index: sapi/apache2filter/apache_config.c =================================================================== RCS file: /repository/php-src/sapi/apache2filter/apache_config.c,v retrieving revision 1.34.2.1.2.3 diff -u -a -r1.34.2.1.2.3 apache_config.c --- sapi/apache2filter/apache_config.c 3 Aug 2007 09:33:30 -0000 1.34.2.1.2.3 +++ sapi/apache2filter/apache_config.c 18 Sep 2007 15:36:42 -0000 @@ -159,7 +159,7 @@ return ""; } -void apply_config(void *dummy) +void apply_config(void *dummy TSRMLS_DC) { php_conf_rec *d = dummy; char *str; @@ -172,7 +172,7 @@ zend_hash_move_forward(&d->config)) { zend_hash_get_current_data(&d->config, (void **) &data); phpapdebug((stderr, "APPLYING (%s)(%s)\n", str, data->value)); - if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == FAILURE) { + if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, data->status, data->htaccess ? PHP_INI_STAGE_HTACCESS : PHP_INI_STAGE_ACTIVATE TSRMLS_CC) == FAILURE) { phpapdebug((stderr, "..FAILED\n")); } } Index: sapi/apache2filter/php_apache.h =================================================================== RCS file: /repository/php-src/sapi/apache2filter/php_apache.h,v retrieving revision 1.25.2.1.2.2 diff -u -a -r1.25.2.1.2.2 php_apache.h --- sapi/apache2filter/php_apache.h 1 Jan 2007 09:36:12 -0000 1.25.2.1.2.2 +++ sapi/apache2filter/php_apache.h 18 Sep 2007 15:36:42 -0000 @@ -56,7 +56,7 @@ void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf); void *create_php_config(apr_pool_t *p, char *dummy); char *get_php_config(void *conf, char *name, size_t name_len); -void apply_config(void *); +void apply_config(void * TSRMLS_DC); extern const command_rec php_dir_cmds[]; static size_t php_apache_read_stream(void *, char *, size_t TSRMLS_DC); Index: sapi/apache2filter/sapi_apache2.c =================================================================== RCS file: /repository/php-src/sapi/apache2filter/sapi_apache2.c,v retrieving revision 1.136.2.2.2.8 diff -u -a -r1.136.2.2.2.8 sapi_apache2.c --- sapi/apache2filter/sapi_apache2.c 1 Jan 2007 09:36:12 -0000 1.136.2.2.2.8 +++ sapi/apache2filter/sapi_apache2.c 18 Sep 2007 15:36:42 -0000 @@ -511,7 +511,7 @@ return ap_pass_brigade(f->next, bb); } - apply_config(conf); + apply_config(conf TSRMLS_CC); php_apache_request_ctor(f, ctx TSRMLS_CC); // It'd be nice if we could highlight based of a zend_file_handle here.... @@ -531,8 +531,7 @@ php_execute_script(&zfd TSRMLS_CC); - apr_table_set(ctx->r->notes, "mod_php_memory_usage", - apr_psprintf(ctx->r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC))); + apr_table_set(ctx->r->notes, "mod_php_memory_usage", apr_psprintf(ctx->r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC))); php_apache_request_dtor(f TSRMLS_CC); Index: sapi/apache2handler/apache_config.c =================================================================== RCS file: /repository/php-src/sapi/apache2handler/apache_config.c,v retrieving revision 1.7.2.1.2.4 diff -u -a -r1.7.2.1.2.4 apache_config.c --- sapi/apache2handler/apache_config.c 3 Aug 2007 09:33:17 -0000 1.7.2.1.2.4 +++ sapi/apache2handler/apache_config.c 18 Sep 2007 15:36:42 -0000 @@ -159,7 +159,7 @@ return ""; } -void apply_config(void *dummy) +void apply_config(void *dummy TSRMLS_DC) { php_conf_rec *d = dummy; char *str; @@ -172,7 +172,7 @@ zend_hash_move_forward(&d->config)) { zend_hash_get_current_data(&d->config, (void **) &data); phpapdebug((stderr, "APPLYING (%s)(%s)\n", str, data->value)); - if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == FAILURE) { + if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE TSRMLS_CC) == FAILURE) { phpapdebug((stderr, "..FAILED\n")); } } Index: sapi/apache2handler/php_apache.h =================================================================== RCS file: /repository/php-src/sapi/apache2handler/php_apache.h,v retrieving revision 1.8.2.1.2.2 diff -u -a -r1.8.2.1.2.2 php_apache.h --- sapi/apache2handler/php_apache.h 1 Jan 2007 09:36:12 -0000 1.8.2.1.2.2 +++ sapi/apache2handler/php_apache.h 18 Sep 2007 15:36:42 -0000 @@ -51,7 +51,7 @@ void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf); void *create_php_config(apr_pool_t *p, char *dummy); char *get_php_config(void *conf, char *name, size_t name_len); -void apply_config(void *); +void apply_config(void * TSRMLS_DC); extern const command_rec php_dir_cmds[]; void php_ap2_register_hook(apr_pool_t *p); Index: sapi/apache2handler/sapi_apache2.c =================================================================== RCS file: /repository/php-src/sapi/apache2handler/sapi_apache2.c,v retrieving revision 1.57.2.10.2.15 diff -u -a -r1.57.2.10.2.15 sapi_apache2.c --- sapi/apache2handler/sapi_apache2.c 28 Jun 2007 17:23:07 -0000 1.57.2.10.2.15 +++ sapi/apache2handler/sapi_apache2.c 18 Sep 2007 15:36:42 -0000 @@ -527,7 +527,7 @@ parent_req = ctx->r; ctx->r = r; } - apply_config(conf); + apply_config(conf TSRMLS_CC); if (strcmp(r->handler, PHP_MAGIC_TYPE) && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(r->handler, PHP_SCRIPT)) { /* Check for xbithack in this case. */ @@ -617,7 +617,8 @@ /* Determine if we need to parse the file or show the source */ if (strncmp(r->handler, PHP_SOURCE_MAGIC_TYPE, sizeof(PHP_SOURCE_MAGIC_TYPE) - 1) == 0) { zend_syntax_highlighter_ini syntax_highlighter_ini; - php_get_highlight_struct(&syntax_highlighter_ini); + + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); highlight_file((char *)r->filename, &syntax_highlighter_ini TSRMLS_CC); } else { zend_file_handle zfd; Index: sapi/apache_hooks/mod_php5.c =================================================================== RCS file: /repository/php-src/sapi/apache_hooks/mod_php5.c,v retrieving revision 1.11.2.1.2.5 diff -u -a -r1.11.2.1.2.5 mod_php5.c --- sapi/apache_hooks/mod_php5.c 1 Jan 2007 09:36:12 -0000 1.11.2.1.2.5 +++ sapi/apache_hooks/mod_php5.c 18 Sep 2007 15:36:42 -0000 @@ -605,7 +605,7 @@ */ static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC) { - zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); return 0; } /* }}} */ Index: sapi/apache_hooks/sapi_apache.c =================================================================== RCS file: /repository/php-src/sapi/apache_hooks/sapi_apache.c,v retrieving revision 1.9.2.1.2.1 diff -u -a -r1.9.2.1.2.1 sapi_apache.c --- sapi/apache_hooks/sapi_apache.c 1 Jan 2007 09:36:12 -0000 1.9.2.1.2.1 +++ sapi/apache_hooks/sapi_apache.c 18 Sep 2007 15:36:42 -0000 @@ -38,7 +38,7 @@ if (display_source_mode) { zend_syntax_highlighter_ini syntax_highlighter_ini; - php_get_highlight_struct(&syntax_highlighter_ini); + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); if (highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC)){ return OK; } else { Index: sapi/cgi/cgi_main.c =================================================================== RCS file: /repository/php-src/sapi/cgi/cgi_main.c,v retrieving revision 1.267.2.15.2.49 diff -u -a -r1.267.2.15.2.49 cgi_main.c --- sapi/cgi/cgi_main.c 10 Sep 2007 10:55:26 -0000 1.267.2.15.2.49 +++ sapi/cgi/cgi_main.c 18 Sep 2007 15:36:42 -0000 @@ -161,8 +161,30 @@ zend_bool impersonate; # endif #endif + HashTable user_config_cache; } php_cgi_globals_struct; +/* {{{ user_config_cache + * + * Key for each cache entry is dirname(PATH_TRANSLATED). + * + * NOTE: Each cache entry config_hash contains the combination from all user ini files found in + * the path starting from doc_root throught to dirname(PATH_TRANSLATED). There is no point + * storing per-file entries as it would not be possible to detect added / deleted entries + * between separate files. + */ +typedef struct _user_config_cache_entry { + time_t expires; + HashTable *user_config; +} user_config_cache_entry; + +static void user_config_cache_entry_dtor(user_config_cache_entry *entry) /* {{{ */ +{ + zend_hash_destroy(entry->user_config); + free(entry->user_config); +} +/* }}} */ + #ifdef ZTS static int php_cgi_globals_id; #define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v) @@ -573,6 +595,91 @@ fprintf(stderr, "%s\n", message); } +/* {{{ php_cgi_ini_activate_user_config + */ +static void php_cgi_ini_activate_user_config(char *path, int path_len, int start TSRMLS_DC) +{ + char *ptr; + user_config_cache_entry *new_entry, *entry; + time_t request_time = sapi_get_request_time(TSRMLS_C); + + /* Find cached config entry: If not found, create one */ + if (zend_hash_find(&CGIG(user_config_cache), path, path_len + 1, (void **) &entry) == FAILURE) { + new_entry = pemalloc(sizeof(user_config_cache_entry), 1); + new_entry->expires = 0; + new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1); + zend_hash_init(new_entry->user_config, 0, NULL, (dtor_func_t) config_zval_dtor, 1); + zend_hash_update(&CGIG(user_config_cache), path, path_len + 1, new_entry, sizeof(user_config_cache_entry), (void **) &entry); + free(new_entry); + } + + /* Check whether cache entry has expired and rescan if it is */ + if (request_time > entry->expires) { + + /* Clear the expired config */ + zend_hash_clean(entry->user_config); + + /* Walk through each directory and apply entries to user_config hash */ + ptr = path + start; /* start is the point where doc_root ends! */ + while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) { + *ptr = 0; + php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC); + *ptr = '/'; + ptr++; + } + entry->expires = request_time + PG(user_ini_cache_ttl); + } + + /* Activate ini entries with values from the user config hash */ + php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS TSRMLS_CC); +} +/* }}} */ + +static int sapi_cgi_activate(TSRMLS_D) +{ + char *path, *doc_root; + uint path_len, doc_root_len; + + /* PATH_TRANSLATED should be defined at this stage but better safe than sorry :) */ + if (!SG(request_info).path_translated) { + return FAILURE; + } + + doc_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1 TSRMLS_CC); + + /* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */ + if (!doc_root) { + return FAILURE; + } + doc_root_len = strlen(doc_root); + if (doc_root[doc_root_len - 1] == '/') { + --doc_root_len; + } + + /* Prepare search path */ + path_len = strlen(SG(request_info).path_translated); + path = zend_strndup(SG(request_info).path_translated, path_len); + php_dirname(path, path_len); + path_len = strlen(path); + + /* Make sure we have trailing slash! */ + if (!IS_SLASH(path[path_len])) { + path[path_len++] = DEFAULT_SLASH; + } + path[path_len] = 0; + + /* Activate per-dir-system-configuration defined in php.ini and stored into configuration_hash during startup */ + php_ini_activate_per_dir_config(path, path_len TSRMLS_CC); /* Note: for global settings sake we check from root to path */ + + /* Load and activate user ini files in path starting from DOCUMENT_ROOT */ + if (strlen(PG(user_ini_filename))) { + php_cgi_ini_activate_user_config(path, path_len, doc_root_len - 1 TSRMLS_CC); + } + + free(path); + return SUCCESS; +} + static int sapi_cgi_deactivate(TSRMLS_D) { /* flush only when SAPI was started. The reasons are: @@ -594,7 +701,6 @@ return SUCCESS; } - /* {{{ sapi_module_struct cgi_sapi_module */ static sapi_module_struct cgi_sapi_module = { @@ -609,7 +715,7 @@ php_cgi_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ - NULL, /* activate */ + sapi_cgi_activate, /* activate */ sapi_cgi_deactivate, /* deactivate */ sapi_cgibin_ub_write, /* unbuffered write */ @@ -1103,6 +1209,7 @@ php_cgi_globals->impersonate = 0; # endif #endif + zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, (dtor_func_t) user_config_cache_entry_dtor, 1); } /* }}} */ @@ -1124,6 +1231,8 @@ */ static PHP_MSHUTDOWN_FUNCTION(cgi) { + zend_hash_destroy(&CGIG(user_config_cache)); + UNREGISTER_INI_ENTRIES(); return SUCCESS; } @@ -1819,7 +1928,7 @@ zend_syntax_highlighter_ini syntax_highlighter_ini; if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) { - php_get_highlight_struct(&syntax_highlighter_ini); + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); zend_highlight(&syntax_highlighter_ini TSRMLS_CC); #if PHP_FASTCGI if (fastcgi) { Index: sapi/cli/php_cli.c =================================================================== RCS file: /repository/php-src/sapi/cli/php_cli.c,v retrieving revision 1.129.2.13.2.22 diff -u -a -r1.129.2.13.2.22 php_cli.c --- sapi/cli/php_cli.c 8 Aug 2007 23:51:24 -0000 1.129.2.13.2.22 +++ sapi/cli/php_cli.c 18 Sep 2007 15:36:42 -0000 @@ -1159,7 +1159,7 @@ zend_syntax_highlighter_ini syntax_highlighter_ini; if (open_file_for_scanning(&file_handle TSRMLS_CC)==SUCCESS) { - php_get_highlight_struct(&syntax_highlighter_ini); + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); zend_highlight(&syntax_highlighter_ini TSRMLS_CC); } goto out; @@ -1291,7 +1291,7 @@ if (zend_hash_find(&module_registry, lcname, len+1, (void**)&module) == FAILURE) { if (!strcmp(reflection_what, "main")) { - display_ini_entries(NULL); + display_ini_entries(NULL TSRMLS_CC); } else { zend_printf("Extension '%s' not present.\n", reflection_what); exit_status = 1; Index: sapi/milter/php_milter.c =================================================================== RCS file: /repository/php-src/sapi/milter/php_milter.c,v retrieving revision 1.14.2.2.2.3 diff -u -a -r1.14.2.2.2.3 php_milter.c --- sapi/milter/php_milter.c 28 Mar 2007 10:08:31 -0000 1.14.2.2.2.3 +++ sapi/milter/php_milter.c 18 Sep 2007 15:36:42 -0000 @@ -18,6 +18,7 @@ +----------------------------------------------------------------------+ */ +/* $Id$ */ #include "php.h" #include "php_globals.h" @@ -915,7 +916,7 @@ } /* }}} */ -static void define_command_line_ini_entry(char *arg) /* {{{ */ +static void define_command_line_ini_entry(char *arg TSRMLS_DC) /* {{{ */ { char *name, *value; @@ -927,7 +928,7 @@ } else { value = "1"; } - zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); } /* }}} */ @@ -1001,8 +1002,8 @@ /* Set some CLI defaults */ SG(options) |= SAPI_OPTION_NO_CHDIR; - zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); - zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); + zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */ @@ -1025,7 +1026,7 @@ /* This is default so NOP */ break; case 'd': /* define ini entries on command line */ - define_command_line_ini_entry(ap_php_optarg); + define_command_line_ini_entry(ap_php_optarg TSRMLS_CC); break; case 'D': /* daemon */ Index: sapi/nsapi/nsapi.c =================================================================== RCS file: /repository/php-src/sapi/nsapi/nsapi.c,v retrieving revision 1.69.2.3.2.6 diff -u -a -r1.69.2.3.2.6 nsapi.c --- sapi/nsapi/nsapi.c 27 Apr 2007 00:29:26 -0000 1.69.2.3.2.6 +++ sapi/nsapi/nsapi.c 18 Sep 2007 15:36:42 -0000 @@ -780,9 +780,7 @@ if (ok) { /* change the ini entry */ - if (zend_alter_ini_entry(entry->param->name, strlen(entry->param->name)+1, - entry->param->value, strlen(entry->param->value), - PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE)==FAILURE) { + if (zend_alter_ini_entry(entry->param->name, strlen(entry->param->name) + 1, entry->param->value, strlen(entry->param->value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC) == FAILURE) { log_error(LOG_WARN, pblock_findval("fn", NSG(pb)), NSG(sn), NSG(rq), "Cannot change php.ini key \"%s\" to \"%s\"", entry->param->name, entry->param->value); } } Index: sapi/pi3web/pi3web_sapi.c =================================================================== RCS file: /repository/php-src/sapi/pi3web/pi3web_sapi.c,v retrieving revision 1.60.2.1.2.1 diff -u -a -r1.60.2.1.2.1 pi3web_sapi.c --- sapi/pi3web/pi3web_sapi.c 1 Jan 2007 09:36:13 -0000 1.60.2.1.2.1 +++ sapi/pi3web/pi3web_sapi.c 18 Sep 2007 15:36:42 -0000 @@ -365,7 +365,7 @@ zend_syntax_highlighter_ini syntax_highlighter_ini; if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS ) { - php_get_highlight_struct( &syntax_highlighter_ini ); + php_get_highlight_struct( &syntax_highlighter_ini TSRMLS_CC ); zend_highlight( &syntax_highlighter_ini TSRMLS_CC ); } else Index: sapi/thttpd/thttpd.c =================================================================== RCS file: /repository/php-src/sapi/thttpd/thttpd.c,v retrieving revision 1.95.2.1.2.1 diff -u -a -r1.95.2.1.2.1 thttpd.c --- sapi/thttpd/thttpd.c 1 Jan 2007 09:36:13 -0000 1.95.2.1.2.1 +++ sapi/thttpd/thttpd.c 18 Sep 2007 15:36:42 -0000 @@ -417,7 +417,7 @@ if (show_source) { zend_syntax_highlighter_ini syntax_highlighter_ini; - php_get_highlight_struct(&syntax_highlighter_ini); + php_get_highlight_struct(&syntax_highlighter_ini TSRMLS_CC); highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC); } else { file_handle.type = ZEND_HANDLE_FILENAME; Index: win32/registry.c =================================================================== RCS file: /repository/php-src/win32/registry.c,v retrieving revision 1.16.4.5 diff -u -a -r1.16.4.5 registry.c --- win32/registry.c 2 May 2007 10:16:34 -0000 1.16.4.5 +++ win32/registry.c 18 Sep 2007 15:36:42 -0000 @@ -247,7 +247,7 @@ zend_hash_get_current_data_ex(ht, (void**)&data, &pos) == SUCCESS && zend_hash_get_current_key_ex(ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING; zend_hash_move_forward_ex(ht, &pos)) { - zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); } break; }