diff options
Diffstat (limited to 'src/mhd/mhd_parsing.c')
-rw-r--r-- | src/mhd/mhd_parsing.c | 167 |
1 files changed, 155 insertions, 12 deletions
diff --git a/src/mhd/mhd_parsing.c b/src/mhd/mhd_parsing.c index ee647f4b7..b1f8417e4 100644 --- a/src/mhd/mhd_parsing.c +++ b/src/mhd/mhd_parsing.c @@ -86,25 +86,40 @@ TALER_MHD_parse_post_cleanup_callback (void *con_cls) } -enum GNUNET_GenericReturnValue -TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, - const char *param_name, - void *out_data, - size_t out_size) +/** + * Extract fixed-size base32crockford encoded data from request. + * + * Queues an error response to the connection if the parameter is missing or + * invalid. + * + * @param connection the MHD connection + * @param param_name the name of the HTTP key with the value + * @param kind whether to extract from header, argument or footer + * @param[out] out_data pointer to store the result + * @param out_size expected size of @a out_data + * @param[out] present set to true if argument was found + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +static enum GNUNET_GenericReturnValue +parse_request_data (struct MHD_Connection *connection, + const char *param_name, + enum MHD_ValueKind kind, + void *out_data, + size_t out_size, + bool *present) { const char *str; str = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, + kind, param_name); if (NULL == str) { - return (MHD_NO == - TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MISSING, - param_name)) - ? GNUNET_SYSERR : GNUNET_NO; + *present = false; + return GNUNET_OK; } if (GNUNET_OK != GNUNET_STRINGS_string_to_data (str, @@ -117,6 +132,79 @@ TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, TALER_EC_GENERIC_PARAMETER_MALFORMED, param_name)) ? GNUNET_SYSERR : GNUNET_NO; + *present = true; + return GNUNET_OK; +} + + +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, + const char *param_name, + void *out_data, + size_t out_size, + bool *present) +{ + return parse_request_data (connection, + param_name, + MHD_GET_ARGUMENT_KIND, + out_data, + out_size, + present); +} + + +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_header_data (struct MHD_Connection *connection, + const char *header_name, + void *out_data, + size_t out_size, + bool *present) +{ + return parse_request_data (connection, + header_name, + MHD_HEADER_KIND, + out_data, + out_size, + present); +} + + +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_timeout (struct MHD_Connection *connection, + struct GNUNET_TIME_Absolute *expiration) +{ + const char *ts; + char dummy; + unsigned long long tms; + + ts = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "timeout_ms"); + if (NULL == ts) + { + *expiration = GNUNET_TIME_UNIT_ZERO_ABS; + return GNUNET_OK; + } + if (1 != + sscanf (ts, + "%llu%c", + &tms, + &dummy)) + { + MHD_RESULT mret; + + GNUNET_break_op (0); + mret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "timeout_ms"); + return (MHD_YES == mret) + ? GNUNET_NO + : GNUNET_SYSERR; + } + *expiration = GNUNET_TIME_relative_to_absolute ( + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, + tms)); return GNUNET_OK; } @@ -262,4 +350,59 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection, } +enum GNUNET_GenericReturnValue +TALER_MHD_check_content_length_ (struct MHD_Connection *connection, + unsigned long long max_len) +{ + const char *cl; + unsigned long long cv; + char dummy; + + /* Maybe check for maximum upload size + and refuse requests if they are just too big. */ + cl = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_CONTENT_LENGTH); + if (NULL == cl) + { + return GNUNET_OK; +#if 0 + /* wallet currently doesn't always send content-length! */ + GNUNET_break_op (0); + return (MHD_YES == + TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MISSING, + MHD_HTTP_HEADER_CONTENT_LENGTH)) + ? GNUNET_NO + : GNUNET_SYSERR; +#endif + } + if (1 != sscanf (cl, + "%llu%c", + &cv, + &dummy)) + { + /* Not valid HTTP request, just close connection. */ + GNUNET_break_op (0); + return (MHD_YES == + TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + MHD_HTTP_HEADER_CONTENT_LENGTH)) + ? GNUNET_NO + : GNUNET_SYSERR; + } + if (cv > TALER_MHD_REQUEST_BUFFER_MAX) + { + GNUNET_break_op (0); + return (MHD_YES == + TALER_MHD_reply_request_too_large (connection)) + ? GNUNET_NO + : GNUNET_SYSERR; + } + return GNUNET_OK; +} + + /* end of mhd_parsing.c */ |