PHP INI Includes patch Brian Shire & Facebook Inc. Provides ability to do INI includes. To use: Apply the patch with the following commands: cd php-5.2.4 patch -p1 -i php_ini_includes.5.2.4.patch Rebuild/install php and you'll have the ability to add the following to your PHP ini files: include common.ini Provide feedback to d/zend_ini.h b/Zend/zend_ini.h index a39aca4..2689d9c 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -202,6 +202,7 @@ END_EXTERN_C() #define ZEND_INI_PARSER_ENTRY 1 #define ZEND_INI_PARSER_SECTION 2 #define ZEND_INI_PARSER_POP_ENTRY 3 +#define ZEND_INI_PARSER_INCLUDE 4 /**** PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ typedef struct _zend_ini_parser_param { zend_ini_parser_cb_t ini_parser_cb; diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index a11d911..08eb94b 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -52,6 +52,17 @@ extern FILE *ini_in; extern void init_cfg_scanner(void); #endif +/**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ +#ifdef ZTS +#define INI_SCNG_SAVE(buf) memcpy( buf, (((zend_scanner_globals*) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(ini_scanner_globals_id)])), sizeof(zend_scanner_globals)) +#define INI_SCNG_RESTORE(buf) memcpy( (((zend_scanner_globals*) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(ini_scanner_globals_id)])), buf, sizeof(zend_scanner_globals)) +#else +#define INI_SCNG_SAVE(buf) memcpy( (void*)buf, (void*)&ini_scanner_globals, sizeof(zend_scanner_globals)) +#define INI_SCNG_RESTORE(buf) memcpy( (void*)&ini_scanner_globals, (void*)buf, sizeof(zend_scanner_globals)) +#endif +/**** END PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + + void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2) { int i_result; @@ -234,6 +245,7 @@ ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, zend_ %pure_parser %token TC_STRING %token TC_ENCAPSULATED_STRING +%token INCLUDE /**** PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ %token BRACK %token SECTION %token CFG_TRUE @@ -266,6 +278,23 @@ statement: free(Z_STRVAL($1)); free(Z_STRVAL($4)); } + /**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + | INCLUDE string_or_value { +#if DEBUG_CFG_PARSER + printf("include '%s'\n", $2.value.str.val); +#endif + zval *arg2; + zend_scanner_globals orig_scng; + TSRMLS_FETCH(); + MAKE_STD_ZVAL(arg2); + ZVAL_STRING(arg2, zend_ini_scanner_get_filename(TSRMLS_C), 1); + INI_SCNG_SAVE(&orig_scng); + ZEND_INI_PARSER_CB(&$2, arg2, ZEND_INI_PARSER_INCLUDE, ZEND_INI_PARSER_ARG); + zval_ptr_dtor(&arg2); + free($2.value.str.val); + INI_SCNG_RESTORE(&orig_scng); + } + /**** END PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ | 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' diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index 6546e47..8a82a2c 100644 --- a/Zend/zend_ini_scanner.l +++ b/Zend/zend_ini_scanner.l @@ -107,6 +107,12 @@ NEWLINE ("\r"|"\n"|"\r\n") %% + /**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ +[ ]*"include"[ ]* { + return INCLUDE; +} + /**** END PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + [ ]*[\[][ ]*[\]][ ]* { return BRACK; } diff --git a/main/php_ini.c b/main/php_ini.c index ed69841..6cb4a8c 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -49,6 +49,7 @@ typedef struct _php_extension_lists { /* True globals */ static HashTable configuration_hash; PHPAPI char *php_ini_opened_path=NULL; +static char *php_ini_search_path=NULL; /*** PATCH: "php_ini_includes", (c) 2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ static php_extension_lists extension_lists; PHPAPI char *php_ini_scanned_files=NULL; @@ -167,6 +168,15 @@ PHPAPI void display_ini_entries(zend_module_entry *module) */ static void php_config_ini_parser_cb(zval *arg1, zval *arg2, int callback_type, void *arg) { + /**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + zend_file_handle fh; + char *filepath; + int pos; + char *orig_php_ini_opened_path; + zend_ini_parser_param *orig_ini_parser_param; + TSRMLS_FETCH(); + /**** END PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + switch (callback_type) { case ZEND_INI_PARSER_ENTRY: { zval *entry; @@ -221,6 +231,43 @@ static void php_config_ini_parser_cb(zval *arg1, zval *arg2, int callback_type, case ZEND_INI_PARSER_SECTION: break; + + /**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + case ZEND_INI_PARSER_INCLUDE: + /* arg1=, arg2= */ + + /* save current state to be restored later */ + orig_php_ini_opened_path = php_ini_opened_path; + orig_ini_parser_param = CG(ini_parser_param); + + memset(&fh, 0, sizeof(fh)); + /* Look for include file relative to including script, otherwise try the usual places */ + filepath = (char*)emalloc(Z_STRLEN_P(arg1) + Z_STRLEN_P(arg2) + 1); + memcpy(filepath, Z_STRVAL_P(arg2), Z_STRLEN_P(arg2)); + filepath[Z_STRLEN_P(arg2)] = 0; + pos = strlen(filepath); + while(!IS_SLASH(filepath[--pos])) { } + pos++; + memcpy(&filepath[pos], Z_STRVAL_P(arg1), Z_STRLEN_P(arg1)); + filepath[pos+Z_STRLEN_P(arg1)] = 0; + fh.handle.fp = php_fopen_with_path(filepath, "r", NULL, &php_ini_opened_path TSRMLS_CC); + efree(filepath); + if (!fh.handle.fp) { + fh.handle.fp = php_fopen_with_path(Z_STRVAL_P(arg1), "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC); + } + if (!fh.handle.fp) { + zend_error(E_CORE_ERROR, "Unable to open included ini file: '%s'", Z_STRVAL_P(arg1)); + } + fh.type = ZEND_HANDLE_FP; + fh.filename = php_ini_opened_path; + + zend_parse_ini_file(&fh, 1, php_config_ini_parser_cb, &extension_lists); + + php_ini_opened_path = orig_php_ini_opened_path; + CG(ini_parser_param) = orig_ini_parser_param; + + break; + /**** END PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ } } /* }}} */ @@ -259,7 +306,7 @@ static void pvalue_config_destructor(zval *pvalue) int php_init_config(TSRMLS_D) { char *php_ini_file_name = NULL; - char *php_ini_search_path = NULL; + /* char *php_ini_search_path = NULL; */ /**** PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ int safe_mode_state; char *open_basedir; int free_ini_search_path = 0; @@ -483,9 +530,13 @@ int php_init_config(TSRMLS_D) } } + /**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ +#if 0 if (free_ini_search_path) { efree(php_ini_search_path); } +#endif + /**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ PG(safe_mode) = safe_mode_state; PG(open_basedir) = open_basedir; @@ -561,6 +612,12 @@ int php_init_config(TSRMLS_D) zend_parse_ini_string(sapi_module.ini_entries, 1, php_config_ini_parser_cb, &extension_lists); } + /**** BEGIN PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + if (free_ini_search_path) { + efree(php_ini_search_path); + } + /**** END PATCH: "php_ini_includes", (c)2007 Brian Shire & Facebook Inc, Licensed under MIT License ***/ + return SUCCESS; } /* }}} */