diff options
author | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-27 06:03:16 +0000 |
---|---|---|
committer | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-27 06:03:16 +0000 |
commit | 56eab2f216ce86217149753a407f981cb6d5de6c (patch) | |
tree | bf4b45a8fbb845b5ec177332df0ebafcfaedb98f /net/http/http_content_disposition.cc | |
parent | 9b961c91eeb8ba43be7918563a07432cbcb1c4df (diff) | |
download | chromium_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.cc | 93 |
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 |