TLA Line data Source code
1 : //
2 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.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/cppalliance/http
8 : //
9 :
10 : #include "src/rfc/detail/rules.hpp"
11 :
12 : #include <boost/http/error.hpp>
13 : #include <boost/http/detail/config.hpp>
14 : #include <boost/http/rfc/token_rule.hpp>
15 :
16 : #include <boost/core/detail/string_view.hpp>
17 : #include <boost/url/grammar/delim_rule.hpp>
18 : #include <boost/url/grammar/digit_chars.hpp>
19 : #include <boost/url/grammar/error.hpp>
20 : #include <boost/url/grammar/hexdig_chars.hpp>
21 : #include <boost/url/grammar/lut_chars.hpp>
22 : #include <boost/url/grammar/parse.hpp>
23 : #include <boost/url/grammar/tuple_rule.hpp>
24 :
25 : #include "src/rfc/detail/rules.hpp"
26 :
27 : namespace boost {
28 : namespace http {
29 : namespace detail {
30 :
31 : auto
32 HIT 28890 : crlf_rule_t::
33 : parse(
34 : char const*& it,
35 : char const* end) const noexcept ->
36 : system::result<value_type>
37 : {
38 28890 : if(it == end)
39 6535 : return grammar::error::need_more;
40 22355 : if(*it != '\r')
41 29 : return grammar::error::mismatch;
42 22326 : ++it;
43 22326 : if(it == end)
44 961 : return grammar::error::need_more;
45 21365 : if(*it != '\n')
46 51 : return grammar::error::mismatch;
47 21314 : ++it;
48 21314 : return {};
49 : }
50 :
51 : //------------------------------------------------
52 :
53 : auto
54 28506 : version_rule_t::
55 : parse(
56 : char const*& it,
57 : char const* end) const noexcept ->
58 : system::result<value_type>
59 : {
60 28506 : value_type v = 0;
61 28506 : if(it == end)
62 : {
63 : // expected "HTTP/"
64 1619 : return grammar::error::need_more;
65 : }
66 26887 : if(end - it >= 5)
67 : {
68 22177 : if(std::memcmp(
69 : it, "HTTP/", 5) != 0)
70 : {
71 MIS 0 : return grammar::error::mismatch;
72 : }
73 HIT 22177 : it += 5;
74 : }
75 26887 : if(it == end)
76 : {
77 : // expected DIGIT
78 1087 : return grammar::error::need_more;
79 : }
80 25800 : if(! grammar::digit_chars(*it))
81 : {
82 : // expected DIGIT
83 4710 : return grammar::error::need_more;
84 : }
85 21090 : v = 10 * (*it++ - '0');
86 21090 : if(it == end)
87 : {
88 : // expected "."
89 1213 : return grammar::error::need_more;
90 : }
91 19877 : if(*it != '.')
92 : {
93 : // expected "."
94 MIS 0 : return grammar::error::need_more;
95 : }
96 HIT 19877 : ++it;
97 19877 : if(it == end)
98 : {
99 : // expected DIGIT
100 1051 : return grammar::error::need_more;
101 : }
102 18826 : if(! grammar::digit_chars(*it))
103 : {
104 : // expected DIGIT
105 MIS 0 : return grammar::error::need_more;
106 : }
107 HIT 18826 : v += *it++ - '0';
108 18826 : return v;
109 : }
110 :
111 : //------------------------------------------------
112 :
113 : auto
114 8184 : status_code_rule_t::
115 : parse(
116 : char const*& it,
117 : char const* end) const noexcept ->
118 : system::result<value_type>
119 : {
120 : auto const dig =
121 19020 : [](char c) -> int
122 : {
123 19020 : unsigned char uc(c - '0');
124 19020 : if(uc > 9)
125 MIS 0 : return -1;
126 HIT 19020 : return uc;
127 : };
128 :
129 8184 : if(it == end)
130 : {
131 : // end
132 934 : return grammar::error::need_more;
133 : }
134 7250 : auto it0 = it;
135 7250 : int v = dig(*it);
136 7250 : if(v == -1)
137 : {
138 : // expected DIGIT
139 MIS 0 : return grammar::error::mismatch;
140 : }
141 HIT 7250 : value_type t;
142 7250 : t.v = 100 * v;
143 7250 : ++it;
144 7250 : if(it == end)
145 : {
146 : // end
147 916 : return grammar::error::need_more;
148 : }
149 6334 : v = dig(*it);
150 6334 : if(v == -1)
151 : {
152 : // expected DIGIT
153 MIS 0 : return grammar::error::mismatch;
154 : }
155 HIT 6334 : t.v = t.v + (10 * v);
156 6334 : ++it;
157 6334 : if(it == end)
158 : {
159 : // end
160 898 : return grammar::error::need_more;
161 : }
162 5436 : v = dig(*it);
163 5436 : if(v == -1)
164 : {
165 : // expected DIGIT
166 MIS 0 : return grammar::error::need_more;
167 : }
168 HIT 5436 : t.v = t.v + v;
169 5436 : ++it;
170 :
171 5436 : t.s = core::string_view(it0, it - it0);
172 5436 : t.st = int_to_status(t.v);
173 5436 : return t;
174 : }
175 :
176 : //------------------------------------------------
177 :
178 : auto
179 4556 : reason_phrase_rule_t::
180 : parse(
181 : char const*& it,
182 : char const* end) const noexcept ->
183 : system::result<value_type>
184 : {
185 4556 : auto begin = it;
186 4556 : it = grammar::find_if_not(it, end, ws_vchars);
187 4556 : return core::string_view(begin, it);
188 : }
189 :
190 : //------------------------------------------------
191 :
192 : auto
193 26365 : field_name_rule_t::
194 : parse(
195 : char const*& it,
196 : char const* end) const noexcept ->
197 : system::result<value_type>
198 : {
199 26365 : if( it == end )
200 1 : return grammar::error::need_more;
201 :
202 26364 : value_type v;
203 :
204 26364 : auto begin = it;
205 26364 : auto rv = grammar::parse(
206 : it, end, token_rule);
207 26364 : if( rv.has_error() || (it != end) )
208 : {
209 15941 : if( it != begin )
210 : {
211 15875 : v = core::string_view(begin, it - begin);
212 15875 : return v;
213 : }
214 132 : return make_error_code(
215 66 : error::bad_field_name);
216 : }
217 :
218 10423 : v = core::string_view(begin, end - begin);
219 10423 : return v;
220 : }
221 :
222 : auto
223 16144 : field_value_rule_t::
224 : parse(
225 : char const*& it,
226 : char const* end) const noexcept ->
227 : system::result<value_type>
228 : {
229 16144 : value_type v;
230 16144 : if( it == end )
231 : {
232 693 : v.value = core::string_view(it, 0);
233 693 : return v;
234 : }
235 :
236 : // field-line = field-name ":" OWS field-value OWS
237 : // field-value = *field-content
238 : // field-content = field-vchar
239 : // [ 1*( SP / HTAB / field-vchar ) field-vchar ]
240 : // field-vchar = VCHAR / obs-text
241 : // obs-text = %x80-FF
242 : // VCHAR = %x21-7E
243 : // ; visible (printing) characters
244 :
245 66585 : auto is_field_vchar = [](unsigned char ch)
246 : {
247 66585 : return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80;
248 : };
249 :
250 15451 : char const* s0 = nullptr;
251 15451 : char const* s1 = nullptr;
252 :
253 15451 : bool has_crlf = false;
254 15451 : bool has_obs_fold = false;
255 :
256 100095 : while( it < end )
257 : {
258 96599 : auto ch = *it;
259 96599 : if( ws(ch) )
260 : {
261 17363 : ++it;
262 17363 : continue;
263 : }
264 :
265 79236 : if( ch == '\r' )
266 : {
267 : // too short to know if we have a potential obs-fold
268 : // occurrence
269 12651 : if( end - it < 2 )
270 592 : return grammar::error::need_more;
271 :
272 12059 : if( it[1] != '\n' )
273 53 : goto done;
274 :
275 12006 : if( end - it < 3 )
276 546 : return grammar::error::need_more;
277 :
278 11460 : if(! ws(it[2]) )
279 : {
280 10730 : has_crlf = true;
281 10730 : goto done;
282 : }
283 :
284 730 : has_obs_fold = true;
285 730 : it = it + 3;
286 730 : continue;
287 : }
288 :
289 66585 : if(! is_field_vchar(ch) )
290 : {
291 34 : goto done;
292 : }
293 :
294 66551 : if(! s0 )
295 14348 : s0 = it;
296 :
297 66551 : ++it;
298 66551 : s1 = it;
299 : }
300 :
301 3496 : done:
302 : // later routines wind up doing pointer
303 : // subtraction using the .data() member
304 : // of the value so we need a valid 0-len range
305 14313 : if(! s0 )
306 : {
307 939 : s0 = it;
308 939 : s1 = s0;
309 : }
310 :
311 14313 : v.value = core::string_view(s0, s1 - s0);
312 14313 : v.has_crlf = has_crlf;
313 14313 : v.has_obs_fold = has_obs_fold;
314 14313 : return v;
315 : }
316 :
317 : auto
318 37744 : field_rule_t::
319 : parse(
320 : char const*& it,
321 : char const* end) const noexcept ->
322 : system::result<value_type>
323 : {
324 37744 : if(it == end)
325 : {
326 979 : return grammar::error::need_more;
327 : }
328 : // check for leading CRLF
329 36765 : if(it[0] == '\r')
330 : {
331 10641 : ++it;
332 10641 : if(it == end)
333 : {
334 489 : return grammar::error::need_more;
335 : }
336 10152 : if(*it != '\n')
337 : {
338 21 : return grammar::error::mismatch;
339 : }
340 : // end of fields
341 10131 : ++it;
342 10131 : return grammar::error::end_of_range;
343 : }
344 :
345 26124 : value_type v;
346 : auto rv = grammar::parse(
347 26124 : it, end, grammar::tuple_rule(
348 : field_name_rule,
349 26124 : grammar::delim_rule(':'),
350 : field_value_rule,
351 26124 : crlf_rule));
352 :
353 26124 : if( rv.has_error() )
354 15410 : return rv.error();
355 :
356 10714 : auto val = rv.value();
357 10714 : v.name = std::get<0>(val);
358 10714 : v.value = std::get<2>(val).value;
359 10714 : v.has_obs_fold = std::get<2>(val).has_obs_fold;
360 :
361 10714 : return v;
362 : }
363 :
364 : //------------------------------------------------
365 :
366 : void
367 244 : remove_obs_fold(
368 : char* it,
369 : char const* const end) noexcept
370 : {
371 2262 : while(it != end)
372 : {
373 2236 : if(*it != '\r')
374 : {
375 1637 : ++it;
376 1637 : continue;
377 : }
378 599 : if(end - it < 3)
379 218 : break;
380 381 : BOOST_ASSERT(it[1] == '\n');
381 762 : if( it[1] == '\n' &&
382 381 : ws(it[2]))
383 : {
384 378 : it[0] = ' ';
385 378 : it[1] = ' ';
386 378 : it += 3;
387 : }
388 : else
389 : {
390 3 : ++it;
391 : }
392 : }
393 244 : }
394 :
395 : } // detail
396 : } // http
397 : } // boost
|