/src/mhd2/src/mhd2/request_get_value.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ |
2 | | /* |
3 | | This file is part of GNU libmicrohttpd. |
4 | | Copyright (C) 2024 Christian Grothoff |
5 | | Copyright (C) 2024 Evgeny Grin (Karlson2k) |
6 | | |
7 | | GNU libmicrohttpd is free software; you can redistribute it and/or |
8 | | modify it under the terms of the GNU Lesser General Public |
9 | | License as published by the Free Software Foundation; either |
10 | | version 2.1 of the License, or (at your option) any later version. |
11 | | |
12 | | GNU libmicrohttpd is distributed in the hope that it will be useful, |
13 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | Lesser General Public License for more details. |
16 | | |
17 | | Alternatively, you can redistribute GNU libmicrohttpd and/or |
18 | | modify it under the terms of the GNU General Public License as |
19 | | published by the Free Software Foundation; either version 2 of |
20 | | the License, or (at your option) any later version, together |
21 | | with the eCos exception, as follows: |
22 | | |
23 | | As a special exception, if other files instantiate templates or |
24 | | use macros or inline functions from this file, or you compile this |
25 | | file and link it with other works to produce a work based on this |
26 | | file, this file does not by itself cause the resulting work to be |
27 | | covered by the GNU General Public License. However the source code |
28 | | for this file must still be made available in accordance with |
29 | | section (3) of the GNU General Public License v2. |
30 | | |
31 | | This exception does not invalidate any other reasons why a work |
32 | | based on this file might be covered by the GNU General Public |
33 | | License. |
34 | | |
35 | | You should have received copies of the GNU Lesser General Public |
36 | | License and the GNU General Public License along with this library; |
37 | | if not, see <https://www.gnu.org/licenses/>. |
38 | | */ |
39 | | |
40 | | /** |
41 | | * @file src/mhd2/request_get_value.c |
42 | | * @brief The implementation of MHD_request_get_value*() functions |
43 | | * @author Karlson2k (Evgeny Grin) |
44 | | */ |
45 | | |
46 | | #include "mhd_sys_options.h" |
47 | | #include "request_get_value.h" |
48 | | #include "sys_base_types.h" |
49 | | #include <string.h> |
50 | | |
51 | | #include "mhd_request.h" |
52 | | |
53 | | #include "mhd_connection.h" |
54 | | |
55 | | #include "mhd_dlinked_list.h" |
56 | | #include "mhd_assert.h" |
57 | | #include "mhd_str.h" |
58 | | |
59 | | #ifdef MHD_SUPPORT_HTTP2 |
60 | | # include "h2/h2_req_get_items.h" |
61 | | #endif /* MHD_SUPPORT_HTTP2 */ |
62 | | |
63 | | #include "mhd_public_api.h" |
64 | | |
65 | | |
66 | | MHD_INTERNAL |
67 | | MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_IN_SIZE_ (4,3) |
68 | | MHD_FN_PAR_NONNULL_ (4) MHD_FN_PAR_CSTR_ (4) |
69 | | MHD_FN_PAR_OUT_ (5) bool |
70 | | mhd_request_get_value_n (struct MHD_Request *restrict request, |
71 | | enum MHD_ValueKind kind, |
72 | | size_t key_len, |
73 | | const char *restrict key, |
74 | | struct MHD_StringNullable *restrict value_out) |
75 | 2.85k | { |
76 | 2.85k | mhd_assert (strlen (key) == key_len); |
77 | 2.85k | value_out->len = 0u; |
78 | 2.85k | value_out->cstr = NULL; |
79 | | |
80 | 2.85k | mhd_assert (strlen (key) == key_len); |
81 | | |
82 | 2.85k | #ifdef MHD_SUPPORT_HTTP2 |
83 | 2.85k | if (mhd_REQ_IS_HTTP2 (request)) |
84 | 0 | return mhd_h2_request_get_value_n (request, |
85 | 0 | kind, |
86 | 0 | key_len, |
87 | 0 | key, |
88 | 0 | value_out); |
89 | 2.85k | #endif /* MHD_SUPPORT_HTTP2 */ |
90 | | |
91 | 2.85k | if (MHD_VK_POSTDATA != kind) |
92 | 2.85k | { |
93 | 2.85k | struct mhd_RequestField *f; |
94 | | |
95 | 5.96k | for (f = mhd_DLINKEDL_GET_FIRST (request, fields); NULL != f; |
96 | 3.10k | f = mhd_DLINKEDL_GET_NEXT (f, fields)) |
97 | 5.54k | { |
98 | 5.54k | if ((key_len == f->field.nv.name.len) && |
99 | 2.44k | (0 != (kind & f->field.kind)) && |
100 | 2.44k | mhd_str_equal_caseless_bin_n (key, |
101 | 2.44k | f->field.nv.name.cstr, |
102 | 2.44k | key_len)) |
103 | 2.44k | { |
104 | 2.44k | *value_out = f->field.nv.value; |
105 | 2.44k | return true; |
106 | 2.44k | } |
107 | 5.54k | } |
108 | 2.85k | } |
109 | | |
110 | 417 | #if MHD_SUPPORT_POST_PARSER |
111 | 417 | if (0 != (MHD_VK_POSTDATA & kind)) |
112 | 0 | { |
113 | 0 | struct mhd_RequestPostField *f; |
114 | 0 | char *const buf = request->cntn.lbuf.data; // TODO: support processing in connection buffer |
115 | 0 | for (f = mhd_DLINKEDL_GET_FIRST (request, post_fields); NULL != f; |
116 | 0 | f = mhd_DLINKEDL_GET_NEXT (f, post_fields)) |
117 | 0 | { |
118 | 0 | if ((key_len == f->field.name.len) && |
119 | 0 | mhd_str_equal_caseless_bin_n (key, |
120 | 0 | buf + f->field.name.pos, |
121 | 0 | key_len)) |
122 | 0 | { |
123 | 0 | value_out->cstr = |
124 | 0 | (0 == f->field.value.pos) ? |
125 | 0 | NULL : (buf + f->field.value.pos); |
126 | 0 | value_out->len = f->field.value.len; |
127 | |
|
128 | 0 | mhd_assert ((NULL != value_out->cstr) || \ |
129 | 0 | (0 == value_out->len)); |
130 | |
|
131 | 0 | return true; |
132 | 0 | } |
133 | 0 | } |
134 | 0 | } |
135 | 417 | #endif /* MHD_SUPPORT_POST_PARSER */ |
136 | | |
137 | 417 | return false; |
138 | 417 | } |
139 | | |
140 | | |
141 | | MHD_EXTERN_ |
142 | | MHD_FN_PAR_NONNULL_ (1) |
143 | | MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_CSTR_ (3) |
144 | | MHD_FN_PAR_OUT_ (4) enum MHD_Bool |
145 | | MHD_request_get_value (struct MHD_Request *MHD_RESTRICT request, |
146 | | enum MHD_ValueKind kind, |
147 | | const char *MHD_RESTRICT key, |
148 | | struct MHD_StringNullable *MHD_RESTRICT value_out) |
149 | 0 | { |
150 | 0 | size_t len; |
151 | 0 | len = strlen (key); |
152 | 0 | return mhd_request_get_value_n (request, |
153 | 0 | kind, |
154 | 0 | len, |
155 | 0 | key, |
156 | 0 | value_out) ? MHD_YES : MHD_NO; |
157 | 0 | } |
158 | | |
159 | | |
160 | | MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ |
161 | | MHD_FN_PAR_CSTR_ (3) |
162 | | MHD_FN_PAR_CSTR_ (5) bool |
163 | | mhd_stream_has_header_token (const struct MHD_Connection *restrict c, |
164 | | size_t header_len, |
165 | | const char *restrict header, |
166 | | size_t token_len, |
167 | | const char *restrict token) |
168 | 0 | { |
169 | 0 | struct mhd_RequestField *f; |
170 | |
|
171 | 0 | mhd_assert (mhd_HTTP_STAGE_START_REPLY >= c->stage); |
172 | |
|
173 | 0 | for (f = mhd_DLINKEDL_GET_FIRST (&(c->rq), fields); |
174 | 0 | NULL != f; |
175 | 0 | f = mhd_DLINKEDL_GET_NEXT (f, fields)) |
176 | 0 | { |
177 | 0 | if ((MHD_VK_HEADER == f->field.kind) && |
178 | 0 | (header_len == f->field.nv.name.len) && |
179 | 0 | (mhd_str_equal_caseless_bin_n (header, |
180 | 0 | f->field.nv.name.cstr, |
181 | 0 | header_len)) && |
182 | 0 | (mhd_str_has_token_caseless (f->field.nv.value.cstr, |
183 | 0 | token, |
184 | 0 | token_len))) |
185 | 0 | return true; |
186 | 0 | } |
187 | | |
188 | 0 | return false; |
189 | 0 | } |
190 | | |
191 | | |
192 | | MHD_EXTERN_ |
193 | | MHD_FN_PAR_NONNULL_ (1) size_t |
194 | | MHD_request_get_values_cb (struct MHD_Request *request, |
195 | | enum MHD_ValueKind kind, |
196 | | MHD_NameValueIterator iterator, |
197 | | void *iterator_cls) |
198 | 0 | { |
199 | 0 | size_t count; |
200 | |
|
201 | 0 | #ifdef MHD_SUPPORT_HTTP2 |
202 | 0 | if (mhd_REQ_IS_HTTP2 (request)) |
203 | 0 | return mhd_h2_request_get_values_cb (request, |
204 | 0 | kind, |
205 | 0 | iterator, |
206 | 0 | iterator_cls); |
207 | 0 | #endif /* MHD_SUPPORT_HTTP2 */ |
208 | | |
209 | 0 | count = 0; |
210 | 0 | if (MHD_VK_POSTDATA != kind) |
211 | 0 | { |
212 | 0 | struct mhd_RequestField *f; |
213 | |
|
214 | 0 | for (f = mhd_DLINKEDL_GET_FIRST (request, fields); NULL != f; |
215 | 0 | f = mhd_DLINKEDL_GET_NEXT (f, fields)) |
216 | 0 | { |
217 | 0 | if (0 == (kind & f->field.kind)) |
218 | 0 | continue; |
219 | | |
220 | 0 | ++count; |
221 | 0 | if (NULL != iterator) |
222 | 0 | { |
223 | 0 | if (MHD_NO == |
224 | 0 | iterator (iterator_cls, |
225 | 0 | f->field.kind, |
226 | 0 | &(f->field.nv))) |
227 | 0 | return count; |
228 | 0 | } |
229 | 0 | } |
230 | 0 | } |
231 | | |
232 | 0 | #if MHD_SUPPORT_POST_PARSER |
233 | 0 | if (0 != (MHD_VK_POSTDATA & kind)) |
234 | 0 | { |
235 | 0 | struct mhd_RequestPostField *f; |
236 | 0 | char *const buf = request->cntn.lbuf.data; // TODO: support processing in connection buffer |
237 | 0 | for (f = mhd_DLINKEDL_GET_FIRST (request, post_fields); NULL != f; |
238 | 0 | f = mhd_DLINKEDL_GET_NEXT (f, post_fields)) |
239 | 0 | { |
240 | 0 | ++count; |
241 | 0 | if (NULL != iterator) |
242 | 0 | { |
243 | 0 | struct MHD_NameAndValue field; |
244 | |
|
245 | 0 | field.name.cstr = buf + f->field.name.pos; |
246 | 0 | field.name.len = f->field.name.len; |
247 | 0 | field.value.cstr = |
248 | 0 | (0 == f->field.value.pos) ? NULL : (buf + f->field.value.pos); |
249 | 0 | field.value.len = f->field.value.len; |
250 | |
|
251 | 0 | if (MHD_NO == |
252 | 0 | iterator (iterator_cls, |
253 | 0 | MHD_VK_POSTDATA, |
254 | 0 | &field)) |
255 | 0 | return count; |
256 | 0 | } |
257 | 0 | } |
258 | 0 | } |
259 | 0 | #endif /* MHD_SUPPORT_POST_PARSER */ |
260 | | |
261 | 0 | return count; |
262 | 0 | } |
263 | | |
264 | | |
265 | | #if MHD_SUPPORT_POST_PARSER |
266 | | |
267 | | MHD_EXTERN_ |
268 | | MHD_FN_PAR_NONNULL_ (1) size_t |
269 | | MHD_request_get_post_data_cb (struct MHD_Request *request, |
270 | | MHD_PostDataIterator iterator, |
271 | | void *iterator_cls) |
272 | 0 | { |
273 | 0 | struct mhd_RequestPostField *f; |
274 | 0 | char *const buf = request->cntn.lbuf.data; // TODO: support processing in connection buffer |
275 | 0 | size_t count; |
276 | |
|
277 | 0 | count = 0; |
278 | 0 | for (f = mhd_DLINKEDL_GET_FIRST (request, post_fields); NULL != f; |
279 | 0 | f = mhd_DLINKEDL_GET_NEXT (f, post_fields)) |
280 | 0 | { |
281 | 0 | ++count; |
282 | 0 | if (NULL != iterator) |
283 | 0 | { |
284 | 0 | struct MHD_PostField field; |
285 | |
|
286 | 0 | field.name.cstr = buf + f->field.name.pos; |
287 | 0 | field.name.len = f->field.name.len; |
288 | 0 | if (0 == f->field.value.pos) |
289 | 0 | field.value.cstr = NULL; |
290 | 0 | else |
291 | 0 | field.value.cstr = buf + f->field.value.pos; |
292 | 0 | field.value.len = f->field.value.len; |
293 | |
|
294 | 0 | if (0 == f->field.filename.pos) |
295 | 0 | field.filename.cstr = NULL; |
296 | 0 | else |
297 | 0 | field.filename.cstr = buf + f->field.filename.pos; |
298 | 0 | field.filename.len = f->field.filename.len; |
299 | |
|
300 | 0 | if (0 == f->field.content_type.pos) |
301 | 0 | field.content_type.cstr = NULL; |
302 | 0 | else |
303 | 0 | field.content_type.cstr = buf + f->field.content_type.pos; |
304 | 0 | field.content_type.len = f->field.content_type.len; |
305 | |
|
306 | 0 | if (0 == f->field.transfer_encoding.pos) |
307 | 0 | field.transfer_encoding.cstr = NULL; |
308 | 0 | else |
309 | 0 | field.transfer_encoding.cstr = buf + f->field.transfer_encoding.pos; |
310 | 0 | field.transfer_encoding.len = f->field.transfer_encoding.len; |
311 | |
|
312 | 0 | mhd_assert ((NULL != field.value.cstr) || (0 == field.value.len)); |
313 | 0 | mhd_assert ((NULL != field.filename.cstr) || (0 == field.filename.len)); |
314 | 0 | mhd_assert ((NULL != field.content_type.cstr) || \ |
315 | 0 | (0 == field.content_type.len)); |
316 | 0 | mhd_assert ((NULL != field.transfer_encoding.cstr) || \ |
317 | 0 | (0 == field.transfer_encoding.len)); |
318 | |
|
319 | 0 | if (MHD_NO == |
320 | 0 | iterator (iterator_cls, |
321 | 0 | &field)) |
322 | 0 | return count; |
323 | 0 | } |
324 | 0 | } |
325 | 0 | return count; |
326 | 0 | } |
327 | | |
328 | | |
329 | | #endif /* MHD_SUPPORT_POST_PARSER */ |