rippled
Loading...
Searching...
No Matches
rfc2616.h
1#pragma once
2
3#include <boost/beast/http/message.hpp>
4#include <boost/beast/http/rfc7230.hpp>
5#include <boost/range/algorithm/equal.hpp>
6#include <boost/range/iterator_range.hpp>
7#include <boost/utility/string_ref.hpp>
8
9#include <algorithm>
10#include <cctype>
11#include <iterator>
12#include <string>
13#include <vector>
14
15namespace beast {
16namespace rfc2616 {
17
18namespace detail {
19
21{
22 explicit ci_equal_pred() = default;
23
24 bool
25 operator()(char c1, char c2)
26 {
27 // VFALCO TODO Use a table lookup here
28 return std::tolower(static_cast<unsigned char>(c1)) ==
29 std::tolower(static_cast<unsigned char>(c2));
30 }
31};
32
37inline bool
38is_lws(char c)
39{
40 return c == ' ' || c == '\t';
41}
42
44inline bool
45is_white(char c)
46{
47 switch (c)
48 {
49 case ' ':
50 case '\f':
51 case '\n':
52 case '\r':
53 case '\t':
54 case '\v':
55 return true;
56 };
57 return false;
58}
59
60template <class FwdIter>
61FwdIter
62trim_right(FwdIter first, FwdIter last)
63{
64 if (first == last)
65 return last;
66 do
67 {
68 --last;
69 if (!is_white(*last))
70 return ++last;
71 } while (last != first);
72 return first;
73}
74
75template <class String>
76String
77trim_right(String const& s)
78{
79 using std::begin;
80 using std::end;
81 auto first(begin(s));
82 auto last(end(s));
83 last = trim_right(first, last);
84 return {first, last};
85}
86
87} // namespace detail
88
97template <
98 class FwdIt,
100 class Char>
101Result
102split(FwdIt first, FwdIt last, Char delim)
103{
104 using namespace detail;
105 using string = typename Result::value_type;
106
107 Result result;
108
109 FwdIt iter = first;
110 string e;
111 while (iter != last)
112 {
113 if (*iter == '"')
114 {
115 // quoted-string
116 ++iter;
117 while (iter != last)
118 {
119 if (*iter == '"')
120 {
121 ++iter;
122 break;
123 }
124
125 if (*iter == '\\')
126 {
127 // quoted-pair
128 ++iter;
129 if (iter != last)
130 e.append(1, *iter++);
131 }
132 else
133 {
134 // qdtext
135 e.append(1, *iter++);
136 }
137 }
138 if (!e.empty())
139 {
140 result.emplace_back(std::move(e));
141 e.clear();
142 }
143 }
144 else if (*iter == delim)
145 {
146 e = trim_right(e);
147 if (!e.empty())
148 {
149 result.emplace_back(std::move(e));
150 e.clear();
151 }
152 ++iter;
153 }
154 else if (is_lws(*iter))
155 {
156 ++iter;
157 }
158 else
159 {
160 e.append(1, *iter++);
161 }
162 }
163
164 if (!e.empty())
165 {
166 e = trim_right(e);
167 if (!e.empty())
168 result.emplace_back(std::move(e));
169 }
170 return result;
171}
172
173template <
174 class FwdIt,
176Result
177split_commas(FwdIt first, FwdIt last)
178{
179 return split(first, last, ',');
180}
181
182template <class Result = std::vector<std::string>>
183Result
184split_commas(boost::beast::string_view const& s)
185{
186 return split_commas(s.begin(), s.end());
187}
188
189//------------------------------------------------------------------------------
190
200{
201 using iter_type = boost::string_ref::const_iterator;
202
205 boost::string_ref value_;
206
207public:
208 using value_type = boost::string_ref;
209 using pointer = value_type const*;
210 using reference = value_type const&;
213
214 list_iterator(iter_type begin, iter_type end) : it_(begin), end_(end)
215 {
216 if (it_ != end_)
217 increment();
218 }
219
220 bool
221 operator==(list_iterator const& other) const
222 {
223 return other.it_ == it_ && other.end_ == end_ && other.value_.size() == value_.size();
224 }
225
226 bool
227 operator!=(list_iterator const& other) const
228 {
229 return !(*this == other);
230 }
231
233 operator*() const
234 {
235 return value_;
236 }
237
238 pointer
240 {
241 return &*(*this);
242 }
243
246 {
247 increment();
248 return *this;
249 }
250
253 {
254 auto temp = *this;
255 ++(*this);
256 return temp;
257 }
258
259private:
260 template <class = void>
261 void
262 increment();
263};
264
265template <class>
266void
268{
269 using namespace detail;
270 value_.clear();
271 while (it_ != end_)
272 {
273 if (*it_ == '"')
274 {
275 // quoted-string
276 ++it_;
277 if (it_ == end_)
278 return;
279 if (*it_ != '"')
280 {
281 auto start = it_;
282 for (;;)
283 {
284 ++it_;
285 if (it_ == end_)
286 {
287 value_ = boost::string_ref(&*start, std::distance(start, it_));
288 return;
289 }
290 if (*it_ == '"')
291 {
292 value_ = boost::string_ref(&*start, std::distance(start, it_));
293 ++it_;
294 return;
295 }
296 }
297 }
298 ++it_;
299 }
300 else if (*it_ == ',')
301 {
302 it_++;
303 continue;
304 }
305 else if (is_lws(*it_))
306 {
307 ++it_;
308 continue;
309 }
310 else
311 {
312 auto start = it_;
313 for (;;)
314 {
315 ++it_;
316 if (it_ == end_ || *it_ == ',' || is_lws(*it_))
317 {
318 value_ = boost::string_ref(&*start, std::distance(start, it_));
319 return;
320 }
321 }
322 }
323 }
324}
329inline bool
330ci_equal(boost::string_ref s1, boost::string_ref s2)
331{
332 return boost::range::equal(s1, s2, detail::ci_equal_pred{});
333}
334
336inline boost::iterator_range<list_iterator>
337make_list(boost::string_ref const& field)
338{
339 return boost::iterator_range<list_iterator>{
340 list_iterator{field.begin(), field.end()}, list_iterator{field.end(), field.end()}};
341}
342
347template <class = void>
348bool
349token_in_list(boost::string_ref const& value, boost::string_ref const& token)
350{
351 for (auto const& item : make_list(value))
352 if (ci_equal(item, token))
353 return true;
354 return false;
355}
356
357template <bool isRequest, class Body, class Fields>
358bool
359is_keep_alive(boost::beast::http::message<isRequest, Body, Fields> const& m)
360{
361 if (m.version() <= 10)
362 return boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists(
363 "keep-alive");
364 return !boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists(
365 "close");
366}
367
368} // namespace rfc2616
369} // namespace beast
T begin(T... args)
Iterates through a comma separated list.
Definition rfc2616.h:200
pointer operator->() const
Definition rfc2616.h:239
boost::string_ref::const_iterator iter_type
Definition rfc2616.h:201
value_type const * pointer
Definition rfc2616.h:209
list_iterator(iter_type begin, iter_type end)
Definition rfc2616.h:214
boost::string_ref value_
Definition rfc2616.h:205
boost::string_ref value_type
Definition rfc2616.h:208
bool operator!=(list_iterator const &other) const
Definition rfc2616.h:227
reference operator*() const
Definition rfc2616.h:233
list_iterator & operator++()
Definition rfc2616.h:245
bool operator==(list_iterator const &other) const
Definition rfc2616.h:221
value_type const & reference
Definition rfc2616.h:210
list_iterator operator++(int)
Definition rfc2616.h:252
T distance(T... args)
T end(T... args)
bool is_white(char c)
Returns true if c is any whitespace character.
Definition rfc2616.h:45
bool is_lws(char c)
Returns true if c is linear white space.
Definition rfc2616.h:38
FwdIter trim_right(FwdIter first, FwdIter last)
Definition rfc2616.h:62
boost::iterator_range< list_iterator > make_list(boost::string_ref const &field)
Returns a range representing the list.
Definition rfc2616.h:337
Result split_commas(FwdIt first, FwdIt last)
Definition rfc2616.h:177
Result split(FwdIt first, FwdIt last, Char delim)
Parse a character sequence of values separated by commas.
Definition rfc2616.h:102
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
Definition rfc2616.h:359
bool ci_equal(boost::string_ref s1, boost::string_ref s2)
Returns true if two strings are equal.
Definition rfc2616.h:330
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:349
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:133
bool operator()(char c1, char c2)
Definition rfc2616.h:25