Skip to content

Commit

Permalink
Fixed bug #61548
Browse files Browse the repository at this point in the history
  • Loading branch information
m6w6 committed Oct 1, 2013
1 parent 679bf47 commit 18b04b4
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 30 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
61 changes: 31 additions & 30 deletions ext/standard/http_fopen_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -425,40 +449,17 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
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) == ' ')) {
Expand Down
118 changes: 118 additions & 0 deletions ext/standard/tests/http/bug61548.phpt
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 18b04b4

Please sign in to comment.