summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/Makefile.am2
-rw-r--r--Zend/flex.skl42
-rw-r--r--Zend/zend.c2
-rw-r--r--Zend/zend.h3
-rw-r--r--Zend/zend_compile.h13
-rw-r--r--Zend/zend_execute.c20
-rw-r--r--Zend/zend_globals.h4
-rw-r--r--Zend/zend_ini_scanner.l22
-rw-r--r--Zend/zend_language_scanner.h2
-rw-r--r--Zend/zend_language_scanner.l33
-rw-r--r--Zend/zend_stream.c123
-rw-r--r--Zend/zend_stream.h59
-rw-r--r--configure.in2
-rw-r--r--ext/standard/basic_functions.c17
-rw-r--r--main/main.c27
-rw-r--r--main/php_ini.c2
16 files changed, 274 insertions, 99 deletions
diff --git a/Zend/Makefile.am b/Zend/Makefile.am
index 2182442d5b..ac7a68e57d 100644
--- a/Zend/Makefile.am
+++ b/Zend/Makefile.am
@@ -14,7 +14,7 @@ libZend_la_SOURCES=\
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.c zend_objects.c zend_object_handlers.c \
- zend_object_API.c
+ zend_object_API.c zend_ts_hash.c zend_stream.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
diff --git a/Zend/flex.skl b/Zend/flex.skl
index 65ed5ca2a5..919aacad69 100644
--- a/Zend/flex.skl
+++ b/Zend/flex.skl
@@ -2,6 +2,7 @@
/* Scanner skeleton version:
* $Header$
+ * vim:ft=lex:
*/
#define FLEX_SCANNER
@@ -154,7 +155,7 @@ typedef unsigned int yy_size_t;
struct yy_buffer_state
{
%-
- FILE *yy_input_file;
+ struct _zend_file_handle *yy_input_file;
%+
istream* yy_input_file;
%*
@@ -256,13 +257,13 @@ static int yy_n_chars; /* number of characters read into yy_ch_buf */
/* static int yy_did_buffer_switch_on_eof; */
#define yy_did_buffer_switch_on_eof SCNG(_yy_did_buffer_switch_on_eof)
-void yyrestart YY_PROTO(( FILE *input_file TSRMLS_DC ));
+void yyrestart YY_PROTO(( struct _zend_file_handle *input_file TSRMLS_DC ));
void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer TSRMLS_DC ));
void yy_load_buffer_state YY_PROTO(( TSRMLS_D ));
-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size TSRMLS_DC ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( struct _zend_file_handle *file, int size TSRMLS_DC ));
void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b TSRMLS_DC ));
-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file TSRMLS_DC ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, struct _zend_file_handle *file TSRMLS_DC ));
void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b TSRMLS_DC ));
#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer TSRMLS_CC )
@@ -434,6 +435,18 @@ YY_MALLOC_DECL
/* Copy whatever the last rule matched to the standard output. */
+/* Zend file handle reading */
+#ifndef ECHO
+#define ECHO /* There is no output */
+#endif
+
+#define YY_INPUT(buf, result, max_size) \
+ if ( ((result = zend_stream_read(yyin, buf, max_size TSRMLS_CC)) == 0) \
+ && zend_stream_ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+
+
+
#ifndef ECHO
%- Standard (non-C++) definition
/* This used to be an fputs(), but since the string might contain NUL's,
@@ -524,6 +537,7 @@ YY_DECL
if ( ! yy_start )
yy_start = 1; /* first start state */
+#if 0
if ( ! SCNG(yy_in) )
%-
SCNG(yy_in) = stdin;
@@ -537,6 +551,7 @@ YY_DECL
%+
SCNG(yy_out) = &cout;
%*
+#endif
if ( ! yy_current_buffer )
yy_current_buffer =
@@ -1111,10 +1126,10 @@ int yyFlexLexer::yyinput(TSRMLS_D)
%-
#ifdef YY_USE_PROTOS
-void yyrestart( FILE *input_file TSRMLS_DC )
+void yyrestart( struct _zend_file_handle *input_file TSRMLS_DC )
#else
void yyrestart( input_file TSRMLS_CC )
-FILE *input_file;
+struct _zend_file_handle *input_file;
#endif
%+
void yyFlexLexer::yyrestart( istream* input_file TSRMLS_DC )
@@ -1187,10 +1202,10 @@ void yyFlexLexer::yy_load_buffer_state()
%-
#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size TSRMLS_DC )
+YY_BUFFER_STATE yy_create_buffer( struct _zend_file_handle *file, int size TSRMLS_DC )
#else
YY_BUFFER_STATE yy_create_buffer( file, size TSRMLS_CC )
-FILE *file;
+struct _zend_file_handle *file;
int size;
#ifdef ZTS
void ***tsrm_ls;
@@ -1251,18 +1266,13 @@ void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b TSRMLS_DC )
%-
-#ifndef YY_ALWAYS_INTERACTIVE
-#ifndef YY_NEVER_INTERACTIVE
-ZEND_DLIMPORT int isatty YY_PROTO(( int ));
-#endif
-#endif
#ifdef YY_USE_PROTOS
-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file TSRMLS_DC )
+void yy_init_buffer( YY_BUFFER_STATE b, struct _zend_file_handle *file TSRMLS_DC )
#else
void yy_init_buffer( b, file TSRMLS_CC )
YY_BUFFER_STATE b;
-FILE *file;
+struct _zend_file_handle *file;
#ifdef ZTS
void ***tsrm_ls;
#endif
@@ -1286,7 +1296,7 @@ void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, istream* file TSRMLS_DC )
#if YY_NEVER_INTERACTIVE
b->yy_is_interactive = 0;
#else
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+ b->yy_is_interactive = file->handle.stream.interactive;
#endif
#endif
%+
diff --git a/Zend/zend.c b/Zend/zend.c
index 2a0c1c88b7..9a4e1460de 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -48,6 +48,7 @@ ZEND_API zend_class_entry *zend_standard_class_def = NULL;
ZEND_API int (*zend_printf)(const char *format, ...);
ZEND_API zend_write_func_t zend_write;
ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
+ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
ZEND_API void (*zend_block_interruptions)(void);
ZEND_API void (*zend_unblock_interruptions)(void);
ZEND_API void (*zend_ticks_function)(int ticks);
@@ -534,6 +535,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
if (!zend_fopen) {
zend_fopen = zend_fopen_wrapper;
}
+ zend_stream_open_function = utility_functions->stream_open_function;
zend_message_dispatcher_p = utility_functions->message_handler;
zend_block_interruptions = utility_functions->block_interruptions;
zend_unblock_interruptions = utility_functions->unblock_interruptions;
diff --git a/Zend/zend.h b/Zend/zend.h
index c031bce103..f6eca9989e 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -342,6 +342,7 @@ struct _zend_class_entry {
typedef struct _zend_class_entry zend_namespace; /* namespace is the same as class */
+#include "zend_stream.h"
typedef struct _zend_utility_functions {
void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
int (*printf_function)(const char *format, ...);
@@ -353,6 +354,7 @@ typedef struct _zend_utility_functions {
int (*get_configuration_directive)(char *name, uint name_length, zval *contents);
void (*ticks_function)(int ticks);
void (*on_timeout)(int seconds TSRMLS_DC);
+ int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
} zend_utility_functions;
@@ -485,6 +487,7 @@ extern ZEND_API void (*zend_unblock_interruptions)(void);
extern ZEND_API void (*zend_ticks_function)(int ticks);
extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
+extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
ZEND_API void zend_error(int type, const char *format, ...);
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index aec37e0159..83622a8f01 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -198,18 +198,6 @@ typedef struct _list_llist_element {
znode value;
} list_llist_element;
-
-typedef struct _zend_file_handle {
- zend_uchar type;
- char *filename;
- char *opened_path;
- union {
- int fd;
- FILE *fp;
- } handle;
- zend_bool free_filename;
-} zend_file_handle;
-
union _temp_variable;
struct _zend_execute_data {
@@ -726,6 +714,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_HANDLE_FP 2
#define ZEND_HANDLE_STDIOSTREAM 3
#define ZEND_HANDLE_FSTREAM 4
+#define ZEND_HANDLE_STREAM 5
#define ZEND_FETCH_STANDARD 0
#define ZEND_FETCH_ADD_LOCK 1
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 961a52fd93..052f6e87c4 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -3338,28 +3338,21 @@ int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
switch (EX(opline)->op2.u.constant.value.lval) {
case ZEND_INCLUDE_ONCE:
case ZEND_REQUIRE_ONCE: {
- char *opened_path=NULL;
int dummy = 1;
zend_file_handle file_handle;
- file_handle.handle.fp = zend_fopen(inc_filename->value.str.val, &opened_path);
- file_handle.type = ZEND_HANDLE_FP;
- file_handle.filename = inc_filename->value.str.val;
- file_handle.opened_path = opened_path;
- file_handle.free_filename = 0;
+ if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
- if (file_handle.handle.fp) {
- if (!opened_path) {
- opened_path = file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
+ if (!file_handle.opened_path) {
+ file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
}
- if (zend_hash_add(&EG(included_files), opened_path, strlen(opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) {
+ if (zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) {
CG(active_namespace) = EG(active_namespace);
new_op_array = zend_compile_file(&file_handle, (EX(opline)->op2.u.constant.value.lval==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
- opened_path = NULL; /* zend_destroy_file_handle() already frees it */
} else {
- fclose(file_handle.handle.fp);
+ zend_file_handle_dtor(&file_handle);
failure_retval=1;
}
} else {
@@ -3369,9 +3362,6 @@ int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle.filename);
}
}
- if (opened_path) {
- efree(opened_path);
- }
break;
}
break;
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index e5c6520787..016c935cef 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -254,8 +254,8 @@ struct _zend_alloc_globals {
};
struct _zend_scanner_globals {
- FILE *yy_in;
- FILE *yy_out;
+ zend_file_handle *yy_in;
+ zend_file_handle *yy_out;
int yy_leng;
char *yy_text;
struct yy_buffer_state *current_buffer;
diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l
index 45aae83154..33d1d294dd 100644
--- a/Zend/zend_ini_scanner.l
+++ b/Zend/zend_ini_scanner.l
@@ -71,22 +71,12 @@ char *zend_ini_scanner_get_filename(TSRMLS_D)
int zend_ini_open_file_for_scanning(zend_file_handle *fh TSRMLS_DC)
{
- FILE *fp;
-
- switch (fh->type) {
- case ZEND_HANDLE_FP:
- fp = fh->handle.fp;
- break;
- case ZEND_HANDLE_FILENAME:
- fp = zend_fopen(fh->filename, NULL);
- fh->type = ZEND_HANDLE_FP;
- break;
- default:
- return FAILURE;
+ if (FAILURE == zend_stream_fixup(fh TSRMLS_CC)) {
+ return FAILURE;
}
init_ini_scanner(TSRMLS_C);
- yyin = fp;
+ yyin = fh;
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC);
ini_filename = fh->filename;
return SUCCESS;
@@ -95,11 +85,7 @@ int zend_ini_open_file_for_scanning(zend_file_handle *fh TSRMLS_DC)
void zend_ini_close_file(zend_file_handle *fh TSRMLS_DC)
{
- switch (fh->type) {
- case ZEND_HANDLE_FP:
- fclose(fh->handle.fp);
- break;
- }
+ zend_stream_close(fh);
}
%}
diff --git a/Zend/zend_language_scanner.h b/Zend/zend_language_scanner.h
index be373c2100..50227ee9c7 100644
--- a/Zend/zend_language_scanner.h
+++ b/Zend/zend_language_scanner.h
@@ -25,7 +25,7 @@
typedef struct _zend_lex_state {
YY_BUFFER_STATE buffer_state;
int state;
- FILE *in;
+ zend_file_handle *in;
uint lineno;
char *filename;
} zend_lex_state;
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index 6908e15318..d8f4d28362 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -171,10 +171,15 @@ BEGIN_EXTERN_C()
ZEND_API void zend_file_handle_dtor(zend_file_handle *fh)
{
+ TSRMLS_FETCH();
+
switch (fh->type) {
case ZEND_HANDLE_FP:
fclose(fh->handle.fp);
break;
+ case ZEND_HANDLE_STREAM:
+ fh->handle.stream.closer(fh->handle.stream.handle TSRMLS_CC);
+ break;
case ZEND_HANDLE_FILENAME:
/* We're only supposed to get here when destructing the used_files hash,
* which doesn't really contain open files, but references to their names/paths
@@ -183,9 +188,11 @@ ZEND_API void zend_file_handle_dtor(zend_file_handle *fh)
}
if (fh->opened_path) {
efree(fh->opened_path);
+ fh->opened_path = NULL;
}
if (fh->free_filename && fh->filename) {
efree(fh->filename);
+ fh->filename = NULL;
}
}
@@ -199,6 +206,9 @@ int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2)
case ZEND_HANDLE_FP:
return fh1->handle.fp==fh2->handle.fp;
break;
+ case ZEND_HANDLE_STREAM:
+ return fh1->handle.stream.handle == fh2->handle.stream.handle;
+ break;
}
return 0;
}
@@ -214,27 +224,14 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
{
char *file_path=NULL;
- switch (file_handle->type) {
- case ZEND_HANDLE_FILENAME:
- file_handle->handle.fp = zend_fopen(file_handle->filename, &file_handle->opened_path);
- break;
- case ZEND_HANDLE_FD:
- file_handle->handle.fp = fdopen(file_handle->handle.fd, "r");
- break;
- case ZEND_HANDLE_FP:
- file_handle->handle.fp = file_handle->handle.fp;
- break;
- }
- if (!file_handle->handle.fp) {
+ if (FAILURE == zend_stream_fixup(file_handle TSRMLS_CC)) {
return FAILURE;
}
- file_handle->type = ZEND_HANDLE_FP;
- if (file_handle->handle.fp != stdin) {
- zend_llist_add_element(&CG(open_files), file_handle);
- }
+ zend_llist_add_element(&CG(open_files), file_handle);
+
/* Reset the scanner for scanning the new file */
- SCNG(yy_in) = file_handle->handle.fp;
+ SCNG(yy_in) = file_handle;
yy_switch_to_buffer(yy_create_buffer(SCNG(yy_in), YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC);
BEGIN(INITIAL);
@@ -339,7 +336,7 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
retval = zend_compile_file(&file_handle, type TSRMLS_CC);
- if (retval && file_handle.handle.fp) {
+ if (retval && file_handle.handle.stream.handle) {
int dummy = 1;
if (!file_handle.opened_path) {
diff --git a/Zend/zend_stream.c b/Zend/zend_stream.c
new file mode 100644
index 0000000000..f6d6e16072
--- /dev/null
+++ b/Zend/zend_stream.c
@@ -0,0 +1,123 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Wez Furlong <wez@thebrainroom.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+
+#include "zend.h"
+#include "zend_compile.h"
+
+ZEND_DLIMPORT int isatty(int fd);
+
+static size_t zend_stream_stdio_reader(void *handle, char *buf, size_t len TSRMLS_DC)
+{
+ return fread(buf, 1, len, (FILE*)handle);
+}
+
+static void zend_stream_stdio_closer(void *handle TSRMLS_DC)
+{
+ if ((FILE*)handle != stdin)
+ fclose((FILE*)handle);
+}
+
+int zend_stream_open(const char *filename, zend_file_handle *handle TSRMLS_DC)
+{
+ if (zend_stream_open) {
+ return zend_stream_open_function(filename, handle TSRMLS_CC);
+ }
+ handle->type = ZEND_HANDLE_FP;
+ handle->opened_path = NULL;
+ handle->handle.fp = zend_fopen(filename, &handle->opened_path);
+ handle->filename = (char *)filename;
+ handle->free_filename = 0;
+
+ return (handle->handle.fp) ? SUCCESS : FAILURE;
+}
+
+int zend_stream_fixup(zend_file_handle *file_handle TSRMLS_DC)
+{
+ switch (file_handle->type) {
+ case ZEND_HANDLE_FILENAME:
+ if (FAILURE == zend_stream_open(file_handle->filename, file_handle TSRMLS_CC)) {
+ return FAILURE;
+ }
+ break;
+
+ case ZEND_HANDLE_FD:
+ file_handle->handle.fp = fdopen(file_handle->handle.fd, "rb");
+ file_handle->type = ZEND_HANDLE_FP;
+ break;
+
+ case ZEND_HANDLE_FP:
+ file_handle->handle.fp = file_handle->handle.fp;
+ break;
+
+ case ZEND_HANDLE_STREAM:
+ /* nothing to do */
+ return SUCCESS;
+
+ default:
+ return FAILURE;
+ }
+ if (file_handle->type == ZEND_HANDLE_FP) {
+ if (!file_handle->handle.fp) {
+ return FAILURE;
+ }
+
+ /* promote to stream */
+ file_handle->handle.stream.handle = file_handle->handle.fp;
+ file_handle->handle.stream.reader = zend_stream_stdio_reader;
+ file_handle->handle.stream.closer = zend_stream_stdio_closer;
+ file_handle->type = ZEND_HANDLE_STREAM;
+
+ file_handle->handle.stream.interactive = isatty(fileno(file_handle->handle.stream.handle));
+ }
+ return SUCCESS;
+}
+
+size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC)
+{
+ if (file_handle->handle.stream.interactive) {
+ int c = '*', n;
+
+ for ( n = 0; n < len && (c = zend_stream_getc( file_handle TSRMLS_CC)) != EOF && c != '\n'; ++n )
+ buf[n] = (char) c;
+ if ( c == '\n' )
+ buf[n++] = (char) c;
+
+ return n;
+ }
+ return file_handle->handle.stream.reader(file_handle->handle.stream.handle, buf, len TSRMLS_CC);
+}
+
+int zend_stream_getc(zend_file_handle *file_handle TSRMLS_DC)
+{
+ char buf;
+
+ if (zend_stream_read(file_handle, &buf, sizeof(buf) TSRMLS_CC)) {
+ return buf;
+ }
+ return EOF;
+}
+
+int zend_stream_ferror(zend_file_handle *file_handle TSRMLS_DC)
+{
+ return 0;
+}
+
+
diff --git a/Zend/zend_stream.h b/Zend/zend_stream.h
new file mode 100644
index 0000000000..130793287c
--- /dev/null
+++ b/Zend/zend_stream.h
@@ -0,0 +1,59 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Wez Furlong <wez@thebrainroom.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef ZEND_STREAM_H
+#define ZEND_STREAM_H
+
+/* Lightweight stream implementation for the ZE scanners.
+ * These functions are private to the engine.
+ * */
+
+typedef size_t (*zend_stream_reader_t)(void *handle, char *buf, size_t len TSRMLS_DC);
+typedef void (*zend_stream_closer_t)(void *handle TSRMLS_DC);
+
+typedef struct _zend_stream {
+ void *handle;
+ zend_stream_reader_t reader;
+ zend_stream_closer_t closer;
+ int interactive;
+} zend_stream;
+
+typedef struct _zend_file_handle {
+ zend_uchar type;
+ char *filename;
+ char *opened_path;
+ union {
+ int fd;
+ FILE *fp;
+ zend_stream stream;
+ } handle;
+ zend_bool free_filename;
+} zend_file_handle;
+
+int zend_stream_open(const char *filename, zend_file_handle *handle TSRMLS_DC);
+int zend_stream_ferror(zend_file_handle *file_handle TSRMLS_DC);
+int zend_stream_getc(zend_file_handle *file_handle TSRMLS_DC);
+size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC);
+int zend_stream_fixup(zend_file_handle *file_handle TSRMLS_DC);
+
+#define zend_stream_close(handle) zend_file_handle_dtor((handle))
+
+#endif
+
diff --git a/configure.in b/configure.in
index 00aa4ac5de..fb7dc63b54 100644
--- a/configure.in
+++ b/configure.in
@@ -1116,7 +1116,7 @@ PHP_ADD_SOURCES(Zend, \
zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
- zend_ini.c zend_qsort.c zend_multibyte.c)
+ zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c)
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c)
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index a9930811a9..fed8e51b93 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -2941,21 +2941,10 @@ PHP_FUNCTION(parse_ini_file)
convert_to_string_ex(filename);
- if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_ALLOW_ONLY_FILE))) {
- RETURN_FALSE;
- }
-
- if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- fh.handle.fp = VCWD_FOPEN(Z_STRVAL_PP(filename), "r");
- if (!fh.handle.fp) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open '%s' for reading", Z_STRVAL_PP(filename));
- RETURN_FALSE;
- }
- Z_TYPE(fh) = ZEND_HANDLE_FP;
+ memset(&fh, 0, sizeof(fh));
fh.filename = Z_STRVAL_PP(filename);
+ Z_TYPE(fh) = ZEND_HANDLE_FILENAME;
+
array_init(return_value);
zend_parse_ini_file(&fh, 0, ini_parser_cb, return_value);
}
diff --git a/main/main.c b/main/main.c
index 1cf0bf7eb6..d5d8d15623 100644
--- a/main/main.c
+++ b/main/main.c
@@ -732,6 +732,32 @@ static FILE *php_fopen_wrapper_for_zend(const char *filename, char **opened_path
}
/* }}} */
+static void stream_closer_for_zend(void *handle TSRMLS_DC)
+{
+ php_stream_close((php_stream*)handle);
+}
+
+static int php_stream_open_for_zend(const char *filename, zend_file_handle *handle TSRMLS_DC)
+{
+ php_stream *stream;
+
+ stream = php_stream_open_wrapper((char *)filename, "rb", ENFORCE_SAFE_MODE|USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE, &handle->opened_path);
+
+ if (stream) {
+ handle->type = ZEND_HANDLE_STREAM;
+ handle->filename = (char*)filename;
+ handle->free_filename = 0;
+ handle->handle.stream.handle = stream;
+ handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read;
+ handle->handle.stream.closer = stream_closer_for_zend;
+ handle->handle.stream.interactive = 0;
+
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+
/* {{{ php_get_configuration_directive_for_zend
*/
static int php_get_configuration_directive_for_zend(char *name, uint name_length, zval *contents)
@@ -1185,6 +1211,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
zuf.ticks_function = php_run_ticks;
zuf.on_timeout = php_on_timeout;
+ zuf.stream_open_function = php_stream_open_for_zend;
zend_startup(&zuf, NULL, 1);
#ifdef ZTS
diff --git a/main/php_ini.c b/main/php_ini.c
index 6380a1b831..6e599ebcaf 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -370,7 +370,7 @@ int php_init_config()
PG(safe_mode) = 0;
PG(open_basedir) = NULL;
- fh.handle.fp = NULL;
+ memset(&fh, 0, sizeof(fh));
/* Check if php_ini_path_override is a file */
if (!sapi_module.php_ini_ignore) {
if (sapi_module.php_ini_path_override && sapi_module.php_ini_path_override[0]) {