1 #include "quiche/balsa/header_properties.h"
2
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
9 namespace quiche::header_properties {
10
11 namespace {
12
13 using MultivaluedHeadersSet =
14 absl::flat_hash_set<absl::string_view, StringPieceCaseHash,
15 StringPieceCaseEqual>;
16
buildMultivaluedHeaders()17 MultivaluedHeadersSet* 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
buildInvalidHeaderKeyCharLookupTable()62 std::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
buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote()71 std::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
buildInvalidCharLookupTable()80 std::array<bool, 256> buildInvalidCharLookupTable() {
81 std::array<bool, 256> invalidCharTable;
82 invalidCharTable.fill(false);
83 for (uint8_t c : kInvalidHeaderCharList) {
84 invalidCharTable[c] = true;
85 }
86 return invalidCharTable;
87 }
88
89 } // anonymous namespace
90
IsMultivaluedHeader(absl::string_view header)91 bool IsMultivaluedHeader(absl::string_view header) {
92 static const MultivaluedHeadersSet* const multivalued_headers =
93 buildMultivaluedHeaders();
94 return multivalued_headers->contains(header);
95 }
96
IsInvalidHeaderKeyChar(uint8_t c)97 bool IsInvalidHeaderKeyChar(uint8_t c) {
98 static const std::array<bool, 256> invalidHeaderKeyCharTable =
99 buildInvalidHeaderKeyCharLookupTable();
100
101 return invalidHeaderKeyCharTable[c];
102 }
103
IsInvalidHeaderKeyCharAllowDoubleQuote(uint8_t c)104 bool IsInvalidHeaderKeyCharAllowDoubleQuote(uint8_t c) {
105 static const std::array<bool, 256> invalidHeaderKeyCharTable =
106 buildInvalidHeaderKeyCharLookupTableAllowDoubleQuote();
107
108 return invalidHeaderKeyCharTable[c];
109 }
110
IsInvalidHeaderChar(uint8_t c)111 bool IsInvalidHeaderChar(uint8_t c) {
112 static const std::array<bool, 256> invalidCharTable =
113 buildInvalidCharLookupTable();
114
115 return invalidCharTable[c];
116 }
117
HasInvalidHeaderChars(absl::string_view value)118 bool 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
128