mirror of
https://github.com/php/php-src.git
synced 2025-01-22 11:44:09 +08:00
Always initialize wrappers, regardless of PG(allow_url_fopen).
Add is_url field to wrapper structure; the stream wrapper openers will disallow opening is is_url && !PG(allow_url_fopen). Add infrastructure for stat($url) and opendir($url). Tidy up/centralize code that locates and instantiates wrappers for the various operations. Implement opendir for plain files. Make the PHP opendir and dir functions use the streams implementations. Add modelines for syntax highlighting the pear scripts in vim
This commit is contained in:
parent
fe2badf64e
commit
b10b24d50c
@ -983,21 +983,14 @@ PHP_MINIT_FUNCTION(basic)
|
||||
PHP_MINIT(url_scanner_ex) (INIT_FUNC_ARGS_PASSTHRU);
|
||||
PHP_MINIT(proc_open) (INIT_FUNC_ARGS_PASSTHRU);
|
||||
|
||||
PHP_MINIT(user_streams) (INIT_FUNC_ARGS_PASSTHRU);
|
||||
|
||||
if (PG(allow_url_fopen)) {
|
||||
PHP_MINIT(user_streams) (INIT_FUNC_ARGS_PASSTHRU);
|
||||
|
||||
if (FAILURE == php_register_url_stream_wrapper("http", &php_stream_http_wrapper TSRMLS_CC))
|
||||
return FAILURE;
|
||||
if (FAILURE == php_register_url_stream_wrapper("php", &php_stream_php_wrapper TSRMLS_CC))
|
||||
return FAILURE;
|
||||
if (FAILURE == php_register_url_stream_wrapper("ftp", &php_stream_ftp_wrapper TSRMLS_CC))
|
||||
return FAILURE;
|
||||
php_register_url_stream_wrapper("http", &php_stream_http_wrapper TSRMLS_CC);
|
||||
php_register_url_stream_wrapper("php", &php_stream_php_wrapper TSRMLS_CC);
|
||||
php_register_url_stream_wrapper("ftp", &php_stream_ftp_wrapper TSRMLS_CC);
|
||||
# if HAVE_OPENSSL_EXT
|
||||
if (FAILURE == php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC))
|
||||
return FAILURE;
|
||||
php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC);
|
||||
# endif
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -1011,16 +1004,13 @@ PHP_MSHUTDOWN_FUNCTION(basic)
|
||||
basic_globals_dtor(&basic_globals TSRMLS_CC);
|
||||
#endif
|
||||
|
||||
if (PG(allow_url_fopen)) {
|
||||
php_unregister_url_stream_wrapper("http" TSRMLS_CC);
|
||||
php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
|
||||
php_unregister_url_stream_wrapper("php" TSRMLS_CC);
|
||||
php_unregister_url_stream_wrapper("http" TSRMLS_CC);
|
||||
php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
|
||||
php_unregister_url_stream_wrapper("php" TSRMLS_CC);
|
||||
# if HAVE_OPENSSL_EXT
|
||||
php_unregister_url_stream_wrapper("https" TSRMLS_CC);
|
||||
php_unregister_url_stream_wrapper("https" TSRMLS_CC);
|
||||
# endif
|
||||
|
||||
}
|
||||
|
||||
UNREGISTER_INI_ENTRIES();
|
||||
|
||||
PHP_MSHUTDOWN(regex) (SHUTDOWN_FUNC_ARGS_PASSTHRU);
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "php.h"
|
||||
#include "fopen_wrappers.h"
|
||||
|
||||
#include "file.h"
|
||||
#include "php_dir.h"
|
||||
|
||||
#ifdef HAVE_DIRENT_H
|
||||
@ -55,12 +55,14 @@ int dir_globals_id;
|
||||
php_dir_globals dir_globals;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
int id;
|
||||
DIR *dir;
|
||||
} php_dir;
|
||||
|
||||
static int le_dirp;
|
||||
#endif
|
||||
|
||||
static zend_class_entry *dir_class_entry_ptr;
|
||||
|
||||
@ -72,14 +74,14 @@ static zend_class_entry *dir_class_entry_ptr;
|
||||
php_error(E_WARNING, "unable to find my handle property"); \
|
||||
RETURN_FALSE; \
|
||||
} \
|
||||
ZEND_FETCH_RESOURCE(dirp, php_dir *, tmp, -1, "Directory", le_dirp); \
|
||||
ZEND_FETCH_RESOURCE(dirp, php_stream *, tmp, -1, "Directory", php_file_le_stream()); \
|
||||
} else { \
|
||||
ZEND_FETCH_RESOURCE(dirp, php_dir *, 0, DIRG(default_dir), "Directory", le_dirp); \
|
||||
ZEND_FETCH_RESOURCE(dirp, php_stream *, 0, DIRG(default_dir), "Directory", php_file_le_stream()); \
|
||||
} \
|
||||
} else if ((ZEND_NUM_ARGS() != 1) || zend_get_parameters_ex(1, &id) == FAILURE) { \
|
||||
WRONG_PARAM_COUNT; \
|
||||
} else { \
|
||||
ZEND_FETCH_RESOURCE(dirp, php_dir *, id,-1, "Directory", le_dirp); \
|
||||
ZEND_FETCH_RESOURCE(dirp, php_stream *, id,-1, "Directory", php_file_le_stream()); \
|
||||
}
|
||||
|
||||
static zend_function_entry php_dir_class_functions[] = {
|
||||
@ -103,15 +105,6 @@ static void php_set_default_dir(int id TSRMLS_DC)
|
||||
DIRG(default_dir) = id;
|
||||
}
|
||||
|
||||
|
||||
static void _dir_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
{
|
||||
php_dir *dirp = (php_dir *)rsrc->ptr;
|
||||
|
||||
closedir(dirp->dir);
|
||||
efree(dirp);
|
||||
}
|
||||
|
||||
PHP_RINIT_FUNCTION(dir)
|
||||
{
|
||||
DIRG(default_dir) = -1;
|
||||
@ -123,8 +116,6 @@ PHP_MINIT_FUNCTION(dir)
|
||||
static char tmpstr[2];
|
||||
zend_class_entry dir_class_entry;
|
||||
|
||||
le_dirp = zend_register_list_destructors_ex(_dir_dtor, NULL, "dir", module_number);
|
||||
|
||||
INIT_CLASS_ENTRY(dir_class_entry, "Directory", php_dir_class_functions);
|
||||
dir_class_entry_ptr = zend_register_internal_class(&dir_class_entry TSRMLS_CC);
|
||||
|
||||
@ -144,49 +135,29 @@ PHP_MINIT_FUNCTION(dir)
|
||||
static void _php_do_opendir(INTERNAL_FUNCTION_PARAMETERS, int createobject)
|
||||
{
|
||||
pval **arg;
|
||||
php_dir *dirp;
|
||||
php_stream *dirp;
|
||||
|
||||
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
convert_to_string_ex(arg);
|
||||
|
||||
if (php_check_open_basedir(Z_STRVAL_PP(arg) TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (PG(safe_mode) &&(!php_checkuid(Z_STRVAL_PP(arg), NULL, CHECKUID_ALLOW_ONLY_FILE))) {
|
||||
dirp = php_stream_opendir(Z_STRVAL_PP(arg), ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
|
||||
|
||||
if (dirp == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
dirp = emalloc(sizeof(php_dir));
|
||||
|
||||
dirp->dir = VCWD_OPENDIR(Z_STRVAL_PP(arg));
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
if (!dirp->dir || dirp->dir->finished) {
|
||||
if (dirp->dir) {
|
||||
closedir(dirp->dir);
|
||||
}
|
||||
#else
|
||||
if (!dirp->dir) {
|
||||
#endif
|
||||
efree(dirp);
|
||||
php_error(E_WARNING, "OpenDir: %s (errno %d)", strerror(errno), errno);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
dirp->id = zend_list_insert(dirp, le_dirp);
|
||||
|
||||
php_set_default_dir(dirp->id TSRMLS_CC);
|
||||
|
||||
php_set_default_dir(dirp->rsrc_id TSRMLS_CC);
|
||||
|
||||
if (createobject) {
|
||||
object_init_ex(return_value, dir_class_entry_ptr);
|
||||
add_property_stringl(return_value, "path", Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), 1);
|
||||
add_property_resource(return_value, "handle", dirp->id);
|
||||
zend_list_addref(dirp->id);
|
||||
add_property_resource(return_value, "handle", dirp->rsrc_id);
|
||||
zend_list_addref(dirp->rsrc_id); /* might not be needed */
|
||||
php_stream_auto_cleanup(dirp); /* so we don't get warnings under debug */
|
||||
} else {
|
||||
RETURN_RESOURCE(dirp->id);
|
||||
php_stream_to_zval(dirp, return_value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,13 +186,13 @@ PHP_FUNCTION(getdir)
|
||||
PHP_FUNCTION(closedir)
|
||||
{
|
||||
pval **id, **tmp, *myself;
|
||||
php_dir *dirp;
|
||||
php_stream *dirp;
|
||||
|
||||
FETCH_DIRP();
|
||||
|
||||
zend_list_delete(dirp->id);
|
||||
zend_list_delete(dirp->rsrc_id);
|
||||
|
||||
if (dirp->id == DIRG(default_dir)) {
|
||||
if (dirp->rsrc_id == DIRG(default_dir)) {
|
||||
php_set_default_dir(-1 TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
@ -323,11 +294,11 @@ PHP_FUNCTION(getcwd)
|
||||
PHP_FUNCTION(rewinddir)
|
||||
{
|
||||
pval **id, **tmp, *myself;
|
||||
php_dir *dirp;
|
||||
php_stream *dirp;
|
||||
|
||||
FETCH_DIRP();
|
||||
|
||||
rewinddir(dirp->dir);
|
||||
php_stream_rewinddir(dirp);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -337,14 +308,13 @@ PHP_FUNCTION(rewinddir)
|
||||
PHP_NAMED_FUNCTION(php_if_readdir)
|
||||
{
|
||||
pval **id, **tmp, *myself;
|
||||
php_dir *dirp;
|
||||
char entry[sizeof(struct dirent)+MAXPATHLEN];
|
||||
struct dirent *result = (struct dirent *)&entry; /* patch for libc5 readdir problems */
|
||||
php_stream *dirp;
|
||||
php_stream_dirent entry;
|
||||
|
||||
FETCH_DIRP();
|
||||
|
||||
if (php_readdir_r(dirp->dir, (struct dirent *) entry, &result) == 0 && result) {
|
||||
RETURN_STRINGL(result->d_name, strlen(result->d_name), 1);
|
||||
if (php_stream_readdir(dirp, &entry)) {
|
||||
RETURN_STRINGL(entry.d_name, strlen(entry.d_name), 1);
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
@ -97,7 +97,8 @@ static php_stream_wrapper_ops ftp_stream_wops = {
|
||||
|
||||
php_stream_wrapper php_stream_ftp_wrapper = {
|
||||
&ftp_stream_wops,
|
||||
NULL
|
||||
NULL,
|
||||
1 /* is_url */
|
||||
};
|
||||
|
||||
|
||||
|
@ -367,7 +367,8 @@ static php_stream_wrapper_ops http_stream_wops = {
|
||||
|
||||
php_stream_wrapper php_stream_http_wrapper = {
|
||||
&http_stream_wops,
|
||||
NULL
|
||||
NULL,
|
||||
1 /* is_url */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -64,7 +64,8 @@ static php_stream_wrapper_ops php_stdio_wops = {
|
||||
|
||||
php_stream_wrapper php_stream_php_wrapper = {
|
||||
&php_stdio_wops,
|
||||
NULL
|
||||
NULL,
|
||||
0, /* is_url */
|
||||
};
|
||||
|
||||
|
||||
|
@ -181,9 +181,7 @@ PHP_MINIT_FUNCTION(zlib)
|
||||
#ifdef ZTS
|
||||
ts_allocate_id(&zlib_globals_id, sizeof(zend_zlib_globals), (ts_allocate_ctor) php_zlib_init_globals, NULL);
|
||||
#endif
|
||||
if(PG(allow_url_fopen)) {
|
||||
php_register_url_stream_wrapper("zlib", &php_stream_gzip_wrapper TSRMLS_CC);
|
||||
}
|
||||
php_register_url_stream_wrapper("zlib", &php_stream_gzip_wrapper TSRMLS_CC);
|
||||
|
||||
REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT);
|
||||
@ -216,8 +214,7 @@ PHP_RINIT_FUNCTION(zlib)
|
||||
*/
|
||||
PHP_MSHUTDOWN_FUNCTION(zlib)
|
||||
{
|
||||
if (PG(allow_url_fopen))
|
||||
php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
|
||||
php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
|
||||
|
||||
UNREGISTER_INI_ENTRIES();
|
||||
|
||||
|
@ -132,12 +132,15 @@ php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mod
|
||||
|
||||
static php_stream_wrapper_ops gzip_stream_wops = {
|
||||
php_stream_gzopen,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
php_stream_wrapper php_stream_gzip_wrapper = {
|
||||
&gzip_stream_wops,
|
||||
NULL
|
||||
NULL,
|
||||
0, /* is_url */
|
||||
};
|
||||
|
||||
|
||||
|
@ -171,10 +171,6 @@ typedef unsigned int socklen_t;
|
||||
char *strerror(int);
|
||||
#endif
|
||||
|
||||
#include "php_streams.h"
|
||||
#include "php_memory_streams.h"
|
||||
#include "fopen_wrappers.h"
|
||||
|
||||
#if (REGEX == 1 || REGEX == 0) && !defined(NO_REGEX_EXTRA_H)
|
||||
#include "regex/regex_extra.h"
|
||||
#endif
|
||||
@ -221,6 +217,11 @@ char *strerror(int);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "php_streams.h"
|
||||
#include "php_memory_streams.h"
|
||||
#include "fopen_wrappers.h"
|
||||
|
||||
|
||||
/* global variables */
|
||||
extern pval *data;
|
||||
#if !defined(PHP_WIN32)
|
||||
|
@ -104,6 +104,10 @@ typedef struct _php_stream_statbuf {
|
||||
/* extended info to go here some day */
|
||||
} php_stream_statbuf;
|
||||
|
||||
typedef struct _php_stream_dirent {
|
||||
char d_name[MAXPATHLEN];
|
||||
} php_stream_dirent;
|
||||
|
||||
#define PHP_STREAM_NOTIFIER_PROGRESS 1
|
||||
|
||||
typedef struct _php_stream_notifier {
|
||||
@ -128,6 +132,7 @@ typedef struct _php_stream_wrapper_options {
|
||||
* to go here some day */
|
||||
} php_stream_wrapper_options;
|
||||
|
||||
/* operations on streams that are file-handles */
|
||||
typedef struct _php_stream_ops {
|
||||
/* stdio like functions - these are mandatory! */
|
||||
size_t (*write)(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
|
||||
@ -146,22 +151,26 @@ typedef struct _php_stream_ops {
|
||||
|
||||
typedef struct _php_stream_wrapper_ops {
|
||||
/* open/create a wrapped stream */
|
||||
php_stream *(*opener)(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
php_stream *(*stream_opener)(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
|
||||
/* close/destroy a wrapped stream */
|
||||
int (*closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC);
|
||||
int (*stream_closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC);
|
||||
/* stat a wrapped stream */
|
||||
int (*stream_stat)(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
|
||||
/* stat a URL */
|
||||
int (*url_stat)(php_stream_wrapper *wrapper, php_stream_statbuf *ssb TSRMLS_DC);
|
||||
int (*url_stat)(php_stream_wrapper *wrapper, char *url, php_stream_statbuf *ssb TSRMLS_DC);
|
||||
/* open a "directory" stream */
|
||||
php_stream *(*dir_opener)(php_stream_wrapper *wrapper, char *filename, char *mode,
|
||||
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
|
||||
|
||||
} php_stream_wrapper_ops;
|
||||
|
||||
struct _php_stream_wrapper {
|
||||
php_stream_wrapper_ops *wops; /* operations the wrapper can perform */
|
||||
void *abstract; /* context for the wrapper */
|
||||
int is_url; /* so that PG(allow_url_fopen) can be respected */
|
||||
};
|
||||
|
||||
|
||||
struct _php_stream {
|
||||
php_stream_ops *ops;
|
||||
void *abstract; /* convenience pointer for abstraction */
|
||||
@ -255,12 +264,24 @@ PHPAPI int _php_stream_puts(php_stream *stream, char *buf TSRMLS_DC);
|
||||
PHPAPI int _php_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
|
||||
#define php_stream_stat(stream, ssb) _php_stream_stat((stream), (ssb) TSRMLS_CC)
|
||||
|
||||
PHPAPI int _php_stream_stat_path(char *path, php_stream_statbuf *ssb TSRMLS_DC);
|
||||
#define php_stream_stat_path(path, ssb) _php_stream_stat((path), (ssb) TSRMLS_CC)
|
||||
|
||||
PHPAPI php_stream *_php_stream_opendir(char *path, int options, php_stream_context *context STREAMS_DC TSRMLS_DC);
|
||||
#define php_stream_opendir(path, options, context) _php_stream_opendir((path), (options), (context) STREAMS_CC TSRMLS_CC)
|
||||
PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_dirent *ent TSRMLS_DC);
|
||||
#define php_stream_readdir(dirstream, dirent) _php_stream_readdir((dirstream), (dirent) TSRMLS_CC)
|
||||
#define php_stream_closedir(dirstream) php_stream_close((dirstream))
|
||||
#define php_stream_rewinddir(dirstream) php_stream_rewind((dirstream))
|
||||
|
||||
|
||||
/* copy up to maxlen bytes from src to dest. If maxlen is PHP_STREAM_COPY_ALL, copy until eof(src).
|
||||
* Uses mmap if the src is a plain file and at offset 0 */
|
||||
#define PHP_STREAM_COPY_ALL -1
|
||||
PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC);
|
||||
#define php_stream_copy_to_stream(src, dest, maxlen) _php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC)
|
||||
|
||||
|
||||
/* read all data from stream and put into a buffer. Caller must free buffer when done.
|
||||
* The copy will use mmap if available. */
|
||||
PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen,
|
||||
@ -364,7 +385,7 @@ PHPAPI FILE * _php_stream_open_wrapper_as_file(char * path, char * mode, int opt
|
||||
#define php_stream_open_wrapper_as_file(path, mode, options, opened_path) _php_stream_open_wrapper_as_file((path), (mode), (options), (opened_path) STREAMS_CC TSRMLS_CC)
|
||||
|
||||
/* for user-space streams */
|
||||
extern php_stream_ops php_stream_userspace_ops;
|
||||
PHPAPI extern php_stream_ops php_stream_userspace_ops;
|
||||
#define PHP_STREAM_IS_USERSPACE &php_stream_userspace_ops
|
||||
|
||||
PHPAPI void php_stream_context_free(php_stream_context *context);
|
||||
|
271
main/streams.c
271
main/streams.c
@ -45,6 +45,8 @@
|
||||
|
||||
#define STREAM_DEBUG 0
|
||||
|
||||
#define STREAM_WRAPPER_PLAIN_FILES ((php_stream_wrapper*)-1)
|
||||
|
||||
/* {{{ some macros to help track leaks */
|
||||
#if ZEND_DEBUG
|
||||
#define emalloc_rel_orig(size) \
|
||||
@ -134,8 +136,8 @@ fprintf(stderr, "stream_free: %s:%p in_free=%d opts=%08x\n", stream->ops->label,
|
||||
|
||||
if (close_options & PHP_STREAM_FREE_RELEASE_STREAM) {
|
||||
|
||||
if (stream->wrapper && stream->wrapper->wops && stream->wrapper->wops->closer) {
|
||||
stream->wrapper->wops->closer(stream->wrapper, stream TSRMLS_CC);
|
||||
if (stream->wrapper && stream->wrapper->wops && stream->wrapper->wops->stream_closer) {
|
||||
stream->wrapper->wops->stream_closer(stream->wrapper, stream TSRMLS_CC);
|
||||
stream->wrapper = NULL;
|
||||
}
|
||||
|
||||
@ -169,7 +171,7 @@ fprintf(stderr, "stream_free: %s:%p in_free=%d opts=%08x\n", stream->ops->label,
|
||||
/* {{{ generic stream operations */
|
||||
PHPAPI size_t _php_stream_read(php_stream *stream, char *buf, size_t size TSRMLS_DC)
|
||||
{
|
||||
return stream->ops->read(stream, buf, size TSRMLS_CC);
|
||||
return stream->ops->read == NULL ? 0 : stream->ops->read(stream, buf, size TSRMLS_CC);
|
||||
}
|
||||
|
||||
PHPAPI int _php_stream_eof(php_stream *stream TSRMLS_DC)
|
||||
@ -177,7 +179,7 @@ PHPAPI int _php_stream_eof(php_stream *stream TSRMLS_DC)
|
||||
/* we define our stream reading function so that it
|
||||
must return EOF when an EOF condition occurs, when
|
||||
working in unbuffered mode and called with these args */
|
||||
return stream->ops->read(stream, NULL, 0 TSRMLS_CC) == EOF ? 1 : 0;
|
||||
return stream->ops->read == NULL ? -1 : stream->ops->read(stream, NULL, 0 TSRMLS_CC) == EOF ? 1 : 0;
|
||||
}
|
||||
|
||||
PHPAPI int _php_stream_putc(php_stream *stream, int c TSRMLS_DC)
|
||||
@ -242,6 +244,8 @@ PHPAPI char *_php_stream_gets(php_stream *stream, char *buf, size_t maxlen TSRML
|
||||
|
||||
if (stream->ops->gets) {
|
||||
return stream->ops->gets(stream, buf, maxlen TSRMLS_CC);
|
||||
} else if (stream->ops->read == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
/* unbuffered fgets - poor performance ! */
|
||||
size_t n = 1;
|
||||
@ -273,7 +277,7 @@ PHPAPI int _php_stream_flush(php_stream *stream TSRMLS_DC)
|
||||
PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
|
||||
{
|
||||
assert(stream);
|
||||
if (buf == NULL || count == 0)
|
||||
if (buf == NULL || count == 0 || stream->ops->write == NULL)
|
||||
return 0;
|
||||
return stream->ops->write(stream, buf, count TSRMLS_CC);
|
||||
}
|
||||
@ -1037,45 +1041,145 @@ exit_success:
|
||||
/* {{{ wrapper init and registration */
|
||||
int php_init_stream_wrappers(TSRMLS_D)
|
||||
{
|
||||
if (PG(allow_url_fopen)) {
|
||||
return zend_hash_init(&url_stream_wrappers_hash, 0, NULL, NULL, 1);
|
||||
}
|
||||
return SUCCESS;
|
||||
return zend_hash_init(&url_stream_wrappers_hash, 0, NULL, NULL, 1);
|
||||
}
|
||||
|
||||
int php_shutdown_stream_wrappers(TSRMLS_D)
|
||||
{
|
||||
if (PG(allow_url_fopen)) {
|
||||
zend_hash_destroy(&url_stream_wrappers_hash);
|
||||
}
|
||||
zend_hash_destroy(&url_stream_wrappers_hash);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC)
|
||||
{
|
||||
if (PG(allow_url_fopen)) {
|
||||
return zend_hash_add(&url_stream_wrappers_hash, protocol, strlen(protocol), wrapper, sizeof(*wrapper), NULL);
|
||||
}
|
||||
return FAILURE;
|
||||
if (!PG(allow_url_fopen) && wrapper->is_url)
|
||||
return FAILURE;
|
||||
|
||||
return zend_hash_add(&url_stream_wrappers_hash, protocol, strlen(protocol), wrapper, sizeof(*wrapper), NULL);
|
||||
}
|
||||
|
||||
PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC)
|
||||
{
|
||||
if (PG(allow_url_fopen)) {
|
||||
return zend_hash_del(&url_stream_wrappers_hash, protocol, strlen(protocol));
|
||||
}
|
||||
return SUCCESS;
|
||||
return zend_hash_del(&url_stream_wrappers_hash, protocol, strlen(protocol));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_stream_open_url */
|
||||
static php_stream *php_stream_open_url(char *path, char *mode, int options,
|
||||
char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
|
||||
|
||||
static size_t php_plain_files_dirstream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
||||
{
|
||||
php_stream_wrapper *wrapper;
|
||||
DIR *dir = (DIR*)stream->abstract;
|
||||
/* avoid libc5 readdir problems */
|
||||
char entry[sizeof(struct dirent)+MAXPATHLEN];
|
||||
struct dirent *result = (struct dirent *)&entry;
|
||||
php_stream_dirent *ent = (php_stream_dirent*)buf;
|
||||
|
||||
/* avoid problems if someone mis-uses the stream */
|
||||
if (count != sizeof(php_stream_dirent))
|
||||
return 0;
|
||||
|
||||
if (php_readdir_r(dir, (struct dirent *)entry, &result) == 0 && result) {
|
||||
PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name));
|
||||
return sizeof(php_stream_dirent);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int php_plain_files_dirstream_close(php_stream *stream, int close_handle TSRMLS_DC)
|
||||
{
|
||||
return closedir((DIR *)stream->abstract);
|
||||
}
|
||||
|
||||
static int php_plain_files_dirstream_rewind(php_stream *stream, off_t offset, int whence TSRMLS_DC)
|
||||
{
|
||||
rewinddir((DIR *)stream->abstract);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static php_stream_ops php_plain_files_dirstream_ops = {
|
||||
NULL, php_plain_files_dirstream_read,
|
||||
php_plain_files_dirstream_close, NULL,
|
||||
"dir",
|
||||
php_plain_files_dirstream_rewind,
|
||||
NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char *path, char *mode,
|
||||
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
|
||||
{
|
||||
DIR *dir = NULL;
|
||||
php_stream *stream = NULL;
|
||||
|
||||
if (php_check_open_basedir(path TSRMLS_CC)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PG(safe_mode) &&(!php_checkuid(path, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir = VCWD_OPENDIR(path);
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
if (dir && dir->finished) {
|
||||
closedir(dir);
|
||||
dir = NULL;
|
||||
}
|
||||
#endif
|
||||
if (dir) {
|
||||
stream = php_stream_alloc(&php_plain_files_dirstream_ops, dir, 0, mode);
|
||||
if (stream == NULL)
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode,
|
||||
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
|
||||
{
|
||||
if ((options & USE_PATH) && PG(include_path) != NULL) {
|
||||
return php_stream_fopen_with_path_rel(path, mode, PG(include_path), opened_path);
|
||||
}
|
||||
|
||||
if ((options & ENFORCE_SAFE_MODE) && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM)))
|
||||
return NULL;
|
||||
|
||||
return php_stream_fopen_rel(path, mode, opened_path);
|
||||
}
|
||||
|
||||
static int php_plain_files_url_stater(php_stream_wrapper *wrapper, char *url, php_stream_statbuf *ssb TSRMLS_DC)
|
||||
{
|
||||
return VCWD_STAT(url, &ssb->sb);
|
||||
}
|
||||
|
||||
static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
|
||||
php_plain_files_stream_opener,
|
||||
NULL,
|
||||
NULL,
|
||||
php_plain_files_url_stater,
|
||||
php_plain_files_dir_opener
|
||||
};
|
||||
|
||||
static php_stream_wrapper php_plain_files_wrapper = {
|
||||
&php_plain_files_wrapper_ops,
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
|
||||
static php_stream_wrapper *locate_url_wrapper(char *path, char **path_for_open, int options TSRMLS_DC)
|
||||
{
|
||||
php_stream_wrapper *wrapper = NULL;
|
||||
const char *p, *protocol = NULL;
|
||||
int n = 0;
|
||||
|
||||
*path_for_open = path;
|
||||
|
||||
if (options & IGNORE_URL)
|
||||
return &php_plain_files_wrapper;
|
||||
|
||||
for (p = path; isalnum((int)*p); p++) {
|
||||
n++;
|
||||
}
|
||||
@ -1103,58 +1207,114 @@ static php_stream *php_stream_open_url(char *path, char *mode, int options,
|
||||
wrapper = NULL;
|
||||
protocol = NULL;
|
||||
}
|
||||
if (wrapper) {
|
||||
php_stream *stream = wrapper->wops->opener(wrapper, path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC);
|
||||
if (stream)
|
||||
stream->wrapper = wrapper;
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
if (!protocol || !strncasecmp(protocol, "file", n)) {
|
||||
if (protocol && path[n+1] == '/' && path[n+2] == '/') {
|
||||
zend_error(E_WARNING, "remote host file access not supported, %s", path);
|
||||
return NULL;
|
||||
}
|
||||
if (protocol)
|
||||
path += n + 1;
|
||||
|
||||
*path_for_open = path + n + 1;
|
||||
|
||||
/* fall back on regular file access */
|
||||
return php_stream_open_wrapper_rel(path, mode, (options & ~REPORT_ERRORS) | IGNORE_URL,
|
||||
opened_path);
|
||||
return &php_plain_files_wrapper;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
if (wrapper && wrapper->is_url && !PG(allow_url_fopen)) {
|
||||
zend_error(E_WARNING, "URL file-access is disabled in the server configuration");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
PHPAPI int _php_stream_stat_path(char *path, php_stream_statbuf *ssb TSRMLS_DC)
|
||||
{
|
||||
php_stream_wrapper *wrapper = NULL;
|
||||
char *path_to_open = path;
|
||||
|
||||
wrapper = locate_url_wrapper(path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC);
|
||||
if (wrapper && wrapper->wops->url_stat) {
|
||||
return wrapper->wops->url_stat(wrapper, path_to_open, ssb TSRMLS_CC);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* {{{ php_stream_opendir */
|
||||
PHPAPI php_stream *_php_stream_opendir(char *path, int options,
|
||||
php_stream_context *context STREAMS_DC TSRMLS_DC)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_stream_wrapper *wrapper = NULL;
|
||||
char *path_to_open;
|
||||
|
||||
if (!path || !*path)
|
||||
return NULL;
|
||||
|
||||
path_to_open = path;
|
||||
|
||||
wrapper = locate_url_wrapper(path, &path_to_open, options TSRMLS_CC);
|
||||
|
||||
if (wrapper && wrapper->wops->dir_opener) {
|
||||
stream = wrapper->wops->dir_opener(wrapper,
|
||||
path_to_open, "r", options, NULL,
|
||||
context STREAMS_REL_CC TSRMLS_CC);
|
||||
|
||||
if (stream)
|
||||
stream->wrapper = wrapper;
|
||||
}
|
||||
|
||||
if (stream == NULL && (options & REPORT_ERRORS)) {
|
||||
char *tmp = estrdup(path);
|
||||
char *msg;
|
||||
|
||||
if (wrapper)
|
||||
msg = strerror(errno);
|
||||
else
|
||||
msg = "no suitable wrapper could be found";
|
||||
|
||||
php_strip_url_passwd(tmp);
|
||||
zend_error(E_WARNING, "%s(\"%s\") - %s", get_active_function_name(TSRMLS_C), tmp, msg);
|
||||
efree(tmp);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_dirent *ent TSRMLS_DC)
|
||||
{
|
||||
if (sizeof(php_stream_dirent) == php_stream_read(dirstream, (char*)ent, sizeof(php_stream_dirent)))
|
||||
return ent;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* {{{ php_stream_open_wrapper_ex */
|
||||
PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options,
|
||||
char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
|
||||
php_stream_wrapper *wrapper = NULL;
|
||||
char *path_to_open;
|
||||
|
||||
if (opened_path)
|
||||
*opened_path = NULL;
|
||||
|
||||
if (!path || !*path)
|
||||
return NULL;
|
||||
|
||||
if (PG(allow_url_fopen) && !(options & IGNORE_URL)) {
|
||||
stream = php_stream_open_url(path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC);
|
||||
goto out;
|
||||
path_to_open = path;
|
||||
|
||||
wrapper = locate_url_wrapper(path, &path_to_open, options TSRMLS_CC);
|
||||
|
||||
if (wrapper) {
|
||||
stream = wrapper->wops->stream_opener(wrapper,
|
||||
path_to_open, mode, options,
|
||||
opened_path, context STREAMS_REL_CC TSRMLS_CC);
|
||||
if (stream)
|
||||
stream->wrapper = wrapper;
|
||||
}
|
||||
|
||||
if ((options & USE_PATH) && PG(include_path) != NULL) {
|
||||
stream = php_stream_fopen_with_path_rel(path, mode, PG(include_path), opened_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((options & ENFORCE_SAFE_MODE) && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM)))
|
||||
return NULL;
|
||||
|
||||
stream = php_stream_fopen_rel(path, mode, opened_path);
|
||||
out:
|
||||
|
||||
if (stream != NULL && (options & STREAM_MUST_SEEK)) {
|
||||
php_stream *newstream;
|
||||
|
||||
@ -1179,8 +1339,15 @@ out:
|
||||
}
|
||||
if (stream == NULL && (options & REPORT_ERRORS)) {
|
||||
char *tmp = estrdup(path);
|
||||
char *msg;
|
||||
|
||||
if (wrapper)
|
||||
msg = strerror(errno);
|
||||
else
|
||||
msg = "no suitable wrapper could be found";
|
||||
|
||||
php_strip_url_passwd(tmp);
|
||||
zend_error(E_WARNING, "%s(\"%s\") - %s", get_active_function_name(TSRMLS_C), tmp, strerror(errno));
|
||||
zend_error(E_WARNING, "%s(\"%s\") - %s", get_active_function_name(TSRMLS_C), tmp, msg);
|
||||
efree(tmp);
|
||||
}
|
||||
return stream;
|
||||
|
@ -186,5 +186,6 @@ function cmdHelp($command)
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
// vim600:syn=php
|
||||
|
||||
?>
|
||||
|
@ -1,6 +1,5 @@
|
||||
#!@prefix@/bin/php -Cq
|
||||
<?php // -*- PHP -*-
|
||||
|
||||
main($argc, $argv, $_ENV);
|
||||
|
||||
// {{{ main()
|
||||
@ -222,4 +221,5 @@ function cdata_handler($xp, $data)
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
// vim600:syn=php
|
||||
?>
|
||||
|
Loading…
Reference in New Issue
Block a user