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// TODO: This include <cstdint> is a workaround for beast compilation bug.
24// Remove when fix https://github.com/boostorg/beast/pull/2682/ is available.
25#include <cstdint>
26
27#include <boost/beast/http/message.hpp>
28#include <boost/beast/http/rfc7230.hpp>
29#include <boost/range/algorithm/equal.hpp>
30#include <boost/range/iterator_range.hpp>
31#include <boost/utility/string_ref.hpp>
32
33#include <algorithm>
34#include <cctype>
35#include <iterator>
36#include <string>
37#include <utility>
38#include <vector>
39
40namespace beast {
41namespace rfc2616 {
42
43namespace detail {
44
46{
47 explicit ci_equal_pred() = default;
48
49 bool
50 operator()(char c1, char c2)
51 {
52 // VFALCO TODO Use a table lookup here
53 return std::tolower(static_cast<unsigned char>(c1)) ==
54 std::tolower(static_cast<unsigned char>(c2));
55 }
56};
57
62inline bool
63is_lws(char c)
64{
65 return c == ' ' || c == '\t';
66}
67
69inline bool
70is_white(char c)
71{
72 switch (c)
73 {
74 case ' ':
75 case '\f':
76 case '\n':
77 case '\r':
78 case '\t':
79 case '\v':
80 return true;
81 };
82 return false;
83}
84
85template <class FwdIter>
86FwdIter
87trim_right(FwdIter first, FwdIter last)
88{
89 if (first == last)
90 return last;
91 do
92 {
93 --last;
94 if (!is_white(*last))
95 return ++last;
96 } while (last != first);
97 return first;
98}
99
100template <class String>
101String
102trim_right(String const& s)
103{
104 using std::begin;
105 using std::end;
106 auto first(begin(s));
107 auto last(end(s));
108 last = trim_right(first, last);
109 return {first, last};
110}
111
112} // namespace detail
113
122template <
123 class FwdIt,
124 class Result = std::vector<
126 class Char>
127Result
128split(FwdIt first, FwdIt last, Char delim)
129{
130 using namespace detail;
131 using string = typename Result::value_type;
132
133 Result result;
134
135 FwdIt iter = first;
136 string e;
137 while (iter != last)
138 {
139 if (*iter == '"')
140 {
141 // quoted-string
142 ++iter;
143 while (iter != last)
144 {
145 if (*iter == '"')
146 {
147 ++iter;
148 break;
149 }
150
151 if (*iter == '\\')
152 {
153 // quoted-pair
154 ++iter;
155 if (iter != last)
156 e.append(1, *iter++);
157 }
158 else
159 {
160 // qdtext
161 e.append(1, *iter++);
162 }
163 }
164 if (!e.empty())
165 {
166 result.emplace_back(std::move(e));
167 e.clear();
168 }
169 }
170 else if (*iter == delim)
171 {
172 e = trim_right(e);
173 if (!e.empty())
174 {
175 result.emplace_back(std::move(e));
176 e.clear();
177 }
178 ++iter;
179 }
180 else if (is_lws(*iter))
181 {
182 ++iter;
183 }
184 else
185 {
186 e.append(1, *iter++);
187 }
188 }
189
190 if (!e.empty())
191 {
192 e = trim_right(e);
193 if (!e.empty())
194 result.emplace_back(std::move(e));
195 }
196 return result;
197}
198
199template <
200 class FwdIt,
201 class Result = std::vector<
203Result
204split_commas(FwdIt first, FwdIt last)
205{
206 return split(first, last, ',');
207}
208
209template <class Result = std::vector<std::string>>
210Result
211split_commas(boost::beast::string_view const& s)
212{
213 return split_commas(s.begin(), s.end());
214}
215
216//------------------------------------------------------------------------------
217
227{
228 using iter_type = boost::string_ref::const_iterator;
229
232 boost::string_ref value_;
233
234public:
235 using value_type = boost::string_ref;
236 using pointer = value_type const*;
237 using reference = value_type const&;
240
241 list_iterator(iter_type begin, iter_type end) : it_(begin), end_(end)
242 {
243 if (it_ != end_)
244 increment();
245 }
246
247 bool
248 operator==(list_iterator const& other) const
249 {
250 return other.it_ == it_ && other.end_ == end_ &&
251 other.value_.size() == value_.size();
252 }
253
254 bool
255 operator!=(list_iterator const& other) const
256 {
257 return !(*this == other);
258 }
259
261 operator*() const
262 {
263 return value_;
264 }
265
266 pointer
268 {
269 return &*(*this);
270 }
271
274 {
275 increment();
276 return *this;
277 }
278
281 {
282 auto temp = *this;
283 ++(*this);
284 return temp;
285 }
286
287private:
288 template <class = void>
289 void
290 increment();
291};
292
293template <class>
294void
296{
297 using namespace detail;
298 value_.clear();
299 while (it_ != end_)
300 {
301 if (*it_ == '"')
302 {
303 // quoted-string
304 ++it_;
305 if (it_ == end_)
306 return;
307 if (*it_ != '"')
308 {
309 auto start = it_;
310 for (;;)
311 {
312 ++it_;
313 if (it_ == end_)
314 {
315 value_ = boost::string_ref(
316 &*start, std::distance(start, it_));
317 return;
318 }
319 if (*it_ == '"')
320 {
321 value_ = boost::string_ref(
322 &*start, std::distance(start, it_));
323 ++it_;
324 return;
325 }
326 }
327 }
328 ++it_;
329 }
330 else if (*it_ == ',')
331 {
332 it_++;
333 continue;
334 }
335 else if (is_lws(*it_))
336 {
337 ++it_;
338 continue;
339 }
340 else
341 {
342 auto start = it_;
343 for (;;)
344 {
345 ++it_;
346 if (it_ == end_ || *it_ == ',' || is_lws(*it_))
347 {
348 value_ =
349 boost::string_ref(&*start, std::distance(start, it_));
350 return;
351 }
352 }
353 }
354 }
355}
360inline bool
361ci_equal(boost::string_ref s1, boost::string_ref s2)
362{
363 return boost::range::equal(s1, s2, detail::ci_equal_pred{});
364}
365
367inline boost::iterator_range<list_iterator>
368make_list(boost::string_ref const& field)
369{
370 return boost::iterator_range<list_iterator>{
371 list_iterator{field.begin(), field.end()},
372 list_iterator{field.end(), field.end()}};
373}
374
379template <class = void>
380bool
381token_in_list(boost::string_ref const& value, boost::string_ref const& token)
382{
383 for (auto const& item : make_list(value))
384 if (ci_equal(item, token))
385 return true;
386 return false;
387}
388
389template <bool isRequest, class Body, class Fields>
390bool
391is_keep_alive(boost::beast::http::message<isRequest, Body, Fields> const& m)
392{
393 if (m.version() <= 10)
394 return boost::beast::http::token_list{
395 m[boost::beast::http::field::connection]}
396 .exists("keep-alive");
397 return !boost::beast::http::token_list{
398 m[boost::beast::http::field::connection]}
399 .exists("close");
400}
401
402} // namespace rfc2616
403} // namespace beast
404
405#endif
T begin(T... args)
Iterates through a comma separated list.
Definition: rfc2616.h:227
pointer operator->() const
Definition: rfc2616.h:267
boost::string_ref::const_iterator iter_type
Definition: rfc2616.h:228
value_type const * pointer
Definition: rfc2616.h:236
list_iterator(iter_type begin, iter_type end)
Definition: rfc2616.h:241
boost::string_ref value_
Definition: rfc2616.h:232
boost::string_ref value_type
Definition: rfc2616.h:235
bool operator!=(list_iterator const &other) const
Definition: rfc2616.h:255
reference operator*() const
Definition: rfc2616.h:261
list_iterator & operator++()
Definition: rfc2616.h:273
bool operator==(list_iterator const &other) const
Definition: rfc2616.h:248
value_type const & reference
Definition: rfc2616.h:237
list_iterator operator++(int)
Definition: rfc2616.h:280
T distance(T... args)
T end(T... args)
bool is_white(char c)
Returns true if c is any whitespace character.
Definition: rfc2616.h:70
bool is_lws(char c)
Returns true if c is linear white space.
Definition: rfc2616.h:63
FwdIter trim_right(FwdIter first, FwdIter last)
Definition: rfc2616.h:87
boost::iterator_range< list_iterator > make_list(boost::string_ref const &field)
Returns a range representing the list.
Definition: rfc2616.h:368
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:204
Result split(FwdIt first, FwdIt last, Char delim)
Parse a character sequence of values separated by commas.
Definition: rfc2616.h:128
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
Definition: rfc2616.h:391
bool ci_equal(boost::string_ref s1, boost::string_ref s2)
Returns true if two strings are equal.
Definition: rfc2616.h:361
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:381
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:50