libmicrohttpd

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

postprocessor.c (38301B)


      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          (pp->buffer_pos + key_len < pp->buffer_pos) )
    537     {
    538       pp->state = PP_Error;
    539       return MHD_NO;
    540     }
    541     memcpy (&kbuf[pp->buffer_pos],
    542             start_key,
    543             key_len);
    544     pp->buffer_pos += key_len;
    545     pp->must_unescape_key = true;
    546     start_key = NULL;
    547     end_key = NULL;
    548   }
    549   if ( (NULL != start_value) &&
    550        (PP_ProcessValue == pp->state) )
    551   {
    552     /* compute key, if we have not already */
    553     if (pp->must_unescape_key)
    554     {
    555       kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
    556       MHD_unescape_plus (kbuf);
    557       MHD_http_unescape (kbuf);
    558       pp->must_unescape_key = false;
    559     }
    560     if (NULL == end_value)
    561       end_value = &post_data[poff];
    562     if ( (NULL != last_escape) &&
    563          (2 < (end_value - last_escape)) )
    564       last_escape = NULL;
    565     process_value (pp,
    566                    start_value,
    567                    end_value,
    568                    last_escape);
    569     pp->must_ikvi = false;
    570   }
    571   if (PP_Error == pp->state)
    572   {
    573     /* State in error, returning failure */
    574     return MHD_NO;
    575   }
    576   return MHD_YES;
    577 }
    578 
    579 
    580 /**
    581  * If the given line matches the prefix, strdup the
    582  * rest of the line into the suffix ptr.
    583  *
    584  * @param prefix prefix to match
    585  * @param prefix_len length of @a prefix
    586  * @param line line to match prefix in
    587  * @param suffix set to a copy of the rest of the line, starting at the end of the match
    588  * @return #MHD_YES if there was a match, #MHD_NO if not
    589  */
    590 static int
    591 try_match_header (const char *prefix,
    592                   size_t prefix_len,
    593                   char *line,
    594                   char **suffix)
    595 {
    596   if (NULL != *suffix)
    597     return MHD_NO;
    598   if (MHD_str_equal_caseless_n_ (prefix,
    599                                  line,
    600                                  prefix_len))
    601   {
    602     *suffix = strdup (&line[prefix_len]);
    603     return MHD_YES;
    604   }
    605   return MHD_NO;
    606 }
    607 
    608 
    609 /**
    610  *
    611  * @param pp post processor context
    612  * @param boundary boundary to look for
    613  * @param blen number of bytes in boundary
    614  * @param ioffptr set to the end of the boundary if found,
    615  *                otherwise incremented by one (FIXME: quirky API!)
    616  * @param next_state state to which we should advance the post processor
    617  *                   if the boundary is found
    618  * @param next_dash_state dash_state to which we should advance the
    619  *                   post processor if the boundary is found
    620  * @return #MHD_NO if the boundary is not found, #MHD_YES if we did find it
    621  */
    622 static int
    623 find_boundary (struct MHD_PostProcessor *pp,
    624                const char *boundary,
    625                size_t blen,
    626                size_t *ioffptr,
    627                enum PP_State next_state,
    628                enum PP_State next_dash_state)
    629 {
    630   char *buf = (char *) &pp[1];
    631   const char *dash;
    632 
    633   if (pp->buffer_pos < 2 + blen)
    634   {
    635     if (pp->buffer_pos == pp->buffer_size)
    636       pp->state = PP_Error;     /* out of memory */
    637     /* ++(*ioffptr); */
    638     return MHD_NO;              /* not enough data */
    639   }
    640   if ( (0 != memcmp ("--",
    641                      buf,
    642                      2)) ||
    643        (0 != memcmp (&buf[2],
    644                      boundary,
    645                      blen)))
    646   {
    647     if (pp->state != PP_Init)
    648     {
    649       /* garbage not allowed */
    650       pp->state = PP_Error;
    651     }
    652     else
    653     {
    654       /* skip over garbage (RFC 2046, 5.1.1) */
    655       dash = memchr (buf,
    656                      '-',
    657                      pp->buffer_pos);
    658       if (NULL == dash)
    659         (*ioffptr) += pp->buffer_pos;         /* skip entire buffer */
    660       else if (dash == buf)
    661         (*ioffptr)++;                         /* at least skip one byte */
    662       else
    663         (*ioffptr) += (size_t) (dash - buf);  /* skip to first possible boundary */
    664     }
    665     return MHD_NO;                            /* expected boundary */
    666   }
    667   /* remove boundary from buffer */
    668   (*ioffptr) += 2 + blen;
    669   /* next: start with headers */
    670   pp->skip_rn = RN_Dash;
    671   pp->state = next_state;
    672   pp->dash_state = next_dash_state;
    673   return MHD_YES;
    674 }
    675 
    676 
    677 /**
    678  * In buf, there maybe an expression '$key="$value"'.  If that is the
    679  * case, copy a copy of $value to destination.
    680  *
    681  * If destination is already non-NULL, do nothing.
    682  */
    683 static void
    684 try_get_value (const char *buf,
    685                const char *key,
    686                char **destination)
    687 {
    688   const char *spos;
    689   const char *bpos;
    690   const char *endv;
    691   size_t klen;
    692   size_t vlen;
    693 
    694   if (NULL != *destination)
    695     return;
    696   bpos = buf;
    697   klen = strlen (key);
    698   while (NULL != (spos = strstr (bpos, key)))
    699   {
    700     if ( (spos[klen] != '=') ||
    701          ( (spos != buf) &&
    702            (spos[-1] != ' ') ) )
    703     {
    704       /* no match */
    705       bpos = spos + 1;
    706       continue;
    707     }
    708     if (spos[klen + 1] != '"')
    709       return;                   /* not quoted */
    710     if (NULL == (endv = strchr (&spos[klen + 2],
    711                                 '\"')))
    712       return;                   /* no end-quote */
    713     vlen = (size_t) (endv - spos) - klen - 1;
    714     *destination = malloc (vlen);
    715     if (NULL == *destination)
    716       return;                   /* out of memory */
    717     (*destination)[vlen - 1] = '\0';
    718     memcpy (*destination,
    719             &spos[klen + 2],
    720             vlen - 1);
    721     return;                     /* success */
    722   }
    723 }
    724 
    725 
    726 /**
    727  * Go over the headers of the part and update
    728  * the fields in "pp" according to what we find.
    729  * If we are at the end of the headers (as indicated
    730  * by an empty line), transition into next_state.
    731  *
    732  * @param pp post processor context
    733  * @param ioffptr set to how many bytes have been
    734  *                processed
    735  * @param next_state state to which the post processor should
    736  *                be advanced if we find the end of the headers
    737  * @return #MHD_YES if we can continue processing,
    738  *         #MHD_NO on error or if we do not have
    739  *                enough data yet
    740  */
    741 static int
    742 process_multipart_headers (struct MHD_PostProcessor *pp,
    743                            size_t *ioffptr,
    744                            enum PP_State next_state)
    745 {
    746   char *buf = (char *) &pp[1];
    747   size_t newline;
    748 
    749   newline = 0;
    750   while ( (newline < pp->buffer_pos) &&
    751           (buf[newline] != '\r') &&
    752           (buf[newline] != '\n') )
    753     newline++;
    754   if (newline == pp->buffer_size)
    755   {
    756     pp->state = PP_Error;
    757     return MHD_NO;              /* out of memory */
    758   }
    759   if (newline == pp->buffer_pos)
    760     return MHD_NO;              /* will need more data */
    761   if (0 == newline)
    762   {
    763     /* empty line - end of headers */
    764     pp->skip_rn = RN_Full;
    765     pp->state = next_state;
    766     return MHD_YES;
    767   }
    768   /* got an actual header */
    769   if (buf[newline] == '\r')
    770     pp->skip_rn = RN_OptN;
    771   buf[newline] = '\0';
    772   if (MHD_str_equal_caseless_n_ ("Content-disposition: ",
    773                                  buf,
    774                                  MHD_STATICSTR_LEN_ ("Content-disposition: ")))
    775   {
    776     try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")],
    777                    "name",
    778                    &pp->content_name);
    779     try_get_value (&buf[MHD_STATICSTR_LEN_ ("Content-disposition: ")],
    780                    "filename",
    781                    &pp->content_filename);
    782   }
    783   else
    784   {
    785     try_match_header ("Content-type: ",
    786                       MHD_STATICSTR_LEN_ ("Content-type: "),
    787                       buf,
    788                       &pp->content_type);
    789     try_match_header ("Content-Transfer-Encoding: ",
    790                       MHD_STATICSTR_LEN_ ("Content-Transfer-Encoding: "),
    791                       buf,
    792                       &pp->content_transfer_encoding);
    793   }
    794   (*ioffptr) += newline + 1;
    795   return MHD_YES;
    796 }
    797 
    798 
    799 /**
    800  * We have the value until we hit the given boundary;
    801  * process accordingly.
    802  *
    803  * @param pp post processor context
    804  * @param ioffptr incremented based on the number of bytes processed
    805  * @param boundary the boundary to look for
    806  * @param blen strlen(boundary)
    807  * @param next_state what state to go into after the
    808  *        boundary was found
    809  * @param next_dash_state state to go into if the next
    810  *        boundary ends with "--"
    811  * @return #MHD_YES if we can continue processing,
    812  *         #MHD_NO on error or if we do not have
    813  *                enough data yet
    814  */
    815 static int
    816 process_value_to_boundary (struct MHD_PostProcessor *pp,
    817                            size_t *ioffptr,
    818                            const char *boundary,
    819                            size_t blen,
    820                            enum PP_State next_state,
    821                            enum PP_State next_dash_state)
    822 {
    823   char *buf = (char *) &pp[1];
    824   size_t newline;
    825   const char *r;
    826 
    827   /* all data in buf until the boundary
    828      (\r\n--+boundary) is part of the value */
    829   newline = 0;
    830   while (1)
    831   {
    832     while (newline + 4 < pp->buffer_pos)
    833     {
    834       r = memchr (&buf[newline],
    835                   '\r',
    836                   pp->buffer_pos - newline - 4);
    837       if (NULL == r)
    838       {
    839         newline = pp->buffer_pos - 4;
    840         break;
    841       }
    842       newline = (size_t) (r - buf);
    843       if (0 == memcmp ("\r\n--",
    844                        &buf[newline],
    845                        4))
    846         break;
    847       newline++;
    848     }
    849     if (newline + blen + 4 <= pp->buffer_pos)
    850     {
    851       /* can check boundary */
    852       if (0 != memcmp (&buf[newline + 4],
    853                        boundary,
    854                        blen))
    855       {
    856         /* no boundary, "\r\n--" is part of content, skip */
    857         newline += 4;
    858         continue;
    859       }
    860       else
    861       {
    862         /* boundary found, process until newline then
    863            skip boundary and go back to init */
    864         pp->skip_rn = RN_Dash;
    865         pp->state = next_state;
    866         pp->dash_state = next_dash_state;
    867         (*ioffptr) += blen + 4;             /* skip boundary as well */
    868         buf[newline] = '\0';
    869         break;
    870       }
    871     }
    872     else
    873     {
    874       /* cannot check for boundary, process content that
    875          we have and check again later; except, if we have
    876          no content, abort (out of memory) */
    877       if ( (0 == newline) &&
    878            (pp->buffer_pos == pp->buffer_size) )
    879       {
    880         pp->state = PP_Error;
    881         return MHD_NO;
    882       }
    883       break;
    884     }
    885   }
    886   /* newline is either at beginning of boundary or
    887      at least at the last character that we are sure
    888      is not part of the boundary */
    889   if ( ( (pp->must_ikvi) ||
    890          (0 != newline) ) &&
    891        (MHD_NO == pp->ikvi (pp->cls,
    892                             MHD_POSTDATA_KIND,
    893                             pp->content_name,
    894                             pp->content_filename,
    895                             pp->content_type,
    896                             pp->content_transfer_encoding,
    897                             buf,
    898                             pp->value_offset,
    899                             newline)) )
    900   {
    901     pp->state = PP_Error;
    902     return MHD_NO;
    903   }
    904   pp->must_ikvi = false;
    905   pp->value_offset += newline;
    906   (*ioffptr) += newline;
    907   return MHD_YES;
    908 }
    909 
    910 
    911 /**
    912  *
    913  * @param pp post processor context
    914  */
    915 static void
    916 free_unmarked (struct MHD_PostProcessor *pp)
    917 {
    918   if ( (NULL != pp->content_name) &&
    919        (0 == (pp->have & NE_content_name)) )
    920   {
    921     free (pp->content_name);
    922     pp->content_name = NULL;
    923   }
    924   if ( (NULL != pp->content_type) &&
    925        (0 == (pp->have & NE_content_type)) )
    926   {
    927     free (pp->content_type);
    928     pp->content_type = NULL;
    929   }
    930   if ( (NULL != pp->content_filename) &&
    931        (0 == (pp->have & NE_content_filename)) )
    932   {
    933     free (pp->content_filename);
    934     pp->content_filename = NULL;
    935   }
    936   if ( (NULL != pp->content_transfer_encoding) &&
    937        (0 == (pp->have & NE_content_transfer_encoding)) )
    938   {
    939     free (pp->content_transfer_encoding);
    940     pp->content_transfer_encoding = NULL;
    941   }
    942 }
    943 
    944 
    945 /**
    946  * Decode multipart POST data.
    947  *
    948  * @param pp post processor context
    949  * @param post_data data to decode
    950  * @param post_data_len number of bytes in @a post_data
    951  * @return #MHD_NO on error,
    952  */
    953 static enum MHD_Result
    954 post_process_multipart (struct MHD_PostProcessor *pp,
    955                         const char *post_data,
    956                         size_t post_data_len)
    957 {
    958   char *buf;
    959   size_t max;
    960   size_t ioff;
    961   size_t poff;
    962   int state_changed;
    963 
    964   buf = (char *) &pp[1];
    965   ioff = 0;
    966   poff = 0;
    967   state_changed = 1;
    968   while ( (poff < post_data_len) ||
    969           ( (pp->buffer_pos > 0) &&
    970             (0 != state_changed) ) )
    971   {
    972     /* first, move as much input data
    973        as possible to our internal buffer */
    974     max = pp->buffer_size - pp->buffer_pos;
    975     if (max > post_data_len - poff)
    976       max = post_data_len - poff;
    977     memcpy (&buf[pp->buffer_pos],
    978             &post_data[poff],
    979             max);
    980     poff += max;
    981     pp->buffer_pos += max;
    982     if ( (0 == max) &&
    983          (0 == state_changed) &&
    984          (poff < post_data_len) )
    985     {
    986       pp->state = PP_Error;
    987       return MHD_NO;            /* out of memory */
    988     }
    989     state_changed = 0;
    990 
    991     /* first state machine for '\r'-'\n' and '--' handling */
    992     switch (pp->skip_rn)
    993     {
    994     case RN_Inactive:
    995       break;
    996     case RN_OptN:
    997       if (buf[0] == '\n')
    998       {
    999         ioff++;
   1000         pp->skip_rn = RN_Inactive;
   1001         goto AGAIN;
   1002       }
   1003     /* fall-through! */
   1004     case RN_Dash:
   1005       if (buf[0] == '-')
   1006       {
   1007         ioff++;
   1008         pp->skip_rn = RN_Dash2;
   1009         goto AGAIN;
   1010       }
   1011       pp->skip_rn = RN_Full;
   1012     /* fall-through! */
   1013     case RN_Full:
   1014       if (buf[0] == '\r')
   1015       {
   1016         if ( (pp->buffer_pos > 1) &&
   1017              ('\n' == buf[1]) )
   1018         {
   1019           pp->skip_rn = RN_Inactive;
   1020           ioff += 2;
   1021         }
   1022         else
   1023         {
   1024           pp->skip_rn = RN_OptN;
   1025           ioff++;
   1026         }
   1027         goto AGAIN;
   1028       }
   1029       if (buf[0] == '\n')
   1030       {
   1031         ioff++;
   1032         pp->skip_rn = RN_Inactive;
   1033         goto AGAIN;
   1034       }
   1035       pp->skip_rn = RN_Inactive;
   1036       pp->state = PP_Error;
   1037       return MHD_NO;            /* no '\r\n' */
   1038     case RN_Dash2:
   1039       if (buf[0] == '-')
   1040       {
   1041         ioff++;
   1042         pp->skip_rn = RN_Full;
   1043         pp->state = pp->dash_state;
   1044         goto AGAIN;
   1045       }
   1046       pp->state = PP_Error;
   1047       break;
   1048     }
   1049 
   1050     /* main state engine */
   1051     switch (pp->state)
   1052     {
   1053     case PP_Error:
   1054       return MHD_NO;
   1055     case PP_Done:
   1056       /* did not expect to receive more data */
   1057       pp->state = PP_Error;
   1058       return MHD_NO;
   1059     case PP_Init:
   1060       /**
   1061        * Per RFC2046 5.1.1 NOTE TO IMPLEMENTORS, consume anything
   1062        * prior to the first multipart boundary:
   1063        *
   1064        * > There appears to be room for additional information prior
   1065        * > to the first boundary delimiter line and following the
   1066        * > final boundary delimiter line.  These areas should
   1067        * > generally be left blank, and implementations must ignore
   1068        * > anything that appears before the first boundary delimiter
   1069        * > line or after the last one.
   1070        */
   1071       (void) find_boundary (pp,
   1072                             pp->boundary,
   1073                             pp->blen,
   1074                             &ioff,
   1075                             PP_ProcessEntryHeaders,
   1076                             PP_Done);
   1077       break;
   1078     case PP_NextBoundary:
   1079       if (MHD_NO == find_boundary (pp,
   1080                                    pp->boundary,
   1081                                    pp->blen,
   1082                                    &ioff,
   1083                                    PP_ProcessEntryHeaders,
   1084                                    PP_Done))
   1085       {
   1086         if (pp->state == PP_Error)
   1087           return MHD_NO;
   1088         goto END;
   1089       }
   1090       break;
   1091     case PP_ProcessEntryHeaders:
   1092       pp->must_ikvi = true;
   1093       if (MHD_NO ==
   1094           process_multipart_headers (pp,
   1095                                      &ioff,
   1096                                      PP_PerformCheckMultipart))
   1097       {
   1098         if (pp->state == PP_Error)
   1099           return MHD_NO;
   1100         else
   1101           goto END;
   1102       }
   1103       state_changed = 1;
   1104       break;
   1105     case PP_PerformCheckMultipart:
   1106       if ( (NULL != pp->content_type) &&
   1107            (MHD_str_equal_caseless_n_ (pp->content_type,
   1108                                        "multipart/mixed",
   1109                                        MHD_STATICSTR_LEN_ ("multipart/mixed"))))
   1110       {
   1111         pp->nested_boundary = strstr (pp->content_type,
   1112                                       "boundary=");
   1113         if (NULL == pp->nested_boundary)
   1114         {
   1115           pp->state = PP_Error;
   1116           return MHD_NO;
   1117         }
   1118         pp->nested_boundary =
   1119           strdup (&pp->nested_boundary[MHD_STATICSTR_LEN_ ("boundary=")]);
   1120         if (NULL == pp->nested_boundary)
   1121         {
   1122           /* out of memory */
   1123           pp->state = PP_Error;
   1124           return MHD_NO;
   1125         }
   1126         /* free old content type, we will need that field
   1127            for the content type of the nested elements */
   1128         free (pp->content_type);
   1129         pp->content_type = NULL;
   1130         pp->nlen = strlen (pp->nested_boundary);
   1131         pp->state = PP_Nested_Init;
   1132         state_changed = 1;
   1133         break;
   1134       }
   1135       pp->state = PP_ProcessValueToBoundary;
   1136       pp->value_offset = 0;
   1137       state_changed = 1;
   1138       break;
   1139     case PP_ProcessValueToBoundary:
   1140       if (MHD_NO == process_value_to_boundary (pp,
   1141                                                &ioff,
   1142                                                pp->boundary,
   1143                                                pp->blen,
   1144                                                PP_PerformCleanup,
   1145                                                PP_Done))
   1146       {
   1147         if (pp->state == PP_Error)
   1148           return MHD_NO;
   1149         break;
   1150       }
   1151       break;
   1152     case PP_PerformCleanup:
   1153       /* clean up state of one multipart form-data element! */
   1154       pp->have = NE_none;
   1155       free_unmarked (pp);
   1156       if (NULL != pp->nested_boundary)
   1157       {
   1158         free (pp->nested_boundary);
   1159         pp->nested_boundary = NULL;
   1160       }
   1161       pp->state = PP_ProcessEntryHeaders;
   1162       state_changed = 1;
   1163       break;
   1164     case PP_Nested_Init:
   1165       if (NULL == pp->nested_boundary)
   1166       {
   1167         pp->state = PP_Error;
   1168         return MHD_NO;
   1169       }
   1170       if (MHD_NO == find_boundary (pp,
   1171                                    pp->nested_boundary,
   1172                                    pp->nlen,
   1173                                    &ioff,
   1174                                    PP_Nested_PerformMarking,
   1175                                    PP_NextBoundary /* or PP_Error? */))
   1176       {
   1177         if (pp->state == PP_Error)
   1178           return MHD_NO;
   1179         goto END;
   1180       }
   1181       break;
   1182     case PP_Nested_PerformMarking:
   1183       /* remember what headers were given
   1184          globally */
   1185       pp->have = NE_none;
   1186       if (NULL != pp->content_name)
   1187         pp->have |= NE_content_name;
   1188       if (NULL != pp->content_type)
   1189         pp->have |= NE_content_type;
   1190       if (NULL != pp->content_filename)
   1191         pp->have |= NE_content_filename;
   1192       if (NULL != pp->content_transfer_encoding)
   1193         pp->have |= NE_content_transfer_encoding;
   1194       pp->state = PP_Nested_ProcessEntryHeaders;
   1195       state_changed = 1;
   1196       break;
   1197     case PP_Nested_ProcessEntryHeaders:
   1198       pp->value_offset = 0;
   1199       if (MHD_NO ==
   1200           process_multipart_headers (pp,
   1201                                      &ioff,
   1202                                      PP_Nested_ProcessValueToBoundary))
   1203       {
   1204         if (pp->state == PP_Error)
   1205           return MHD_NO;
   1206         else
   1207           goto END;
   1208       }
   1209       state_changed = 1;
   1210       break;
   1211     case PP_Nested_ProcessValueToBoundary:
   1212       if (MHD_NO == process_value_to_boundary (pp,
   1213                                                &ioff,
   1214                                                pp->nested_boundary,
   1215                                                pp->nlen,
   1216                                                PP_Nested_PerformCleanup,
   1217                                                PP_NextBoundary))
   1218       {
   1219         if (pp->state == PP_Error)
   1220           return MHD_NO;
   1221         break;
   1222       }
   1223       break;
   1224     case PP_Nested_PerformCleanup:
   1225       free_unmarked (pp);
   1226       pp->state = PP_Nested_ProcessEntryHeaders;
   1227       state_changed = 1;
   1228       break;
   1229     case PP_ProcessKey:
   1230     case PP_ProcessValue:
   1231     case PP_Callback:
   1232     default:
   1233       MHD_PANIC (_ ("internal error.\n")); /* should never happen! */
   1234     }
   1235 AGAIN:
   1236     if (ioff > 0)
   1237     {
   1238       memmove (buf,
   1239                &buf[ioff],
   1240                pp->buffer_pos - ioff);
   1241       pp->buffer_pos -= ioff;
   1242       ioff = 0;
   1243       state_changed = 1;
   1244     }
   1245   }
   1246 END:
   1247   if (0 != ioff)
   1248   {
   1249     memmove (buf,
   1250              &buf[ioff],
   1251              pp->buffer_pos - ioff);
   1252     pp->buffer_pos -= ioff;
   1253   }
   1254   if (poff < post_data_len)
   1255   {
   1256     pp->state = PP_Error;
   1257     return MHD_NO;              /* serious error */
   1258   }
   1259   return MHD_YES;
   1260 }
   1261 
   1262 
   1263 _MHD_EXTERN enum MHD_Result
   1264 MHD_post_process (struct MHD_PostProcessor *pp,
   1265                   const char *post_data,
   1266                   size_t post_data_len)
   1267 {
   1268   if (0 == post_data_len)
   1269     return MHD_YES;
   1270   if (NULL == pp)
   1271     return MHD_NO;
   1272   if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
   1273                                  pp->encoding,
   1274                                  MHD_STATICSTR_LEN_ (
   1275                                    MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
   1276     return post_process_urlencoded (pp,
   1277                                     post_data,
   1278                                     post_data_len);
   1279   if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA,
   1280                                  pp->encoding,
   1281                                  MHD_STATICSTR_LEN_ (
   1282                                    MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
   1283     return post_process_multipart (pp,
   1284                                    post_data,
   1285                                    post_data_len);
   1286   /* this should never be reached */
   1287   return MHD_NO;
   1288 }
   1289 
   1290 
   1291 _MHD_EXTERN enum MHD_Result
   1292 MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
   1293 {
   1294   enum MHD_Result ret;
   1295 
   1296   if (NULL == pp)
   1297     return MHD_YES;
   1298   if (PP_ProcessValue == pp->state)
   1299   {
   1300     /* key without terminated value left at the end of the
   1301        buffer; fake receiving a termination character to
   1302        ensure it is also processed */
   1303     post_process_urlencoded (pp,
   1304                              "\n",
   1305                              1);
   1306   }
   1307   /* These internal strings need cleaning up since
   1308      the post-processing may have been interrupted
   1309      at any stage */
   1310   if ( (pp->xbuf_pos > 0) ||
   1311        ( (pp->state != PP_Done) &&
   1312          (pp->state != PP_Init) ) )
   1313     ret = MHD_NO;
   1314   else
   1315     ret = MHD_YES;
   1316   pp->have = NE_none;
   1317   free_unmarked (pp);
   1318   if (NULL != pp->nested_boundary)
   1319     free (pp->nested_boundary);
   1320   free (pp);
   1321   return ret;
   1322 }
   1323 
   1324 
   1325 /* end of postprocessor.c */