Commit:    18b04b480ebc41841b2004cc11797eda40fb3958
Author:    Michael Wallner <m...@php.net>         Tue, 1 Oct 2013 11:07:55 +0200
Parents:   679bf479b63356f977c0bb04b5650b86cd4e15a1
Branches:  PHP-5.4 PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=18b04b480ebc41841b2004cc11797eda40fb3958

Log:
Fixed bug #61548

Bugs:
https://bugs.php.net/61548

Changed paths:
  M  NEWS
  M  ext/standard/http_fopen_wrapper.c
  A  ext/standard/tests/http/bug61548.phpt


Diff:
diff --git a/NEWS b/NEWS
index 4dc7ef7..9bb6032 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,10 @@ PHP                                                          
              NEWS
   . Fixed bug #65721 (configure script broken in 5.5.4 and 5.4.20 when enabling
     imap). (ryotakatsuki at gmail dot com)
 
+- Standard:
+  . Fixed bug #61548 (content-type must appear at the end of headers for 201 
+    Location to work in http). (Mike)
+
 19 Sep 2013, PHP 5.4.20
 
 - Core:
diff --git a/ext/standard/http_fopen_wrapper.c 
b/ext/standard/http_fopen_wrapper.c
index b8676bb..4605e74 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -84,6 +84,30 @@
 #define HTTP_WRAPPER_HEADER_INIT    1
 #define HTTP_WRAPPER_REDIRECTED     2
 
+static inline void strip_header(char *header_bag, char *lc_header_bag,
+               const char *lc_header_name)
+{
+       char *lc_header_start = strstr(lc_header_bag, lc_header_name);
+       char *header_start = header_bag + (lc_header_start - lc_header_bag);
+
+       if (lc_header_start
+       && (lc_header_start == lc_header_bag || *(lc_header_start-1) == '\n')
+       ) {
+               char *lc_eol = strchr(lc_header_start, '\n');
+               char *eol = header_start + (lc_eol - lc_header_start);
+
+               if (lc_eol) {
+                       size_t eollen = strlen(lc_eol);
+
+                       memmove(lc_header_start, lc_eol+1, eollen);
+                       memmove(header_start, eol+1, eollen);
+               } else {
+                       *lc_header_start = '\0';
+                       *header_start = '\0';
+               }
+       }
+}
+
 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 *stream = NULL;
@@ -425,40 +449,17 @@ finish:
                if (tmp && strlen(tmp) > 0) {
                        char *s;
 
-                       if (!header_init) { /* Remove post headers for 
redirects */
-                               int l = strlen(tmp);
-                               char *s2, *tmp_c = estrdup(tmp);
-                               
-                               php_strtolower(tmp_c, l);
-                               if ((s = strstr(tmp_c, "content-length:"))) {
-                                       if ((s2 = memchr(s, '\n', tmp_c + l - 
s))) {
-                                               int b = tmp_c + l - 1 - s2;
-                                               memmove(tmp, tmp + (s2 + 1 - 
tmp_c), b);
-                                               memmove(tmp_c, s2 + 1, b);
-                                               
-                                       } else {
-                                               tmp[s - tmp_c] = *s = '\0';
-                                       }
-                                       l = strlen(tmp_c);
-                               }
-                               if ((s = strstr(tmp_c, "content-type:"))) {
-                                       if ((s2 = memchr(s, '\n', tmp_c + l - 
s))) {
-                                               memmove(tmp, tmp + (s2 + 1 - 
tmp_c), tmp_c + l - 1 - s2);
-                                       } else {
-                                               tmp[s - tmp_c] = '\0';
-                                       }
-                               }
-
-                               efree(tmp_c);
-                               tmp_c = php_trim(tmp, strlen(tmp), NULL, 0, 
NULL, 3 TSRMLS_CC);
-                               efree(tmp);
-                               tmp = tmp_c;
-                       }
-
                        user_headers = estrdup(tmp);
 
                        /* Make lowercase for easy comparison against 
'standard' headers */
                        php_strtolower(tmp, strlen(tmp));
+
+                       if (!header_init) {
+                               /* strip POST headers on redirect */
+                               strip_header(user_headers, tmp, 
"content-length:");
+                               strip_header(user_headers, tmp, 
"content-type:");
+                       }
+
                        if ((s = strstr(tmp, "user-agent:")) && 
                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
                                         *(s-1) == '\t' || *(s-1) == ' ')) {
diff --git a/ext/standard/tests/http/bug61548.phpt 
b/ext/standard/tests/http/bug61548.phpt
new file mode 100644
index 0000000..138b15a
--- /dev/null
+++ b/ext/standard/tests/http/bug61548.phpt
@@ -0,0 +1,118 @@
+--TEST--
+Bug #61548 (content-type must appear at the end of headers)
+--INI--
+allow_url_fopen=1
+--SKIPIF--
+<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
+--FILE--
+<?php
+require 'server.inc';
+
+function do_test($header) {
+    $options = [
+        'http' => [
+                       'method' => 'POST',
+                       'header' => $header,
+            'follow_location' => true,
+        ],
+    ];
+
+    $ctx = stream_context_create($options);
+
+    $responses = [
+               "data://text/plain,HTTP/1.1 201\r\nLocation: /foo\r\n\r\n",
+               "data://text/plain,HTTP/1.1 200\r\nConnection: close\r\n\r\n",
+       ];
+    $pid = http_server('tcp://127.0.0.1:12342', $responses, $output);
+
+    $fd = fopen('http://127.0.0.1:12342/', 'rb', false, $ctx);
+    fseek($output, 0, SEEK_SET);
+    echo stream_get_contents($output);
+
+    http_server_kill($pid);
+}
+
+do_test("First:1\nSecond:2\nContent-type: text/plain");
+do_test("First:1\nSecond:2\nContent-type: text/plain\n");
+do_test("First:1\nSecond:2\nContent-type: text/plain\nThird:");
+do_test("First:1\nContent-type:text/plain\nSecond:2");
+do_test("First:1\nContent-type:text/plain\nSecond:2\n");
+do_test("First:1\nContent-type:text/plain\nSecond:2\nThird:");
+
+?>
+Done
+--EXPECT--
+POST / HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+Content-type: text/plain
+
+GET /foo HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+
+
+POST / HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+Content-type: text/plain
+
+GET /foo HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+
+
+POST / HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+Content-type: text/plain
+Third:
+
+GET /foo HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+Third:
+
+POST / HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Content-type:text/plain
+Second:2
+
+GET /foo HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+
+POST / HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Content-type:text/plain
+Second:2
+
+GET /foo HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+
+POST / HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Content-type:text/plain
+Second:2
+Third:
+
+GET /foo HTTP/1.0
+Host: 127.0.0.1:12342
+First:1
+Second:2
+Third:
+
+Done
+


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to