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