Skip to content

Commit 5a21ab4

Browse files
committed
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.
1 parent 1861f1b commit 5a21ab4

File tree

5 files changed

+97
-14
lines changed

5 files changed

+97
-14
lines changed

README.STREAMS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ An Overview of the PHP Streams abstraction
22
==========================================
33
$Id$
44

5+
WARNING: some prototypes in this file are out of date.
6+
The information contained here is being integrated into
7+
the php manual - stay tuned...
8+
59
Please send comments to: Wez Furlong <wez@thebrainroom.com>
610

711
Why Streams?

ext/standard/ftp_fopen_wrapper.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
115115
int i;
116116
char *tpath, *ttpath;
117117
size_t file_size = 0;
118+
119+
if (strchr(mode, 'a') || strchr(mode, '+')) {
120+
php_stream_wrapper_log_error(wrapper, options, "FTP does not support simultaneous read/write connections.");
121+
return NULL;
122+
}
118123

119124
resource = php_url_parse((char *) path);
120125
if (resource == NULL || resource->path == NULL)
@@ -314,7 +319,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
314319
php_stream_close(stream);
315320
}
316321
if (tmp_line[0] != '\0')
317-
zend_error(E_WARNING, "FTP server reports %s", tmp_line);
322+
php_stream_wrapper_log_error(wrapper, options, "FTP server reports %s", tmp_line);
318323
return NULL;
319324
}
320325
/* }}} */

ext/standard/http_fopen_wrapper.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,16 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
8686
char tmp_line[128];
8787
size_t chunk_size = 0, file_size = 0;
8888

89+
if (strchr(mode, 'a') || strchr(mode, '+') || strchr(mode, 'w')) {
90+
php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper does not writeable connections.");
91+
return NULL;
92+
}
93+
8994
resource = php_url_parse(path);
9095
if (resource == NULL)
9196
return NULL;
9297

93-
use_ssl = resource->scheme && resource->scheme[4] == 's';
98+
use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's';
9499

95100
/* choose default ports */
96101
if (use_ssl && resource->port == 0)
@@ -113,9 +118,7 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
113118
#if HAVE_OPENSSL_EXT
114119
if (use_ssl) {
115120
if (php_stream_sock_ssl_activate(stream, 1) == FAILURE) {
116-
if (options & REPORT_ERRORS) {
117-
zend_error(E_WARNING, "Unable to activate SSL mode");
118-
}
121+
php_stream_wrapper_log_error(wrapper, options, "Unable to activate SSL mode");
119122
php_stream_close(stream);
120123
stream = NULL;
121124
goto out;
@@ -323,8 +326,7 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
323326
FREE_ZVAL(stream->wrapperdata);
324327
}
325328
} else {
326-
if (options & REPORT_ERRORS)
327-
zend_error(E_WARNING, "HTTP request failed! %s", tmp_line);
329+
php_stream_wrapper_log_error(wrapper, options, "HTTP request failed! %s", tmp_line);
328330
}
329331
}
330332
out:

main/php_streams.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,15 @@ struct _php_stream_wrapper {
169169
php_stream_wrapper_ops *wops; /* operations the wrapper can perform */
170170
void *abstract; /* context for the wrapper */
171171
int is_url; /* so that PG(allow_url_fopen) can be respected */
172+
173+
/* support for wrappers to return (multiple) error messages to the stream opener */
174+
int err_count;
175+
char **err_stack;
172176
};
173177

178+
/* pushes an error message onto the stack for a wrapper instance */
179+
PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options TSRMLS_DC, const char *fmt, ...);
180+
174181
struct _php_stream {
175182
php_stream_ops *ops;
176183
void *abstract; /* convenience pointer for abstraction */

main/streams.c

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,26 @@ PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_
12861286
return NULL;
12871287
}
12881288

1289+
PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options TSRMLS_DC, const char *fmt, ...)
1290+
{
1291+
va_list args;
1292+
char *buffer = NULL;
1293+
1294+
va_start(args, fmt);
1295+
vspprintf(&buffer, 0, fmt, args);
1296+
va_end(args);
1297+
1298+
if (options & REPORT_ERRORS || wrapper == NULL) {
1299+
php_error_docref(NULL TSRMLS_CC, E_WARNING, buffer);
1300+
efree(buffer);
1301+
} else {
1302+
/* append to stack */
1303+
wrapper->err_stack = erealloc(wrapper->err_stack, (wrapper->err_count + 1) * sizeof(char *));
1304+
if (wrapper->err_stack)
1305+
wrapper->err_stack[wrapper->err_count++] = buffer;
1306+
}
1307+
}
1308+
12891309
/* {{{ php_stream_open_wrapper_ex */
12901310
PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options,
12911311
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
13051325
wrapper = locate_url_wrapper(path, &path_to_open, options TSRMLS_CC);
13061326

13071327
if (wrapper) {
1328+
1329+
/* prepare error stack */
1330+
wrapper->err_count = 0;
1331+
wrapper->err_stack = NULL;
1332+
13081333
stream = wrapper->wops->stream_opener(wrapper,
1309-
path_to_open, mode, options,
1334+
path_to_open, mode, options ^ REPORT_ERRORS,
13101335
opened_path, context STREAMS_REL_CC TSRMLS_CC);
13111336
if (stream)
13121337
stream->wrapper = wrapper;
@@ -1326,8 +1351,8 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio
13261351
if (options & REPORT_ERRORS) {
13271352
char *tmp = estrdup(path);
13281353
php_strip_url_passwd(tmp);
1329-
zend_error(E_WARNING, "%s(\"%s\") - could not make seekable - %s",
1330-
get_active_function_name(TSRMLS_C), tmp, strerror(errno));
1354+
php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "could not make seekable - %s",
1355+
tmp, strerror(errno));
13311356
efree(tmp);
13321357

13331358
options ^= REPORT_ERRORS;
@@ -1338,15 +1363,55 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio
13381363
char *tmp = estrdup(path);
13391364
char *msg;
13401365

1341-
if (wrapper)
1342-
msg = strerror(errno);
1343-
else
1366+
if (wrapper) {
1367+
if (wrapper->err_count) {
1368+
int i;
1369+
size_t l;
1370+
int brlen;
1371+
char *br;
1372+
1373+
if (PG(html_errors)) {
1374+
brlen = 7;
1375+
br = "<br />\n";
1376+
} else {
1377+
brlen = 1;
1378+
br = "\n";
1379+
}
1380+
1381+
for (i = 0, l = 0; i < wrapper->err_count; i++) {
1382+
l += strlen(wrapper->err_stack[i]);
1383+
if (i < wrapper->err_count - 1)
1384+
l += brlen;
1385+
}
1386+
msg = emalloc(l + 1);
1387+
msg[0] = '\0';
1388+
for (i = 0; i < wrapper->err_count; i++) {
1389+
strcat(msg, wrapper->err_stack[i]);
1390+
if (i < wrapper->err_count - 1)
1391+
strcat(msg, br);
1392+
}
1393+
1394+
} else {
1395+
msg = strerror(errno);
1396+
}
1397+
} else {
13441398
msg = "no suitable wrapper could be found";
1399+
}
13451400

13461401
php_strip_url_passwd(tmp);
1347-
zend_error(E_WARNING, "%s(\"%s\") - %s", get_active_function_name(TSRMLS_C), tmp, msg);
1402+
php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "failed to create stream: %s", msg);
13481403
efree(tmp);
13491404
}
1405+
if (wrapper) {
1406+
/* tidy up the error stack */
1407+
int i;
1408+
1409+
for (i = 0; i < wrapper->err_count; i++)
1410+
efree(wrapper->err_stack[i]);
1411+
if (wrapper->err_stack)
1412+
efree(wrapper->err_stack);
1413+
wrapper->err_stack = NULL;
1414+
}
13501415
return stream;
13511416
}
13521417
/* }}} */

0 commit comments

Comments
 (0)