1/*
2 * Copyright (C) 2006 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include "HTTPHeaderNames.h"
30#include <utility>
31#include <wtf/HashMap.h>
32#include <wtf/Optional.h>
33#include <wtf/text/StringHash.h>
34
35namespace WebCore {
36
37// FIXME: Not every header fits into a map. Notably, multiple Set-Cookie header fields are needed to set multiple cookies.
38
39class HTTPHeaderMap {
40public:
41 struct CommonHeader {
42 HTTPHeaderName key;
43 String value;
44
45 CommonHeader isolatedCopy() const { return { key , value.isolatedCopy() }; }
46 template <class Encoder> void encode(Encoder&) const;
47 template <class Decoder> static Optional<CommonHeader> decode(Decoder&);
48
49 bool operator==(const CommonHeader& other) const { return key == other.key && value == other.value; }
50 };
51
52 struct UncommonHeader {
53 String key;
54 String value;
55
56 UncommonHeader isolatedCopy() const { return { key.isolatedCopy() , value.isolatedCopy() }; }
57 template <class Encoder> void encode(Encoder&) const;
58 template <class Decoder> static Optional<UncommonHeader> decode(Decoder&);
59
60 bool operator==(const UncommonHeader& other) const { return key == other.key && value == other.value; }
61 };
62
63 typedef Vector<CommonHeader, 0, CrashOnOverflow, 6> CommonHeadersVector;
64 typedef Vector<UncommonHeader, 0, CrashOnOverflow, 0> UncommonHeadersVector;
65
66 class HTTPHeaderMapConstIterator {
67 public:
68 HTTPHeaderMapConstIterator(const HTTPHeaderMap& table, CommonHeadersVector::const_iterator commonHeadersIt, UncommonHeadersVector::const_iterator uncommonHeadersIt)
69 : m_table(table)
70 , m_commonHeadersIt(commonHeadersIt)
71 , m_uncommonHeadersIt(uncommonHeadersIt)
72 {
73 if (!updateKeyValue(m_commonHeadersIt))
74 updateKeyValue(m_uncommonHeadersIt);
75 }
76
77 struct KeyValue {
78 String key;
79 Optional<HTTPHeaderName> keyAsHTTPHeaderName;
80 String value;
81 };
82
83 const KeyValue* get() const
84 {
85 ASSERT(*this != m_table.end());
86 return &m_keyValue;
87 }
88 const KeyValue& operator*() const { return *get(); }
89 const KeyValue* operator->() const { return get(); }
90
91 HTTPHeaderMapConstIterator& operator++()
92 {
93 if (m_commonHeadersIt != m_table.m_commonHeaders.end()) {
94 if (updateKeyValue(++m_commonHeadersIt))
95 return *this;
96 } else
97 ++m_uncommonHeadersIt;
98
99 updateKeyValue(m_uncommonHeadersIt);
100 return *this;
101 }
102
103 bool operator!=(const HTTPHeaderMapConstIterator& other) const { return !(*this == other); }
104 bool operator==(const HTTPHeaderMapConstIterator& other) const
105 {
106 return m_commonHeadersIt == other.m_commonHeadersIt && m_uncommonHeadersIt == other.m_uncommonHeadersIt;
107 }
108
109 private:
110 bool updateKeyValue(CommonHeadersVector::const_iterator it)
111 {
112 if (it == m_table.commonHeaders().end())
113 return false;
114 m_keyValue.key = httpHeaderNameString(it->key).toStringWithoutCopying();
115 m_keyValue.keyAsHTTPHeaderName = it->key;
116 m_keyValue.value = it->value;
117 return true;
118 }
119 bool updateKeyValue(UncommonHeadersVector::const_iterator it)
120 {
121 if (it == m_table.uncommonHeaders().end())
122 return false;
123 m_keyValue.key = it->key;
124 m_keyValue.keyAsHTTPHeaderName = WTF::nullopt;
125 m_keyValue.value = it->value;
126 return true;
127 }
128
129 const HTTPHeaderMap& m_table;
130 CommonHeadersVector::const_iterator m_commonHeadersIt;
131 UncommonHeadersVector::const_iterator m_uncommonHeadersIt;
132 KeyValue m_keyValue;
133 };
134 typedef HTTPHeaderMapConstIterator const_iterator;
135
136 WEBCORE_EXPORT HTTPHeaderMap();
137
138 // Gets a copy of the data suitable for passing to another thread.
139 WEBCORE_EXPORT HTTPHeaderMap isolatedCopy() const;
140
141 bool isEmpty() const { return m_commonHeaders.isEmpty() && m_uncommonHeaders.isEmpty(); }
142 int size() const { return m_commonHeaders.size() + m_uncommonHeaders.size(); }
143
144 void clear()
145 {
146 m_commonHeaders.clear();
147 m_uncommonHeaders.clear();
148 }
149
150 void shrinkToFit()
151 {
152 m_commonHeaders.shrinkToFit();
153 m_uncommonHeaders.shrinkToFit();
154 }
155
156 WEBCORE_EXPORT String get(const String& name) const;
157 WEBCORE_EXPORT void set(const String& name, const String& value);
158 WEBCORE_EXPORT void add(const String& name, const String& value);
159 WEBCORE_EXPORT void append(const String& name, const String& value);
160 WEBCORE_EXPORT bool contains(const String&) const;
161 bool remove(const String&);
162
163#if USE(CF)
164 void set(CFStringRef name, const String& value);
165#ifdef __OBJC__
166 void set(NSString *name, const String& value) { set((__bridge CFStringRef)name, value); }
167#endif
168#endif
169
170 WEBCORE_EXPORT String get(HTTPHeaderName) const;
171 void set(HTTPHeaderName, const String& value);
172 void add(HTTPHeaderName, const String& value);
173 bool addIfNotPresent(HTTPHeaderName, const String&);
174 WEBCORE_EXPORT bool contains(HTTPHeaderName) const;
175 WEBCORE_EXPORT bool remove(HTTPHeaderName);
176
177 // Instead of passing a string literal to any of these functions, just use a HTTPHeaderName instead.
178 template<size_t length> String get(const char (&)[length]) const = delete;
179 template<size_t length> void set(const char (&)[length], const String&) = delete;
180 template<size_t length> bool contains(const char (&)[length]) = delete;
181 template<size_t length> bool remove(const char (&)[length]) = delete;
182
183 const CommonHeadersVector& commonHeaders() const { return m_commonHeaders; }
184 const UncommonHeadersVector& uncommonHeaders() const { return m_uncommonHeaders; }
185 CommonHeadersVector& commonHeaders() { return m_commonHeaders; }
186 UncommonHeadersVector& uncommonHeaders() { return m_uncommonHeaders; }
187
188 const_iterator begin() const { return const_iterator(*this, m_commonHeaders.begin(), m_uncommonHeaders.begin()); }
189 const_iterator end() const { return const_iterator(*this, m_commonHeaders.end(), m_uncommonHeaders.end()); }
190
191 friend bool operator==(const HTTPHeaderMap& a, const HTTPHeaderMap& b)
192 {
193 return a.m_commonHeaders == b.m_commonHeaders && a.m_uncommonHeaders == b.m_uncommonHeaders;
194 }
195
196 friend bool operator!=(const HTTPHeaderMap& a, const HTTPHeaderMap& b)
197 {
198 return !(a == b);
199 }
200
201 template <class Encoder> void encode(Encoder&) const;
202 template <class Decoder> static bool decode(Decoder&, HTTPHeaderMap&);
203
204private:
205 CommonHeadersVector m_commonHeaders;
206 UncommonHeadersVector m_uncommonHeaders;
207};
208
209template <class Encoder>
210void HTTPHeaderMap::CommonHeader::encode(Encoder& encoder) const
211{
212 encoder.encodeEnum(key);
213 encoder << value;
214}
215
216template <class Decoder>
217auto HTTPHeaderMap::CommonHeader::decode(Decoder& decoder) -> Optional<CommonHeader>
218{
219 HTTPHeaderName name;
220 if (!decoder.decodeEnum(name))
221 return WTF::nullopt;
222 String value;
223 if (!decoder.decode(value))
224 return WTF::nullopt;
225
226 return CommonHeader { name, WTFMove(value) };
227}
228
229template <class Encoder>
230void HTTPHeaderMap::UncommonHeader::encode(Encoder& encoder) const
231{
232 encoder << key;
233 encoder << value;
234}
235
236template <class Decoder>
237auto HTTPHeaderMap::UncommonHeader::decode(Decoder& decoder) -> Optional<UncommonHeader>
238{
239 String name;
240 if (!decoder.decode(name))
241 return WTF::nullopt;
242 String value;
243 if (!decoder.decode(value))
244 return WTF::nullopt;
245
246 return UncommonHeader { WTFMove(name), WTFMove(value) };
247}
248
249template <class Encoder>
250void HTTPHeaderMap::encode(Encoder& encoder) const
251{
252 encoder << m_commonHeaders;
253 encoder << m_uncommonHeaders;
254}
255
256template <class Decoder>
257bool HTTPHeaderMap::decode(Decoder& decoder, HTTPHeaderMap& headerMap)
258{
259 if (!decoder.decode(headerMap.m_commonHeaders))
260 return false;
261
262 if (!decoder.decode(headerMap.m_uncommonHeaders))
263 return false;
264
265 return true;
266}
267
268} // namespace WebCore
269