RESTinio
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 
18 namespace restinio
19 {
20 
21 namespace http_field_parsers
22 {
23 
25 {
26 
27 namespace ep_impl = restinio::easy_parser::impl;
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 {
48 public:
49  [[nodiscard]]
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,
62  error_reason_t::unexpected_character
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 {
90 public:
91  [[nodiscard]]
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(),
104  error_reason_t::pattern_not_found
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]]
162 inline 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]]
206 inline 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]]
258 inline 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
275 ext-value = mime-charset "'" [ language ] "'" value-chars
276 
277 mime-charset = 1*mime-charsetc
278 mime-charsetc = ALPHA / DIGIT
279  / "!" / "#" / "$" / "%" / "&"
280  / "+" / "-" / "^" / "_" / "`"
281  / "{" / "}" / "~"
282 
283 language = 0*language-char
284 language-char = ALPHA / DIGIT / "-"
285 
286 value-chars = *( pct-encoded / attr-char )
287 
288 pct-encoded = "%" HEXDIG HEXDIG
289 
290 attr-char = ALPHA / DIGIT
291  / "!" / "#" / "$" / "&" / "+" / "-" / "."
292  / "^" / "_" / "`" / "|" / "~"
293 @endverbatim
294  *
295  * @since v.0.6.1
296  */
297 [[nodiscard]]
298 inline 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 
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]]
396  {
397  return restinio::easy_parser::try_parse( what, make_parser() );
398  }
399 };
400 
401 } /* namespace http_field_parsers */
402 
403 } /* namespace restinio */
expected_t< std::optional< string_view_t >, not_found_t > find_first(const parameter_with_optional_value_container_t &where, string_view_t what)
A helper function to find the first occurence of a parameter with the specified value.
Definition: basics.hpp:1740
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 attr-char symbol from RCF5987...
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
A producer for token that is an "extended parameter name" in sense of RCF6266 and RCF5987...
auto ext_parameter_value_p()
A producer for an "extended parameter value" in sense of RCF6266 and RCF5987.
static auto make_parser()
A factory function for a parser of Content-Disposition value.
auto attr_char_symbol_p()
A factory for producer that extracts attr-char symbols.
expected_t< result_type, parse_error_t > try_parse(ep_impl::source_t &from) const
expected_t< result_type, parse_error_t > try_parse(ep_impl::source_t &from) const
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.
A producer for token that is a "regular parameter name" in sense of RCF6266 and RCF5987.
Tools for working with the value of Content-Disposition HTTP-field.
auto mime_charsetc_symbol_p()
A factory for producer that extracts mime-charsetc symbols.
A preducate for symbol_producer_template that checks that a symbol is mime-charsetc symbol from RCF59...
auto language_symbol_p()
A factory for producer that extracts language symbols.