1// 2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3// 4// Distributed under the Boost Software License, Version 1.0. (See accompanying 5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6// 7// Official repository: https://github.com/boostorg/beast 8// 9 10#ifndef BOOST_BEAST_HTTP_IMPL_RFC7230_IPP 11#define BOOST_BEAST_HTTP_IMPL_RFC7230_IPP 12 13#include <boost/beast/http/rfc7230.hpp> 14#include <algorithm> 15 16namespace boost { 17namespace beast { 18namespace http { 19 20 21std::string 22param_list::const_iterator:: 23unquote(string_view sr) 24{ 25 std::string s; 26 s.reserve(sr.size()); 27 auto it = sr.begin() + 1; 28 auto end = sr.end() - 1; 29 while(it != end) 30 { 31 if(*it == '\\') 32 ++it; 33 s.push_back(*it); 34 ++it; 35 } 36 return s; 37} 38 39void 40param_list::const_iterator:: 41increment() 42{ 43 s_.clear(); 44 pi_.increment(); 45 if(pi_.empty()) 46 { 47 pi_.it = pi_.last; 48 pi_.first = pi_.last; 49 } 50 else if(! pi_.v.second.empty() && 51 pi_.v.second.front() == '"') 52 { 53 s_ = unquote(pi_.v.second); 54 pi_.v.second = string_view{ 55 s_.data(), s_.size()}; 56 } 57} 58 59void 60ext_list::const_iterator:: 61increment() 62{ 63 /* 64 ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] ) 65 ext = token param-list 66 param-list = *( OWS ";" OWS param ) 67 param = token OWS "=" OWS ( token / quoted-string ) 68 69 chunked;a=b;i=j;gzip;windowBits=12 70 x,y 71 ,,,,,chameleon 72 */ 73 auto const err = 74 [&] 75 { 76 it_ = last_; 77 first_ = last_; 78 }; 79 auto need_comma = it_ != first_; 80 v_.first = {}; 81 first_ = it_; 82 for(;;) 83 { 84 detail::skip_ows(it_, last_); 85 if(it_ == last_) 86 return err(); 87 auto const c = *it_; 88 if(detail::is_token_char(c)) 89 { 90 if(need_comma) 91 return err(); 92 auto const p0 = it_; 93 for(;;) 94 { 95 ++it_; 96 if(it_ == last_) 97 break; 98 if(! detail::is_token_char(*it_)) 99 break; 100 } 101 v_.first = string_view{&*p0, 102 static_cast<std::size_t>(it_ - p0)}; 103 if (it_ == last_) 104 return; 105 detail::param_iter pi; 106 pi.it = it_; 107 pi.first = it_; 108 pi.last = last_; 109 for(;;) 110 { 111 pi.increment(); 112 if(pi.empty()) 113 break; 114 } 115 v_.second = param_list{string_view{&*it_, 116 static_cast<std::size_t>(pi.it - it_)}}; 117 it_ = pi.it; 118 return; 119 } 120 if(c != ',') 121 return err(); 122 need_comma = false; 123 ++it_; 124 } 125} 126 127auto 128ext_list:: 129find(string_view const& s) -> const_iterator 130{ 131 return std::find_if(begin(), end(), 132 [&s](value_type const& v) 133 { 134 return beast::iequals(s, v.first); 135 }); 136} 137 138bool 139ext_list:: 140exists(string_view const& s) 141{ 142 return find(s) != end(); 143} 144 145void 146token_list::const_iterator:: 147increment() 148{ 149 /* 150 token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] ) 151 */ 152 auto const err = 153 [&] 154 { 155 it_ = last_; 156 first_ = last_; 157 }; 158 auto need_comma = it_ != first_; 159 v_ = {}; 160 first_ = it_; 161 for(;;) 162 { 163 detail::skip_ows(it_, last_); 164 if(it_ == last_) 165 return err(); 166 auto const c = *it_; 167 if(detail::is_token_char(c)) 168 { 169 if(need_comma) 170 return err(); 171 auto const p0 = it_; 172 for(;;) 173 { 174 ++it_; 175 if(it_ == last_) 176 break; 177 if(! detail::is_token_char(*it_)) 178 break; 179 } 180 v_ = string_view{&*p0, 181 static_cast<std::size_t>(it_ - p0)}; 182 return; 183 } 184 if(c != ',') 185 return err(); 186 need_comma = false; 187 ++it_; 188 } 189} 190 191bool 192token_list:: 193exists(string_view const& s) 194{ 195 return std::find_if(begin(), end(), 196 [&s](value_type const& v) 197 { 198 return beast::iequals(s, v); 199 } 200 ) != end(); 201} 202 203} // http 204} // beast 205} // boost 206 207#endif // BOOST_BEAST_HTTP_IMPL_RFC7230_IPP 208