rippled
Loading...
Searching...
No Matches
rfc2616.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of Beast: https://github.com/vinniefalco/Beast
4 Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef BEAST_RFC2616_HPP
21#define BEAST_RFC2616_HPP
22
23#include <boost/beast/http/message.hpp>
24#include <boost/beast/http/rfc7230.hpp>
25#include <boost/range/algorithm/equal.hpp>
26#include <boost/range/iterator_range.hpp>
27#include <boost/utility/string_ref.hpp>
28
29#include <algorithm>
30#include <cctype>
31#include <cstdint>
32#include <iterator>
33#include <string>
34#include <utility>
35#include <vector>
36
37namespace beast {
38namespace rfc2616 {
39
40namespace detail {
41
43{
44 explicit ci_equal_pred() = default;
45
46 bool
47 operator()(char c1, char c2)
48 {
49 // VFALCO TODO Use a table lookup here
50 return std::tolower(static_cast<unsigned char>(c1)) ==
51 std::tolower(static_cast<unsigned char>(c2));
52 }
53};
54
59inline bool
60is_lws(char c)
61{
62 return c == ' ' || c == '\t';
63}
64
66inline bool
67is_white(char c)
68{
69 switch (c)
70 {
71 case ' ':
72 case '\f':
73 case '\n':
74 case '\r':
75 case '\t':
76 case '\v':
77 return true;
78 };
79 return false;
80}
81
82template <class FwdIter>
83FwdIter
84trim_right(FwdIter first, FwdIter last)
85{
86 if (first == last)
87 return last;
88 do
89 {
90 --last;
91 if (!is_white(*last))
92 return ++last;
93 } while (last != first);
94 return first;
95}
96
97template <class String>
98String
99trim_right(String const& s)
100{
101 using std::begin;
102 using std::end;
103 auto first(begin(s));
104 auto last(end(s));
105 last = trim_right(first, last);
106 return {first, last};
107}
108
109} // namespace detail
110
119template <
120 class FwdIt,
121 class Result = std::vector<
123 class Char>
124Result
125split(FwdIt first, FwdIt last, Char delim)
126{
127 using namespace detail;
128 using string = typename Result::value_type;
129
130 Result result;
131
132 FwdIt iter = first;
133 string e;
134 while (iter != last)
135 {
136 if (*iter == '"')
137 {
138 // quoted-string
139 ++iter;
140 while (iter != last)
141 {
142 if (*iter == '"')
143 {
144 ++iter;
145 break;
146 }
147
148 if (*iter == '\\')
149 {
150 // quoted-pair
151 ++iter;
152 if (iter != last)
153 e.append(1, *iter++);
154 }
155 else
156 {
157 // qdtext
158 e.append(1, *iter++);
159 }
160 }
161 if (!e.empty())
162 {
163 result.emplace_back(std::move(e));
164 e.clear();
165 }
166 }
167 else if (*iter == delim)
168 {
169 e = trim_right(e);
170 if (!e.empty())
171 {
172 result.emplace_back(std::move(e));
173 e.clear();
174 }
175 ++iter;
176 }
177 else if (is_lws(*iter))
178 {
179 ++iter;
180 }
181 else
182 {
183 e.append(1, *iter++);
184 }
185 }
186
187 if (!e.empty())
188 {
189 e = trim_right(e);
190 if (!e.empty())
191 result.emplace_back(std::move(e));
192 }
193 return result;
194}
195
196template <
197 class FwdIt,
198 class Result = std::vector<
200Result
201split_commas(FwdIt first, FwdIt last)
202{
203 return split(first, last, ',');
204}
205
206template <class Result = std::vector<std::string>>
207Result
208split_commas(boost::beast::string_view const& s)
209{
210 return split_commas(s.begin(), s.end());
211}
212
213//------------------------------------------------------------------------------
214
224{
225 using iter_type = boost::string_ref::const_iterator;
226
229 boost::string_ref value_;
230
231public:
232 using value_type = boost::string_ref;
233 using pointer = value_type const*;
234 using reference = value_type const&;
237
238 list_iterator(iter_type begin, iter_type end) : it_(begin), end_(end)
239 {
240 if (it_ != end_)
241 increment();
242 }
243
244 bool
245 operator==(list_iterator const& other) const
246 {
247 return other.it_ == it_ && other.end_ == end_ &&
248 other.value_.size() == value_.size();
249 }
250
251 bool
252 operator!=(list_iterator const& other) const
253 {
254 return !(*this == other);
255 }
256
258 operator*() const
259 {
260 return value_;
261 }
262
263 pointer
265 {
266 return &*(*this);
267 }
268
271 {
272 increment();
273 return *this;
274 }
275
278 {
279 auto temp = *this;
280 ++(*this);
281 return temp;
282 }
283
284private:
285 template <class = void>
286 void
287 increment();
288};
289
290template <class>
291void
293{
294 using namespace detail;
295 value_.clear();
296 while (it_ != end_)
297 {
298 if (*it_ == '"')
299 {
300 // quoted-string
301 ++it_;
302 if (it_ == end_)
303 return;
304 if (*it_ != '"')
305 {
306 auto start = it_;
307 for (;;)
308 {
309 ++it_;
310 if (it_ == end_)
311 {
312 value_ = boost::string_ref(
313 &*start, std::distance(start, it_));
314 return;
315 }
316 if (*it_ == '"')
317 {
318 value_ = boost::string_ref(
319 &*start, std::distance(start, it_));
320 ++it_;
321 return;
322 }
323 }
324 }
325 ++it_;
326 }
327 else if (*it_ == ',')
328 {
329 it_++;
330 continue;
331 }
332 else if (is_lws(*it_))
333 {
334 ++it_;
335 continue;
336 }
337 else
338 {
339 auto start = it_;
340 for (;;)
341 {
342 ++it_;
343 if (it_ == end_ || *it_ == ',' || is_lws(*it_))
344 {
345 value_ =
346 boost::string_ref(&*start, std::distance(start, it_));
347 return;
348 }
349 }
350 }
351 }
352}
357inline bool
358ci_equal(boost::string_ref s1, boost::string_ref s2)
359{
360 return boost::range::equal(s1, s2, detail::ci_equal_pred{});
361}
362
364inline boost::iterator_range<list_iterator>
365make_list(boost::string_ref const& field)
366{
367 return boost::iterator_range<list_iterator>{
368 list_iterator{field.begin(), field.end()},
369 list_iterator{field.end(), field.end()}};
370}
371
376template <class = void>
377bool
378token_in_list(boost::string_ref const& value, boost::string_ref const& token)
379{
380 for (auto const& item : make_list(value))
381 if (ci_equal(item, token))
382 return true;
383 return false;
384}
385
386template <bool isRequest, class Body, class Fields>
387bool
388is_keep_alive(boost::beast::http::message<isRequest, Body, Fields> const& m)
389{
390 if (m.version() <= 10)
391 return boost::beast::http::token_list{
392 m[boost::beast::http::field::connection]}
393 .exists("keep-alive");
394 return !boost::beast::http::token_list{
395 m[boost::beast::http::field::connection]}
396 .exists("close");
397}
398
399} // namespace rfc2616
400} // namespace beast
401
402#endif
T begin(T... args)
Iterates through a comma separated list.
Definition: rfc2616.h:224
pointer operator->() const
Definition: rfc2616.h:264
boost::string_ref::const_iterator iter_type
Definition: rfc2616.h:225
value_type const * pointer
Definition: rfc2616.h:233
list_iterator(iter_type begin, iter_type end)
Definition: rfc2616.h:238
boost::string_ref value_
Definition: rfc2616.h:229
boost::string_ref value_type
Definition: rfc2616.h:232
bool operator!=(list_iterator const &other) const
Definition: rfc2616.h:252
reference operator*() const
Definition: rfc2616.h:258
list_iterator & operator++()
Definition: rfc2616.h:270
bool operator==(list_iterator const &other) const
Definition: rfc2616.h:245
value_type const & reference
Definition: rfc2616.h:234
list_iterator operator++(int)
Definition: rfc2616.h:277
T distance(T... args)
T end(T... args)
bool is_white(char c)
Returns true if c is any whitespace character.
Definition: rfc2616.h:67
bool is_lws(char c)
Returns true if c is linear white space.
Definition: rfc2616.h:60
FwdIter trim_right(FwdIter first, FwdIter last)
Definition: rfc2616.h:84
boost::iterator_range< list_iterator > make_list(boost::string_ref const &field)
Returns a range representing the list.
Definition: rfc2616.h:365
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:201
Result split(FwdIt first, FwdIt last, Char delim)
Parse a character sequence of values separated by commas.
Definition: rfc2616.h:125
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
Definition: rfc2616.h:388
bool ci_equal(boost::string_ref s1, boost::string_ref s2)
Returns true if two strings are equal.
Definition: rfc2616.h:358
bool token_in_list(boost::string_ref const &value, boost::string_ref const &token)
Returns true if the specified token exists in the list.
Definition: rfc2616.h:378
field_t< CharT, Traits, Allocator > field(std::basic_string< CharT, Traits, Allocator > const &text, int width=8, int pad=0, bool right=false)
Definition: iosformat.h:162
bool operator()(char c1, char c2)
Definition: rfc2616.h:47