request_get_value.c (10335B)
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 { 76 mhd_assert (strlen (key) == key_len); 77 value_out->len = 0u; 78 value_out->cstr = NULL; 79 80 mhd_assert (strlen (key) == key_len); 81 82 #ifdef MHD_SUPPORT_HTTP2 83 if (mhd_REQ_IS_HTTP2 (request)) 84 return mhd_h2_request_get_value_n (request, 85 kind, 86 key_len, 87 key, 88 value_out); 89 #endif /* MHD_SUPPORT_HTTP2 */ 90 91 if (MHD_VK_POSTDATA != kind) 92 { 93 struct mhd_RequestField *f; 94 95 for (f = mhd_DLINKEDL_GET_FIRST (request, fields); NULL != f; 96 f = mhd_DLINKEDL_GET_NEXT (f, fields)) 97 { 98 if ((key_len == f->field.nv.name.len) && 99 (0 != (kind & f->field.kind)) && 100 mhd_str_equal_caseless_bin_n (key, 101 f->field.nv.name.cstr, 102 key_len)) 103 { 104 *value_out = f->field.nv.value; 105 return true; 106 } 107 } 108 } 109 110 #if MHD_SUPPORT_POST_PARSER 111 if (0 != (MHD_VK_POSTDATA & kind)) 112 { 113 struct mhd_RequestPostField *f; 114 char *const buf = request->cntn.lbuf.data; // TODO: support processing in connection buffer 115 for (f = mhd_DLINKEDL_GET_FIRST (request, post_fields); NULL != f; 116 f = mhd_DLINKEDL_GET_NEXT (f, post_fields)) 117 { 118 if ((key_len == f->field.name.len) && 119 mhd_str_equal_caseless_bin_n (key, 120 buf + f->field.name.pos, 121 key_len)) 122 { 123 value_out->cstr = 124 (0 == f->field.value.pos) ? 125 NULL : (buf + f->field.value.pos); 126 value_out->len = f->field.value.len; 127 128 mhd_assert ((NULL != value_out->cstr) || \ 129 (0 == value_out->len)); 130 131 return true; 132 } 133 } 134 } 135 #endif /* MHD_SUPPORT_POST_PARSER */ 136 137 return false; 138 } 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 { 150 size_t len; 151 len = strlen (key); 152 return mhd_request_get_value_n (request, 153 kind, 154 len, 155 key, 156 value_out) ? MHD_YES : MHD_NO; 157 } 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 { 169 struct mhd_RequestField *f; 170 171 mhd_assert (mhd_HTTP_STAGE_START_REPLY >= c->stage); 172 173 for (f = mhd_DLINKEDL_GET_FIRST (&(c->rq), fields); 174 NULL != f; 175 f = mhd_DLINKEDL_GET_NEXT (f, fields)) 176 { 177 if ((MHD_VK_HEADER == f->field.kind) && 178 (header_len == f->field.nv.name.len) && 179 (mhd_str_equal_caseless_bin_n (header, 180 f->field.nv.name.cstr, 181 header_len)) && 182 (mhd_str_has_token_caseless (f->field.nv.value.cstr, 183 token, 184 token_len))) 185 return true; 186 } 187 188 return false; 189 } 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 { 199 size_t count; 200 201 #ifdef MHD_SUPPORT_HTTP2 202 if (mhd_REQ_IS_HTTP2 (request)) 203 return mhd_h2_request_get_values_cb (request, 204 kind, 205 iterator, 206 iterator_cls); 207 #endif /* MHD_SUPPORT_HTTP2 */ 208 209 count = 0; 210 if (MHD_VK_POSTDATA != kind) 211 { 212 struct mhd_RequestField *f; 213 214 for (f = mhd_DLINKEDL_GET_FIRST (request, fields); NULL != f; 215 f = mhd_DLINKEDL_GET_NEXT (f, fields)) 216 { 217 if (0 == (kind & f->field.kind)) 218 continue; 219 220 ++count; 221 if (NULL != iterator) 222 { 223 if (MHD_NO == 224 iterator (iterator_cls, 225 f->field.kind, 226 &(f->field.nv))) 227 return count; 228 } 229 } 230 } 231 232 #if MHD_SUPPORT_POST_PARSER 233 if (0 != (MHD_VK_POSTDATA & kind)) 234 { 235 struct mhd_RequestPostField *f; 236 char *const buf = request->cntn.lbuf.data; // TODO: support processing in connection buffer 237 for (f = mhd_DLINKEDL_GET_FIRST (request, post_fields); NULL != f; 238 f = mhd_DLINKEDL_GET_NEXT (f, post_fields)) 239 { 240 ++count; 241 if (NULL != iterator) 242 { 243 struct MHD_NameAndValue field; 244 245 field.name.cstr = buf + f->field.name.pos; 246 field.name.len = f->field.name.len; 247 field.value.cstr = 248 (0 == f->field.value.pos) ? NULL : (buf + f->field.value.pos); 249 field.value.len = f->field.value.len; 250 251 if (MHD_NO == 252 iterator (iterator_cls, 253 MHD_VK_POSTDATA, 254 &field)) 255 return count; 256 } 257 } 258 } 259 #endif /* MHD_SUPPORT_POST_PARSER */ 260 261 return count; 262 } 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 { 273 struct mhd_RequestPostField *f; 274 char *const buf = request->cntn.lbuf.data; // TODO: support processing in connection buffer 275 size_t count; 276 277 count = 0; 278 for (f = mhd_DLINKEDL_GET_FIRST (request, post_fields); NULL != f; 279 f = mhd_DLINKEDL_GET_NEXT (f, post_fields)) 280 { 281 ++count; 282 if (NULL != iterator) 283 { 284 struct MHD_PostField field; 285 286 field.name.cstr = buf + f->field.name.pos; 287 field.name.len = f->field.name.len; 288 if (0 == f->field.value.pos) 289 field.value.cstr = NULL; 290 else 291 field.value.cstr = buf + f->field.value.pos; 292 field.value.len = f->field.value.len; 293 294 if (0 == f->field.filename.pos) 295 field.filename.cstr = NULL; 296 else 297 field.filename.cstr = buf + f->field.filename.pos; 298 field.filename.len = f->field.filename.len; 299 300 if (0 == f->field.content_type.pos) 301 field.content_type.cstr = NULL; 302 else 303 field.content_type.cstr = buf + f->field.content_type.pos; 304 field.content_type.len = f->field.content_type.len; 305 306 if (0 == f->field.transfer_encoding.pos) 307 field.transfer_encoding.cstr = NULL; 308 else 309 field.transfer_encoding.cstr = buf + f->field.transfer_encoding.pos; 310 field.transfer_encoding.len = f->field.transfer_encoding.len; 311 312 mhd_assert ((NULL != field.value.cstr) || (0 == field.value.len)); 313 mhd_assert ((NULL != field.filename.cstr) || (0 == field.filename.len)); 314 mhd_assert ((NULL != field.content_type.cstr) || \ 315 (0 == field.content_type.len)); 316 mhd_assert ((NULL != field.transfer_encoding.cstr) || \ 317 (0 == field.transfer_encoding.len)); 318 319 if (MHD_NO == 320 iterator (iterator_cls, 321 &field)) 322 return count; 323 } 324 } 325 return count; 326 } 327 328 329 #endif /* MHD_SUPPORT_POST_PARSER */