• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
buildInvalidCharLookupTable()71 std::array<bool, 256> buildInvalidCharLookupTable() {
72   std::array<bool, 256> invalidCharTable;
73   invalidCharTable.fill(false);
74   for (uint8_t c : kInvalidHeaderCharList) {
75     invalidCharTable[c] = true;
76   }
77   return invalidCharTable;
78 }
79 
80 }  // anonymous namespace
81 
IsMultivaluedHeader(absl::string_view header)82 bool IsMultivaluedHeader(absl::string_view header) {
83   static const MultivaluedHeadersSet* const multivalued_headers =
84       buildMultivaluedHeaders();
85   return multivalued_headers->contains(header);
86 }
87 
IsInvalidHeaderKeyChar(uint8_t c)88 bool IsInvalidHeaderKeyChar(uint8_t c) {
89   static const std::array<bool, 256> invalidHeaderKeyCharTable =
90       buildInvalidHeaderKeyCharLookupTable();
91 
92   return invalidHeaderKeyCharTable[c];
93 }
94 
IsInvalidHeaderChar(uint8_t c)95 bool IsInvalidHeaderChar(uint8_t c) {
96   static const std::array<bool, 256> invalidCharTable =
97       buildInvalidCharLookupTable();
98 
99   return invalidCharTable[c];
100 }
101 
HasInvalidHeaderChars(absl::string_view value)102 bool HasInvalidHeaderChars(absl::string_view value) {
103   for (const char c : value) {
104     if (IsInvalidHeaderChar(c)) {
105       return true;
106     }
107   }
108   return false;
109 }
110 
111 }  // namespace quiche::header_properties
112