rippled
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 #include <algorithm>
29 #include <cctype>
30 #include <iterator>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 namespace beast {
36 namespace rfc2616 {
37 
38 namespace 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 
57 inline bool
58 is_lws(char c)
59 {
60  return c == ' ' || c == '\t';
61 }
62 
64 inline bool
65 is_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 
80 template <class FwdIter>
81 FwdIter
82 trim_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 
95 template <class String>
96 String
97 trim_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 
117 template <
118  class FwdIt,
119  class Result = std::vector<
121  class Char>
122 Result
123 split(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 
194 template <
195  class FwdIt,
196  class Result = std::vector<
198 Result
199 split_commas(FwdIt first, FwdIt last)
200 {
201  return split(first, last, ',');
202 }
203 
204 template <class Result = std::vector<std::string>>
205 Result
206 split_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 
229 public:
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 
255  reference
256  operator*() const
257  {
258  return value_;
259  }
260 
261  pointer
262  operator->() const
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 
282 private:
283  template <class = void>
284  void
285  increment();
286 };
287 
288 template <class>
289 void
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 }
355 inline bool
356 ci_equal(boost::string_ref s1, boost::string_ref s2)
357 {
358  return boost::range::equal(s1, s2, detail::ci_equal_pred{});
359 }
360 
362 inline boost::iterator_range<list_iterator>
363 make_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 
374 template <class = void>
375 bool
376 token_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 
384 template <bool isRequest, class Body, class Fields>
385 bool
386 is_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
beast::rfc2616::list_iterator::value_type
boost::string_ref value_type
Definition: rfc2616.h:230
beast::rfc2616::list_iterator::it_
iter_type it_
Definition: rfc2616.h:225
std::basic_string
STL class.
beast::rfc2616::list_iterator::reference
value_type const & reference
Definition: rfc2616.h:232
beast::rfc2616::list_iterator::pointer
value_type const * pointer
Definition: rfc2616.h:231
utility
beast::rfc2616::list_iterator::operator==
bool operator==(list_iterator const &other) const
Definition: rfc2616.h:243
vector
beast::rfc2616::split
Result split(FwdIt first, FwdIt last, Char delim)
Parse a character sequence of values separated by commas.
Definition: rfc2616.h:123
beast::rfc2616::detail::ci_equal_pred::ci_equal_pred
ci_equal_pred()=default
iterator
std::forward_iterator_tag
std::distance
T distance(T... args)
beast::rfc2616::list_iterator::increment
void increment()
Definition: rfc2616.h:290
algorithm
beast::rfc2616::make_list
boost::iterator_range< list_iterator > make_list(boost::string_ref const &field)
Returns a range representing the list.
Definition: rfc2616.h:363
beast::rfc2616::detail::ci_equal_pred::operator()
bool operator()(char c1, char c2)
Definition: rfc2616.h:45
beast::rfc2616::is_keep_alive
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
Definition: rfc2616.h:386
beast::rfc2616::list_iterator::list_iterator
list_iterator(iter_type begin, iter_type end)
Definition: rfc2616.h:236
beast::rfc2616::list_iterator::operator->
pointer operator->() const
Definition: rfc2616.h:262
beast::rfc2616::list_iterator
Iterates through a comma separated list.
Definition: rfc2616.h:221
beast::rfc2616::detail::is_lws
bool is_lws(char c)
Returns true if c is linear white space.
Definition: rfc2616.h:58
beast::rfc2616::list_iterator::value_
boost::string_ref value_
Definition: rfc2616.h:227
beast::rfc2616::split_commas
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:199
beast::rfc2616::ci_equal
bool ci_equal(boost::string_ref s1, boost::string_ref s2)
Returns true if two strings are equal.
Definition: rfc2616.h:356
beast::rfc2616::list_iterator::operator*
reference operator*() const
Definition: rfc2616.h:256
beast::field
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
beast::rfc2616::detail::ci_equal_pred
Definition: rfc2616.h:40
beast::rfc2616::token_in_list
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
beast::rfc2616::detail::trim_right
FwdIter trim_right(FwdIter first, FwdIter last)
Definition: rfc2616.h:82
beast::rfc2616::list_iterator::operator++
list_iterator operator++(int)
Definition: rfc2616.h:275
beast::rfc2616::list_iterator::iter_type
boost::string_ref::const_iterator iter_type
Definition: rfc2616.h:223
std::begin
T begin(T... args)
beast::rfc2616::list_iterator::end_
iter_type end_
Definition: rfc2616.h:226
std::ptrdiff_t
cctype
std::end
T end(T... args)
beast::rfc2616::detail::is_white
bool is_white(char c)
Returns true if c is any whitespace character.
Definition: rfc2616.h:65
beast::rfc2616::list_iterator::operator++
list_iterator & operator++()
Definition: rfc2616.h:268
beast::rfc2616::list_iterator::operator!=
bool operator!=(list_iterator const &other) const
Definition: rfc2616.h:250
beast
Definition: base_uint.h:641
string