diff options
Diffstat (limited to 'src/mint/taler-mint-httpd_mhd.c')
-rw-r--r-- | src/mint/taler-mint-httpd_mhd.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/src/mint/taler-mint-httpd_mhd.c b/src/mint/taler-mint-httpd_mhd.c new file mode 100644 index 000000000..09f3025b8 --- /dev/null +++ b/src/mint/taler-mint-httpd_mhd.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | This file is part of TALER | ||
3 | (C) 2014 GNUnet e.V. | ||
4 | |||
5 | TALER is free software; you can redistribute it and/or modify it under the | ||
6 | terms of the GNU Affero General Public License as published by the Free Software | ||
7 | Foundation; either version 3, or (at your option) any later version. | ||
8 | |||
9 | TALER is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU Affero General Public License along with | ||
14 | TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file taler-mint-httpd_mhd.c | ||
19 | * @brief helpers for MHD interaction | ||
20 | * @author Florian Dold | ||
21 | * @author Benedikt Mueller | ||
22 | * @author Christian Grothoff | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include <gnunet/gnunet_util_lib.h> | ||
26 | #include <jansson.h> | ||
27 | #include <microhttpd.h> | ||
28 | #include <libpq-fe.h> | ||
29 | #include <pthread.h> | ||
30 | #include "taler_microhttpd_lib.h" | ||
31 | #include "taler-mint-httpd.h" | ||
32 | #include "taler-mint-httpd_mhd.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Function to call to handle the request by sending | ||
37 | * back static data from the @a rh. | ||
38 | * | ||
39 | * @param rh context of the handler | ||
40 | * @param connection the MHD connection to handle | ||
41 | * @param[IN|OUT] connection_cls the connection's closure (can be updated) | ||
42 | * @param upload_data upload data | ||
43 | * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data | ||
44 | * @return MHD result code | ||
45 | */ | ||
46 | int | ||
47 | TALER_MINT_handler_static_response (struct RequestHandler *rh, | ||
48 | struct MHD_Connection *connection, | ||
49 | void **connection_cls, | ||
50 | const char *upload_data, | ||
51 | size_t *upload_data_size) | ||
52 | { | ||
53 | struct MHD_Response *response; | ||
54 | int ret; | ||
55 | |||
56 | if (0 == rh->data_size) | ||
57 | rh->data_size = strlen ((const char *) rh->data); | ||
58 | response = MHD_create_response_from_buffer (rh->data_size, | ||
59 | (void *) rh->data, | ||
60 | MHD_RESPMEM_PERSISTENT); | ||
61 | if (NULL == response) | ||
62 | { | ||
63 | GNUNET_break (0); | ||
64 | return MHD_NO; | ||
65 | } | ||
66 | if (NULL != rh->mime_type) | ||
67 | (void) MHD_add_response_header (response, | ||
68 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
69 | rh->mime_type); | ||
70 | ret = MHD_queue_response (connection, | ||
71 | rh->response_code, | ||
72 | response); | ||
73 | MHD_destroy_response (response); | ||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | |||
78 | /** | ||
79 | * Function to call to handle the request by sending | ||
80 | * back a redirect to the AGPL source code. | ||
81 | * | ||
82 | * @param rh context of the handler | ||
83 | * @param connection the MHD connection to handle | ||
84 | * @param[IN|OUT] connection_cls the connection's closure (can be updated) | ||
85 | * @param upload_data upload data | ||
86 | * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data | ||
87 | * @return MHD result code | ||
88 | */ | ||
89 | int | ||
90 | TALER_MINT_handler_agpl_redirect (struct RequestHandler *rh, | ||
91 | struct MHD_Connection *connection, | ||
92 | void **connection_cls, | ||
93 | const char *upload_data, | ||
94 | size_t *upload_data_size) | ||
95 | { | ||
96 | const char *agpl = | ||
97 | "This server is licensed under the Affero GPL. You will now be redirected to the source code."; | ||
98 | struct MHD_Response *response; | ||
99 | int ret; | ||
100 | |||
101 | response = MHD_create_response_from_buffer (strlen (agpl), | ||
102 | (void *) agpl, | ||
103 | MHD_RESPMEM_PERSISTENT); | ||
104 | if (NULL == response) | ||
105 | { | ||
106 | GNUNET_break (0); | ||
107 | return MHD_NO; | ||
108 | } | ||
109 | if (NULL != rh->mime_type) | ||
110 | (void) MHD_add_response_header (response, | ||
111 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
112 | rh->mime_type); | ||
113 | MHD_add_response_header (response, | ||
114 | MHD_HTTP_HEADER_LOCATION, | ||
115 | "http://www.git.taler.net/?p=mint.git"); | ||
116 | ret = MHD_queue_response (connection, | ||
117 | rh->response_code, | ||
118 | response); | ||
119 | MHD_destroy_response (response); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | |||
124 | /** | ||
125 | * Function to call to handle the request by building a JSON | ||
126 | * reply from varargs. | ||
127 | * | ||
128 | * @param rh context of the handler | ||
129 | * @param connection the MHD connection to handle | ||
130 | * @param[IN|OUT] connection_cls the connection's closure (can be updated) | ||
131 | * @param response_code HTTP response code to use | ||
132 | * @param do_cache can the response be cached? (0: no, 1: yes) | ||
133 | * @param fmt format string for pack | ||
134 | * @param ... varargs | ||
135 | * @return MHD result code | ||
136 | */ | ||
137 | int | ||
138 | TALER_MINT_helper_send_json_pack (struct RequestHandler *rh, | ||
139 | struct MHD_Connection *connection, | ||
140 | void *connection_cls, | ||
141 | int response_code, | ||
142 | int do_cache, | ||
143 | const char *fmt, | ||
144 | ...) | ||
145 | { | ||
146 | int ret; | ||
147 | json_t *json; | ||
148 | va_list argp; | ||
149 | char *json_str; | ||
150 | struct MHD_Response *response; | ||
151 | |||
152 | va_start (argp, fmt); | ||
153 | json = json_vpack_ex (NULL, 0, fmt, argp); | ||
154 | va_end (argp); | ||
155 | if (NULL == json) | ||
156 | return MHD_NO; | ||
157 | json_str = json_dumps (json, JSON_INDENT(2)); | ||
158 | json_decref (json); | ||
159 | if (NULL == json_str) | ||
160 | return MHD_NO; | ||
161 | response = MHD_create_response_from_buffer (strlen (json_str), | ||
162 | json_str, | ||
163 | MHD_RESPMEM_MUST_FREE); | ||
164 | if (NULL == response) | ||
165 | { | ||
166 | free (json_str); | ||
167 | return MHD_NO; | ||
168 | } | ||
169 | if (NULL != rh->mime_type) | ||
170 | (void) MHD_add_response_header (response, | ||
171 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
172 | rh->mime_type); | ||
173 | ret = MHD_queue_response (connection, | ||
174 | response_code, | ||
175 | response); | ||
176 | MHD_destroy_response (response); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Function to call to handle the request by building a JSON | ||
183 | * reply with an error message from @a rh. | ||
184 | * | ||
185 | * @param rh context of the handler | ||
186 | * @param connection the MHD connection to handle | ||
187 | * @param[IN|OUT] connection_cls the connection's closure (can be updated) | ||
188 | * @param upload_data upload data | ||
189 | * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data | ||
190 | * @return MHD result code | ||
191 | */ | ||
192 | int | ||
193 | TALER_MINT_handler_send_json_pack_error (struct RequestHandler *rh, | ||
194 | struct MHD_Connection *connection, | ||
195 | void **connection_cls, | ||
196 | const char *upload_data, | ||
197 | size_t *upload_data_size) | ||
198 | { | ||
199 | return TALER_MINT_helper_send_json_pack (rh, | ||
200 | connection, | ||
201 | connection_cls, | ||
202 | 1, /* caching enabled */ | ||
203 | rh->response_code, | ||
204 | "{s:s}", | ||
205 | "error", | ||
206 | rh->data); | ||
207 | } | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Send a response for an invalid argument. | ||
212 | * | ||
213 | * @param connection the MHD connection to use | ||
214 | * @param param_name the parameter that is missing | ||
215 | * @return a GNUnet result code | ||
216 | */ | ||
217 | static int | ||
218 | request_arg_invalid (struct MHD_Connection *connection, | ||
219 | const char *param_name) | ||
220 | { | ||
221 | json_t *json; | ||
222 | json = json_pack ("{ s:s, s:s }", | ||
223 | "error", "invalid parameter", | ||
224 | "parameter", param_name); | ||
225 | if (MHD_YES != send_response_json (connection, json, MHD_HTTP_BAD_REQUEST)) | ||
226 | { | ||
227 | GNUNET_break (0); | ||
228 | return GNUNET_SYSERR; | ||
229 | } | ||
230 | return GNUNET_NO; | ||
231 | } | ||
232 | |||
233 | |||
234 | /** | ||
235 | * Get a GET paramater that is a string, | ||
236 | * or send an error response if the parameter is missing. | ||
237 | * | ||
238 | * @param connection the connection to get the parameter from / | ||
239 | * send the error response to | ||
240 | * @param param_name the parameter name | ||
241 | * @param str pointer to store the parameter string, | ||
242 | * must be freed by the caller | ||
243 | * @return GNUNET_YES if the parameter is present and valid, | ||
244 | * GNUNET_NO if the parameter is missing | ||
245 | * GNUNET_SYSERR on internal error | ||
246 | */ | ||
247 | static int | ||
248 | request_arg_require_string (struct MHD_Connection *connection, | ||
249 | const char *param_name, | ||
250 | const char **str) | ||
251 | { | ||
252 | *str = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, param_name); | ||
253 | if (NULL == *str) | ||
254 | { | ||
255 | if (MHD_NO == | ||
256 | request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, | ||
257 | "{ s:s, s:s }", | ||
258 | "error", "missing parameter", | ||
259 | "parameter", param_name)) | ||
260 | return GNUNET_SYSERR; | ||
261 | return GNUNET_NO; | ||
262 | } | ||
263 | return GNUNET_OK; | ||
264 | } | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Extraxt base32crockford encoded data from request. | ||
269 | * | ||
270 | * Queues an error response to the connection if the parameter is missing or | ||
271 | * invalid. | ||
272 | * | ||
273 | * @param connection the MHD connection | ||
274 | * @param param_name the name of the parameter with the key | ||
275 | * @param[out] out_data pointer to store the result | ||
276 | * @param out_size expected size of data | ||
277 | * @return | ||
278 | * GNUNET_YES if the the argument is present | ||
279 | * GNUNET_NO if the argument is absent or malformed | ||
280 | * GNUNET_SYSERR on internal error (error response could not be sent) | ||
281 | */ | ||
282 | int | ||
283 | TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection, | ||
284 | const char *param_name, | ||
285 | void *out_data, | ||
286 | size_t out_size) | ||
287 | { | ||
288 | const char *str; | ||
289 | int ret; | ||
290 | |||
291 | if (GNUNET_OK != (ret = request_arg_require_string (connection, param_name, &str))) | ||
292 | return ret; | ||
293 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (str, strlen (str), out_data, out_size)) | ||
294 | return request_arg_invalid (connection, param_name); | ||
295 | return GNUNET_OK; | ||
296 | } | ||
297 | |||
298 | |||
299 | |||
300 | /* end of taler-mint-httpd_mhd.c */ | ||