summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhaavardm <haavardm@opera.com>2015-06-11 01:19:54 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-11 08:20:39 +0000
commit8e7ed88c4187c496961b87fdcd1a2c307c39fe1b (patch)
treec5f52bbcb033ca27404ddb067868e7112b55790b
parent8ca72d1504c20967ec2693ec453a5f13ae0926cf (diff)
downloadchromium_src-8e7ed88c4187c496961b87fdcd1a2c307c39fe1b.zip
chromium_src-8e7ed88c4187c496961b87fdcd1a2c307c39fe1b.tar.gz
chromium_src-8e7ed88c4187c496961b87fdcd1a2c307c39fe1b.tar.bz2
Use net's response header parser for parsing multipart headers.
BUG=493379 Review URL: https://codereview.chromium.org/1166953002 Cr-Commit-Position: refs/heads/master@{#333909}
-rw-r--r--content/child/multipart_response_delegate.cc70
-rw-r--r--net/http/http_util.cc24
-rw-r--r--net/http/http_util.h11
-rw-r--r--net/http/http_util_unittest.cc40
4 files changed, 96 insertions, 49 deletions
diff --git a/content/child/multipart_response_delegate.cc b/content/child/multipart_response_delegate.cc
index c29fe55..ff8bd58 100644
--- a/content/child/multipart_response_delegate.cc
+++ b/content/child/multipart_response_delegate.cc
@@ -5,9 +5,11 @@
#include "content/child/multipart_response_delegate.h"
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "net/base/net_util.h"
+#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -209,59 +211,47 @@ int MultipartResponseDelegate::PushOverLine(const std::string& data,
}
bool MultipartResponseDelegate::ParseHeaders() {
- int line_feed_increment = 1;
-
- // Grab the headers being liberal about line endings.
- size_t line_start_pos = 0;
- size_t line_end_pos = data_.find('\n');
- while (line_end_pos != std::string::npos) {
- // Handle CRLF
- if (line_end_pos > line_start_pos && data_[line_end_pos - 1] == '\r') {
- line_feed_increment = 2;
- --line_end_pos;
- } else {
- line_feed_increment = 1;
- }
- if (line_start_pos == line_end_pos) {
- // A blank line, end of headers
- line_end_pos += line_feed_increment;
- break;
- }
- // Find the next header line.
- line_start_pos = line_end_pos + line_feed_increment;
- line_end_pos = data_.find('\n', line_start_pos);
- }
- // Truncated in the middle of a header, stop parsing.
- if (line_end_pos == std::string::npos)
+ int headers_end_pos = net::HttpUtil::LocateEndOfAdditionalHeaders(
+ data_.c_str(), data_.size(), 0);
+
+ if (headers_end_pos < 0)
return false;
- // Eat headers
- std::string headers("\n");
- headers.append(data_, 0, line_end_pos);
- data_ = data_.substr(line_end_pos);
+ // Eat headers and prepend a status line as is required by
+ // HttpResponseHeaders.
+ std::string headers("HTTP/1.1 200 OK\r\n");
+ headers.append(data_, 0, headers_end_pos);
+ data_ = data_.substr(headers_end_pos);
+
+ scoped_refptr<net::HttpResponseHeaders> response_headers =
+ new net::HttpResponseHeaders(
+ net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
// Create a WebURLResponse based on the original set of headers + the
- // replacement headers. We only replace the same few headers that gecko
- // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp.
- std::string content_type = net::GetSpecificHeader(headers, "content-type");
- std::string mime_type;
- std::string charset;
- bool has_charset = false;
- net::HttpUtil::ParseContentType(content_type, &mime_type, &charset,
- &has_charset, NULL);
+ // replacement headers. We only replace the same few headers that gecko
+ // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp.
WebURLResponse response(original_response_.url());
+
+ std::string mime_type;
+ response_headers->GetMimeType(&mime_type);
response.setMIMEType(WebString::fromUTF8(mime_type));
+
+ std::string charset;
+ response_headers->GetCharset(&charset);
response.setTextEncodingName(WebString::fromUTF8(charset));
+ // Copy the response headers from the original response.
HeaderCopier copier(&response);
original_response_.visitHTTPHeaderFields(&copier);
+ // Replace original headers with multipart headers listed in kReplaceHeaders.
for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
std::string name(kReplaceHeaders[i]);
- std::string value = net::GetSpecificHeader(headers, name);
- if (!value.empty()) {
- response.setHTTPHeaderField(WebString::fromUTF8(name),
- WebString::fromUTF8(value));
+ std::string value;
+ void* iterator = nullptr;
+ while (response_headers->EnumerateHeader(&iterator, name, &value)) {
+ response.addHTTPHeaderField(WebString::fromLatin1(name),
+ WebString::fromLatin1(value));
}
}
// To avoid recording every multipart load as a separate visit in
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index a22ee60..fa40ed7 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -544,9 +544,19 @@ int HttpUtil::LocateStartOfStatusLine(const char* buf, int buf_len) {
return -1; // Not found
}
-int HttpUtil::LocateEndOfHeaders(const char* buf, int buf_len, int i) {
- bool was_lf = false;
+static int LocateEndOfHeadersHelper(const char* buf,
+ int buf_len,
+ int i,
+ bool accept_empty_header_list) {
char last_c = '\0';
+ bool was_lf = false;
+ if (accept_empty_header_list) {
+ // Normally two line breaks signal the end of a header list. An empty header
+ // list ends with a single line break at the start of the buffer.
+ last_c = '\n';
+ was_lf = true;
+ }
+
for (; i < buf_len; ++i) {
char c = buf[i];
if (c == '\n') {
@@ -561,6 +571,16 @@ int HttpUtil::LocateEndOfHeaders(const char* buf, int buf_len, int i) {
return -1;
}
+int HttpUtil::LocateEndOfAdditionalHeaders(const char* buf,
+ int buf_len,
+ int i) {
+ return LocateEndOfHeadersHelper(buf, buf_len, i, true);
+}
+
+int HttpUtil::LocateEndOfHeaders(const char* buf, int buf_len, int i) {
+ return LocateEndOfHeadersHelper(buf, buf_len, i, false);
+}
+
// In order for a line to be continuable, it must specify a
// non-blank header-name. Line continuations are specifically for
// header values -- do not allow headers names to span lines.
diff --git a/net/http/http_util.h b/net/http/http_util.h
index b158524..79a41ac 100644
--- a/net/http/http_util.h
+++ b/net/http/http_util.h
@@ -147,10 +147,19 @@ class NET_EXPORT HttpUtil {
// 2616 defines the end-of-headers marker as a double CRLF; however, some
// servers only send back LFs (e.g., Unix-based CGI scripts written using the
// ASIS Apache module). This function therefore accepts the pattern LF[CR]LF
- // as end-of-headers (just like Mozilla).
+ // as end-of-headers (just like Mozilla). The first line of |buf| is
+ // considered the status line, even if empty.
// The parameter |i| is the offset within |buf| to begin searching from.
static int LocateEndOfHeaders(const char* buf, int buf_len, int i = 0);
+ // Same as |LocateEndOfHeaders|, but does not expect a status line, so can be
+ // used on multi-part responses or HTTP/1.x trailers. As a result, if |buf|
+ // starts with a single [CR]LF, it is considered an empty header list, as
+ // opposed to an empty status line above a header list.
+ static int LocateEndOfAdditionalHeaders(const char* buf,
+ int buf_len,
+ int i = 0);
+
// Assemble "raw headers" in the format required by HttpResponseHeaders.
// This involves normalizing line terminators, converting [CR]LF to \0 and
// handling HTTP line continuations (i.e., lines starting with LWS are
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc
index 980c388..8d0a219 100644
--- a/net/http/http_util_unittest.cc
+++ b/net/http/http_util_unittest.cc
@@ -267,12 +267,17 @@ TEST(HttpUtilTest, LocateEndOfHeaders) {
const char* const input;
int expected_result;
} tests[] = {
- { "foo\r\nbar\r\n\r\n", 12 },
- { "foo\nbar\n\n", 9 },
- { "foo\r\nbar\r\n\r\njunk", 12 },
- { "foo\nbar\n\njunk", 9 },
- { "foo\nbar\n\r\njunk", 10 },
- { "foo\nbar\r\n\njunk", 10 },
+ {"\r\n", -1},
+ {"\n", -1},
+ {"\r", -1},
+ {"foo", -1},
+ {"\r\n\r\n", 4},
+ {"foo\r\nbar\r\n\r\n", 12},
+ {"foo\nbar\n\n", 9},
+ {"foo\r\nbar\r\n\r\njunk", 12},
+ {"foo\nbar\n\njunk", 9},
+ {"foo\nbar\n\r\njunk", 10},
+ {"foo\nbar\r\n\njunk", 10},
};
for (size_t i = 0; i < arraysize(tests); ++i) {
int input_len = static_cast<int>(strlen(tests[i].input));
@@ -281,6 +286,29 @@ TEST(HttpUtilTest, LocateEndOfHeaders) {
}
}
+TEST(HttpUtilTest, LocateEndOfAdditionalHeaders) {
+ struct {
+ const char* const input;
+ int expected_result;
+ } tests[] = {
+ {"\r\n", 2},
+ {"\n", 1},
+ {"\r", -1},
+ {"foo", -1},
+ {"\r\n\r\n", 2},
+ {"foo\r\nbar\r\n\r\n", 12},
+ {"foo\nbar\n\n", 9},
+ {"foo\r\nbar\r\n\r\njunk", 12},
+ {"foo\nbar\n\njunk", 9},
+ {"foo\nbar\n\r\njunk", 10},
+ {"foo\nbar\r\n\njunk", 10},
+ };
+ for (size_t i = 0; i < arraysize(tests); ++i) {
+ int input_len = static_cast<int>(strlen(tests[i].input));
+ int eoh = HttpUtil::LocateEndOfAdditionalHeaders(tests[i].input, input_len);
+ EXPECT_EQ(tests[i].expected_result, eoh);
+ }
+}
TEST(HttpUtilTest, AssembleRawHeaders) {
struct {
const char* const input; // with '|' representing '\0'