libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

postprocessor.c (38296B)


      1 /*
      2      This file is part of libmicrohttpd
      3      Copyright (C) 2007-2021 Daniel Pittman and Christian Grothoff
      4      Copyright (C) 2014-2022 Karlson2k (Evgeny Grin)
      5 
      6      This library is free software; you can redistribute it and/or
      7      modify it under the terms of the GNU Lesser General Public
      8      License as published by the Free Software Foundation; either
      9      version 2.1 of the License, or (at your option) any later version.
     10 
     11      This library is distributed in the hope that it will be useful,
     12      but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14      Lesser General Public License for more details.
     15 
     16      You should have received a copy of the GNU Lesser General Public
     17      License along with this library; if not, write to the Free Software
     18      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     19 */
     20 
     21 /**
     22  * @file postprocessor.c
     23  * @brief  Methods for parsing POST data
     24  * @author Christian Grothoff
     25  * @author Karlson2k (Evgeny Grin)
     26  */
     27 
     28 #include "postprocessor.h"
     29 #include "internal.h"
     30 #include "mhd_str.h"
     31 #include "mhd_compat.h"
     32 #include "mhd_assert.h"
     33 
     34 /**
     35  * Size of on-stack buffer that we use for un-escaping of the value.
     36  * We use a pretty small value to be nice to the stack on embedded
     37  * systems.
     38  */
     39 #define XBUF_SIZE 512
     40 
     41 
     42 _MHD_EXTERN struct MHD_PostProcessor *
     43 MHD_create_post_processor (struct MHD_Connection *connection,
     44                            size_t buffer_size,
     45                            MHD_PostDataIterator iter,
     46                            void *iter_cls)
     47 {
     48   struct MHD_PostProcessor *ret;
     49   const char *encoding;
     50   const char *boundary;
     51   size_t blen;
     52 
     53   if ( (buffer_size < 256) ||
     54        (NULL == connection) ||
     55        (NULL == iter))
     56     MHD_PANIC (_ ("libmicrohttpd API violation.\n"));
     57   encoding = NULL;
     58   if (MHD_NO ==
     59       MHD_lookup_connection_value_n (connection,
     60                                      MHD_HEADER_KIND,
     61                                      MHD_HTTP_HEADER_CONTENT_TYPE,
     62                                      MHD_STATICSTR_LEN_ (
     63                                        MHD_HTTP_HEADER_CONTENT_TYPE),
     64                                      &encoding,
     65                                      NULL))
     66     return NULL;
     67   mhd_assert (NULL != encoding);
     68   boundary = NULL;
     69   if (! MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
     70                                    encoding,
     71                                    MHD_STATICSTR_LEN_ (
     72                                      MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
     73   {
     74     if (! MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA,
     75                                      encoding,
     76                                      MHD_STATICSTR_LEN_ (
     77                                        MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
     78       return NULL;
     79     boundary =
     80       &encoding[MHD_STATICSTR_LEN_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)];
     81     /* Q: should this be "strcasestr"? */
     82     boundary = strstr (boundary, "boundary=");
     83     if (NULL == boundary)
     84       return NULL; /* failed to determine boundary */
     85     boundary += MHD_STATICSTR_LEN_ ("boundary=");
     86     blen = strlen (boundary);
     87     if ( (blen < 2) ||
     88          (blen * 2 + 2 > buffer_size) )
     89       return NULL;              /* (will be) out of memory or invalid boundary */
     90     if ( (boundary[0] == '"') &&
     91          (boundary[blen - 1] == '"') )
     92     {
     93       /* remove enclosing quotes */
     94       ++boundary;
     95       blen -= 2;
     96     }
     97   }
     98   else
     99     blen = 0;
    100   buffer_size += 4; /* round up to get nice block sizes despite boundary search */
    101 
    102   /* add +1 to ensure we ALWAYS have a zero-termination at the end */
    103   if (NULL == (ret = MHD_calloc_ (1, sizeof (struct MHD_PostProcessor)
    104                                   + buffer_size + 1)))
    105     return NULL;
    106   ret->connection = connection;
    107   ret->ikvi = iter;
    108   ret->cls = iter_cls;
    109   ret->encoding = encoding;
    110   ret->buffer_size = buffer_size;
    111   ret->state = PP_Init;
    112   ret->blen = blen;
    113   ret->boundary = boundary;
    114   ret->skip_rn = RN_Inactive;
    115   return ret;
    116 }
    117 
    118 
    119 /**
    120  * Give a (possibly partial) value to the application callback.  We have some
    121  * part of the value in the 'pp->xbuf', the rest is between @a value_start and
    122  * @a value_end.  If @a last_escape is non-NULL, there may be an incomplete
    123  * escape sequence at at @a value_escape between @a value_start and @a
    124  * value_end which we should preserve in 'pp->xbuf' for the future.
    125  *
    126  * Unescapes the value and calls the iterator together with the key.  The key
    127  * must already be in the key buffer allocated and 0-terminated at the end of
    128  * @a pp at the time of the call.
    129  *
    130  * @param[in,out] pp post processor to act upon
    131  * @param value_start where in memory is the value
    132  * @param value_end where does the value end
    133  * @param last_escape last '%'-sign in value range,
    134  *        if relevant, or NULL
    135  */
    136 static void
    137 process_value (struct MHD_PostProcessor *pp,
    138                const char *value_start,
    139                const char *value_end,
    140                const char *last_escape)
    141 {
    142   char xbuf[XBUF_SIZE + 1];
    143   size_t xoff;
    144 
    145   mhd_assert (pp->xbuf_pos < sizeof (xbuf));
    146   /* 'value_start' and 'value_end' must be either both non-NULL or both NULL */
    147   mhd_assert ( (NULL == value_start) || (NULL != value_end) );
    148   mhd_assert ( (NULL != value_start) || (NULL == value_end) );
    149   mhd_assert ( (NULL == last_escape) || (NULL != value_start) );
    150   /* move remaining input from previous round into processing buffer */
    151   if (0 != pp->xbuf_pos)
    152     memcpy (xbuf,
    153             pp->xbuf,
    154             pp->xbuf_pos);
    155   xoff = pp->xbuf_pos;
    156   pp->xbuf_pos = 0;
    157   if ( (NULL != last_escape) &&
    158        (((size_t) (value_end - last_escape)) < sizeof (pp->xbuf)) )
    159   {
    160     mhd_assert (value_end >= last_escape);
    161     pp->xbuf_pos = (size_t) (value_end - last_escape);
    162     memcpy (pp->xbuf,
    163             last_escape,
    164             (size_t) (value_end - last_escape));
    165     value_end = last_escape;
    166   }
    167   while ( (value_start != value_end) ||
    168           (pp->must_ikvi) ||
    169           (xoff > 0) )
    170   {
    171     size_t delta = (size_t) (value_end - value_start);
    172     bool cut = false;
    173     size_t clen = 0;
    174 
    175     mhd_assert (value_end >= value_start);
    176 
    177     if (delta > XBUF_SIZE - xoff)
    178       delta = XBUF_SIZE - xoff;
    179     /* move (additional) input into processing buffer */
    180     if (0 != delta)
    181     {
    182       memcpy (&xbuf[xoff],
    183               value_start,
    184               delta);
    185       xoff += delta;
    186       value_start += delta;
    187     }
    188     /* find if escape sequence is at the end of the processing buffer;
    189        if so, exclude those from processing (reduce delta to point at
    190        end of processed region) */
    191     if ( (xoff > 0) &&
    192          ('%' == xbuf[xoff - 1]) )
    193     {
    194       cut = (xoff != XBUF_SIZE);
    195       xoff--;
    196       if (cut)
    197       {
    198         /* move escape sequence into buffer for next function invocation */
    199         pp->xbuf[0] = '%';
    200         pp->xbuf_pos = 1;
    201       }
    202       else
    203       {
    204         /* just skip escape sequence for next loop iteration */
    205         delta = xoff;
    206         clen = 1;
    207       }
    208     }
    209     else if ( (xoff > 1) &&
    210               ('%' == xbuf[xoff - 2]) )
    211     {
    212       cut = (xoff != XBUF_SIZE);
    213       xoff -= 2;
    214       if (cut)
    215       {
    216         /* move escape sequence into buffer for next function invocation */
    217         memcpy (pp->xbuf,
    218                 &xbuf[xoff],
    219                 2);
    220         pp->xbuf_pos = 2;
    221       }
    222       else
    223       {
    224         /* just skip escape sequence for next loop iteration */
    225         delta = xoff;
    226         clen = 2;
    227       }
    228     }
    229     mhd_assert (xoff < sizeof (xbuf));
    230     /* unescape */
    231     xbuf[xoff] = '\0';        /* 0-terminate in preparation */
    232     if (0 != xoff)
    233     {
    234       MHD_unescape_plus (xbuf);
    235       xoff = MHD_http_unescape (xbuf);
    236     }
    237     /* finally: call application! */
    238     if (pp->must_ikvi || (0 != xoff) )
    239     {
    240       pp->must_ikvi = false;
    241       if (MHD_NO == pp->ikvi (pp->cls,
    242                               MHD_POSTDATA_KIND,
    243                               (const char *) &pp[1],      /* key */
    244                               NULL,
    245                               NULL,
    246                               NULL,
    247                               xbuf,
    248                               pp->value_offset,
    249                               xoff))
    250       {
    251         pp->state = PP_Error;
    252         return;
    253       }
    254     }
    255     pp->value_offset += xoff;
    256     if (cut)
    257       break;
    258     if (0 != clen)
    259     {
    260       xbuf[delta] = '%';        /* undo 0-termination */
    261       memmove (xbuf,
    262                &xbuf[delta],
    263                clen);
    264     }
    265     xoff = clen;
    266   }
    267 }
    268 
    269 
    270 /**
    271  * Process url-encoded POST data.
    272  *
    273  * @param pp post processor context
    274  * @param post_data upload data
    275  * @param post_data_len number of bytes in @a post_data
    276  * @return #MHD_YES on success, #MHD_NO if there was an error processing the data
    277  */
    278 static enum MHD_Result
    279 post_process_urlencoded (struct MHD_PostProcessor *pp,
    280                          const char *post_data,
    281                          size_t post_data_len)
    282 {
    283   char *kbuf = (char *) &pp[1];
    284   size_t poff;
    285   const char *start_key = NULL;
    286   const char *end_key = NULL;
    287   const char *start_value = NULL;
    288   const char *end_value = NULL;
    289   const char *last_escape = NULL;
    290 
    291   mhd_assert (PP_Callback != pp->state);
    292 
    293   poff = 0;
    294   while ( ( (poff < post_data_len) ||
    295             (pp->state == PP_Callback) ) &&
    296           (pp->state != PP_Error) )
    297   {
    298     switch (pp->state)
    299     {
    300     case PP_Error:
    301       /* clearly impossible as per while loop invariant */
    302       abort ();
    303       break; /* Unreachable */
    304     case PP_Init:
    305       /* initial phase */
    306       mhd_assert (NULL == start_key);
    307       mhd_assert (NULL == end_key);
    308       mhd_assert (NULL == start_value);
    309       mhd_assert (NULL == end_value);
    310       switch (post_data[poff])
    311       {
    312       case '=':
    313         /* Case: (no key)'=' */
    314         /* Empty key with value */
    315         pp->state = PP_Error;
    316         continue;
    317       case '&':
    318         /* Case: (no key)'&' */
    319         /* Empty key without value */
    320         poff++;
    321         continue;
    322       case '\n':
    323       case '\r':
    324         /* Case: (no key)'\n' or (no key)'\r' */
    325         pp->state = PP_Done;
    326         poff++;
    327         break;
    328       default:
    329         /* normal character, key start, advance! */
    330         pp->state = PP_ProcessKey;
    331         start_key = &post_data[poff];
    332         pp->must_ikvi = true;
    333         poff++;
    334         continue;
    335       }
    336       break; /* end PP_Init */
    337     case PP_ProcessKey:
    338       /* key phase */
    339       mhd_assert (NULL == start_value);
    340       mhd_assert (NULL == end_value);
    341       mhd_assert (NULL != start_key || 0 == poff);
    342       mhd_assert (0 != poff || NULL == start_key);
    343       mhd_assert (NULL == end_key);
    344       switch (post_data[poff])
    345       {
    346       case '=':
    347         /* Case: 'key=' */
    348         if (0 != poff)
    349           end_key = &post_data[poff];
    350         poff++;
    351         pp->state = PP_ProcessValue;
    352         break;
    353       case '&':
    354         /* Case: 'key&' */
    355         if (0 != poff)
    356           end_key = &post_data[poff];
    357         poff++;
    358         pp->state = PP_Callback;
    359         break;
    360       case '\n':
    361       case '\r':
    362         /* Case: 'key\n' or 'key\r' */
    363         if (0 != poff)
    364           end_key = &post_data[poff];
    365         /* No advance here, 'PP_Done' will be selected by next 'PP_Init' phase */
    366         pp->state = PP_Callback;
    367         break;
    368       default:
    369         /* normal character, advance! */
    370         if (0 == poff)
    371           start_key = post_data;
    372         poff++;
    373         break;
    374       }
    375       mhd_assert (NULL == end_key || NULL != start_key);
    376       break; /* end PP_ProcessKey */
    377     case PP_ProcessValue:
    378       if (NULL == start_value)
    379         start_value = &post_data[poff];
    380       switch (post_data[poff])
    381       {
    382       case '=':
    383         /* case 'key==' */
    384         pp->state = PP_Error;
    385         continue;
    386       case '&':
    387         /* case 'value&' */
    388         end_value = &post_data[poff];
    389         poff++;
    390         if (pp->must_ikvi ||
    391             (start_value != end_value) )
    392         {
    393           pp->state = PP_Callback;
    394         }
    395         else
    396         {
    397           pp->buffer_pos = 0;
    398           pp->value_offset = 0;
    399           pp->state = PP_Init;
    400           start_value = NULL;
    401           end_value = NULL;
    402         }
    403         continue;
    404       case '\n':
    405       case '\r':
    406         /* Case: 'value\n' or 'value\r' */
    407         end_value = &post_data[poff];
    408         if (pp->must_ikvi ||
    409             (start_value != end_value) )
    410           pp->state = PP_Callback; /* No poff advance here to set PP_Done in the next iteration */
    411         else
    412         {
    413           poff++;
    414           pp->state = PP_Done;
    415         }
    416         break;
    417       case '%':
    418         last_escape = &post_data[poff];
    419         poff++;
    420         break;
    421       case '0':
    422       case '1':
    423       case '2':
    424       case '3':
    425       case '4':
    426       case '5':
    427       case '6':
    428       case '7':
    429       case '8':
    430       case '9':
    431         /* character, may be part of escaping */
    432         poff++;
    433         continue;
    434       default:
    435         /* normal character, no more escaping! */
    436         last_escape = NULL;
    437         poff++;
    438         continue;
    439       }
    440       break; /* end PP_ProcessValue */
    441     case PP_Done:
    442       switch (post_data[poff])
    443       {
    444       case '\n':
    445       case '\r':
    446         poff++;
    447         continue;
    448       }
    449       /* unexpected data at the end, fail! */
    450       pp->state = PP_Error;
    451       break;
    452     case PP_Callback:
    453       mhd_assert ((NULL != end_key) || (NULL == start_key));
    454       if (1)
    455       {
    456         const size_t key_len = (size_t) (end_key - start_key);
    457         mhd_assert (end_key >= start_key);
    458         if (0 != key_len)
    459         {
    460           if ( (pp->buffer_pos + key_len >= pp->buffer_size) ||
    461                (pp->buffer_pos + key_len < pp->buffer_pos) )
    462           {
    463             /* key too long, cannot parse! */
    464             pp->state = PP_Error;
    465             continue;
    466           }
    467           /* compute key, if we have not already */
    468           memcpy (&kbuf[pp->buffer_pos],
    469                   start_key,
    470                   key_len);
    471           pp->buffer_pos += key_len;
    472           start_key = NULL;
    473           end_key = NULL;
    474           pp->must_unescape_key = true;
    475         }
    476       }
    477 #ifdef _DEBUG
    478       else
    479         mhd_assert (0 != pp->buffer_pos);
    480 #endif /* _DEBUG */
    481       if (pp->must_unescape_key)
    482       {
    483         kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
    484         MHD_unescape_plus (kbuf);
    485         MHD_http_unescape (kbuf);
    486         pp->must_unescape_key = false;
    487       }
    488       process_value (pp,
    489                      start_value,
    490                      end_value,
    491                      NULL);
    492       if (PP_Error == pp->state)
    493         continue;
    494       pp->value_offset = 0;
    495       start_value = NULL;
    496       end_value = NULL;
    497       pp->buffer_pos = 0;
    498       pp->state = PP_Init;
    499       break;
    500     case PP_NextBoundary:
    501     case PP_ProcessEntryHeaders:
    502     case PP_PerformCheckMultipart:
    503     case PP_ProcessValueToBoundary:
    504     case PP_PerformCleanup:
    505     case PP_Nested_Init:
    506     case PP_Nested_PerformMarking:
    507     case PP_Nested_ProcessEntryHeaders:
    508     case PP_Nested_ProcessValueToBoundary:
    509     case PP_Nested_PerformCleanup:
    510     default:
    511       MHD_PANIC (_ ("internal error.\n")); /* should never happen! */
    512     }
    513     mhd_assert ((end_key == NULL) || (start_key != NULL));
    514     mhd_assert ((end_value == NULL) || (start_value != NULL));
    515   }
    516 
    517   mhd_assert (PP_Callback != pp->state);
    518 
    519   if (PP_Error == pp->state)
    520   {
    521     /* State in error, returning failure */
    522     return MHD_NO;
    523   }
    524 
    525   /* save remaining data for next iteration */
    526   if (NULL != start_key)
    527   {
    528     size_t key_len;
    529     mhd_assert ((PP_ProcessKey == pp->state) || (NULL != end_key));
    530     if (NULL == end_key)
    531       end_key = &post_data[poff];
    532     mhd_assert (end_key >= start_key);
    533     key_len = (size_t) (end_key - start_key);
    534     mhd_assert (0 != key_len); /* it must be always non-zero here */
    535     if (pp->buffer_pos + key_len >= pp->buffer_size)
    536     {
    537       pp->state = PP_Error;
    538       return MHD_NO;
    539     }
    540     memcpy (&kbuf[pp->buffer_pos],
    541             start_key,
    542             key_len);
    543     pp->buffer_pos += key_len;
    544     pp->must_unescape_key = true;
    545     start_key = NULL;
    546     end_key = NULL;
    547   }
    548   if ( (NULL != start_value) &&
    549        (PP_ProcessValue == pp->state) )
    550   {
    551     /* compute key, if we have not already */
    552     if (pp->must_unescape_key)
    553     {
    554       kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
    555       MHD_unescape_plus (kbuf);
    556       MHD_http_unescape (kbuf);
    557       pp->must_unescape_key = false;
    558     }
    559     if (NULL == end_value)
    560       end_value = &post_data[poff];
    561     if ( (NULL != last_escape) &&
    562          (2 < (end_value - last_escape)) )
    563       last_escape = NULL;
    564     process_value (pp,
    565                    start_value,
    566                    end_value,
    567                    last_escape);
    568     pp->must_ikvi = false;
    569   }
    570   if (PP_Error == pp->state)
    571   {
    572     /* State in error, returning failure */
    573     return MHD_NO;
    574   }
    575   return MHD_YES;
    576 }
    577 
    578 
    579 /**
    580  * If the given line matches the prefix, strdup the
    581  * rest of the line into the suffix ptr.
    582  *
    583  * @param prefix prefix to match
    584  * @param prefix_len length of @a prefix
    585  * @param line line to match prefix in
    586  * @param suffix set to a copy of the rest of the line, starting at the end of the match
    587  * @return #MHD_YES if there was a match, #MHD_NO if not
    588  */
    589 static int
    590 try_match_header (const char *prefix,
    591                   size_t prefix_len,
    592                   char *line,
    593                   char **suffix)
    594 {
    595   if (NULL != *suffix)
    596     return MHD_NO;
    597   while (0 != *line)
    598   {
    599     if (MHD_str_equal_caseless_n_ (prefix,
    600                                    line,
    601                                    prefix_len))
    602     {
    603       *suffix = strdup (&line[prefix_len]);
    604       return MHD_YES;
    605     }
    606     ++line;
    607   }
    608   return MHD_NO;
    609 }
    610 
    611 
    612 /**
    613  *
    614  * @param pp post processor context
    615  * @param boundary boundary to look for
    616  * @param blen number of bytes in boundary
    617  * @param ioffptr set to the end of the boundary if found,
    618  *                otherwise incremented by one (FIXME: quirky API!)
    619  * @param next_state state to which we should advance the post processor
    620  *                   if the boundary is found
    621  * @param next_dash_state dash_state to which we should advance the
    622  *                   post processor if the boundary is found
    623  * @return #MHD_NO if the boundary is not found, #MHD_YES if we did find it
    624  */
    625 static int
    626 find_boundary (struct MHD_PostProcessor *pp,
    627                const char *boundary,
    628                size_t blen,
    629                size_t *ioffptr,
    630                enum PP_State next_state,
    631                enum PP_State next_dash_state)
    632 {
    633   char *buf = (char *) &pp[1];
    634   const char *dash;
    635 
    636   if (pp->buffer_pos < 2 + blen)
    637   {
    638     if (pp->buffer_pos == pp->buffer_size)
    639       pp->state = PP_Error;     /* out of memory */
    640     /* ++(*ioffptr); */
    641     return MHD_NO;              /* not enough data */
    642   }
    643   if ( (0 != memcmp ("--",
    644                      buf,
    645                      2)) ||
    646        (0 != memcmp (&buf[2],
    647                      boundary,
    648                      blen)))
    649   {
    650     if (pp->state != PP_Init)
    651     {
    652       /* garbage not allowed */
    653       pp->state = PP_Error;
    654     }
    655     else
    656     {
    657       /* skip over garbage (RFC 2046, 5.1.1) */
    658       dash = memchr (buf,
    659                      '-',
    660                      pp->buffer_pos);
    661       if (NULL == dash)
    662         (*ioffptr) += pp->buffer_pos;         /* skip entire buffer */
    663       else if (dash == buf)
    664         (*ioffptr)++;                         /* at least skip one byte */
    665       else
    666         (*ioffptr) += (size_t) (dash - buf);  /* skip to first possible boundary */
    667     }
    668     return MHD_NO;                            /* expected boundary */
    669   }
    670   /* remove boundary from buffer */
    671   (*ioffptr) += 2 + blen;
    672   /* next: start with headers */
    673   pp->skip_rn = RN_Dash;
    674   pp->state = next_state;
    675   pp->dash_state = next_dash_state;
    676   return MHD_YES;
    677 }
    678 
    679 
    680 /**
    681  * In buf, there maybe an expression '$key="$value"'.  If that is the
    682  * case, copy a copy of $value to destination.
    683  *
    684  * If destination is already non-NULL, do nothing.
    685  */
    686 static void
    687 try_get_value (const char *buf,
    688                const char *key,
    689                char **destination)
    690 {
    691   const char *spos;
    692   const char *bpos;
    693   const char *endv;
    694   size_t klen;
    695   size_t vlen;
    696 
    697   if (NULL != *destination)
    698     return;
    699   bpos = buf;
    700   klen = strlen (key);
    701   while (NULL != (spos = strstr (bpos, key)))
    702   {
    703     if ( (spos[klen] != '=') ||
    704          ( (spos != buf) &&
    705            (spos[-1] != ' ') ) )
    706     {
    707       /* no match */
    708       bpos = spos + 1;
    709       continue;
    710     }
    711     if (spos[klen + 1] != '"')
    712       return;                   /* not quoted */
    713     if (NULL == (endv = strchr (&spos[klen + 2],
    714                                 '\"')))
    715       return;                   /* no end-quote */
    716     vlen = (size_t) (endv - spos) - klen - 1;
    717     *destination = malloc (vlen);
    718     if (NULL == *destination)
    719       return;                   /* out of memory */
    720     (*destination)[vlen - 1] = '\0';
    721     memcpy (*destination,
    722             &spos[klen + 2],
    723             vlen - 1);
    724     return;                     /* success */
    725   }
    726 }
    727 
    728 
    729 /**
    730  * Go over the headers of the part and update
    731  * the fields in "pp" according to what we find.
    732  * If we are at the end of the headers (as indicated
    733  * by an empty line), transition into next_state.
    734  *
    735  * @param pp post processor context
    736  * @param ioffptr set to how many bytes have been
    737  *                processed
    738  * @param next_state state to which the post processor should
    739  *                be advanced if we find the end of the headers
    740  * @return #MHD_YES if we can continue processing,
    741  *         #MHD_NO on error or if we do not have
    742  *                enough data yet
    743  */
    744 static int
    745 process_multipart_headers (struct MHD_PostProcessor *pp,
    746                            size_t *ioffptr,
    747                            enum PP_State next_state)
    748 {
    749   char *buf = (char *) &pp[1];
    750   size_t newline;
    751 
    752   newline = 0;
    753   while ( (newline < pp->buffer_pos) &&
    754           (buf[newline] != '\r') &&
    755           (buf[newline] != '\n') )
    756     newline++;
    757   if (newline == pp->buffer_size)
    758   {
    759     pp->state = PP_Error;
    760     return MHD_NO;              /* out of memory */
    761   }
    762   if (newline == pp->buffer_pos)
    763     return MHD_NO;              /* will need more data */
    764   if (0 == newline)
    765   {
    766     /* empty line - end of headers */
    767     pp->skip_rn = RN_Full;
    768     pp->state = next_state;
    769     return MHD_YES;
    770   }
    771   /* got an actual header */
    772   if (buf[newline] == '\r')
    773     pp->skip_rn = RN_OptN;
    774   buf[newline] = '\0';
    775   if (MHD_str_equal_caseless_n_ ("Content-disposition: ",
    776                                  buf,
    777                                  MHD_STATICSTR_LEN_ ("Content-disposition: ")))
    778   {
    779     try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")],
    780                    "name",
    781                    &pp->content_name);
    782     try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")],
    783                    "filename",
    784                    &pp->content_filename);
    785   }
    786   else
    787   {
    788     try_match_header ("Content-type: ",
    789                       MHD_STATICSTR_LEN_ ("Content-type: "),
    790                       buf,
    791                       &pp->content_type);
    792     try_match_header ("Content-Transfer-Encoding: ",
    793                       MHD_STATICSTR_LEN_ ("Content-Transfer-Encoding: "),
    794                       buf,
    795                       &pp->content_transfer_encoding);
    796   }
    797   (*ioffptr) += newline + 1;
    798   return MHD_YES;
    799 }
    800 
    801 
    802 /**
    803  * We have the value until we hit the given boundary;
    804  * process accordingly.
    805  *
    806  * @param pp post processor context
    807  * @param ioffptr incremented based on the number of bytes processed
    808  * @param boundary the boundary to look for
    809  * @param blen strlen(boundary)
    810  * @param next_state what state to go into after the
    811  *        boundary was found
    812  * @param next_dash_state state to go into if the next
    813  *        boundary ends with "--"
    814  * @return #MHD_YES if we can continue processing,
    815  *         #MHD_NO on error or if we do not have
    816  *                enough data yet
    817  */
    818 static int
    819 process_value_to_boundary (struct MHD_PostProcessor *pp,
    820                            size_t *ioffptr,
    821                            const char *boundary,
    822                            size_t blen,
    823                            enum PP_State next_state,
    824                            enum PP_State next_dash_state)
    825 {
    826   char *buf = (char *) &pp[1];
    827   size_t newline;
    828   const char *r;
    829 
    830   /* all data in buf until the boundary
    831      (\r\n--+boundary) is part of the value */
    832   newline = 0;
    833   while (1)
    834   {
    835     while (newline + 4 < pp->buffer_pos)
    836     {
    837       r = memchr (&buf[newline],
    838                   '\r',
    839                   pp->buffer_pos - newline - 4);
    840       if (NULL == r)
    841       {
    842         newline = pp->buffer_pos - 4;
    843         break;
    844       }
    845       newline = (size_t) (r - buf);
    846       if (0 == memcmp ("\r\n--",
    847                        &buf[newline],
    848                        4))
    849         break;
    850       newline++;
    851     }
    852     if (newline + blen + 4 <= pp->buffer_pos)
    853     {
    854       /* can check boundary */
    855       if (0 != memcmp (&buf[newline + 4],
    856                        boundary,
    857                        blen))
    858       {
    859         /* no boundary, "\r\n--" is part of content, skip */
    860         newline += 4;
    861         continue;
    862       }
    863       else
    864       {
    865         /* boundary found, process until newline then
    866            skip boundary and go back to init */
    867         pp->skip_rn = RN_Dash;
    868         pp->state = next_state;
    869         pp->dash_state = next_dash_state;
    870         (*ioffptr) += blen + 4;             /* skip boundary as well */
    871         buf[newline] = '\0';
    872         break;
    873       }
    874     }
    875     else
    876     {
    877       /* cannot check for boundary, process content that
    878          we have and check again later; except, if we have
    879          no content, abort (out of memory) */
    880       if ( (0 == newline) &&
    881            (pp->buffer_pos == pp->buffer_size) )
    882       {
    883         pp->state = PP_Error;
    884         return MHD_NO;
    885       }
    886       break;
    887     }
    888   }
    889   /* newline is either at beginning of boundary or
    890      at least at the last character that we are sure
    891      is not part of the boundary */
    892   if ( ( (pp->must_ikvi) ||
    893          (0 != newline) ) &&
    894        (MHD_NO == pp->ikvi (pp->cls,
    895                             MHD_POSTDATA_KIND,
    896                             pp->content_name,
    897                             pp->content_filename,
    898                             pp->content_type,
    899                             pp->content_transfer_encoding,
    900                             buf,
    901                             pp->value_offset,
    902                             newline)) )
    903   {
    904     pp->state = PP_Error;
    905     return MHD_NO;
    906   }
    907   pp->must_ikvi = false;
    908   pp->value_offset += newline;
    909   (*ioffptr) += newline;
    910   return MHD_YES;
    911 }
    912 
    913 
    914 /**
    915  *
    916  * @param pp post processor context
    917  */
    918 static void
    919 free_unmarked (struct MHD_PostProcessor *pp)
    920 {
    921   if ( (NULL != pp->content_name) &&
    922        (0 == (pp->have & NE_content_name)) )
    923   {
    924     free (pp->content_name);
    925     pp->content_name = NULL;
    926   }
    927   if ( (NULL != pp->content_type) &&
    928        (0 == (pp->have & NE_content_type)) )
    929   {
    930     free (pp->content_type);
    931     pp->content_type = NULL;
    932   }
    933   if ( (NULL != pp->content_filename) &&
    934        (0 == (pp->have & NE_content_filename)) )
    935   {
    936     free (pp->content_filename);
    937     pp->content_filename = NULL;
    938   }
    939   if ( (NULL != pp->content_transfer_encoding) &&
    940        (0 == (pp->have & NE_content_transfer_encoding)) )
    941   {
    942     free (pp->content_transfer_encoding);
    943     pp->content_transfer_encoding = NULL;
    944   }
    945 }
    946 
    947 
    948 /**
    949  * Decode multipart POST data.
    950  *
    951  * @param pp post processor context
    952  * @param post_data data to decode
    953  * @param post_data_len number of bytes in @a post_data
    954  * @return #MHD_NO on error,
    955  */
    956 static enum MHD_Result
    957 post_process_multipart (struct MHD_PostProcessor *pp,
    958                         const char *post_data,
    959                         size_t post_data_len)
    960 {
    961   char *buf;
    962   size_t max;
    963   size_t ioff;
    964   size_t poff;
    965   int state_changed;
    966 
    967   buf = (char *) &pp[1];
    968   ioff = 0;
    969   poff = 0;
    970   state_changed = 1;
    971   while ( (poff < post_data_len) ||
    972           ( (pp->buffer_pos > 0) &&
    973             (0 != state_changed) ) )
    974   {
    975     /* first, move as much input data
    976        as possible to our internal buffer */
    977     max = pp->buffer_size - pp->buffer_pos;
    978     if (max > post_data_len - poff)
    979       max = post_data_len - poff;
    980     memcpy (&buf[pp->buffer_pos],
    981             &post_data[poff],
    982             max);
    983     poff += max;
    984     pp->buffer_pos += max;
    985     if ( (0 == max) &&
    986          (0 == state_changed) &&
    987          (poff < post_data_len) )
    988     {
    989       pp->state = PP_Error;
    990       return MHD_NO;            /* out of memory */
    991     }
    992     state_changed = 0;
    993 
    994     /* first state machine for '\r'-'\n' and '--' handling */
    995     switch (pp->skip_rn)
    996     {
    997     case RN_Inactive:
    998       break;
    999     case RN_OptN:
   1000       if (buf[0] == '\n')
   1001       {
   1002         ioff++;
   1003         pp->skip_rn = RN_Inactive;
   1004         goto AGAIN;
   1005       }
   1006     /* fall-through! */
   1007     case RN_Dash:
   1008       if (buf[0] == '-')
   1009       {
   1010         ioff++;
   1011         pp->skip_rn = RN_Dash2;
   1012         goto AGAIN;
   1013       }
   1014       pp->skip_rn = RN_Full;
   1015     /* fall-through! */
   1016     case RN_Full:
   1017       if (buf[0] == '\r')
   1018       {
   1019         if ( (pp->buffer_pos > 1) &&
   1020              ('\n' == buf[1]) )
   1021         {
   1022           pp->skip_rn = RN_Inactive;
   1023           ioff += 2;
   1024         }
   1025         else
   1026         {
   1027           pp->skip_rn = RN_OptN;
   1028           ioff++;
   1029         }
   1030         goto AGAIN;
   1031       }
   1032       if (buf[0] == '\n')
   1033       {
   1034         ioff++;
   1035         pp->skip_rn = RN_Inactive;
   1036         goto AGAIN;
   1037       }
   1038       pp->skip_rn = RN_Inactive;
   1039       pp->state = PP_Error;
   1040       return MHD_NO;            /* no '\r\n' */
   1041     case RN_Dash2:
   1042       if (buf[0] == '-')
   1043       {
   1044         ioff++;
   1045         pp->skip_rn = RN_Full;
   1046         pp->state = pp->dash_state;
   1047         goto AGAIN;
   1048       }
   1049       pp->state = PP_Error;
   1050       break;
   1051     }
   1052 
   1053     /* main state engine */
   1054     switch (pp->state)
   1055     {
   1056     case PP_Error:
   1057       return MHD_NO;
   1058     case PP_Done:
   1059       /* did not expect to receive more data */
   1060       pp->state = PP_Error;
   1061       return MHD_NO;
   1062     case PP_Init:
   1063       /**
   1064        * Per RFC2046 5.1.1 NOTE TO IMPLEMENTORS, consume anything
   1065        * prior to the first multipart boundary:
   1066        *
   1067        * > There appears to be room for additional information prior
   1068        * > to the first boundary delimiter line and following the
   1069        * > final boundary delimiter line.  These areas should
   1070        * > generally be left blank, and implementations must ignore
   1071        * > anything that appears before the first boundary delimiter
   1072        * > line or after the last one.
   1073        */
   1074       (void) find_boundary (pp,
   1075                             pp->boundary,
   1076                             pp->blen,
   1077                             &ioff,
   1078                             PP_ProcessEntryHeaders,
   1079                             PP_Done);
   1080       break;
   1081     case PP_NextBoundary:
   1082       if (MHD_NO == find_boundary (pp,
   1083                                    pp->boundary,
   1084                                    pp->blen,
   1085                                    &ioff,
   1086                                    PP_ProcessEntryHeaders,
   1087                                    PP_Done))
   1088       {
   1089         if (pp->state == PP_Error)
   1090           return MHD_NO;
   1091         goto END;
   1092       }
   1093       break;
   1094     case PP_ProcessEntryHeaders:
   1095       pp->must_ikvi = true;
   1096       if (MHD_NO ==
   1097           process_multipart_headers (pp,
   1098                                      &ioff,
   1099                                      PP_PerformCheckMultipart))
   1100       {
   1101         if (pp->state == PP_Error)
   1102           return MHD_NO;
   1103         else
   1104           goto END;
   1105       }
   1106       state_changed = 1;
   1107       break;
   1108     case PP_PerformCheckMultipart:
   1109       if ( (NULL != pp->content_type) &&
   1110            (MHD_str_equal_caseless_n_ (pp->content_type,
   1111                                        "multipart/mixed",
   1112                                        MHD_STATICSTR_LEN_ ("multipart/mixed"))))
   1113       {
   1114         pp->nested_boundary = strstr (pp->content_type,
   1115                                       "boundary=");
   1116         if (NULL == pp->nested_boundary)
   1117         {
   1118           pp->state = PP_Error;
   1119           return MHD_NO;
   1120         }
   1121         pp->nested_boundary =
   1122           strdup (&pp->nested_boundary[MHD_STATICSTR_LEN_ ("boundary=")]);
   1123         if (NULL == pp->nested_boundary)
   1124         {
   1125           /* out of memory */
   1126           pp->state = PP_Error;
   1127           return MHD_NO;
   1128         }
   1129         /* free old content type, we will need that field
   1130            for the content type of the nested elements */
   1131         free (pp->content_type);
   1132         pp->content_type = NULL;
   1133         pp->nlen = strlen (pp->nested_boundary);
   1134         pp->state = PP_Nested_Init;
   1135         state_changed = 1;
   1136         break;
   1137       }
   1138       pp->state = PP_ProcessValueToBoundary;
   1139       pp->value_offset = 0;
   1140       state_changed = 1;
   1141       break;
   1142     case PP_ProcessValueToBoundary:
   1143       if (MHD_NO == process_value_to_boundary (pp,
   1144                                                &ioff,
   1145                                                pp->boundary,
   1146                                                pp->blen,
   1147                                                PP_PerformCleanup,
   1148                                                PP_Done))
   1149       {
   1150         if (pp->state == PP_Error)
   1151           return MHD_NO;
   1152         break;
   1153       }
   1154       break;
   1155     case PP_PerformCleanup:
   1156       /* clean up state of one multipart form-data element! */
   1157       pp->have = NE_none;
   1158       free_unmarked (pp);
   1159       if (NULL != pp->nested_boundary)
   1160       {
   1161         free (pp->nested_boundary);
   1162         pp->nested_boundary = NULL;
   1163       }
   1164       pp->state = PP_ProcessEntryHeaders;
   1165       state_changed = 1;
   1166       break;
   1167     case PP_Nested_Init:
   1168       if (NULL == pp->nested_boundary)
   1169       {
   1170         pp->state = PP_Error;
   1171         return MHD_NO;
   1172       }
   1173       if (MHD_NO == find_boundary (pp,
   1174                                    pp->nested_boundary,
   1175                                    pp->nlen,
   1176                                    &ioff,
   1177                                    PP_Nested_PerformMarking,
   1178                                    PP_NextBoundary /* or PP_Error? */))
   1179       {
   1180         if (pp->state == PP_Error)
   1181           return MHD_NO;
   1182         goto END;
   1183       }
   1184       break;
   1185     case PP_Nested_PerformMarking:
   1186       /* remember what headers were given
   1187          globally */
   1188       pp->have = NE_none;
   1189       if (NULL != pp->content_name)
   1190         pp->have |= NE_content_name;
   1191       if (NULL != pp->content_type)
   1192         pp->have |= NE_content_type;
   1193       if (NULL != pp->content_filename)
   1194         pp->have |= NE_content_filename;
   1195       if (NULL != pp->content_transfer_encoding)
   1196         pp->have |= NE_content_transfer_encoding;
   1197       pp->state = PP_Nested_ProcessEntryHeaders;
   1198       state_changed = 1;
   1199       break;
   1200     case PP_Nested_ProcessEntryHeaders:
   1201       pp->value_offset = 0;
   1202       if (MHD_NO ==
   1203           process_multipart_headers (pp,
   1204                                      &ioff,
   1205                                      PP_Nested_ProcessValueToBoundary))
   1206       {
   1207         if (pp->state == PP_Error)
   1208           return MHD_NO;
   1209         else
   1210           goto END;
   1211       }
   1212       state_changed = 1;
   1213       break;
   1214     case PP_Nested_ProcessValueToBoundary:
   1215       if (MHD_NO == process_value_to_boundary (pp,
   1216                                                &ioff,
   1217                                                pp->nested_boundary,
   1218                                                pp->nlen,
   1219                                                PP_Nested_PerformCleanup,
   1220                                                PP_NextBoundary))
   1221       {
   1222         if (pp->state == PP_Error)
   1223           return MHD_NO;
   1224         break;
   1225       }
   1226       break;
   1227     case PP_Nested_PerformCleanup:
   1228       free_unmarked (pp);
   1229       pp->state = PP_Nested_ProcessEntryHeaders;
   1230       state_changed = 1;
   1231       break;
   1232     case PP_ProcessKey:
   1233     case PP_ProcessValue:
   1234     case PP_Callback:
   1235     default:
   1236       MHD_PANIC (_ ("internal error.\n")); /* should never happen! */
   1237     }
   1238 AGAIN:
   1239     if (ioff > 0)
   1240     {
   1241       memmove (buf,
   1242                &buf[ioff],
   1243                pp->buffer_pos - ioff);
   1244       pp->buffer_pos -= ioff;
   1245       ioff = 0;
   1246       state_changed = 1;
   1247     }
   1248   }
   1249 END:
   1250   if (0 != ioff)
   1251   {
   1252     memmove (buf,
   1253              &buf[ioff],
   1254              pp->buffer_pos - ioff);
   1255     pp->buffer_pos -= ioff;
   1256   }
   1257   if (poff < post_data_len)
   1258   {
   1259     pp->state = PP_Error;
   1260     return MHD_NO;              /* serious error */
   1261   }
   1262   return MHD_YES;
   1263 }
   1264 
   1265 
   1266 _MHD_EXTERN enum MHD_Result
   1267 MHD_post_process (struct MHD_PostProcessor *pp,
   1268                   const char *post_data,
   1269                   size_t post_data_len)
   1270 {
   1271   if (0 == post_data_len)
   1272     return MHD_YES;
   1273   if (NULL == pp)
   1274     return MHD_NO;
   1275   if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
   1276                                  pp->encoding,
   1277                                  MHD_STATICSTR_LEN_ (
   1278                                    MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
   1279     return post_process_urlencoded (pp,
   1280                                     post_data,
   1281                                     post_data_len);
   1282   if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA,
   1283                                  pp->encoding,
   1284                                  MHD_STATICSTR_LEN_ (
   1285                                    MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
   1286     return post_process_multipart (pp,
   1287                                    post_data,
   1288                                    post_data_len);
   1289   /* this should never be reached */
   1290   return MHD_NO;
   1291 }
   1292 
   1293 
   1294 _MHD_EXTERN enum MHD_Result
   1295 MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
   1296 {
   1297   enum MHD_Result ret;
   1298 
   1299   if (NULL == pp)
   1300     return MHD_YES;
   1301   if (PP_ProcessValue == pp->state)
   1302   {
   1303     /* key without terminated value left at the end of the
   1304        buffer; fake receiving a termination character to
   1305        ensure it is also processed */
   1306     post_process_urlencoded (pp,
   1307                              "\n",
   1308                              1);
   1309   }
   1310   /* These internal strings need cleaning up since
   1311      the post-processing may have been interrupted
   1312      at any stage */
   1313   if ( (pp->xbuf_pos > 0) ||
   1314        ( (pp->state != PP_Done) &&
   1315          (pp->state != PP_Init) ) )
   1316     ret = MHD_NO;
   1317   else
   1318     ret = MHD_YES;
   1319   pp->have = NE_none;
   1320   free_unmarked (pp);
   1321   if (NULL != pp->nested_boundary)
   1322     free (pp->nested_boundary);
   1323   free (pp);
   1324   return ret;
   1325 }
   1326 
   1327 
   1328 /* end of postprocessor.c */