Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014--2020 Taler Systems SA
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, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file mhd_parsing.c
18 : * @brief functions to parse incoming requests (MHD arguments and JSON snippets)
19 : * @author Florian Dold
20 : * @author Benedikt Mueller
21 : * @author Christian Grothoff
22 : */
23 : #include "platform.h"
24 : #include <gnunet/gnunet_util_lib.h>
25 : #include <gnunet/gnunet_json_lib.h>
26 : #include "taler_json_lib.h"
27 : #include "taler_mhd_lib.h"
28 :
29 :
30 : enum GNUNET_GenericReturnValue
31 0 : TALER_MHD_parse_post_json (struct MHD_Connection *connection,
32 : void **con_cls,
33 : const char *upload_data,
34 : size_t *upload_data_size,
35 : json_t **json)
36 : {
37 : enum GNUNET_JSON_PostResult pr;
38 :
39 0 : pr = GNUNET_JSON_post_parser (TALER_MHD_REQUEST_BUFFER_MAX,
40 : connection,
41 : con_cls,
42 : upload_data,
43 : upload_data_size,
44 : json);
45 0 : switch (pr)
46 : {
47 0 : case GNUNET_JSON_PR_OUT_OF_MEMORY:
48 0 : GNUNET_break (NULL == *json);
49 : return (MHD_NO ==
50 0 : TALER_MHD_reply_with_error (
51 : connection,
52 : MHD_HTTP_INTERNAL_SERVER_ERROR,
53 : TALER_EC_GENERIC_PARSER_OUT_OF_MEMORY,
54 0 : NULL)) ? GNUNET_SYSERR : GNUNET_NO;
55 :
56 0 : case GNUNET_JSON_PR_CONTINUE:
57 0 : GNUNET_break (NULL == *json);
58 0 : return GNUNET_YES;
59 0 : case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
60 0 : GNUNET_break (NULL == *json);
61 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
62 : "Closing connection, upload too large\n");
63 0 : return GNUNET_SYSERR;
64 0 : case GNUNET_JSON_PR_JSON_INVALID:
65 0 : GNUNET_break (NULL == *json);
66 : return (MHD_YES ==
67 0 : TALER_MHD_reply_with_error (connection,
68 : MHD_HTTP_BAD_REQUEST,
69 : TALER_EC_GENERIC_JSON_INVALID,
70 : NULL))
71 0 : ? GNUNET_NO : GNUNET_SYSERR;
72 0 : case GNUNET_JSON_PR_SUCCESS:
73 0 : GNUNET_break (NULL != *json);
74 0 : return GNUNET_YES;
75 : }
76 : /* this should never happen */
77 0 : GNUNET_break (0);
78 0 : return GNUNET_SYSERR;
79 : }
80 :
81 :
82 : void
83 0 : TALER_MHD_parse_post_cleanup_callback (void *con_cls)
84 : {
85 0 : GNUNET_JSON_post_parser_cleanup (con_cls);
86 0 : }
87 :
88 :
89 : enum GNUNET_GenericReturnValue
90 0 : TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection,
91 : const char *param_name,
92 : void *out_data,
93 : size_t out_size)
94 : {
95 : const char *str;
96 :
97 0 : str = MHD_lookup_connection_value (connection,
98 : MHD_GET_ARGUMENT_KIND,
99 : param_name);
100 0 : if (NULL == str)
101 : {
102 : return (MHD_NO ==
103 0 : TALER_MHD_reply_with_error (connection,
104 : MHD_HTTP_BAD_REQUEST,
105 : TALER_EC_GENERIC_PARAMETER_MISSING,
106 : param_name))
107 0 : ? GNUNET_SYSERR : GNUNET_NO;
108 : }
109 0 : if (GNUNET_OK !=
110 0 : GNUNET_STRINGS_string_to_data (str,
111 : strlen (str),
112 : out_data,
113 : out_size))
114 : return (MHD_NO ==
115 0 : TALER_MHD_reply_with_error (connection,
116 : MHD_HTTP_BAD_REQUEST,
117 : TALER_EC_GENERIC_PARAMETER_MALFORMED,
118 : param_name))
119 0 : ? GNUNET_SYSERR : GNUNET_NO;
120 0 : return GNUNET_OK;
121 : }
122 :
123 :
124 : enum GNUNET_GenericReturnValue
125 8 : TALER_MHD_parse_json_data (struct MHD_Connection *connection,
126 : const json_t *root,
127 : struct GNUNET_JSON_Specification *spec)
128 : {
129 : enum GNUNET_GenericReturnValue ret;
130 : const char *error_json_name;
131 : unsigned int error_line;
132 :
133 8 : ret = GNUNET_JSON_parse (root,
134 : spec,
135 : &error_json_name,
136 : &error_line);
137 8 : if (GNUNET_SYSERR == ret)
138 : {
139 0 : if (NULL == error_json_name)
140 0 : error_json_name = "<no field>";
141 0 : ret = (MHD_YES ==
142 0 : TALER_MHD_REPLY_JSON_PACK (
143 : connection,
144 : MHD_HTTP_BAD_REQUEST,
145 : GNUNET_JSON_pack_string ("hint",
146 : TALER_ErrorCode_get_hint (
147 : TALER_EC_GENERIC_JSON_INVALID)),
148 : GNUNET_JSON_pack_uint64 ("code",
149 : TALER_EC_GENERIC_JSON_INVALID),
150 : GNUNET_JSON_pack_string ("field",
151 : error_json_name),
152 : GNUNET_JSON_pack_uint64 ("line",
153 : error_line)))
154 0 : ? GNUNET_NO : GNUNET_SYSERR;
155 0 : return ret;
156 : }
157 8 : return GNUNET_YES;
158 : }
159 :
160 :
161 : enum GNUNET_GenericReturnValue
162 0 : TALER_MHD_parse_internal_json_data (struct MHD_Connection *connection,
163 : const json_t *root,
164 : struct GNUNET_JSON_Specification *spec)
165 : {
166 : enum GNUNET_GenericReturnValue ret;
167 : const char *error_json_name;
168 : unsigned int error_line;
169 :
170 0 : ret = GNUNET_JSON_parse (root,
171 : spec,
172 : &error_json_name,
173 : &error_line);
174 0 : if (GNUNET_SYSERR == ret)
175 : {
176 0 : if (NULL == error_json_name)
177 0 : error_json_name = "<no field>";
178 0 : ret = (MHD_YES ==
179 0 : TALER_MHD_REPLY_JSON_PACK (
180 : connection,
181 : MHD_HTTP_INTERNAL_SERVER_ERROR,
182 : GNUNET_JSON_pack_string ("hint",
183 : TALER_ErrorCode_get_hint (
184 : TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)),
185 : GNUNET_JSON_pack_uint64 ("code",
186 : TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE),
187 : GNUNET_JSON_pack_string ("field",
188 : error_json_name),
189 : GNUNET_JSON_pack_uint64 ("line",
190 : error_line)))
191 0 : ? GNUNET_NO : GNUNET_SYSERR;
192 0 : return ret;
193 : }
194 0 : return GNUNET_YES;
195 : }
196 :
197 :
198 : enum GNUNET_GenericReturnValue
199 0 : TALER_MHD_parse_json_array (struct MHD_Connection *connection,
200 : const json_t *root,
201 : struct GNUNET_JSON_Specification *spec,
202 : ...)
203 : {
204 : enum GNUNET_GenericReturnValue ret;
205 : const char *error_json_name;
206 : unsigned int error_line;
207 : va_list ap;
208 : json_int_t dim;
209 :
210 0 : va_start (ap, spec);
211 0 : dim = 0;
212 0 : while ( (-1 != (ret = va_arg (ap, int))) &&
213 : (NULL != root) )
214 : {
215 0 : dim++;
216 0 : root = json_array_get (root, ret);
217 : }
218 0 : va_end (ap);
219 0 : if (NULL == root)
220 : {
221 0 : ret = (MHD_YES ==
222 0 : TALER_MHD_REPLY_JSON_PACK (
223 : connection,
224 : MHD_HTTP_BAD_REQUEST,
225 : GNUNET_JSON_pack_string ("hint",
226 : TALER_ErrorCode_get_hint (
227 : TALER_EC_GENERIC_JSON_INVALID)),
228 : GNUNET_JSON_pack_uint64 ("code",
229 : TALER_EC_GENERIC_JSON_INVALID),
230 : GNUNET_JSON_pack_string ("detail",
231 : "expected array"),
232 : GNUNET_JSON_pack_uint64 ("dimension",
233 : dim)))
234 0 : ? GNUNET_NO : GNUNET_SYSERR;
235 0 : return ret;
236 : }
237 0 : ret = GNUNET_JSON_parse (root,
238 : spec,
239 : &error_json_name,
240 : &error_line);
241 0 : if (GNUNET_SYSERR == ret)
242 : {
243 0 : if (NULL == error_json_name)
244 0 : error_json_name = "<no field>";
245 0 : ret = (MHD_YES ==
246 0 : TALER_MHD_REPLY_JSON_PACK (
247 : connection,
248 : MHD_HTTP_BAD_REQUEST,
249 : GNUNET_JSON_pack_string ("detail",
250 : error_json_name),
251 : GNUNET_JSON_pack_string ("hint",
252 : TALER_ErrorCode_get_hint (
253 : TALER_EC_GENERIC_JSON_INVALID)),
254 : GNUNET_JSON_pack_uint64 ("code",
255 : TALER_EC_GENERIC_JSON_INVALID),
256 : GNUNET_JSON_pack_uint64 ("line",
257 : error_line)))
258 0 : ? GNUNET_NO : GNUNET_SYSERR;
259 0 : return ret;
260 : }
261 0 : return GNUNET_YES;
262 : }
263 :
264 :
265 : /* end of mhd_parsing.c */
|