1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
// 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, ';');
std::string::const_iterator type_begin = begin;
std::string::const_iterator type_end = delimiter;
HttpUtil::TrimLWS(&type_begin, &type_end);
// If the disposition-type isn't a valid token the then the
// Content-Disposition header is malformed, and we treat the first bytes as
// a parameter rather than a disposition-type.
if (!HttpUtil::IsToken(type_begin, type_end))
return begin;
DCHECK(std::find(type_begin, type_end, '=') == 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 name;
std::string filename;
std::string ext_filename;
HttpUtil::NameValuePairsIterator iter(pos, end, ';');
while (iter.GetNext()) {
if (filename.empty() && LowerCaseEqualsASCII(iter.name_begin(),
iter.name_end(),
"filename")) {
DecodeFilenameValue(iter.value(), referrer_charset, &filename);
} else if (name.empty() && LowerCaseEqualsASCII(iter.name_begin(),
iter.name_end(),
"name")) {
DecodeFilenameValue(iter.value(), referrer_charset, &name);
} else if (ext_filename.empty() && LowerCaseEqualsASCII(iter.name_begin(),
iter.name_end(),
"filename*")) {
DecodeExtValue(iter.raw_value(), &ext_filename);
}
}
if (!ext_filename.empty())
filename_ = ext_filename;
else if (!filename.empty())
filename_ = filename;
else
filename_ = name;
}
} // namespace net
|