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_RFC7230_HPP
11 #define BOOST_BEAST_HTTP_RFC7230_HPP
12 
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/http/detail/rfc7230.hpp>
15 #include <boost/beast/http/detail/basic_parsed_list.hpp>
16 
17 namespace boost {
18 namespace beast {
19 namespace http {
20 
21 /** A list of parameters in an HTTP extension field value.
22 
23     This container allows iteration of the parameter list in an HTTP
24     extension. The parameter list is a series of name/value pairs
25     with each pair starting with a semicolon. The value is optional.
26 
27     If a parsing error is encountered while iterating the string,
28     the behavior of the container will be as if a string containing
29     only characters up to but excluding the first invalid character
30     was used to construct the list.
31 
32     @par BNF
33     @code
34         param-list  = *( OWS ";" OWS param )
35         param       = token OWS [ "=" OWS ( token / quoted-string ) ]
36     @endcode
37 
38     To use this class, construct with the string to be parsed and
39     then use @ref begin and @ref end, or range-for to iterate each
40     item:
41 
42     @par Example
43     @code
44     for(auto const& param : param_list{";level=9;no_context_takeover;bits=15"})
45     {
46         std::cout << ";" << param.first;
47         if(! param.second.empty())
48             std::cout << "=" << param.second;
49         std::cout << "\n";
50     }
51     @endcode
52 */
53 class param_list
54 {
55     string_view s_;
56 
57 public:
58     /** The type of each element in the list.
59 
60         The first string in the pair is the name of the parameter,
61         and the second string in the pair is its value (which may
62         be empty).
63     */
64     using value_type =
65         std::pair<string_view, string_view>;
66 
67     /// A constant iterator to the list
68 #if BOOST_BEAST_DOXYGEN
69     using const_iterator = __implementation_defined__;
70 #else
71     class const_iterator;
72 #endif
73 
74     /// Default constructor.
75     param_list() = default;
76 
77     /** Construct a list.
78 
79         @param s A string containing the list contents. The string
80         must remain valid for the lifetime of the container.
81     */
82     explicit
param_list(string_view s)83     param_list(string_view s)
84         : s_(s)
85     {
86     }
87 
88     /// Return a const iterator to the beginning of the list
89     const_iterator begin() const;
90 
91     /// Return a const iterator to the end of the list
92     const_iterator end() const;
93 
94     /// Return a const iterator to the beginning of the list
95     const_iterator cbegin() const;
96 
97     /// Return a const iterator to the end of the list
98     const_iterator cend() const;
99 };
100 
101 //------------------------------------------------------------------------------
102 
103 /** A list of extensions in a comma separated HTTP field value.
104 
105     This container allows iteration of the extensions in an HTTP
106     field value. The extension list is a comma separated list of
107     token parameter list pairs.
108 
109     If a parsing error is encountered while iterating the string,
110     the behavior of the container will be as if a string containing
111     only characters up to but excluding the first invalid character
112     was used to construct the list.
113 
114     @par BNF
115     @code
116         ext-list    = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
117         ext         = token param-list
118         param-list  = *( OWS ";" OWS param )
119         param       = token OWS [ "=" OWS ( token / quoted-string ) ]
120     @endcode
121 
122     To use this class, construct with the string to be parsed and
123     then use @ref begin and @ref end, or range-for to iterate each
124     item:
125 
126     @par Example
127     @code
128     for(auto const& ext : ext_list{"none, 7z;level=9, zip;no_context_takeover;bits=15"})
129     {
130         std::cout << ext.first << "\n";
131         for(auto const& param : ext.second)
132         {
133             std::cout << ";" << param.first;
134             if(! param.second.empty())
135                 std::cout << "=" << param.second;
136             std::cout << "\n";
137         }
138     }
139     @endcode
140 */
141 class ext_list
142 {
143     using iter_type = string_view::const_iterator;
144 
145     string_view s_;
146 
147 public:
148     /** The type of each element in the list.
149 
150         The first element of the pair is the extension token, and the
151         second element of the pair is an iterable container holding the
152         extension's name/value parameters.
153     */
154     using value_type = std::pair<string_view, param_list>;
155 
156     /// A constant iterator to the list
157 #if BOOST_BEAST_DOXYGEN
158     using const_iterator = __implementation_defined__;
159 #else
160     class const_iterator;
161 #endif
162 
163     /** Construct a list.
164 
165         @param s A string containing the list contents. The string
166         must remain valid for the lifetime of the container.
167     */
168     explicit
ext_list(string_view s)169     ext_list(string_view s)
170         : s_(s)
171     {
172     }
173 
174     /// Return a const iterator to the beginning of the list
175     const_iterator begin() const;
176 
177     /// Return a const iterator to the end of the list
178     const_iterator end() const;
179 
180     /// Return a const iterator to the beginning of the list
181     const_iterator cbegin() const;
182 
183     /// Return a const iterator to the end of the list
184     const_iterator cend() const;
185 
186     /** Find a token in the list.
187 
188         @param s The token to find. A case-insensitive comparison is used.
189 
190         @return An iterator to the matching token, or `end()` if no
191         token exists.
192     */
193     BOOST_BEAST_DECL
194     const_iterator
195     find(string_view const& s);
196 
197     /** Return `true` if a token is present in the list.
198 
199         @param s The token to find. A case-insensitive comparison is used.
200     */
201     BOOST_BEAST_DECL
202     bool
203     exists(string_view const& s);
204 };
205 
206 //------------------------------------------------------------------------------
207 
208 /** A list of tokens in a comma separated HTTP field value.
209 
210     This container allows iteration of a list of items in a
211     header field value. The input is a comma separated list of
212     tokens.
213 
214     If a parsing error is encountered while iterating the string,
215     the behavior of the container will be as if a string containing
216     only characters up to but excluding the first invalid character
217     was used to construct the list.
218 
219     @par BNF
220     @code
221         token-list  = *( "," OWS ) token *( OWS "," [ OWS token ] )
222     @endcode
223 
224     To use this class, construct with the string to be parsed and
225     then use @ref begin and @ref end, or range-for to iterate each
226     item:
227 
228     @par Example
229     @code
230     for(auto const& token : token_list{"apple, pear, banana"})
231         std::cout << token << "\n";
232     @endcode
233 */
234 class token_list
235 {
236     using iter_type = string_view::const_iterator;
237 
238     string_view s_;
239 
240 public:
241     /// The type of each element in the token list.
242     using value_type = string_view;
243 
244     /// A constant iterator to the list
245 #if BOOST_BEAST_DOXYGEN
246     using const_iterator = __implementation_defined__;
247 #else
248     class const_iterator;
249 #endif
250 
251     /** Construct a list.
252 
253         @param s A string containing the list contents. The string
254         must remain valid for the lifetime of the container.
255     */
256     explicit
token_list(string_view s)257     token_list(string_view s)
258         : s_(s)
259     {
260     }
261 
262     /// Return a const iterator to the beginning of the list
263     const_iterator begin() const;
264 
265     /// Return a const iterator to the end of the list
266     const_iterator end() const;
267 
268     /// Return a const iterator to the beginning of the list
269     const_iterator cbegin() const;
270 
271     /// Return a const iterator to the end of the list
272     const_iterator cend() const;
273 
274     /** Return `true` if a token is present in the list.
275 
276         @param s The token to find. A case-insensitive comparison is used.
277     */
278     BOOST_BEAST_DECL
279     bool
280     exists(string_view const& s);
281 };
282 
283 /** A list of tokens in a comma separated HTTP field value.
284 
285     This container allows iteration of a list of items in a
286     header field value. The input is a comma separated list of
287     tokens.
288 
289     If a parsing error is encountered while iterating the string,
290     the behavior of the container will be as if a string containing
291     only characters up to but excluding the first invalid character
292     was used to construct the list.
293 
294     @par BNF
295     @code
296         token-list  = *( "," OWS ) token *( OWS "," [ OWS token ] )
297     @endcode
298 
299     To use this class, construct with the string to be parsed and
300     then use `begin` and `end`, or range-for to iterate each item:
301 
302     @par Example
303     @code
304     for(auto const& token : token_list{"apple, pear, banana"})
305         std::cout << token << "\n";
306     @endcode
307 */
308 using opt_token_list =
309     detail::basic_parsed_list<
310         detail::opt_token_list_policy>;
311 
312 /** Returns `true` if a parsed list is parsed without errors.
313 
314     This function iterates a single pass through a parsed list
315     and returns `true` if there were no parsing errors, else
316     returns `false`.
317 */
318 template<class Policy>
319 bool
320 validate_list(detail::basic_parsed_list<
321     Policy> const& list);
322 
323 } // http
324 } // beast
325 } // boost
326 
327 #include <boost/beast/http/impl/rfc7230.hpp>
328 
329 #endif
330