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