summaryrefslogtreecommitdiff
path: root/src/include/taler_mhd_lib.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/taler_mhd_lib.h')
-rw-r--r--src/include/taler_mhd_lib.h417
1 files changed, 410 insertions, 7 deletions
diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h
index ba5a072c4..57d041758 100644
--- a/src/include/taler_mhd_lib.h
+++ b/src/include/taler_mhd_lib.h
@@ -27,10 +27,17 @@
#include <jansson.h>
#include <microhttpd.h>
#include "taler_error_codes.h"
+#include "taler_util.h"
#include <gnunet/gnunet_mhd_compat.h>
/**
+ * Maximum POST request size.
+ */
+#define TALER_MHD_REQUEST_BUFFER_MAX (1024 * 1024 * 16)
+
+
+/**
* Global options for response generation.
*/
enum TALER_MHD_GlobalOptions
@@ -166,8 +173,8 @@ TALER_MHD_reply_json_pack (struct MHD_Connection *connection,
* @return MHD result code
*/
#define TALER_MHD_REPLY_JSON_PACK(connection,response_code,...) \
- TALER_MHD_reply_json_steal (connection, GNUNET_JSON_PACK (__VA_ARGS__), \
- response_code)
+ TALER_MHD_reply_json_steal (connection, GNUNET_JSON_PACK (__VA_ARGS__), \
+ response_code)
/**
@@ -202,6 +209,18 @@ TALER_MHD_reply_with_ec (struct MHD_Connection *connection,
/**
+ * Produce HTTP "Date:" header.
+ *
+ * @param at time to write to @a date
+ * @param[out] date where to write the header, with
+ * at least 128 bytes available space.
+ */
+void
+TALER_MHD_get_date_string (struct GNUNET_TIME_Absolute at,
+ char date[128]);
+
+
+/**
* Make JSON response object.
*
* @param json the json object
@@ -240,10 +259,21 @@ TALER_MHD_make_json_pack (const char *fmt,
* @return MHD response object
*/
#define TALER_MHD_MAKE_JSON_PACK(...) \
- TALER_MHD_make_json_steal (GNUNET_JSON_PACK (__VA_ARGS__))
+ TALER_MHD_make_json_steal (GNUNET_JSON_PACK (__VA_ARGS__))
/**
+ * Pack Taler error code @a ec and associated hint into a
+ * JSON object.
+ *
+ * @param ec error code to pack
+ * @return packer array entries (two!)
+ */
+#define TALER_MHD_PACK_EC(ec) \
+ GNUNET_JSON_pack_uint64 ("code", ec), \
+ GNUNET_JSON_pack_string ("hint", TALER_ErrorCode_get_hint (ec))
+
+/**
* Create a response indicating an internal error.
*
* @param ec error code to return
@@ -408,7 +438,201 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection,
/**
- * Extract fixed-size base32crockford encoded data from request.
+ * Extract optional "timeout_ms" argument from request.
+ *
+ * @param connection the MHD connection
+ * @param[out] expiration set to #GNUNET_TIME_UNIT_ZERO_ABS if there was no timeout,
+ * the current time plus the value given under "timeout_ms" otherwise
+ * @return #GNUNET_OK on success, #GNUNET_NO if an
+ * error was returned on @a connection (caller should return #MHD_YES) and
+ * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO)
+ */
+enum GNUNET_GenericReturnValue
+TALER_MHD_parse_request_arg_timeout (struct MHD_Connection *connection,
+ struct GNUNET_TIME_Absolute *expiration);
+
+
+/**
+ * Extract optional "timeout_ms" argument from request.
+ * Macro that *returns* #MHD_YES/#MHD_NO if the "timeout_ms"
+ * argument existed but failed to parse.
+ *
+ * @param connection the MHD connection
+ * @param[out] expiration set to #GNUNET_TIME_UNIT_ZERO_ABS if there was no timeout,
+ * the current time plus the value given under "timeout_ms" otherwise
+ */
+#define TALER_MHD_parse_request_timeout(connection,expiration) \
+ do { \
+ switch (TALER_MHD_parse_request_arg_timeout (connection, \
+ expiration)) \
+ { \
+ case GNUNET_SYSERR: \
+ GNUNET_break (0); \
+ return MHD_NO; \
+ case GNUNET_NO: \
+ GNUNET_break_op (0); \
+ case GNUNET_OK: \
+ break; \
+ } \
+ } while (0)
+
+
+/**
+ * Extract optional numeric limit argument from request.
+ *
+ * @param connection the MHD connection
+ * @param name name of the query parameter
+ * @param[out] off set to the offset, unchanged if the
+ * option was not given
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and
+ * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO)
+ */
+enum GNUNET_GenericReturnValue
+TALER_MHD_parse_request_arg_number (struct MHD_Connection *connection,
+ const char *name,
+ uint64_t *off);
+
+
+/**
+ * Extract optional numeric argument from request.
+ * Macro that *returns* #MHD_YES/#MHD_NO if the
+ * requested argument existed but failed to parse.
+ *
+ * @param connection the MHD connection
+ * @param name name of the argument to parse
+ * @param[out] off set to the given numeric value,
+ * unchanged if value was not specified
+ */
+#define TALER_MHD_parse_request_number(connection,name,off) \
+ do { \
+ switch (TALER_MHD_parse_request_arg_number (connection, \
+ name, \
+ off)) \
+ { \
+ case GNUNET_SYSERR: \
+ GNUNET_break (0); \
+ return MHD_NO; \
+ case GNUNET_NO: \
+ GNUNET_break_op (0); \
+ case GNUNET_OK: \
+ break; \
+ } \
+ } while (0)
+
+
+/**
+ * Extract optional signed numeric limit argument from request.
+ *
+ * @param connection the MHD connection
+ * @param name name of the query parameter
+ * @param[out] val set to the signed value, unchanged if the
+ * option was not given
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and
+ * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO)
+ */
+enum GNUNET_GenericReturnValue
+TALER_MHD_parse_request_arg_snumber (struct MHD_Connection *connection,
+ const char *name,
+ int64_t *val);
+
+
+/**
+ * Extract optional numeric argument from request.
+ * Macro that *returns* #MHD_YES/#MHD_NO if the
+ * requested argument existed but failed to parse.
+ *
+ * @param connection the MHD connection
+ * @param name name of the argument to parse
+ * @param[out] val set to the given numeric value,
+ * unchanged if value was not specified
+ */
+#define TALER_MHD_parse_request_snumber(connection,name,val) \
+ do { \
+ switch (TALER_MHD_parse_request_arg_snumber (connection, \
+ name, \
+ val)) \
+ { \
+ case GNUNET_SYSERR: \
+ GNUNET_break (0); \
+ return MHD_NO; \
+ case GNUNET_NO: \
+ GNUNET_break_op (0); \
+ case GNUNET_OK: \
+ break; \
+ } \
+ } while (0)
+
+
+/**
+ * Extract optional amount argument from request.
+ *
+ * @param connection the MHD connection
+ * @param name name of the query parameter
+ * @param[out] val set to the amount, unchanged if the
+ * option was not given
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and
+ * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO)
+ */
+enum GNUNET_GenericReturnValue
+TALER_MHD_parse_request_arg_amount (struct MHD_Connection *connection,
+ const char *name,
+ struct TALER_Amount *val);
+
+
+/**
+ * Extract optional amount argument from request.
+ * Macro that *returns* #MHD_YES/#MHD_NO if the
+ * requested argument existed but failed to parse.
+ *
+ * @param connection the MHD connection
+ * @param name name of the argument to parse
+ * @param[out] val set to the given amount,
+ * unchanged if value was not specified
+ */
+#define TALER_MHD_parse_request_amount(connection,name,val) \
+ do { \
+ switch (TALER_MHD_parse_request_arg_amount (connection, \
+ name, \
+ val)) \
+ { \
+ case GNUNET_SYSERR: \
+ GNUNET_break (0); \
+ return MHD_NO; \
+ case GNUNET_NO: \
+ GNUNET_break_op (0); \
+ case GNUNET_OK: \
+ break; \
+ } \
+ } while (0)
+
+
+/**
+ * Determines which of the given choices is preferred
+ * by the client. Parses an HTTP header such as
+ * "Accept:" or "Language:" to find entries matching
+ * the list of strings given in the variadic argument
+ * list. Returns the index of the preferred choice.
+ *
+ * @param connection HTTP request handle
+ * @param header type of HTTP header to evaluate
+ * @param ... NULL-terminated list of choices to
+ * check for in the header
+ * @return -1 if none of the given choices is in
+ * the header, -2 if the header is missing,
+ * otherwise index of preferred choice in
+ * the varargs list
+ */
+int
+TALER_MHD_check_accept (struct MHD_Connection *connection,
+ const char *header,
+ ...);
+
+
+/**
+ * Extract fixed-size base32crockford encoded data from request argument.
*
* Queues an error response to the connection if the parameter is missing or
* invalid.
@@ -417,16 +641,195 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection,
* @param param_name the name of the parameter with the key
* @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_NO if the argument is malformed
* #GNUNET_SYSERR on internal error (error response could not be sent)
*/
enum GNUNET_GenericReturnValue
TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection,
const char *param_name,
void *out_data,
- size_t out_size);
+ size_t out_size,
+ bool *present);
+
+
+/**
+ * Extract fixed-size base32crockford encoded data from request header.
+ *
+ * Queues an error response to the connection if the parameter is missing or
+ * invalid.
+ *
+ * @param connection the MHD connection
+ * @param header_name the name of the HTTP header with the value
+ * @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 malformed
+ * #GNUNET_SYSERR on internal error (error response could not be sent)
+ */
+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);
+
+/**
+ * Extract fixed-size base32crockford encoded data from request.
+ *
+ * @param connection the MHD connection
+ * @param name the name of the parameter with the key
+ * @param[out] val pointer to store the result, type must determine size
+ * @param[in,out] required pass true to require presence of this argument; if 'false'
+ * set to true if the 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)
+ */
+#define TALER_MHD_parse_request_arg_auto(connection,name,val,required) \
+ do { \
+ bool p; \
+ switch (TALER_MHD_parse_request_arg_data (connection, name, \
+ val, sizeof (*val), &p)) \
+ { \
+ case GNUNET_SYSERR: \
+ GNUNET_break (0); \
+ return MHD_NO; \
+ case GNUNET_NO: \
+ GNUNET_break_op (0); \
+ return MHD_YES; \
+ case GNUNET_OK: \
+ if (required & (! p)) \
+ return TALER_MHD_reply_with_error ( \
+ connection, \
+ MHD_HTTP_BAD_REQUEST, \
+ TALER_EC_GENERIC_PARAMETER_MISSING, \
+ name); \
+ required = p; \
+ break; \
+ } \
+ } while (0)
+
+
+/**
+ * Extract required fixed-size base32crockford encoded data from request.
+ *
+ * @param connection the MHD connection
+ * @param name the name of the parameter with the key
+ * @param[out] val pointer to store the result, type must determine size
+ * @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)
+ */
+#define TALER_MHD_parse_request_arg_auto_t(connection,name,val) \
+ do { \
+ bool b = true; \
+ TALER_MHD_parse_request_arg_auto (connection,name,val,b); \
+ } while (0)
+
+/**
+ * Extract fixed-size base32crockford encoded data from request.
+ *
+ * @param connection the MHD connection
+ * @param name the name of the header with the key
+ * @param[out] val pointer to store the result, type must determine size
+ * @param[in,out] required pass true to require presence of this argument; if 'false'
+ * set to true if the 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)
+ */
+#define TALER_MHD_parse_request_header_auto(connection,name,val,required) \
+ do { \
+ bool p; \
+ switch (TALER_MHD_parse_request_header_data (connection, name, \
+ val, sizeof (*val), &p)) \
+ { \
+ case GNUNET_SYSERR: \
+ GNUNET_break (0); \
+ return MHD_NO; \
+ case GNUNET_NO: \
+ GNUNET_break_op (0); \
+ return MHD_YES; \
+ case GNUNET_OK: \
+ if (required & (! p)) \
+ return TALER_MHD_reply_with_error ( \
+ connection, \
+ MHD_HTTP_BAD_REQUEST, \
+ TALER_EC_GENERIC_PARAMETER_MISSING, \
+ name); \
+ required = p; \
+ break; \
+ } \
+ } while (0)
+
+
+/**
+ * Extract required fixed-size base32crockford encoded data from request.
+ *
+ * @param connection the MHD connection
+ * @param name the name of the header with the key
+ * @param[out] val pointer to store the result, type must determine size
+ * @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)
+ */
+#define TALER_MHD_parse_request_header_auto_t(connection,name,val) \
+ do { \
+ bool b = true; \
+ TALER_MHD_parse_request_header_auto (connection,name,val,b); \
+ } while (0)
+
+
+/**
+ * Check that the 'Content-Length' header is giving
+ * a length below @a max_len. If not, return an
+ * appropriate error response and return the
+ * correct #MHD_YES/#MHD_NO value from this function.
+ *
+ * @param connection the MHD connection
+ * @param max_len maximum allowed content length
+ * @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)
+ */
+enum GNUNET_GenericReturnValue
+TALER_MHD_check_content_length_ (struct MHD_Connection *connection,
+ unsigned long long max_len);
+
+
+/**
+ * Check that the 'Content-Length' header is giving
+ * a length below @a max_len. If not, return an
+ * appropriate error response and return the
+ * correct #MHD_YES/#MHD_NO value from this function.
+ *
+ * @param connection the MHD connection
+ * @param max_len maximum allowed content length
+ */
+#define TALER_MHD_check_content_length(connection,max_len) \
+ do { \
+ switch (TALER_MHD_check_content_length_ (connection, max_len)) \
+ { \
+ case GNUNET_SYSERR: \
+ GNUNET_break (0); \
+ return MHD_NO; \
+ case GNUNET_NO: \
+ GNUNET_break_op (0); \
+ return MHD_YES; \
+ case GNUNET_OK: \
+ break; \
+ } \
+ } while (0)
/**
@@ -530,7 +933,7 @@ struct TALER_MHD_Legal;
/**
* Load set of legal documents as specified in @a cfg in section @a section
- * where the Etag is given under the @param tagoption and the directory under
+ * where the Etag is given under the @a tagoption and the directory under
* the @a diroption.
*
* @param cfg configuration to use