RESTinio
Loading...
Searching...
No Matches
content-disposition.hpp
Go to the documentation of this file.
1/*
2 * RESTinio
3 */
4
5/*!
6 * @file
7 * @brief Stuff related to value of Content-Disposition HTTP-field.
8 *
9 * @since v.0.6.1
10 */
11
12#pragma once
13
14#include <restinio/helpers/http_field_parsers/basics.hpp>
15
16#include <restinio/helpers/http_field_parsers/details/pct_encoded_symbols.hpp>
17
18namespace restinio
19{
20
21namespace http_field_parsers
22{
23
25{
26
27namespace ep_impl = restinio::easy_parser::impl;
28namespace hfp_impl = restinio::http_field_parsers::impl;
29namespace hfp_details = restinio::http_field_parsers::details;
30
31//
32// regular_token_producer_t
33//
34/*!
35 * @brief A producer for token that is a "regular parameter name" in sense of
36 * RCF6266 and RCF5987
37 *
38 * A regular parameter name can't have '*' symbol at the end.
39 *
40 * See: https://tools.ietf.org/html/rfc5987#section-3.2 and
41 * https://tools.ietf.org/html/rfc6266#section-4.1
42 *
43 * @since v.0.6.1
44 */
46 : public hfp_impl::token_producer_t
47{
48public:
49 [[nodiscard]]
51 try_parse( ep_impl::source_t & from ) const
52 {
53 ep_impl::source_t::content_consumer_t consumer{ from };
54 const auto result = hfp_impl::token_producer_t::try_parse( from );
55 if( result )
56 {
57 if( '*' == *(result->rbegin()) )
58 {
59 // Regular token can't have the trailing '*'.
60 return make_unexpected( parse_error_t{
61 consumer.started_at() + result->size() - 1,
63 } );
64 }
65
66 consumer.commit();
67 }
68
69 return result;
70 }
71};
72
73//
74// ext_token_producer_t
75//
76/*!
77 * @brief A producer for token that is an "extended parameter name" in sense of
78 * RCF6266 and RCF5987
79 *
80 * An extended parameter name has '*' symbol at the end.
81 *
82 * See: https://tools.ietf.org/html/rfc5987#section-3.2 and
83 * https://tools.ietf.org/html/rfc6266#section-4.1
84 *
85 * @since v.0.6.1
86 */
88 : public hfp_impl::token_producer_t
89{
90public:
91 [[nodiscard]]
93 try_parse( ep_impl::source_t & from ) const
94 {
95 ep_impl::source_t::content_consumer_t consumer{ from };
96 const auto result = hfp_impl::token_producer_t::try_parse( from );
97 if( result )
98 {
99 if( '*' != *(result->rbegin()) )
100 {
101 // Extended token should have the trailing '*'.
102 return make_unexpected( parse_error_t{
103 consumer.started_at(),
105 } );
106 }
107
108 consumer.commit();
109 }
110
111 return result;
112 }
113};
114
115//
116// mime_charsetc_predicate_t
117//
118/*!
119 * @brief A preducate for symbol_producer_template that checks that
120 * a symbol is mime-charsetc symbol from RCF5987.
121 *
122 * See: https://tools.ietf.org/html/rfc5987#section-3.2
123 *
124 * @since v.0.6.1
125 */
127{
128 [[nodiscard]]
129 bool
130 operator()( const char actual ) const noexcept
131 {
132 return hfp_impl::is_alpha(actual)
133 || hfp_impl::is_digit(actual)
134 || '!' == actual
135 || '#' == actual
136 || '$' == actual
137 || '%' == actual
138 || '&' == actual
139 || '+' == actual
140 || '-' == actual
141 || '^' == actual
142 || '_' == actual
143 || '`' == actual
144 || '{' == actual
145 || '}' == actual
146 || '~' == actual
147 ;
148 }
149};
150
151//
152// mime_charsetc_symbol_producer
153//
154/*!
155 * @brief A factory for producer that extracts mime-charsetc symbols.
156 *
157 * See: https://tools.ietf.org/html/rfc5987#section-3.2
158 *
159 * @since v.0.6.1
160 */
161[[nodiscard]]
162inline auto
164{
165 return ep_impl::symbol_producer_template_t< mime_charsetc_predicate_t >{};
166}
167
168//
169// language_predicate_t
170//
171/*!
172 * @brief A preducate for symbol_producer_template that checks that
173 * a symbol is language symbol from RCF5646.
174 *
175 * @attention
176 * In the current version of RESTinio only the presence of characters
177 * defined in RFC5646 is checked. But those characters can form illegal
178 * sequencies.
179 *
180 * See: https://tools.ietf.org/html/rfc5646#section-2.1
181 *
182 * @since v.0.6.1
183 */
185{
186 [[nodiscard]]
187 bool
188 operator()( const char actual ) const noexcept
189 {
190 return hfp_impl::is_alpha(actual)
191 || hfp_impl::is_digit(actual)
192 || '-' == actual
193 ;
194 }
195};
196
197//
198// language_symbol_producer
199//
200/*!
201 * @brief A factory for producer that extracts language symbols.
202 *
203 * @since v.0.6.1
204 */
205[[nodiscard]]
206inline auto
208{
209 return ep_impl::symbol_producer_template_t< language_predicate_t >{};
210}
211
212//
213// attr_char_predicate_t
214//
215/*!
216 * @brief A preducate for symbol_producer_template that checks that
217 * a symbol is attr-char symbol from RCF5987.
218 *
219 * See: https://tools.ietf.org/html/rfc5987#section-3.2
220 *
221 * @since v.0.6.1
222 */
224{
225 [[nodiscard]]
226 bool
227 operator()( const char actual ) const noexcept
228 {
229 return hfp_impl::is_alpha(actual)
230 || hfp_impl::is_digit(actual)
231 || '!' == actual
232 || '#' == actual
233 || '$' == actual
234 || '&' == actual
235 || '+' == actual
236 || '-' == actual
237 || '.' == actual
238 || '^' == actual
239 || '_' == actual
240 || '`' == actual
241 || '|' == actual
242 || '~' == actual
243 ;
244 }
245};
246
247//
248// attr_char_symbol_producer
249//
250/*!
251 * @brief A factory for producer that extracts attr-char symbols.
252 *
253 * See: https://tools.ietf.org/html/rfc5987#section-3.2
254 *
255 * @since v.0.6.1
256 */
257[[nodiscard]]
258inline auto
260{
261 return ep_impl::symbol_producer_template_t< attr_char_predicate_t >{};
262}
263
264//
265// ext_parameter_value_producer
266//
267/*!
268 * @brief A producer for an "extended parameter value" in sense of
269 * RCF6266 and RCF5987
270 *
271 * This producer return std::string object.
272 *
273 * It handles the following rules:
274@verbatim
275ext-value = mime-charset "'" [ language ] "'" value-chars
276
277mime-charset = 1*mime-charsetc
278mime-charsetc = ALPHA / DIGIT
279 / "!" / "#" / "$" / "%" / "&"
280 / "+" / "-" / "^" / "_" / "`"
281 / "{" / "}" / "~"
282
283language = 0*language-char
284language-char = ALPHA / DIGIT / "-"
285
286value-chars = *( pct-encoded / attr-char )
287
288pct-encoded = "%" HEXDIG HEXDIG
289
290attr-char = ALPHA / DIGIT
291 / "!" / "#" / "$" / "&" / "+" / "-" / "."
292 / "^" / "_" / "`" / "|" / "~"
293@endverbatim
294 *
295 * @since v.0.6.1
296 */
297[[nodiscard]]
298inline auto
300{
301 return produce< std::string >(
302 repeat( 1, N, mime_charsetc_symbol_p() >> to_container() ),
303 symbol_p( '\'' ) >> to_container(),
304 repeat( 0, N, language_symbol_p() >> to_container() ),
305 symbol_p( '\'' ) >> to_container(),
306 repeat( 0, N,
307 alternatives(
308 attr_char_symbol_p() >> to_container(),
309 hfp_details::pct_encoded_symbols_p() >>
310 hfp_details::pct_encoded_symbols_consumer_t{} )
311 )
312 );
313}
314
315} /* namespace content_disposition_details */
316
317//
318// content_disposition_value_t
319//
320/*!
321 * @brief Tools for working with the value of Content-Disposition HTTP-field.
322 *
323 * This struct represents parsed value of HTTP-field Content-Disposition
324 * (see https://tools.ietf.org/html/rfc6266).
325 *
326 * @note
327 * - the main value of Content-Disposition field is converted to lower case;
328 * - parameter names are converted to lower case during the parsing;
329 * - parameter values are left as they are;
330 * - values of extended parameters are left as they are (it means that if
331 * there is "filename*=utf-8''Some%20name" then the value of
332 * "filename*" parameter will be "utf-8''Some%20name").
333 *
334 * @since v.0.6.1
335 */
337{
339
341
342 std::string value;
344
345 /*!
346 * @brief A factory function for a parser of Content-Disposition value.
347 *
348 * @since v.0.6.1
349 */
350 [[nodiscard]]
351 static auto
353 {
354 using namespace content_disposition_details;
355
356 return produce< content_disposition_value_t >(
357 token_p() >> to_lower()
358 >> &content_disposition_value_t::value,
359 produce< parameter_container_t >(
360 repeat( 0, N,
361 produce< parameter_t >(
362 ows(),
363 symbol(';'),
364 ows(),
365 alternatives(
366 sequence(
367 regular_token_producer_t{}
368 >> to_lower() >> &parameter_t::first,
369 symbol('='),
370 alternatives(
371 token_p() >> &parameter_t::second,
372 quoted_string_p() >> &parameter_t::second
373 )
374 ),
375 sequence(
376 ext_token_producer_t{}
377 >> to_lower() >> &parameter_t::first,
378 symbol('='),
379 ext_parameter_value_p() >> &parameter_t::second
380 )
381 )
382 ) >> to_container()
383 )
384 ) >> &content_disposition_value_t::parameters
385 );
386 }
387
388 /*!
389 * @brief An attempt to parse Content-Disposition HTTP-field.
390 *
391 * @since v.0.6.1
392 */
393 [[nodiscard]]
395 try_parse( string_view_t what )
396 {
397 return restinio::easy_parser::try_parse( what, make_parser() );
398 }
399};
400
401} /* namespace http_field_parsers */
402
403} /* namespace restinio */
A helper class to automatically return acquired content back to the input stream.
void commit() noexcept
Consume all acquired content.
The class that implements "input stream".
Information about parsing error.
A producer for token that is an "extended parameter name" in sense of RCF6266 and RCF5987.
expected_t< result_type, parse_error_t > try_parse(ep_impl::source_t &from) const
A producer for token that is a "regular parameter name" in sense of RCF6266 and RCF5987.
expected_t< result_type, parse_error_t > try_parse(ep_impl::source_t &from) const
constexpr bool is_digit(const char ch) noexcept
Is a character a decimal digit?
error_reason_t
Reason of parsing error.
@ unexpected_character
Unexpected character is found in the input.
@ pattern_not_found
Required pattern is not found in the input.
auto ext_parameter_value_p()
A producer for an "extended parameter value" in sense of RCF6266 and RCF5987.
auto language_symbol_p()
A factory for producer that extracts language symbols.
auto mime_charsetc_symbol_p()
A factory for producer that extracts mime-charsetc symbols.
auto attr_char_symbol_p()
A factory for producer that extracts attr-char symbols.
constexpr bool is_alpha(const char ch) noexcept
Is a character an ALPHA?
Definition basics.hpp:265
std::pair< std::string, std::string > parameter_with_mandatory_value_t
A type that describes a parameter with mandatory value.
Definition basics.hpp:1523
A preducate for symbol_producer_template that checks that a symbol is attr-char symbol from RCF5987.
A preducate for symbol_producer_template that checks that a symbol is language symbol from RCF5646.
A preducate for symbol_producer_template that checks that a symbol is mime-charsetc symbol from RCF59...
Tools for working with the value of Content-Disposition HTTP-field.
static auto make_parser()
A factory function for a parser of Content-Disposition value.
static expected_t< content_disposition_value_t, restinio::easy_parser::parse_error_t > try_parse(string_view_t what)
An attempt to parse Content-Disposition HTTP-field.