php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #73882
Patch patch.txt revision 2017-01-06 15:55 UTC by laurentconstantin at free dot fr

Patch patch.txt for HTTP related Bug #73882

Patch version 2017-01-06 15:55 UTC

Return to Bug #73882 | Download this patch
Patch Revisions:

Developer: laurentconstantin@free.fr

--- ext/standard/http_fopen_wrapper.c.ORI	2016-12-08 07:29:33.000000000 +0100
+++ ext/standard/http_fopen_wrapper.c	2017-01-06 16:27:49.882410127 +0100
@@ -109,6 +109,65 @@ static inline void strip_header(char *he
 	}
 }
 
+/* Check if the header_line matches the header_name followed by ':' and followed by any spaces.
+   Return value:
+    - zero when the line is not recognized/malformed.
+    - one when the line matches. The offset to the begining of the value is stored in *poffset.
+   For example:
+     match_header_and_indicate_value_offset("Head: value", "Test", &of) returns 0 (no match).
+     match_header_and_indicate_value_offset("Head:", "Head", &of) returns 0 (malformed).
+     match_header_and_indicate_value_offset("Head: value", "Head", &of) returns 1, of=6 (offset 4+1+1).
+     match_header_and_indicate_value_offset("Head:  value", "Head", &of) returns 1, of=7 (offset 4+1+2).
+*/
+static inline int match_header_and_indicate_value_offset(const char *header_line, const char *header_name, int *poffset) {
+    int header_name_length;
+    int offset;
+
+    /* Match the header name. */
+    header_name_length = strlen(header_name);
+    if (strncasecmp(header_line, header_name, header_name_length)) {
+        /* No match. */
+        return(0);
+    }
+    offset = header_name_length;
+
+    /* Match the ':', or a premature end of string. */
+    if (header_line[offset] != ':') {
+        /* No match or malformed. */
+        return(0);
+    }
+    offset++;
+
+    /* Match any space. */
+    while (header_line[offset] == ' ') {
+        offset++;
+    }
+    if (header_line[offset] == '\0') {
+        /* Premature end. */
+        return(0);
+    }
+
+    /* Set the offset of the header value. */
+    *poffset = offset;
+    return(1 /*success*/);
+}
+
+/* Check if the header_line matches the header_name followed by ': *' and wanted_value.
+   Return value:
+    - zero when the line is not recognized/malformed.
+    - one when the line matches.
+*/
+static inline int match_header_and_value(const char *header_line, const char *header_name, const char *wanted_value) {
+    int offset_of_matched_header;
+
+    if (! match_header_and_indicate_value_offset(header_line, header_name, &offset_of_matched_header)) {
+        /* No match or malformed. */
+        return(0);
+    }
+
+    return(! strcmp(header_line + offset_of_matched_header, wanted_value));
+}
+
 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) /* {{{ */
@@ -141,6 +200,7 @@ php_stream *php_stream_url_wrap_http_ex(
 	int follow_location = 1;
 	php_stream_filter *transfer_encoding = NULL;
 	int response_code;
+	int offset_of_matched_header;
 
 	tmp_line[0] = '\0';
 
@@ -776,7 +836,7 @@ finish:
 			http_header_line_length = e - http_header_line + 1;
 			http_header_line[http_header_line_length] = '\0';
 
-			if (!strncasecmp(http_header_line, "Location: ", 10)) {
+			if (match_header_and_indicate_value_offset(http_header_line, "Location", &offset_of_matched_header)) {
 				if (context && php_stream_context_get_option(context, "http", "follow_location", &tmpzval) == SUCCESS) {
 					SEPARATE_ZVAL(tmpzval);
 					convert_to_long_ex(tmpzval);
@@ -788,13 +848,13 @@ finish:
 					RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */
 					follow_location = 0;
 				}
-				strlcpy(location, http_header_line + 10, sizeof(location));
-			} else if (!strncasecmp(http_header_line, "Content-Type: ", 14)) {
-				php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + 14, 0);
-			} else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) {
-				file_size = atoi(http_header_line + 16);
+				strlcpy(location, http_header_line + offset_of_matched_header, sizeof(location));
+			} else if (match_header_and_indicate_value_offset(http_header_line, "Content-Type", &offset_of_matched_header)) {
+				php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + offset_of_matched_header, 0);
+			} else if (match_header_and_indicate_value_offset(http_header_line, "Content-Length", &offset_of_matched_header)) {
+				file_size = atoi(http_header_line + offset_of_matched_header);
 				php_stream_notify_file_size(context, file_size, http_header_line, 0);
-			} else if (!strncasecmp(http_header_line, "Transfer-Encoding: chunked", sizeof("Transfer-Encoding: chunked"))) {
+			} else if (match_header_and_value(http_header_line, "Transfer-Encoding", "chunked")) {
 
 				/* create filter to decode response body */
 				if (!(options & STREAM_ONLY_GET_HEADERS)) {
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 19:01:30 2024 UTC