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