summaryrefslogtreecommitdiff
path: root/ext/standard/http_fopen_wrapper.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/http_fopen_wrapper.c')
-rw-r--r--ext/standard/http_fopen_wrapper.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index b8676bbba4..8762fa4849 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -80,11 +80,13 @@
#define HTTP_HEADER_FROM 8
#define HTTP_HEADER_CONTENT_LENGTH 16
#define HTTP_HEADER_TYPE 32
+#define HTTP_HEADER_CONNECTION 64
#define HTTP_WRAPPER_HEADER_INIT 1
#define HTTP_WRAPPER_REDIRECTED 2
-php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context, int redirect_max, int flags STREAMS_DC TSRMLS_DC) /* {{{ */
+php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, const char *path, const char *mode, int options,
+ char **opened_path, php_stream_context *context, int redirect_max, int flags STREAMS_DC TSRMLS_DC) /* {{{ */
{
php_stream *stream = NULL;
php_url *resource = NULL;
@@ -385,8 +387,6 @@ finish:
strlcat(scratch, " HTTP/", scratch_len);
strlcat(scratch, protocol_version, scratch_len);
strlcat(scratch, "\r\n", scratch_len);
- efree(protocol_version);
- protocol_version = NULL;
} else {
strlcat(scratch, " HTTP/1.0\r\n", scratch_len);
}
@@ -489,6 +489,11 @@ finish:
*(s-1) == '\t' || *(s-1) == ' ')) {
have_header |= HTTP_HEADER_TYPE;
}
+ if ((s = strstr(tmp, "connection:")) &&
+ (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' ||
+ *(s-1) == '\t' || *(s-1) == ' ')) {
+ have_header |= HTTP_HEADER_CONNECTION;
+ }
/* remove Proxy-Authorization header */
if (use_proxy && use_ssl && (s = strstr(tmp, "proxy-authorization:")) &&
(s == tmp || *(s-1) == '\r' || *(s-1) == '\n' ||
@@ -562,6 +567,16 @@ finish:
}
}
+ /* Send a Connection: close header when using HTTP 1.1 or later to avoid
+ * hanging when the server interprets the RFC literally and establishes a
+ * keep-alive connection, unless the user specifically requests something
+ * else by specifying a Connection header in the context options. */
+ if (protocol_version &&
+ ((have_header & HTTP_HEADER_CONNECTION) == 0) &&
+ (strncmp(protocol_version, "1.0", MIN(protocol_version_len, 3)) > 0)) {
+ php_stream_write_string(stream, "Connection: close\r\n");
+ }
+
if (context &&
php_stream_context_get_option(context, "http", "user_agent", &ua_zval) == SUCCESS &&
Z_TYPE_PP(ua_zval) == IS_STRING) {
@@ -921,7 +936,7 @@ out:
}
/* }}} */
-php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
+php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
{
return php_stream_url_wrap_http_ex(wrapper, path, mode, options, opened_path, context, PHP_URL_REDIRECT_MAX, HTTP_WRAPPER_HEADER_INIT STREAMS_CC TSRMLS_CC);
}