blob: 53978df5ff04a75770c1a1a8fcf4fe73ac749f8a [file] [log] [blame]
bnc30bbde72022-05-12 06:41:23 -07001#include "quiche/balsa/header_properties.h"
QUICHE teamd7a507e2022-04-15 14:35:46 -07002
3#include <array>
4
5#include "absl/container/flat_hash_set.h"
6#include "absl/strings/string_view.h"
7#include "quiche/common/quiche_text_utils.h"
8
9namespace quiche::header_properties {
10
11namespace {
12
13using MultivaluedHeadersSet =
14 absl::flat_hash_set<absl::string_view, StringPieceCaseHash,
15 StringPieceCaseEqual>;
16
17MultivaluedHeadersSet* buildMultivaluedHeaders() {
18 return new MultivaluedHeadersSet({
19 "accept",
20 "accept-charset",
21 "accept-encoding",
22 "accept-language",
23 "accept-ranges",
24 // The follow four headers are all CORS standard headers
25 "access-control-allow-headers",
26 "access-control-allow-methods",
27 "access-control-expose-headers",
28 "access-control-request-headers",
29 "allow",
30 "cache-control",
31 // IETF draft makes this have cache-control syntax
32 "cdn-cache-control",
33 "connection",
34 "content-encoding",
35 "content-language",
36 "expect",
37 "if-match",
38 "if-none-match",
39 // See RFC 5988 section 5
40 "link",
41 "pragma",
42 "proxy-authenticate",
43 "te",
44 // Used in the opening handshake of the WebSocket protocol.
45 "sec-websocket-extensions",
46 // Not mentioned in RFC 2616, but it can have multiple values.
47 "set-cookie",
48 "trailer",
49 "transfer-encoding",
50 "upgrade",
51 "vary",
52 "via",
53 "warning",
54 "www-authenticate",
55 // De facto standard not in the RFCs
56 "x-forwarded-for",
57 // Internal Google usage gives this cache-control syntax
58 "x-go" /**/ "ogle-cache-control",
59 });
60}
61
bnc1e2d7f92022-05-05 06:45:35 -070062std::array<bool, 256> buildInvalidHeaderKeyCharLookupTable() {
63 std::array<bool, 256> invalidCharTable;
64 invalidCharTable.fill(false);
65 for (uint8_t c : kInvalidHeaderKeyCharList) {
66 invalidCharTable[c] = true;
67 }
68 return invalidCharTable;
69}
70
bncb6ef2012023-06-28 11:36:18 -070071std::array<bool, 256> buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote() {
72 std::array<bool, 256> invalidCharTable;
73 invalidCharTable.fill(false);
74 for (uint8_t c : kInvalidHeaderKeyCharListAllowDoubleQuote) {
75 invalidCharTable[c] = true;
76 }
77 return invalidCharTable;
78}
79
QUICHE teamd7a507e2022-04-15 14:35:46 -070080std::array<bool, 256> buildInvalidCharLookupTable() {
81 std::array<bool, 256> invalidCharTable;
82 invalidCharTable.fill(false);
bnc049f2e12022-05-04 13:26:36 -070083 for (uint8_t c : kInvalidHeaderCharList) {
QUICHE teamd7a507e2022-04-15 14:35:46 -070084 invalidCharTable[c] = true;
85 }
86 return invalidCharTable;
87}
88
89} // anonymous namespace
90
91bool IsMultivaluedHeader(absl::string_view header) {
92 static const MultivaluedHeadersSet* const multivalued_headers =
93 buildMultivaluedHeaders();
94 return multivalued_headers->contains(header);
95}
96
bnc1e2d7f92022-05-05 06:45:35 -070097bool IsInvalidHeaderKeyChar(uint8_t c) {
98 static const std::array<bool, 256> invalidHeaderKeyCharTable =
99 buildInvalidHeaderKeyCharLookupTable();
100
101 return invalidHeaderKeyCharTable[c];
102}
103
bncb6ef2012023-06-28 11:36:18 -0700104bool IsInvalidHeaderKeyCharAllowDoubleQuote(uint8_t c) {
105 static const std::array<bool, 256> invalidHeaderKeyCharTable =
106 buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote();
107
108 return invalidHeaderKeyCharTable[c];
109}
110
bnc049f2e12022-05-04 13:26:36 -0700111bool IsInvalidHeaderChar(uint8_t c) {
QUICHE teamd7a507e2022-04-15 14:35:46 -0700112 static const std::array<bool, 256> invalidCharTable =
113 buildInvalidCharLookupTable();
114
115 return invalidCharTable[c];
116}
117
118bool HasInvalidHeaderChars(absl::string_view value) {
119 for (const char c : value) {
120 if (IsInvalidHeaderChar(c)) {
121 return true;
122 }
123 }
124 return false;
125}
126
127} // namespace quiche::header_properties