libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

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 */