mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
MFH:
- Added ".htaccess" style user-defined php.ini files support for CGI/FastCGI. - Added support for special [PATH=/opt/httpd/www.example.com/] sections in php.ini. All directives set in these sections will not be able to be overridden in user-defined ini-files or during runtime in the specified path. - Improved php.ini handling: . Added better error reporting for syntax errors in php.ini files . Allowed "ini-variables" to be used almost everywhere ini php.ini files . Allowed using alphanumeric/variable indexes in "array" ini options . Fixed get_cfg_var() to be able to return "array" ini options - Fixed bug #27372 (parse error loading browscap.ini at apache startup) - Fixed bug #42069 (parse_ini_file() allows using some non-alpha numeric characters)
This commit is contained in:
parent
0d3bdf23d2
commit
09b6f37f20
21 changed files with 1734 additions and 577 deletions
|
@ -265,6 +265,9 @@ struct _zend_scanner_globals {
|
|||
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;
|
||||
|
|
|
@ -164,7 +164,6 @@ END_EXTERN_C()
|
|||
#define INI_ORIG_STR(name) zend_ini_string((name), sizeof(name), 1)
|
||||
#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)
|
||||
|
@ -193,15 +192,16 @@ END_EXTERN_C()
|
|||
#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, int scanner_mode, 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;
|
||||
|
|
|
@ -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 <zeev@zend.com> |
|
||||
| Authors: Zeev Suraski <zeev@zend.com> |
|
||||
| Jani Taskinen <jani@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define DEBUG_CFG_PARSER 0
|
||||
|
||||
#include "zend.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_ini.h"
|
||||
|
@ -27,32 +29,23 @@
|
|||
#include "zend_ini_scanner.h"
|
||||
#include "zend_extensions.h"
|
||||
|
||||
#define YYERROR_VERBOSE
|
||||
#define YYSTYPE zval
|
||||
|
||||
#ifdef ZTS
|
||||
#define YYPARSE_PARAM tsrm_ls
|
||||
#define YYLEX_PARAM tsrm_ls
|
||||
#endif
|
||||
|
||||
#define ZEND_INI_PARSER_CB (CG(ini_parser_param))->ini_parser_cb
|
||||
#define ZEND_INI_PARSER_ARG (CG(ini_parser_param))->arg
|
||||
|
||||
int ini_lex(zval *ini_lval TSRMLS_DC);
|
||||
#ifdef ZTS
|
||||
int ini_parse(void *arg);
|
||||
#else
|
||||
int ini_parse(void);
|
||||
#endif
|
||||
|
||||
zval yylval;
|
||||
#define ZEND_INI_PARSER_CB (CG(ini_parser_param))->ini_parser_cb
|
||||
#define ZEND_INI_PARSER_ARG (CG(ini_parser_param))->arg
|
||||
|
||||
#ifndef ZTS
|
||||
extern int ini_lex(zval *ini_lval TSRMLS_DC);
|
||||
extern FILE *ini_in;
|
||||
extern void init_cfg_scanner(void);
|
||||
#endif
|
||||
|
||||
void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
||||
/* {{{ zend_ini_do_op()
|
||||
*/
|
||||
static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
||||
{
|
||||
int i_result;
|
||||
int i_op1, i_op2;
|
||||
|
@ -91,16 +84,22 @@ void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
|||
Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
|
||||
Z_TYPE_P(result) = IS_STRING;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_ini_init_string(zval *result)
|
||||
/* {{{ zend_ini_init_string()
|
||||
*/
|
||||
static void zend_ini_init_string(zval *result)
|
||||
{
|
||||
Z_STRVAL_P(result) = malloc(1);
|
||||
Z_STRVAL_P(result)[0] = 0;
|
||||
Z_STRLEN_P(result) = 0;
|
||||
Z_TYPE_P(result) = IS_STRING;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_ini_add_string(zval *result, zval *op1, zval *op2)
|
||||
/* {{{ zend_ini_add_string()
|
||||
*/
|
||||
static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
|
||||
{
|
||||
int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
|
||||
|
||||
|
@ -110,12 +109,15 @@ void zend_ini_add_string(zval *result, zval *op1, zval *op2)
|
|||
Z_STRLEN_P(result) = length;
|
||||
Z_TYPE_P(result) = IS_STRING;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_ini_get_constant(zval *result, zval *name)
|
||||
/* {{{ zend_ini_get_constant()
|
||||
*/
|
||||
static 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 */
|
||||
|
@ -129,16 +131,20 @@ void zend_ini_get_constant(zval *result, zval *name)
|
|||
*result = *name;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_ini_get_var(zval *result, zval *name)
|
||||
/* {{{ zend_ini_get_var()
|
||||
*/
|
||||
static 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);
|
||||
|
@ -147,9 +153,11 @@ void zend_ini_get_var(zval *result, zval *name)
|
|||
zend_ini_init_string(result);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static void ini_error(char *str)
|
||||
/* {{{ ini_error()
|
||||
*/
|
||||
static void ini_error(char *msg)
|
||||
{
|
||||
char *error_buf;
|
||||
int error_buf_len;
|
||||
|
@ -158,10 +166,10 @@ static void ini_error(char *str)
|
|||
|
||||
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");
|
||||
}
|
||||
|
@ -177,71 +185,87 @@ static void ini_error(char *str)
|
|||
}
|
||||
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_parse_ini_file()
|
||||
*/
|
||||
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);
|
||||
|
||||
shutdown_ini_scanner(TSRMLS_C);
|
||||
|
||||
if (retval == 0) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ zend_parse_ini_string()
|
||||
*/
|
||||
ZEND_API int zend_parse_ini_string(char *str, 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;
|
||||
|
||||
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, 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);
|
||||
shutdown_ini_scanner(TSRMLS_C);
|
||||
|
||||
if (retval==0) {
|
||||
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_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;
|
||||
|
||||
if (ini_parse(TSRMLS_C)) {
|
||||
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 +274,94 @@ statement_list:
|
|||
;
|
||||
|
||||
statement:
|
||||
TC_STRING '=' string_or_value {
|
||||
TC_SECTION section_string_or_value ']' {
|
||||
#if DEBUG_CFG_PARSER
|
||||
printf("'%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
|
||||
printf("SECTION: [%s]\n", Z_STRVAL($2));
|
||||
#endif
|
||||
ZEND_INI_PARSER_CB(&$1, &$3, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG);
|
||||
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("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
|
||||
#endif
|
||||
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(&$$); }
|
||||
;
|
||||
|
||||
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)); }
|
||||
;
|
||||
|
||||
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); }
|
||||
;
|
||||
|
||||
cfg_var_ref:
|
||||
TC_DOLLAR_CURLY TC_STRING '}' { zend_ini_get_var(&$$, &$2); free($2.value.str.val); }
|
||||
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); }
|
||||
;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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_prepare_string_for_scanning(char *str 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, int scanner_mode 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 */
|
||||
|
|
|
@ -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 <zeev@zend.com> |
|
||||
| Authors: Zeev Suraski <zeev@zend.com> |
|
||||
| Jani Taskinen <jani@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#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 <errno.h>
|
||||
#include "zend.h"
|
||||
|
@ -35,9 +85,6 @@
|
|||
#include <zend_ini_parser.h>
|
||||
#include "zend_ini_scanner.h"
|
||||
|
||||
#undef YYSTYPE
|
||||
#define YYSTYPE zval
|
||||
|
||||
#define YY_DECL int ini_lex(zval *ini_lval TSRMLS_DC)
|
||||
|
||||
/* Globals Macros */
|
||||
|
@ -48,204 +95,417 @@ ZEND_API ts_rsrc_id ini_scanner_globals_id;
|
|||
ZEND_API zend_scanner_globals ini_scanner_globals;
|
||||
#endif
|
||||
|
||||
# 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) ) \
|
||||
YY_FATAL_ERROR( "input in flex scanner failed" );
|
||||
/* 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; \
|
||||
}
|
||||
|
||||
static char *ini_filename;
|
||||
|
||||
void init_ini_scanner(TSRMLS_D)
|
||||
/* {{{ init_ini_scanner()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ shutdown_ini_scanner()
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ zend_ini_scanner_get_lineno()
|
||||
*/
|
||||
int zend_ini_scanner_get_lineno(TSRMLS_D)
|
||||
{
|
||||
return SCNG(lineno);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ zend_ini_scanner_get_filename()
|
||||
*/
|
||||
char *zend_ini_scanner_get_filename(TSRMLS_D)
|
||||
{
|
||||
return ini_filename;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_ini_open_file_for_scanning(zend_file_handle *fh TSRMLS_DC)
|
||||
/* {{{ zend_ini_open_file_for_scanning()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_ini_prepare_string_for_scanning(char *str TSRMLS_DC)
|
||||
/* {{{ zend_ini_prepare_string_for_scanning()
|
||||
*/
|
||||
int zend_ini_prepare_string_for_scanning(char *str, int scanner_mode TSRMLS_DC)
|
||||
{
|
||||
int len = strlen(str);
|
||||
|
||||
init_ini_scanner(TSRMLS_C);
|
||||
SCNG(scanner_mode) = scanner_mode;
|
||||
yyin = NULL;
|
||||
yy_scan_buffer(str, len + 2 TSRMLS_CC);
|
||||
ini_filename = NULL;
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ zend_ini_close_file()
|
||||
*/
|
||||
void zend_ini_close_file(zend_file_handle *fh TSRMLS_DC)
|
||||
{
|
||||
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
|
||||
|
||||
%%
|
||||
|
||||
<INITIAL>[ ]*[\[][ ]*[\]][ ]* {
|
||||
return BRACK;
|
||||
}
|
||||
|
||||
<INITIAL>[ ]*("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;
|
||||
}
|
||||
|
||||
|
||||
<INITIAL>[ ]*("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;
|
||||
}
|
||||
|
||||
<INITIAL>[[][^\]\n]+[\]][ ]*{NEWLINE}? {
|
||||
/* SECTION */
|
||||
|
||||
/* 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;
|
||||
<INITIAL>"[" { /* 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;
|
||||
}
|
||||
|
||||
<ST_VALUE,ST_SECTION_VALUE,ST_OFFSET>"'"{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);
|
||||
}
|
||||
|
||||
<ST_SECTION_RAW,ST_SECTION_VALUE>"]"{TABS_AND_SPACES}*{NEWLINE}? { /* End of section */
|
||||
BEGIN(INITIAL);
|
||||
SCNG(lineno)++;
|
||||
|
||||
/* eat leading [ */
|
||||
yytext++;
|
||||
yyleng--;
|
||||
|
||||
Z_STRVAL_P(ini_lval) = zend_strndup(yytext, yyleng);
|
||||
Z_STRLEN_P(ini_lval) = yyleng;
|
||||
Z_TYPE_P(ini_lval) = IS_STRING;
|
||||
return SECTION;
|
||||
return ']';
|
||||
}
|
||||
|
||||
<INITIAL>["][^"]*["] {
|
||||
char *p = yytext;
|
||||
<INITIAL>{LABEL}"["{TABS_AND_SPACES}* { /* Start of option with offset */
|
||||
/* Eat trailing whitespace and [ */
|
||||
EAT_TRAILING_WHITESPACE_EX('[');
|
||||
|
||||
/* ENCAPSULATED TC_STRING */
|
||||
|
||||
while ((p = strpbrk(p, "\r\n"))) {
|
||||
if (*p == '\r' && *(p + 1) == '\n') {
|
||||
p++;
|
||||
}
|
||||
SCNG(lineno)++;
|
||||
p++;
|
||||
}
|
||||
|
||||
/* eat trailing " */
|
||||
yytext[yyleng-1]=0;
|
||||
|
||||
/* eat leading " */
|
||||
yytext++;
|
||||
|
||||
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;
|
||||
/* Enter offset lookup state */
|
||||
yy_push_state(ST_OFFSET TSRMLS_CC);
|
||||
|
||||
RETURN_TOKEN(TC_OFFSET, yytext, yyleng);
|
||||
}
|
||||
|
||||
<INITIAL>"${" {
|
||||
<ST_OFFSET>{TABS_AND_SPACES}*"]" { /* End of section or an option offset */
|
||||
BEGIN(INITIAL);
|
||||
return ']';
|
||||
}
|
||||
|
||||
<ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>"${" { /* Variable start */
|
||||
yy_push_state(ST_VARNAME TSRMLS_CC);
|
||||
return TC_DOLLAR_CURLY;
|
||||
}
|
||||
|
||||
<INITIAL>"}" {
|
||||
Z_LVAL_P(ini_lval) = (long) yytext[0];
|
||||
return yytext[0];
|
||||
<ST_VARNAME>{LABEL} { /* Variable name */
|
||||
RETURN_TOKEN(TC_VARNAME, yytext, yyleng);
|
||||
}
|
||||
|
||||
<INITIAL>[&|~$(){}!] {
|
||||
return yytext[0];
|
||||
<ST_VARNAME>"}" { /* Variable end */
|
||||
yy_pop_state(TSRMLS_C);
|
||||
return '}';
|
||||
}
|
||||
|
||||
<INITIAL>[^=\n\r\t;|&$~(){}!"\[]+ {
|
||||
/* STRING */
|
||||
register int i;
|
||||
<INITIAL,ST_VALUE>("true"|"on"|"yes"){TABS_AND_SPACES}* { /* TRUE value (when used outside option value/offset this causes parse error!) */
|
||||
RETURN_TOKEN(BOOL_TRUE, "1", 1);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
<INITIAL,ST_VALUE>("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);
|
||||
}
|
||||
|
||||
<INITIAL,ST_OFFSET>{LABEL} { /* Get option name or option offset value */
|
||||
RETURN_TOKEN(TC_STRING, yytext, yyleng);
|
||||
}
|
||||
|
||||
<INITIAL>{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 {
|
||||
/* whitespace */
|
||||
yy_push_state(ST_VALUE TSRMLS_CC);
|
||||
}
|
||||
return '=';
|
||||
}
|
||||
|
||||
<INITIAL>[=\n] {
|
||||
if (yytext[0] == '\n') {
|
||||
SCNG(lineno)++;
|
||||
<ST_RAW>{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);
|
||||
}
|
||||
|
||||
<ST_SECTION_RAW>{SECTION_RAW_CHARS}+ { /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */
|
||||
RETURN_TOKEN(TC_RAW, yytext, yyleng);
|
||||
}
|
||||
|
||||
<ST_VALUE,ST_RAW>{NEWLINE} { /* End of option value */
|
||||
BEGIN(INITIAL);
|
||||
SCNG(lineno)++;
|
||||
return END_OF_LINE;
|
||||
}
|
||||
|
||||
<ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get constant option value */
|
||||
RETURN_TOKEN(TC_STRING, yytext, yyleng);
|
||||
}
|
||||
|
||||
<ST_VALUE,ST_OFFSET>{NUMBER} { /* Get number option value as string */
|
||||
RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
|
||||
}
|
||||
|
||||
<INITIAL>{TOKENS} { /* Disallow these chars outside option values */
|
||||
return yytext[0];
|
||||
}
|
||||
|
||||
<ST_VALUE>{OPERATORS}{TABS_AND_SPACES}* { /* Boolean operators */
|
||||
return yytext[0];
|
||||
}
|
||||
|
||||
<ST_VALUE>[=] { /* Make = used in option value to trigger error */
|
||||
yyless(yyleng - 1);
|
||||
BEGIN(INITIAL);
|
||||
return END_OF_LINE;
|
||||
}
|
||||
|
||||
<ST_VALUE>{VALUE_CHARS}+ { /* Get everything else as option/offset value */
|
||||
/* Eat trailing tabs and spaces */
|
||||
EAT_TRAILING_WHITESPACE();
|
||||
RETURN_TOKEN(TC_STRING, yytext, yyleng);
|
||||
}
|
||||
|
||||
<ST_SECTION_VALUE,ST_OFFSET>{SECTION_VALUE_CHARS}+ { /* Get rest as section/offset value */
|
||||
RETURN_TOKEN(TC_STRING, yytext, yyleng);
|
||||
}
|
||||
|
||||
<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>["] { /* Double quoted '"' string start */
|
||||
yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC);
|
||||
return '"';
|
||||
}
|
||||
|
||||
<ST_DOUBLE_QUOTES>{DOUBLE_QUOTES_CHARS}+ { /* Escape double quoted string contents */
|
||||
zend_ini_escape_string(ini_lval, yytext, yyleng, '"' TSRMLS_CC);
|
||||
return TC_QUOTED_STRING;
|
||||
}
|
||||
|
||||
<ST_DOUBLE_QUOTES>["] { /* Double quoted '"' string ends */
|
||||
yy_pop_state(TSRMLS_C);
|
||||
return '"';
|
||||
}
|
||||
|
||||
<INITIAL,ST_VALUE,ST_RAW,ST_OFFSET>{TABS_AND_SPACES} {
|
||||
/* eat whitespace */
|
||||
}
|
||||
|
||||
<INITIAL>{NEWLINE} {
|
||||
SCNG(lineno)++;
|
||||
return '\n';
|
||||
return END_OF_LINE;
|
||||
}
|
||||
|
||||
<INITIAL>[;][^\r\n]*{NEWLINE}? {
|
||||
/* comment */
|
||||
<INITIAL,ST_VALUE,ST_RAW>[;][^\r\n]*{NEWLINE} { /* Comment */
|
||||
BEGIN(INITIAL);
|
||||
SCNG(lineno)++;
|
||||
return '\n';
|
||||
return END_OF_LINE;
|
||||
}
|
||||
|
||||
<INITIAL>[ \t] {
|
||||
/* eat whitespace */
|
||||
}
|
||||
|
||||
<INITIAL>. {
|
||||
#if DEBUG
|
||||
php_error(E_NOTICE,"Unexpected character on line %d: '%s' (ASCII %d)\n", yylineno, yytext, yytext[0]);
|
||||
#endif
|
||||
<ST_VALUE,ST_RAW><<EOF>> { /* End of option value (if EOF is reached before EOL */
|
||||
BEGIN(INITIAL);
|
||||
return END_OF_LINE;
|
||||
}
|
||||
|
||||
<<EOF>> {
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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 <zend_language_parser.h>
|
||||
|
||||
|
@ -947,8 +948,15 @@ static
|
|||
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)
|
||||
|
@ -1405,6 +1413,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_fnmatch, 0, 0, 2)
|
|||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_sys_get_temp_dir, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -3384,7 +3393,7 @@ const zend_function_entry basic_functions[] = {
|
|||
PHP_FE(set_magic_quotes_runtime, NULL)
|
||||
PHP_FE(get_magic_quotes_gpc, NULL)
|
||||
PHP_FE(get_magic_quotes_runtime, NULL)
|
||||
|
||||
|
||||
PHP_FE(import_request_variables, arginfo_import_request_variables)
|
||||
PHP_FE(error_log, arginfo_error_log)
|
||||
PHP_FE(error_get_last, arginfo_error_get_last)
|
||||
|
@ -3430,6 +3439,9 @@ const zend_function_entry basic_functions[] = {
|
|||
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 +4000,9 @@ PHP_MINIT_FUNCTION(basic)
|
|||
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 +4862,34 @@ PHP_FUNCTION(get_current_user)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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 +4897,19 @@ PHP_FUNCTION(get_cfg_var)
|
|||
|
||||
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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -5576,7 +5622,7 @@ PHP_FUNCTION(ini_get)
|
|||
|
||||
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);
|
||||
|
||||
if (!str) {
|
||||
RETURN_FALSE;
|
||||
|
@ -5713,8 +5759,7 @@ PHP_FUNCTION(ini_set)
|
|||
}
|
||||
}
|
||||
|
||||
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_ex(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, 0 TSRMLS_CC) == FAILURE) {
|
||||
zval_dtor(return_value);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
@ -5739,7 +5784,6 @@ PHP_FUNCTION(ini_restore)
|
|||
|
||||
/* {{{ proto string set_include_path(string new_include_path)
|
||||
Sets the include_path configuration option */
|
||||
|
||||
PHP_FUNCTION(set_include_path)
|
||||
{
|
||||
zval **new_value;
|
||||
|
@ -5756,19 +5800,15 @@ PHP_FUNCTION(set_include_path)
|
|||
} 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_ex("include_path", sizeof("include_path"), Z_STRVAL_PP(new_value), Z_STRLEN_PP(new_value), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC) == FAILURE) {
|
||||
zval_dtor(return_value);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string get_include_path()
|
||||
Get the current include_path configuration option */
|
||||
|
||||
PHP_FUNCTION(get_include_path)
|
||||
{
|
||||
char *str;
|
||||
|
@ -5781,22 +5821,18 @@ PHP_FUNCTION(get_include_path)
|
|||
}
|
||||
RETURN_STRING(str, 1);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void restore_include_path()
|
||||
Restore the value of the include_path configuration option */
|
||||
|
||||
PHP_FUNCTION(restore_include_path)
|
||||
{
|
||||
if (ZEND_NUM_ARGS() != 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed print_r(mixed var [, bool return])
|
||||
|
@ -5861,7 +5897,7 @@ PHP_FUNCTION(ignore_user_abort)
|
|||
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_ex("ignore_user_abort", sizeof("ignore_user_abort"), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -6116,7 +6152,7 @@ PHP_FUNCTION(move_uploaded_file)
|
|||
|
||||
/* {{{ 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 TSRMLS_DC)
|
||||
{
|
||||
zval *element;
|
||||
|
||||
|
@ -6146,11 +6182,11 @@ static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, int callback_type,
|
|||
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 +6212,12 @@ static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, int callback_type,
|
|||
*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,10 +6229,8 @@ static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, int callback_type,
|
|||
|
||||
/* {{{ 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_DC)
|
||||
{
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (callback_type == ZEND_INI_PARSER_SECTION) {
|
||||
MAKE_STD_ZVAL(BG(active_ini_file_section));
|
||||
array_init(BG(active_ini_file_section));
|
||||
|
@ -6205,59 +6244,62 @@ static void php_ini_parser_cb_with_sections(zval *arg1, zval *arg2, int callback
|
|||
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 TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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;
|
||||
|
||||
default:
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
break;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &filename, &filename_len, &process_sections, &scanner_mode) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_string_ex(filename);
|
||||
if (filename_len == 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename can not be empty!");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
Z_TYPE(fh) = ZEND_HANDLE_FILENAME;
|
||||
fh.filename = filename;
|
||||
fh.type = 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)
|
||||
{
|
||||
char *prefix, *new_key;
|
||||
|
|
|
@ -125,6 +125,9 @@ PHP_FUNCTION(move_uploaded_file);
|
|||
|
||||
/* 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);
|
||||
|
|
|
@ -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 @@ static void convert_browscap_pattern(zval *pattern)
|
|||
|
||||
/* {{{ 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 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, int callback_type, vo
|
|||
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 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, int callback_type, vo
|
|||
|
||||
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 @@ PHP_MINIT_FUNCTION(browscap)
|
|||
}
|
||||
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;
|
||||
|
|
|
@ -50,98 +50,98 @@ Hex_Value2 = 0x103
|
|||
|
||||
[Non-alphanumerics_as_values]
|
||||
;Non-alpha numeric chars without quotes
|
||||
Non-alpha1 = ;
|
||||
Non-alpha2 = +
|
||||
Non-alpha3 = *
|
||||
Non-alpha4 = %
|
||||
Non-alpha5 = <>
|
||||
Non-alpha6 = @
|
||||
Non-alpha7 = #
|
||||
Non-alpha8 = ^
|
||||
non-alpha9 = -
|
||||
Non-alpha10 = :
|
||||
Non-alpha11 = ?
|
||||
Non-alpha12 = /
|
||||
Non-alpha13 = \
|
||||
Non_alpha1 = ;
|
||||
Non_alpha2 = +
|
||||
Non_alpha3 = *
|
||||
Non_alpha4 = %
|
||||
Non_alpha5 = <>
|
||||
Non_alpha6 = @
|
||||
Non_alpha7 = #
|
||||
Non_alpha8 = ^
|
||||
Non_alpha9 = -
|
||||
Non_alpha10 = :
|
||||
Non_alpha11 = ?
|
||||
Non_alpha12 = /
|
||||
Non_alpha13 = \
|
||||
;These chars have a special meaning when used in the value,
|
||||
; hence parser throws an error
|
||||
;Non-alpha14 = &
|
||||
;Non-alpha15 = {}
|
||||
;Non-alpha16 = |
|
||||
;Non-alpha17 = ~
|
||||
;Non-alpha18 = !
|
||||
;Non-alpha19 = $
|
||||
;Non-alpha20 = ()
|
||||
;Non_alpha14 = &
|
||||
;Non_alpha15 = {}
|
||||
;Non_alpha16 = |
|
||||
;Non_alpha17 = ~
|
||||
;Non_alpha18 = !
|
||||
;Non_alpha19 = $
|
||||
;Non_alpha20 = ()
|
||||
|
||||
Non-alpha1_quotes = ";"
|
||||
Non-alpha2_quotes = "+"
|
||||
Non-alpha3_quotes = "*"
|
||||
Non-alpha4_quotes = "%"
|
||||
Non-alpha5_quotes = "<>"
|
||||
Non-alpha6_quotes = "@"
|
||||
Non-alpha7_quotes = "#"
|
||||
Non-alpha8_quotes = "^"
|
||||
Non-alpha9_quotes = "-"
|
||||
Non-alpha10_quotes = "="
|
||||
Non-alpha11_quotes = ":"
|
||||
Non-alpha12_quotes = "?"
|
||||
Non-alpha13_quotes = "/"
|
||||
Non-alpha14_quotes = "\"
|
||||
Non-alpha15_quotes = "&"
|
||||
Non-alpha16_quotes = "{}"
|
||||
Non-alpha17_quotes = "|"
|
||||
Non-alpha18_quotes = "~"
|
||||
Non-alpha19_quotes = "!"
|
||||
non-alpha20_quotes = "$"
|
||||
non-alpha21_quotes = "()"
|
||||
Non_alpha1_quotes = ";"
|
||||
Non_alpha2_quotes = "+"
|
||||
Non_alpha3_quotes = "*"
|
||||
Non_alpha4_quotes = "%"
|
||||
Non_alpha5_quotes = "<>"
|
||||
Non_alpha6_quotes = "@"
|
||||
Non_alpha7_quotes = "#"
|
||||
Non_alpha8_quotes = "^"
|
||||
Non_alpha9_quotes = "-"
|
||||
Non_alpha10_quotes = "="
|
||||
Non_alpha11_quotes = ":"
|
||||
Non_alpha12_quotes = "?"
|
||||
Non_alpha13_quotes = "/"
|
||||
;Non_alpha14_quotes = "\"
|
||||
Non_alpha15_quotes = "&"
|
||||
Non_alpha16_quotes = "{}"
|
||||
Non_alpha17_quotes = "|"
|
||||
Non_alpha18_quotes = "~"
|
||||
Non_alpha19_quotes = "!"
|
||||
;Non_alpha20_quotes = "$"
|
||||
Non_alpha21_quotes = "()"
|
||||
|
||||
[Non-alpha numerics in strings]
|
||||
;expected error, as the non-alphanumeric chars not enclosed in double quotes("")
|
||||
Non-alpha_string1 = Hello@world
|
||||
;Non-alpha_string2 = Hello!world
|
||||
;Non-alpha_string3 = Hello#world
|
||||
;Non-alpha_string4 = Hello%world
|
||||
;Non-alpha_string5 = Hello&world
|
||||
;Non-alpha_string6 = Hello*world
|
||||
;Non-alpha_string7 = Hello+world
|
||||
;Non-alpha_string8 = Hello-world
|
||||
;Non-alpha_string9 = Hello'world
|
||||
;Non-alpha_string10 = Hello:world
|
||||
;Non-alpha_string11 = Hello;world
|
||||
;Non-alpha_string12 = Hello<world
|
||||
;Non-alpha_string13 = Hello>world
|
||||
;Non-alpha_string14 = Hello>world
|
||||
;Non-alpha_string15 = Hello?world
|
||||
;Non-alpha_string16 = Hello\world
|
||||
;Non-alpha_string17 = Hello^world
|
||||
;Non-alpha_string18 = Hello_world
|
||||
;Non-alpha_string19 = Hello|world
|
||||
;Non-alpha_string20 = Hello~world
|
||||
;Non-alpha_string21 = Hello`world
|
||||
;Non-alpha_string22 = Hello(world)
|
||||
Non_alpha_string1 = Hello@world
|
||||
;Non_alpha_string2 = Hello!world
|
||||
;Non_alpha_string3 = Hello#world
|
||||
;Non_alpha_string4 = Hello%world
|
||||
;Non_alpha_string5 = Hello&world
|
||||
;Non_alpha_string6 = Hello*world
|
||||
;Non_alpha_string7 = Hello+world
|
||||
;Non_alpha_string8 = Hello-world
|
||||
;Non_alpha_string9 = Hello'world
|
||||
;Non_alpha_string10 = Hello:world
|
||||
;Non_alpha_string11 = Hello;world
|
||||
;Non_alpha_string12 = Hello<world
|
||||
;Non_alpha_string13 = Hello>world
|
||||
;Non_alpha_string14 = Hello>world
|
||||
;Non_alpha_string15 = Hello?world
|
||||
;Non_alpha_string16 = Hello\world
|
||||
;Non_alpha_string17 = Hello^world
|
||||
;Non_alpha_string18 = Hello_world
|
||||
;Non_alpha_string19 = Hello|world
|
||||
;Non_alpha_string20 = Hello~world
|
||||
;Non_alpha_string21 = Hello`world
|
||||
;Non_alpha_string22 = Hello(world)
|
||||
|
||||
[Non-alpha numerics in strings -with quotes]
|
||||
Non-alpha_string1_quotes = "Hello@world"
|
||||
Non-alpha_string2_quotes = "Hello!world"
|
||||
Non-alpha_string3_quotes = "Hello#world"
|
||||
Non-alpha_string4_quotes = "Hello&world"
|
||||
Non-alpha_string5_quotes = "Hello*world"
|
||||
Non-alpha_string6_quotes = "Hello+world"
|
||||
Non-alpha_string7_quotes = "Hello-world"
|
||||
Non-alpha_string8_quotes = "Hello'world"
|
||||
Non-alpha_string9_quotes = "Hello:world"
|
||||
Non-alpha_string10_quotes = "Hello;world"
|
||||
Non-alpha_string11_quotes = "Hello<world"
|
||||
Non-alpha_string12_quotes = "Hello>world"
|
||||
Non-alpha_string13_quotes = "Hello>world"
|
||||
Non-alpha_string14_quotes = "Hello?world"
|
||||
Non-alpha_string15_quotes = "Hello\world"
|
||||
Non-alpha_string16_quotes = "Hello^world"
|
||||
Non-alpha_string17_quotes = "Hello_world"
|
||||
Non-alpha_string18_quotes = "Hello|world"
|
||||
Non-alpha_string19_quotes = "Hello~world"
|
||||
Non-alpha_string20_quotes = "Hello`world"
|
||||
Non-alpha_string21_quotes = "Hello(world)"
|
||||
Non_alpha_string1_quotes = "Hello@world"
|
||||
Non_alpha_string2_quotes = "Hello!world"
|
||||
Non_alpha_string3_quotes = "Hello#world"
|
||||
Non_alpha_string4_quotes = "Hello&world"
|
||||
Non_alpha_string5_quotes = "Hello*world"
|
||||
Non_alpha_string6_quotes = "Hello+world"
|
||||
Non_alpha_string7_quotes = "Hello-world"
|
||||
Non_alpha_string8_quotes = "Hello'world"
|
||||
Non_alpha_string9_quotes = "Hello:world"
|
||||
Non_alpha_string10_quotes = "Hello;world"
|
||||
Non_alpha_string11_quotes = "Hello<world"
|
||||
Non_alpha_string12_quotes = "Hello>world"
|
||||
Non_alpha_string13_quotes = "Hello>world"
|
||||
Non_alpha_string14_quotes = "Hello?world"
|
||||
Non_alpha_string15_quotes = "Hello\world"
|
||||
Non_alpha_string16_quotes = "Hello^world"
|
||||
Non_alpha_string17_quotes = "Hello_world"
|
||||
Non_alpha_string18_quotes = "Hello|world"
|
||||
Non_alpha_string19_quotes = "Hello~world"
|
||||
Non_alpha_string20_quotes = "Hello`world"
|
||||
Non_alpha_string21_quotes = "Hello(world)"
|
||||
|
||||
[Newlines_in_Values]
|
||||
String1 = "Hello, world\nGood Morning"
|
||||
|
@ -150,7 +150,7 @@ String2 = "\nHello, world
|
|||
String3 = 'Hello, world\tGood Morning'
|
||||
String4 = "\n"
|
||||
String5 = "\n\n"
|
||||
String3 = Hello, world\tGood Morning
|
||||
String6 = Hello, world\tGood Morning
|
||||
|
||||
[ReservedKeys_as_Values]
|
||||
Key1 = YES
|
||||
|
@ -242,74 +242,73 @@ Array
|
|||
[Octal_value] => 0100
|
||||
[Hex_value1] => 0x101
|
||||
[Hex_Value2] => 0x103
|
||||
[Non-alpha1] =>
|
||||
[Non-alpha2] => +
|
||||
[Non-alpha3] => *
|
||||
[Non-alpha4] => %
|
||||
[Non-alpha5] => <>
|
||||
[Non-alpha6] => @
|
||||
[Non-alpha7] => #
|
||||
[Non-alpha8] => ^
|
||||
[non-alpha9] => -
|
||||
[Non-alpha10] => :
|
||||
[Non-alpha11] => ?
|
||||
[Non-alpha12] => /
|
||||
[Non-alpha13] => \
|
||||
[Non-alpha1_quotes] => ;
|
||||
[Non-alpha2_quotes] => +
|
||||
[Non-alpha3_quotes] => *
|
||||
[Non-alpha4_quotes] => %
|
||||
[Non-alpha5_quotes] => <>
|
||||
[Non-alpha6_quotes] => @
|
||||
[Non-alpha7_quotes] => #
|
||||
[Non-alpha8_quotes] => ^
|
||||
[Non-alpha9_quotes] => -
|
||||
[Non-alpha10_quotes] => =
|
||||
[Non-alpha11_quotes] => :
|
||||
[Non-alpha12_quotes] => ?
|
||||
[Non-alpha13_quotes] => /
|
||||
[Non-alpha14_quotes] => \
|
||||
[Non-alpha15_quotes] => &
|
||||
[Non-alpha16_quotes] => {}
|
||||
[Non-alpha17_quotes] => |
|
||||
[Non-alpha18_quotes] => ~
|
||||
[Non-alpha19_quotes] => !
|
||||
[non-alpha20_quotes] => $
|
||||
[non-alpha21_quotes] => ()
|
||||
[Non-alpha_string1] => Hello@world
|
||||
[Non-alpha_string1_quotes] => Hello@world
|
||||
[Non-alpha_string2_quotes] => Hello!world
|
||||
[Non-alpha_string3_quotes] => Hello#world
|
||||
[Non-alpha_string4_quotes] => Hello&world
|
||||
[Non-alpha_string5_quotes] => Hello*world
|
||||
[Non-alpha_string6_quotes] => Hello+world
|
||||
[Non-alpha_string7_quotes] => Hello-world
|
||||
[Non-alpha_string8_quotes] => Hello'world
|
||||
[Non-alpha_string9_quotes] => Hello:world
|
||||
[Non-alpha_string10_quotes] => Hello;world
|
||||
[Non-alpha_string11_quotes] => Hello<world
|
||||
[Non-alpha_string12_quotes] => Hello>world
|
||||
[Non-alpha_string13_quotes] => Hello>world
|
||||
[Non-alpha_string14_quotes] => Hello?world
|
||||
[Non-alpha_string15_quotes] => Hello\world
|
||||
[Non-alpha_string16_quotes] => Hello^world
|
||||
[Non-alpha_string17_quotes] => Hello_world
|
||||
[Non-alpha_string18_quotes] => Hello|world
|
||||
[Non-alpha_string19_quotes] => Hello~world
|
||||
[Non-alpha_string20_quotes] => Hello`world
|
||||
[Non-alpha_string21_quotes] => Hello(world)
|
||||
[Non_alpha1] =>
|
||||
[Non_alpha2] => +
|
||||
[Non_alpha3] => *
|
||||
[Non_alpha4] => %
|
||||
[Non_alpha5] => <>
|
||||
[Non_alpha6] => @
|
||||
[Non_alpha7] => #
|
||||
[Non_alpha8] => ^
|
||||
[Non_alpha9] => -
|
||||
[Non_alpha10] => :
|
||||
[Non_alpha11] => ?
|
||||
[Non_alpha12] => /
|
||||
[Non_alpha13] => \
|
||||
[Non_alpha1_quotes] => ;
|
||||
[Non_alpha2_quotes] => +
|
||||
[Non_alpha3_quotes] => *
|
||||
[Non_alpha4_quotes] => %
|
||||
[Non_alpha5_quotes] => <>
|
||||
[Non_alpha6_quotes] => @
|
||||
[Non_alpha7_quotes] => #
|
||||
[Non_alpha8_quotes] => ^
|
||||
[Non_alpha9_quotes] => -
|
||||
[Non_alpha10_quotes] => =
|
||||
[Non_alpha11_quotes] => :
|
||||
[Non_alpha12_quotes] => ?
|
||||
[Non_alpha13_quotes] => /
|
||||
[Non_alpha15_quotes] => &
|
||||
[Non_alpha16_quotes] => {}
|
||||
[Non_alpha17_quotes] => |
|
||||
[Non_alpha18_quotes] => ~
|
||||
[Non_alpha19_quotes] => !
|
||||
[Non_alpha21_quotes] => ()
|
||||
[Non_alpha_string1] => Hello@world
|
||||
[Non_alpha_string1_quotes] => Hello@world
|
||||
[Non_alpha_string2_quotes] => Hello!world
|
||||
[Non_alpha_string3_quotes] => Hello#world
|
||||
[Non_alpha_string4_quotes] => Hello&world
|
||||
[Non_alpha_string5_quotes] => Hello*world
|
||||
[Non_alpha_string6_quotes] => Hello+world
|
||||
[Non_alpha_string7_quotes] => Hello-world
|
||||
[Non_alpha_string8_quotes] => Hello'world
|
||||
[Non_alpha_string9_quotes] => Hello:world
|
||||
[Non_alpha_string10_quotes] => Hello;world
|
||||
[Non_alpha_string11_quotes] => Hello<world
|
||||
[Non_alpha_string12_quotes] => Hello>world
|
||||
[Non_alpha_string13_quotes] => Hello>world
|
||||
[Non_alpha_string14_quotes] => Hello?world
|
||||
[Non_alpha_string15_quotes] => Hello\world
|
||||
[Non_alpha_string16_quotes] => Hello^world
|
||||
[Non_alpha_string17_quotes] => Hello_world
|
||||
[Non_alpha_string18_quotes] => Hello|world
|
||||
[Non_alpha_string19_quotes] => Hello~world
|
||||
[Non_alpha_string20_quotes] => Hello`world
|
||||
[Non_alpha_string21_quotes] => Hello(world)
|
||||
[String1] => Hello, world
|
||||
Good Morning
|
||||
[String2] =>
|
||||
Hello, world
|
||||
Good Morning
|
||||
|
||||
[String3] => Hello, worldGood Morning
|
||||
[String3] => Hello, world Good Morning
|
||||
[String4] =>
|
||||
|
||||
[String5] =>
|
||||
|
||||
|
||||
[String6] => Hello, world Good Morning
|
||||
[Key1] => 1
|
||||
[Key2] => 1
|
||||
[Key3] => 1
|
||||
|
@ -379,70 +378,68 @@ Array
|
|||
|
||||
[Non-alphanumerics_as_values] => Array
|
||||
(
|
||||
[Non-alpha1] =>
|
||||
[Non-alpha2] => +
|
||||
[Non-alpha3] => *
|
||||
[Non-alpha4] => %
|
||||
[Non-alpha5] => <>
|
||||
[Non-alpha6] => @
|
||||
[Non-alpha7] => #
|
||||
[Non-alpha8] => ^
|
||||
[non-alpha9] => -
|
||||
[Non-alpha10] => :
|
||||
[Non-alpha11] => ?
|
||||
[Non-alpha12] => /
|
||||
[Non-alpha13] => \
|
||||
[Non-alpha1_quotes] => ;
|
||||
[Non-alpha2_quotes] => +
|
||||
[Non-alpha3_quotes] => *
|
||||
[Non-alpha4_quotes] => %
|
||||
[Non-alpha5_quotes] => <>
|
||||
[Non-alpha6_quotes] => @
|
||||
[Non-alpha7_quotes] => #
|
||||
[Non-alpha8_quotes] => ^
|
||||
[Non-alpha9_quotes] => -
|
||||
[Non-alpha10_quotes] => =
|
||||
[Non-alpha11_quotes] => :
|
||||
[Non-alpha12_quotes] => ?
|
||||
[Non-alpha13_quotes] => /
|
||||
[Non-alpha14_quotes] => \
|
||||
[Non-alpha15_quotes] => &
|
||||
[Non-alpha16_quotes] => {}
|
||||
[Non-alpha17_quotes] => |
|
||||
[Non-alpha18_quotes] => ~
|
||||
[Non-alpha19_quotes] => !
|
||||
[non-alpha20_quotes] => $
|
||||
[non-alpha21_quotes] => ()
|
||||
[Non_alpha1] =>
|
||||
[Non_alpha2] => +
|
||||
[Non_alpha3] => *
|
||||
[Non_alpha4] => %
|
||||
[Non_alpha5] => <>
|
||||
[Non_alpha6] => @
|
||||
[Non_alpha7] => #
|
||||
[Non_alpha8] => ^
|
||||
[Non_alpha9] => -
|
||||
[Non_alpha10] => :
|
||||
[Non_alpha11] => ?
|
||||
[Non_alpha12] => /
|
||||
[Non_alpha13] => \
|
||||
[Non_alpha1_quotes] => ;
|
||||
[Non_alpha2_quotes] => +
|
||||
[Non_alpha3_quotes] => *
|
||||
[Non_alpha4_quotes] => %
|
||||
[Non_alpha5_quotes] => <>
|
||||
[Non_alpha6_quotes] => @
|
||||
[Non_alpha7_quotes] => #
|
||||
[Non_alpha8_quotes] => ^
|
||||
[Non_alpha9_quotes] => -
|
||||
[Non_alpha10_quotes] => =
|
||||
[Non_alpha11_quotes] => :
|
||||
[Non_alpha12_quotes] => ?
|
||||
[Non_alpha13_quotes] => /
|
||||
[Non_alpha15_quotes] => &
|
||||
[Non_alpha16_quotes] => {}
|
||||
[Non_alpha17_quotes] => |
|
||||
[Non_alpha18_quotes] => ~
|
||||
[Non_alpha19_quotes] => !
|
||||
[Non_alpha21_quotes] => ()
|
||||
)
|
||||
|
||||
[Non-alpha numerics in strings] => Array
|
||||
(
|
||||
[Non-alpha_string1] => Hello@world
|
||||
[Non_alpha_string1] => Hello@world
|
||||
)
|
||||
|
||||
[Non-alpha numerics in strings -with quotes] => Array
|
||||
(
|
||||
[Non-alpha_string1_quotes] => Hello@world
|
||||
[Non-alpha_string2_quotes] => Hello!world
|
||||
[Non-alpha_string3_quotes] => Hello#world
|
||||
[Non-alpha_string4_quotes] => Hello&world
|
||||
[Non-alpha_string5_quotes] => Hello*world
|
||||
[Non-alpha_string6_quotes] => Hello+world
|
||||
[Non-alpha_string7_quotes] => Hello-world
|
||||
[Non-alpha_string8_quotes] => Hello'world
|
||||
[Non-alpha_string9_quotes] => Hello:world
|
||||
[Non-alpha_string10_quotes] => Hello;world
|
||||
[Non-alpha_string11_quotes] => Hello<world
|
||||
[Non-alpha_string12_quotes] => Hello>world
|
||||
[Non-alpha_string13_quotes] => Hello>world
|
||||
[Non-alpha_string14_quotes] => Hello?world
|
||||
[Non-alpha_string15_quotes] => Hello\world
|
||||
[Non-alpha_string16_quotes] => Hello^world
|
||||
[Non-alpha_string17_quotes] => Hello_world
|
||||
[Non-alpha_string18_quotes] => Hello|world
|
||||
[Non-alpha_string19_quotes] => Hello~world
|
||||
[Non-alpha_string20_quotes] => Hello`world
|
||||
[Non-alpha_string21_quotes] => Hello(world)
|
||||
[Non_alpha_string1_quotes] => Hello@world
|
||||
[Non_alpha_string2_quotes] => Hello!world
|
||||
[Non_alpha_string3_quotes] => Hello#world
|
||||
[Non_alpha_string4_quotes] => Hello&world
|
||||
[Non_alpha_string5_quotes] => Hello*world
|
||||
[Non_alpha_string6_quotes] => Hello+world
|
||||
[Non_alpha_string7_quotes] => Hello-world
|
||||
[Non_alpha_string8_quotes] => Hello'world
|
||||
[Non_alpha_string9_quotes] => Hello:world
|
||||
[Non_alpha_string10_quotes] => Hello;world
|
||||
[Non_alpha_string11_quotes] => Hello<world
|
||||
[Non_alpha_string12_quotes] => Hello>world
|
||||
[Non_alpha_string13_quotes] => Hello>world
|
||||
[Non_alpha_string14_quotes] => Hello?world
|
||||
[Non_alpha_string15_quotes] => Hello\world
|
||||
[Non_alpha_string16_quotes] => Hello^world
|
||||
[Non_alpha_string17_quotes] => Hello_world
|
||||
[Non_alpha_string18_quotes] => Hello|world
|
||||
[Non_alpha_string19_quotes] => Hello~world
|
||||
[Non_alpha_string20_quotes] => Hello`world
|
||||
[Non_alpha_string21_quotes] => Hello(world)
|
||||
)
|
||||
|
||||
[Newlines_in_Values] => Array
|
||||
|
@ -453,12 +450,13 @@ Good Morning
|
|||
Hello, world
|
||||
Good Morning
|
||||
|
||||
[String3] => Hello, worldGood Morning
|
||||
[String3] => Hello, world Good Morning
|
||||
[String4] =>
|
||||
|
||||
[String5] =>
|
||||
|
||||
|
||||
[String6] => Hello, world Good Morning
|
||||
)
|
||||
|
||||
[ReservedKeys_as_Values] => Array
|
||||
|
@ -488,4 +486,4 @@ Hello, world
|
|||
)
|
||||
|
||||
)
|
||||
*** Done **
|
||||
*** Done **
|
||||
|
|
106
ext/standard/tests/general_functions/parse_ini_basic.data
Normal file
106
ext/standard/tests/general_functions/parse_ini_basic.data
Normal file
|
@ -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
|
239
ext/standard/tests/general_functions/parse_ini_basic.phpt
Normal file
239
ext/standard/tests/general_functions/parse_ini_basic.phpt
Normal file
|
@ -0,0 +1,239 @@
|
|||
--TEST--
|
||||
parse_ini_file() tests
|
||||
--ENV--
|
||||
basicval=FUBAR_VARIABLE
|
||||
basicqval=FUBAR_QUOTES_VARIABLE
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$ini_file = dirname(__FILE__)."/parse_ini_basic.data";
|
||||
|
||||
var_dump(parse_ini_file($ini_file, 1));
|
||||
|
||||
echo "Done.\n";
|
||||
?>
|
||||
--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.
|
27
ext/standard/tests/general_functions/parse_ini_booleans.data
Normal file
27
ext/standard/tests/general_functions/parse_ini_booleans.data
Normal file
|
@ -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"
|
69
ext/standard/tests/general_functions/parse_ini_booleans.phpt
Normal file
69
ext/standard/tests/general_functions/parse_ini_booleans.phpt
Normal file
|
@ -0,0 +1,69 @@
|
|||
--TEST--
|
||||
parse_ini_file() boolean operators
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$ini_file = dirname(__FILE__)."/parse_ini_booleans.data";
|
||||
|
||||
var_dump(parse_ini_file($ini_file, 1));
|
||||
|
||||
echo "Done.\n";
|
||||
|
||||
?>
|
||||
--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.
|
|
@ -1,12 +1,13 @@
|
|||
--TEST--
|
||||
parse_ini_file() tests
|
||||
parse_ini_file() multiple calls
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$filename = dirname(__FILE__)."/parse_ini_file.dat";
|
||||
@unlink($filename); /* Make sure the file really does not exist! */
|
||||
|
||||
var_dump(parse_ini_file());
|
||||
var_dump(parse_ini_file(1,1,1));
|
||||
var_dump(parse_ini_file(1,1,1,1));
|
||||
var_dump(parse_ini_file($filename));
|
||||
var_dump(parse_ini_file($filename, true));
|
||||
|
||||
|
@ -15,7 +16,6 @@ test =
|
|||
";
|
||||
file_put_contents($filename, $ini);
|
||||
var_dump(parse_ini_file($filename));
|
||||
|
||||
$ini = "
|
||||
test==
|
||||
";
|
||||
|
@ -81,7 +81,6 @@ $ini = "
|
|||
";
|
||||
file_put_contents($filename, $ini);
|
||||
var_dump(parse_ini_file($filename, true));
|
||||
|
||||
$ini = "
|
||||
test=test2
|
||||
test=test3
|
||||
|
@ -90,22 +89,21 @@ test=test4
|
|||
file_put_contents($filename, $ini);
|
||||
var_dump(parse_ini_file($filename, true));
|
||||
|
||||
|
||||
@unlink($filename);
|
||||
echo "Done\n";
|
||||
?>
|
||||
--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 @@ array(1) {
|
|||
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"
|
||||
|
|
|
@ -447,12 +447,15 @@ PHP_INI_BEGIN()
|
|||
PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
|
||||
PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
|
||||
|
||||
STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
|
||||
STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
|
||||
STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
|
||||
STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
|
||||
STD_PHP_INI_BOOLEAN("always_populate_raw_post_data", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, always_populate_raw_post_data, php_core_globals, core_globals)
|
||||
|
||||
STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
|
||||
STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
|
||||
|
||||
STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
|
||||
STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
|
||||
PHP_INI_END()
|
||||
/* }}} */
|
||||
|
||||
|
@ -1025,7 +1028,7 @@ PHP_FUNCTION(set_time_limit)
|
|||
}
|
||||
|
||||
convert_to_string_ex(new_timeout);
|
||||
if (zend_alter_ini_entry("max_execution_time", sizeof("max_execution_time"), Z_STRVAL_PP(new_timeout), Z_STRLEN_PP(new_timeout), PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) {
|
||||
if (zend_alter_ini_entry_ex("max_execution_time", sizeof("max_execution_time"), Z_STRVAL_PP(new_timeout), Z_STRLEN_PP(new_timeout), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC) == SUCCESS) {
|
||||
RETURN_TRUE;
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
|
|
|
@ -161,6 +161,9 @@ struct _php_core_globals {
|
|||
#endif
|
||||
long max_input_nesting_level;
|
||||
zend_bool in_user_include;
|
||||
|
||||
char *user_ini_filename;
|
||||
long user_ini_cache_ttl;
|
||||
};
|
||||
|
||||
|
||||
|
|
300
main/php_ini.c
300
main/php_ini.c
|
@ -21,6 +21,7 @@
|
|||
#include "php.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "zend_ini.h"
|
||||
#include "zend_ini_scanner.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/dl.h"
|
||||
#include "zend_extensions.h"
|
||||
|
@ -45,8 +46,8 @@ typedef struct _php_extension_lists {
|
|||
zend_llist functions;
|
||||
} php_extension_lists;
|
||||
|
||||
|
||||
/* True globals */
|
||||
static HashTable *active_ini_hash;
|
||||
static HashTable configuration_hash;
|
||||
PHPAPI char *php_ini_opened_path=NULL;
|
||||
static php_extension_lists extension_lists;
|
||||
|
@ -54,14 +55,13 @@ PHPAPI char *php_ini_scanned_files=NULL;
|
|||
|
||||
/* {{{ php_ini_displayer_cb
|
||||
*/
|
||||
static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type)
|
||||
static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type TSRMLS_DC)
|
||||
{
|
||||
if (ini_entry->displayer) {
|
||||
ini_entry->displayer(ini_entry, type);
|
||||
} else {
|
||||
char *display_string;
|
||||
uint display_string_length, esc_html=0;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
|
||||
if (ini_entry->orig_value && ini_entry->orig_value[0]) {
|
||||
|
@ -112,16 +112,16 @@ static int php_ini_displayer(zend_ini_entry *ini_entry, int module_number TSRMLS
|
|||
PUTS("<td class=\"e\">");
|
||||
PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
|
||||
PUTS("</td><td class=\"v\">");
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE);
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
|
||||
PUTS("</td><td class=\"v\">");
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG);
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
|
||||
PUTS("</td></tr>\n");
|
||||
} else {
|
||||
PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
|
||||
PUTS(" => ");
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE);
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
|
||||
PUTS(" => ");
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG);
|
||||
php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
|
||||
PUTS("\n");
|
||||
}
|
||||
return 0;
|
||||
|
@ -148,7 +148,6 @@ PHPAPI void display_ini_entries(zend_module_entry *module)
|
|||
/* }}} */
|
||||
|
||||
/* php.ini support */
|
||||
|
||||
#ifdef ZTS
|
||||
# if (ZEND_DEBUG)
|
||||
# define ZEND_EXTENSION_TOKEN "zend_extension_debug_ts"
|
||||
|
@ -163,17 +162,46 @@ PHPAPI void display_ini_entries(zend_module_entry *module)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* {{{ php_config_ini_parser_cb
|
||||
/* {{{ config_zval_dtor
|
||||
*/
|
||||
static void php_config_ini_parser_cb(zval *arg1, zval *arg2, int callback_type, void *arg)
|
||||
void config_zval_dtor(zval *zvalue)
|
||||
{
|
||||
if (Z_TYPE_P(zvalue) == IS_ARRAY) {
|
||||
zend_hash_destroy(Z_ARRVAL_P(zvalue));
|
||||
free(Z_ARRVAL_P(zvalue));
|
||||
} else if (Z_TYPE_P(zvalue) == IS_STRING) {
|
||||
free(Z_STRVAL_P(zvalue));
|
||||
}
|
||||
}
|
||||
/* Reset / free active_ini_sectin global */
|
||||
#define RESET_ACTIVE_INI_HASH() do { \
|
||||
active_ini_hash = NULL; \
|
||||
} while (0)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_ini_parser_cb
|
||||
*/
|
||||
static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, HashTable *target_hash)
|
||||
{
|
||||
zval *entry;
|
||||
HashTable *active_hash;
|
||||
|
||||
if (active_ini_hash) {
|
||||
active_hash = active_ini_hash;
|
||||
} else {
|
||||
active_hash = target_hash;
|
||||
}
|
||||
|
||||
switch (callback_type) {
|
||||
case ZEND_INI_PARSER_ENTRY: {
|
||||
zval *entry;
|
||||
|
||||
if (!arg2) {
|
||||
/* bare string - nothing to do */
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: Should the extension loading be disabled for PATH sections? */
|
||||
|
||||
/* PHP and Zend extensions are not added into configuration hash! */
|
||||
if (!strcasecmp(Z_STRVAL_P(arg1), "extension")) { /* load function module */
|
||||
zval copy;
|
||||
|
||||
|
@ -185,41 +213,101 @@ static void php_config_ini_parser_cb(zval *arg1, zval *arg2, int callback_type,
|
|||
char *extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
|
||||
|
||||
zend_llist_add_element(&extension_lists.engine, &extension_name);
|
||||
|
||||
/* All other entries are added into either configuration_hash or active ini section array */
|
||||
} else {
|
||||
zend_hash_update(&configuration_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, arg2, sizeof(zval), (void **) &entry);
|
||||
/* Store in active hash */
|
||||
zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, arg2, sizeof(zval), (void **) &entry);
|
||||
Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_INI_PARSER_POP_ENTRY: {
|
||||
zval *hash;
|
||||
zval **find_hash;
|
||||
zval *element;
|
||||
zval *option_arr;
|
||||
zval *find_arr;
|
||||
|
||||
if (!arg2) {
|
||||
/* bare string - nothing to do */
|
||||
break;
|
||||
}
|
||||
|
||||
if (zend_hash_find(&configuration_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, (void **) &find_hash) == FAILURE) {
|
||||
ALLOC_ZVAL(hash);
|
||||
array_init(hash);
|
||||
/* fprintf(stdout, "ZEND_INI_PARSER_POP_ENTRY: %s[%s] = %s\n",Z_STRVAL_P(arg1), Z_STRVAL_P(arg3), Z_STRVAL_P(arg2)); */
|
||||
|
||||
zend_hash_update(&configuration_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, &hash, sizeof(zval *), NULL);
|
||||
} else {
|
||||
hash = *find_hash;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
ALLOC_ZVAL(element);
|
||||
*element = *arg2;
|
||||
zval_copy_ctor(element);
|
||||
INIT_PZVAL(element);
|
||||
add_next_index_zval(hash, element);
|
||||
/* 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 {
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2, sizeof(zval), (void **) &entry);
|
||||
}
|
||||
Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_INI_PARSER_SECTION:
|
||||
case ZEND_INI_PARSER_SECTION: { /* Create an array of entries of each section */
|
||||
|
||||
/* fprintf(stdout, "ZEND_INI_PARSER_SECTION: %s\n",Z_STRVAL_P(arg1)); */
|
||||
|
||||
char *key = NULL;
|
||||
uint key_len;
|
||||
|
||||
/* Only PATH sections are handled here! */
|
||||
if (!strncasecmp(Z_STRVAL_P(arg1), "PATH", sizeof("PATH") - 1)) {
|
||||
key = Z_STRVAL_P(arg1);
|
||||
key = key + sizeof("PATH") - 1;
|
||||
key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1;
|
||||
|
||||
#if 0 /* Disable HOST sections for now. If someone can come up with some good usage case, then I can reconsider :) */
|
||||
} else if (!strncasecmp(Z_STRVAL_P(arg1), "HOST", sizeof("HOST") - 1)) {
|
||||
key = Z_STRVAL_P(arg1);
|
||||
key = key + sizeof("HOST") - 1;
|
||||
key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (key && key_len > 0) {
|
||||
/* Strip any trailing slashes */
|
||||
while (key_len > 0 && (key[key_len - 1] == '/' || key[key_len - 1] == '\\')) {
|
||||
key_len--;
|
||||
key[key_len] = 0;
|
||||
}
|
||||
|
||||
/* Strip any leading whitespace and '=' */
|
||||
while (*key && (
|
||||
*key == '=' ||
|
||||
*key == ' ' ||
|
||||
*key == '\t'
|
||||
)) {
|
||||
key++;
|
||||
key_len--;
|
||||
}
|
||||
|
||||
/* Search for existing entry and if it does not exist create one */
|
||||
if (zend_hash_find(target_hash, key, key_len + 1, (void **) &entry) == FAILURE) {
|
||||
zval *section_arr;
|
||||
|
||||
section_arr = (zval *) pemalloc(sizeof(zval), 1);
|
||||
INIT_PZVAL(section_arr);
|
||||
Z_TYPE_P(section_arr) = IS_ARRAY;
|
||||
Z_ARRVAL_P(section_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
|
||||
zend_hash_init(Z_ARRVAL_P(section_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
|
||||
zend_hash_update(target_hash, key, key_len + 1, section_arr, sizeof(zval), (void **) &entry);
|
||||
free(section_arr);
|
||||
}
|
||||
active_ini_hash = Z_ARRVAL_P(entry);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -244,16 +332,6 @@ static void php_load_zend_extension_cb(void *arg TSRMLS_DC)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ pvalue_config_destructor
|
||||
*/
|
||||
static void pvalue_config_destructor(zval *pvalue)
|
||||
{
|
||||
if (Z_TYPE_P(pvalue) == IS_STRING) {
|
||||
free(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_init_config
|
||||
*/
|
||||
int php_init_config(TSRMLS_D)
|
||||
|
@ -264,14 +342,8 @@ int php_init_config(TSRMLS_D)
|
|||
char *open_basedir;
|
||||
int free_ini_search_path = 0;
|
||||
zend_file_handle fh;
|
||||
struct stat sb;
|
||||
char ini_file[MAXPATHLEN];
|
||||
char *p;
|
||||
zend_llist scanned_ini_list;
|
||||
int l, total_l=0;
|
||||
zend_llist_element *element;
|
||||
|
||||
if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) pvalue_config_destructor, 1) == FAILURE) {
|
||||
if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) config_zval_dtor, 1) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
@ -281,7 +353,6 @@ int php_init_config(TSRMLS_D)
|
|||
|
||||
zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
|
||||
zend_llist_init(&extension_lists.functions, sizeof(zval), (llist_dtor_func_t) ZVAL_DESTRUCTOR, 1);
|
||||
zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
|
||||
|
||||
safe_mode_state = PG(safe_mode);
|
||||
open_basedir = PG(open_basedir);
|
||||
|
@ -492,8 +563,9 @@ int php_init_config(TSRMLS_D)
|
|||
|
||||
if (fh.handle.fp) {
|
||||
fh.type = ZEND_HANDLE_FP;
|
||||
RESET_ACTIVE_INI_HASH();
|
||||
|
||||
zend_parse_ini_file(&fh, 1, php_config_ini_parser_cb, &extension_lists);
|
||||
zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
|
||||
|
||||
{
|
||||
zval tmp;
|
||||
|
@ -501,6 +573,8 @@ int php_init_config(TSRMLS_D)
|
|||
Z_STRLEN(tmp) = strlen(fh.filename);
|
||||
Z_STRVAL(tmp) = zend_strndup(fh.filename, Z_STRLEN(tmp));
|
||||
Z_TYPE(tmp) = IS_STRING;
|
||||
tmp.refcount = 0;
|
||||
|
||||
zend_hash_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path"), (void *) &tmp, sizeof(zval), NULL);
|
||||
if (php_ini_opened_path) {
|
||||
efree(php_ini_opened_path);
|
||||
|
@ -514,10 +588,24 @@ int php_init_config(TSRMLS_D)
|
|||
if (!sapi_module.php_ini_ignore && strlen(PHP_CONFIG_FILE_SCAN_DIR)) {
|
||||
struct dirent **namelist;
|
||||
int ndir, i;
|
||||
struct stat sb;
|
||||
char ini_file[MAXPATHLEN];
|
||||
char *p;
|
||||
zend_file_handle fh;
|
||||
zend_llist scanned_ini_list;
|
||||
zend_llist_element *element;
|
||||
int l, total_l = 0;
|
||||
|
||||
/* Reset active ini section */
|
||||
RESET_ACTIVE_INI_HASH();
|
||||
|
||||
if ((ndir = php_scandir(PHP_CONFIG_FILE_SCAN_DIR, &namelist, 0, php_alphasort)) > 0) {
|
||||
zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
|
||||
memset(&fh, 0, sizeof(fh));
|
||||
|
||||
for (i = 0; i < ndir; i++) {
|
||||
/* check for a .ini extension */
|
||||
|
||||
/* check for any file with .ini extension */
|
||||
if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) {
|
||||
free(namelist[i]);
|
||||
continue;
|
||||
|
@ -528,12 +616,14 @@ int php_init_config(TSRMLS_D)
|
|||
if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
|
||||
fh.filename = ini_file;
|
||||
fh.type = ZEND_HANDLE_FP;
|
||||
zend_parse_ini_file(&fh, 1, php_config_ini_parser_cb, &extension_lists);
|
||||
/* Here, add it to the list of ini files read */
|
||||
l = strlen(ini_file);
|
||||
total_l += l + 2;
|
||||
p = estrndup(ini_file, l);
|
||||
zend_llist_add_element(&scanned_ini_list, &p);
|
||||
|
||||
if (zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) {
|
||||
/* Here, add it to the list of ini files read */
|
||||
l = strlen(ini_file);
|
||||
total_l += l + 2;
|
||||
p = estrndup(ini_file, l);
|
||||
zend_llist_add_element(&scanned_ini_list, &p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -541,14 +631,17 @@ int php_init_config(TSRMLS_D)
|
|||
}
|
||||
free(namelist);
|
||||
|
||||
/*
|
||||
* Don't need an extra byte for the \0 in this malloc as the last
|
||||
* element will not get a trailing , which gives us the byte for the \0
|
||||
*/
|
||||
if (total_l) {
|
||||
php_ini_scanned_files = (char *) malloc(total_l);
|
||||
*php_ini_scanned_files = '\0';
|
||||
int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0;
|
||||
php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
|
||||
if (!php_ini_scanned_files_len) {
|
||||
*php_ini_scanned_files = '\0';
|
||||
}
|
||||
total_l += php_ini_scanned_files_len;
|
||||
for (element = scanned_ini_list.head; element; element = element->next) {
|
||||
if (php_ini_scanned_files_len) {
|
||||
strlcat(php_ini_scanned_files, ",\n", total_l);
|
||||
}
|
||||
strlcat(php_ini_scanned_files, *(char **)element->data, total_l);
|
||||
strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l);
|
||||
}
|
||||
|
@ -558,7 +651,9 @@ int php_init_config(TSRMLS_D)
|
|||
}
|
||||
|
||||
if (sapi_module.ini_entries) {
|
||||
zend_parse_ini_string(sapi_module.ini_entries, 1, php_config_ini_parser_cb, &extension_lists);
|
||||
/* Reset active ini section */
|
||||
RESET_ACTIVE_INI_HASH();
|
||||
zend_parse_ini_string(sapi_module.ini_entries, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
|
@ -594,6 +689,81 @@ void php_ini_register_extensions(TSRMLS_D)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_parse_user_ini_file
|
||||
*/
|
||||
PHPAPI int php_parse_user_ini_file(char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC)
|
||||
{
|
||||
struct stat sb;
|
||||
char ini_file[MAXPATHLEN];
|
||||
zend_file_handle fh;
|
||||
|
||||
snprintf(ini_file, MAXPATHLEN, "%s%c%s", dirname, DEFAULT_SLASH, ini_filename);
|
||||
|
||||
if (VCWD_STAT(ini_file, &sb) == 0) {
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
memset(&fh, 0, sizeof(fh));
|
||||
if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
|
||||
fh.filename = ini_file;
|
||||
fh.type = ZEND_HANDLE_FP;
|
||||
|
||||
/* Reset active ini section */
|
||||
RESET_ACTIVE_INI_HASH();
|
||||
|
||||
if (zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, target_hash TSRMLS_CC) == SUCCESS) {
|
||||
/* FIXME: Add parsed file to the list of user files read? */
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_ini_activate_config
|
||||
*/
|
||||
PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC)
|
||||
{
|
||||
char *str;
|
||||
zval *data;
|
||||
uint str_len;
|
||||
ulong num_index;
|
||||
|
||||
/* Walk through config hash and alter matching ini entries using the values found in the hash */
|
||||
for (zend_hash_internal_pointer_reset(source_hash);
|
||||
zend_hash_get_current_key_ex(source_hash, &str, &str_len, &num_index, 0, NULL) == HASH_KEY_IS_STRING;
|
||||
zend_hash_move_forward(source_hash)
|
||||
) {
|
||||
zend_hash_get_current_data(source_hash, (void **) &data);
|
||||
zend_alter_ini_entry_ex(str, str_len, Z_STRVAL_P(data), Z_STRLEN_P(data), modify_type, stage, 0 TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_ini_activate_per_dir_config
|
||||
*/
|
||||
PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC)
|
||||
{
|
||||
zval *tmp;
|
||||
char *ptr;
|
||||
|
||||
/* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
|
||||
if (path && path_len) {
|
||||
ptr = path + 1;
|
||||
while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) {
|
||||
*ptr = 0;
|
||||
/* Search for source array matching the path from configuration_hash */
|
||||
if (zend_hash_find(&configuration_hash, path, path_len, (void **) &tmp) == SUCCESS) {
|
||||
php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
|
||||
}
|
||||
*ptr = '/';
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ cfg_get_entry
|
||||
*/
|
||||
PHPAPI zval *cfg_get_entry(char *name, uint name_length)
|
||||
|
@ -659,6 +829,14 @@ PHPAPI int cfg_get_string(char *varname, char **result)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
#if ZEND_DEBUG
|
||||
#include "php_ini.h"
|
||||
PHPAPI HashTable get_configuration_hash(void)
|
||||
{
|
||||
return configuration_hash;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "zend_ini.h"
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
void config_zval_dtor(zval *zvalue);
|
||||
int php_init_config(TSRMLS_D);
|
||||
int php_shutdown_config(void);
|
||||
void php_ini_register_extensions(TSRMLS_D);
|
||||
|
@ -31,6 +32,12 @@ PHPAPI zval *cfg_get_entry(char *name, uint name_length);
|
|||
PHPAPI int cfg_get_long(char *varname, long *result);
|
||||
PHPAPI int cfg_get_double(char *varname, double *result);
|
||||
PHPAPI int cfg_get_string(char *varname, char **result);
|
||||
PHPAPI int php_parse_user_ini_file(char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC);
|
||||
PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC);
|
||||
PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC);
|
||||
#if ZEND_DEBUG
|
||||
PHPAPI HashTable get_configuration_hash(void);
|
||||
#endif
|
||||
END_EXTERN_C()
|
||||
|
||||
#define PHP_INI_USER ZEND_INI_USER
|
||||
|
|
11
php.ini-dist
11
php.ini-dist
|
@ -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 ;
|
||||
|
|
|
@ -112,6 +112,18 @@
|
|||
; Using short tags is discouraged when developing code meant for redistribution
|
||||
; 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 ;
|
||||
;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -152,8 +152,30 @@ typedef struct _php_cgi_globals_struct {
|
|||
#ifdef PHP_WIN32
|
||||
zend_bool impersonate;
|
||||
#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)
|
||||
|
@ -566,12 +588,96 @@ static void sapi_cgi_log_message(char *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:
|
||||
1. SAPI Deactivate is called from two places: module init and request shutdown
|
||||
2. When the first call occurs and the request is not set up, flush fails on
|
||||
FastCGI.
|
||||
2. When the first call occurs and the request is not set up, flush fails on FastCGI.
|
||||
*/
|
||||
if (SG(sapi_started)) {
|
||||
sapi_cgibin_flush(SG(server_context));
|
||||
|
@ -587,7 +693,6 @@ static int php_cgi_startup(sapi_module_struct *sapi_module)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* {{{ sapi_module_struct cgi_sapi_module
|
||||
*/
|
||||
static sapi_module_struct cgi_sapi_module = {
|
||||
|
@ -597,7 +702,7 @@ static sapi_module_struct cgi_sapi_module = {
|
|||
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 */
|
||||
|
@ -1072,6 +1177,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_
|
|||
#ifdef PHP_WIN32
|
||||
php_cgi_globals->impersonate = 0;
|
||||
#endif
|
||||
zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, (dtor_func_t) user_config_cache_entry_dtor, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -1093,6 +1199,8 @@ static PHP_MINIT_FUNCTION(cgi)
|
|||
*/
|
||||
static PHP_MSHUTDOWN_FUNCTION(cgi)
|
||||
{
|
||||
zend_hash_destroy(&CGIG(user_config_cache));
|
||||
|
||||
UNREGISTER_INI_ENTRIES();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue