From: Wez Furlong Date: Sun, 11 Aug 2002 10:53:10 +0000 (+0000) Subject: Introduce an error stack for wrappers, to help prevent multiple errors X-Git-Tag: php-4.3.0dev_zend2_alpha3~145 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5a21ab42cb0a7b4d0bc5661a6ae7d6ac085ed800;p=php Introduce an error stack for wrappers, to help prevent multiple errors and warnings (some of which are bogus) when there are problems opening streams. Implement sanity check on the mode used to open ftp and http connections. This fixes Bug 12004. --- diff --git a/README.STREAMS b/README.STREAMS index 870888a6bc..91a9245c0a 100644 --- a/README.STREAMS +++ b/README.STREAMS @@ -2,6 +2,10 @@ An Overview of the PHP Streams abstraction ========================================== $Id$ +WARNING: some prototypes in this file are out of date. +The information contained here is being integrated into +the php manual - stay tuned... + Please send comments to: Wez Furlong Why Streams? diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 9bbdbedee4..b5d3ccdc16 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -115,6 +115,11 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch int i; char *tpath, *ttpath; size_t file_size = 0; + + if (strchr(mode, 'a') || strchr(mode, '+')) { + php_stream_wrapper_log_error(wrapper, options, "FTP does not support simultaneous read/write connections."); + return NULL; + } resource = php_url_parse((char *) path); if (resource == NULL || resource->path == NULL) @@ -314,7 +319,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch php_stream_close(stream); } if (tmp_line[0] != '\0') - zend_error(E_WARNING, "FTP server reports %s", tmp_line); + php_stream_wrapper_log_error(wrapper, options, "FTP server reports %s", tmp_line); return NULL; } /* }}} */ diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 3a2aa8e57e..c06dc6210c 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -86,11 +86,16 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch char tmp_line[128]; size_t chunk_size = 0, file_size = 0; + if (strchr(mode, 'a') || strchr(mode, '+') || strchr(mode, 'w')) { + php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper does not writeable connections."); + return NULL; + } + resource = php_url_parse(path); if (resource == NULL) return NULL; - use_ssl = resource->scheme && resource->scheme[4] == 's'; + use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's'; /* choose default ports */ if (use_ssl && resource->port == 0) @@ -113,9 +118,7 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch #if HAVE_OPENSSL_EXT if (use_ssl) { if (php_stream_sock_ssl_activate(stream, 1) == FAILURE) { - if (options & REPORT_ERRORS) { - zend_error(E_WARNING, "Unable to activate SSL mode"); - } + php_stream_wrapper_log_error(wrapper, options, "Unable to activate SSL mode"); php_stream_close(stream); stream = NULL; goto out; @@ -323,8 +326,7 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch FREE_ZVAL(stream->wrapperdata); } } else { - if (options & REPORT_ERRORS) - zend_error(E_WARNING, "HTTP request failed! %s", tmp_line); + php_stream_wrapper_log_error(wrapper, options, "HTTP request failed! %s", tmp_line); } } out: diff --git a/main/php_streams.h b/main/php_streams.h index d50b8135c4..160d733931 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -169,8 +169,15 @@ 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 */ + + /* support for wrappers to return (multiple) error messages to the stream opener */ + int err_count; + char **err_stack; }; +/* pushes an error message onto the stack for a wrapper instance */ +PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options TSRMLS_DC, const char *fmt, ...); + struct _php_stream { php_stream_ops *ops; void *abstract; /* convenience pointer for abstraction */ diff --git a/main/streams.c b/main/streams.c index 318c815bcc..931e331457 100755 --- a/main/streams.c +++ b/main/streams.c @@ -1286,6 +1286,26 @@ PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_ return NULL; } +PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options TSRMLS_DC, const char *fmt, ...) +{ + va_list args; + char *buffer = NULL; + + va_start(args, fmt); + vspprintf(&buffer, 0, fmt, args); + va_end(args); + + if (options & REPORT_ERRORS || wrapper == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, buffer); + efree(buffer); + } else { + /* append to stack */ + wrapper->err_stack = erealloc(wrapper->err_stack, (wrapper->err_count + 1) * sizeof(char *)); + if (wrapper->err_stack) + wrapper->err_stack[wrapper->err_count++] = buffer; + } +} + /* {{{ 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) @@ -1305,8 +1325,13 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio wrapper = locate_url_wrapper(path, &path_to_open, options TSRMLS_CC); if (wrapper) { + + /* prepare error stack */ + wrapper->err_count = 0; + wrapper->err_stack = NULL; + stream = wrapper->wops->stream_opener(wrapper, - path_to_open, mode, options, + path_to_open, mode, options ^ REPORT_ERRORS, opened_path, context STREAMS_REL_CC TSRMLS_CC); if (stream) stream->wrapper = wrapper; @@ -1326,8 +1351,8 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio if (options & REPORT_ERRORS) { char *tmp = estrdup(path); php_strip_url_passwd(tmp); - zend_error(E_WARNING, "%s(\"%s\") - could not make seekable - %s", - get_active_function_name(TSRMLS_C), tmp, strerror(errno)); + php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "could not make seekable - %s", + tmp, strerror(errno)); efree(tmp); options ^= REPORT_ERRORS; @@ -1338,15 +1363,55 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio char *tmp = estrdup(path); char *msg; - if (wrapper) - msg = strerror(errno); - else + if (wrapper) { + if (wrapper->err_count) { + int i; + size_t l; + int brlen; + char *br; + + if (PG(html_errors)) { + brlen = 7; + br = "
\n"; + } else { + brlen = 1; + br = "\n"; + } + + for (i = 0, l = 0; i < wrapper->err_count; i++) { + l += strlen(wrapper->err_stack[i]); + if (i < wrapper->err_count - 1) + l += brlen; + } + msg = emalloc(l + 1); + msg[0] = '\0'; + for (i = 0; i < wrapper->err_count; i++) { + strcat(msg, wrapper->err_stack[i]); + if (i < wrapper->err_count - 1) + strcat(msg, br); + } + + } else { + 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); + php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "failed to create stream: %s", msg); efree(tmp); } + if (wrapper) { + /* tidy up the error stack */ + int i; + + for (i = 0; i < wrapper->err_count; i++) + efree(wrapper->err_stack[i]); + if (wrapper->err_stack) + efree(wrapper->err_stack); + wrapper->err_stack = NULL; + } return stream; } /* }}} */