summaryrefslogtreecommitdiffstats
path: root/net/http/http_content_disposition.cc
diff options
context:
space:
mode:
authorabarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-27 06:03:16 +0000
committerabarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-27 06:03:16 +0000
commit56eab2f216ce86217149753a407f981cb6d5de6c (patch)
treebf4b45a8fbb845b5ec177332df0ebafcfaedb98f /net/http/http_content_disposition.cc
parent9b961c91eeb8ba43be7918563a07432cbcb1c4df (diff)
downloadchromium_src-56eab2f216ce86217149753a407f981cb6d5de6c.zip
chromium_src-56eab2f216ce86217149753a407f981cb6d5de6c.tar.gz
chromium_src-56eab2f216ce86217149753a407f981cb6d5de6c.tar.bz2
Improve parsing of the Content-Disposition header
Previous, we were using GetHeaderParamValue to parse the Content-Disposition header, which describes itself as a "quick and dirty implementation." After this patch, we use more of our normal HTTP parsing machinery, making our parsing much less quirky and better aligned with RFC 6266. Some notes: 1) Many of the test cases for parsing the Content-Disposition header included the string "Content-Disposition: " in the input. I've looked through all of the callers of these functions, and that seems to be completely bogus. The old parser wasn't careful enough to see that as a problem, but the new one follows the spec more closely. I've updated the test cases to remove this string. 2) After this patch, there's a bunch of code in net_util.cc that really should be moved to http_content_disposition.cc. I didn't move that code in this patch because I didn't want this path to be too large. I'll move it in a future patch. 3) In a future patch, I'll audit the codebase for callers of GetHeaderParamValue. With any luck, we'll be able to remove them all and delete this less-than-amazing function. BUG=65423 Review URL: http://codereview.chromium.org/9234055 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119378 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http/http_content_disposition.cc')
-rw-r--r--net/http/http_content_disposition.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/net/http/http_content_disposition.cc b/net/http/http_content_disposition.cc
new file mode 100644
index 0000000..4e5d94e
--- /dev/null
+++ b/net/http/http_content_disposition.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/http/http_content_disposition.h"
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "net/base/net_util.h"
+#include "net/http/http_util.h"
+
+namespace net {
+
+HttpContentDisposition::HttpContentDisposition(
+ const std::string& header, const std::string& referrer_charset)
+ : type_(INLINE) {
+ Parse(header, referrer_charset);
+}
+
+HttpContentDisposition::~HttpContentDisposition() {
+}
+
+std::string::const_iterator HttpContentDisposition::ConsumeDispositionType(
+ std::string::const_iterator begin, std::string::const_iterator end) {
+ DCHECK(type_ == INLINE);
+
+ std::string::const_iterator delimiter = std::find(begin, end, ';');
+
+ // If there's an '=' in before the first ';', then the Content-Disposition
+ // header is malformed, and we treat the first bytes as a parameter rather
+ // than a disposition-type.
+ if (std::find(begin, delimiter, '=') != delimiter)
+ return begin;
+
+ std::string::const_iterator type_begin = begin;
+ std::string::const_iterator type_end = delimiter;
+ HttpUtil::TrimLWS(&type_begin, &type_end);
+ if (!LowerCaseEqualsASCII(type_begin, type_end, "inline"))
+ type_ = ATTACHMENT;
+ return delimiter;
+}
+
+// http://tools.ietf.org/html/rfc6266
+//
+// content-disposition = "Content-Disposition" ":"
+// disposition-type *( ";" disposition-parm )
+//
+// disposition-type = "inline" | "attachment" | disp-ext-type
+// ; case-insensitive
+// disp-ext-type = token
+//
+// disposition-parm = filename-parm | disp-ext-parm
+//
+// filename-parm = "filename" "=" value
+// | "filename*" "=" ext-value
+//
+// disp-ext-parm = token "=" value
+// | ext-token "=" ext-value
+// ext-token = <the characters in token, followed by "*">
+//
+void HttpContentDisposition::Parse(const std::string& header,
+ const std::string& referrer_charset) {
+ DCHECK(type_ == INLINE);
+ DCHECK(filename_.empty());
+
+ std::string::const_iterator pos = header.begin();
+ std::string::const_iterator end = header.end();
+ pos = ConsumeDispositionType(pos, end);
+
+ std::string filename;
+ std::string ext_filename;
+
+ HttpUtil::NameValuePairsIterator iter(pos, end, ';');
+ while (iter.GetNext()) {
+ if (LowerCaseEqualsASCII(iter.name_begin(),
+ iter.name_end(),
+ "filename")) {
+ DecodeFilenameValue(iter.value(), referrer_charset, &filename);
+ } else if (LowerCaseEqualsASCII(iter.name_begin(),
+ iter.name_end(),
+ "name")) {
+ DecodeFilenameValue(iter.value(), referrer_charset, &filename);
+ } else if (LowerCaseEqualsASCII(iter.name_begin(),
+ iter.name_end(),
+ "filename*")) {
+ DecodeExtValue(iter.raw_value(), &ext_filename);
+ }
+ }
+
+ filename_ = ext_filename.empty() ? filename : ext_filename;
+}
+
+} // namespace net