libmicrohttpd

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

postprocessor.c (38909B)


      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_ (
     75           MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA,
     76           encoding,
     77           MHD_STATICSTR_LEN_ (
     78             MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
     79     {
     80       return NULL;
     81     }
     82     boundary =
     83       &encoding[MHD_STATICSTR_LEN_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)];
     84     /* Q: should this be "strcasestr"? */
     85     boundary = strstr (boundary, "boundary=");
     86     if (NULL == boundary)
     87       return NULL; /* failed to determine boundary */
     88     boundary += MHD_STATICSTR_LEN_ ("boundary=");
     89     blen = strlen (boundary);
     90     if ( (blen < 2) ||
     91          (blen * 2 + 2 > buffer_size) )
     92       return NULL;              /* (will be) out of memory or invalid boundary */
     93     if ( (boundary[0] == '"') &&
     94          (boundary[blen - 1] == '"') )
     95     {
     96       /* remove enclosing quotes */
     97       ++boundary;
     98       blen -= 2;
     99     }
    100   }
    101   else
    102     blen = 0;
    103   buffer_size += 4; /* round up to get nice block sizes despite boundary search */
    104 
    105   /* add +1 to ensure we ALWAYS have a zero-termination at the end */
    106   if (NULL == (ret = MHD_calloc_ (1, sizeof (struct MHD_PostProcessor)
    107                                   + buffer_size + 1)))
    108     return NULL;
    109   ret->connection = connection;
    110   ret->ikvi = iter;
    111   ret->cls = iter_cls;
    112   ret->encoding = encoding;
    113   ret->buffer_size = buffer_size;
    114   ret->state = PP_Init;
    115   ret->blen = blen;
    116   ret->boundary = boundary;
    117   ret->skip_rn = RN_Inactive;
    118   return ret;
    119 }
    120 
    121 
    122 /**
    123  * Give a (possibly partial) value to the application callback.  We have some
    124  * part of the value in the 'pp->xbuf', the rest is between @a value_start and
    125  * @a value_end.  If @a last_escape is non-NULL, there may be an incomplete
    126  * escape sequence at at @a value_escape between @a value_start and @a
    127  * value_end which we should preserve in 'pp->xbuf' for the future.
    128  *
    129  * Unescapes the value and calls the iterator together with the key.  The key
    130  * must already be in the key buffer allocated and 0-terminated at the end of
    131  * @a pp at the time of the call.
    132  *
    133  * @param[in,out] pp post processor to act upon
    134  * @param value_start where in memory is the value
    135  * @param value_end where does the value end
    136  * @param last_escape last '%'-sign in value range,
    137  *        if relevant, or NULL
    138  */
    139 static void
    140 process_value (struct MHD_PostProcessor *pp,
    141                const char *value_start,
    142                const char *value_end,
    143                const char *last_escape)
    144 {
    145   char xbuf[XBUF_SIZE + 1];
    146   size_t xoff;
    147 
    148   mhd_assert (pp->xbuf_pos < sizeof (xbuf));
    149   /* 'value_start' and 'value_end' must be either both non-NULL or both NULL */
    150   mhd_assert ( (NULL == value_start) || (NULL != value_end) );
    151   mhd_assert ( (NULL != value_start) || (NULL == value_end) );
    152   mhd_assert ( (NULL == last_escape) || (NULL != value_start) );
    153   /* move remaining input from previous round into processing buffer */
    154   if (0 != pp->xbuf_pos)
    155     memcpy (xbuf,
    156             pp->xbuf,
    157             pp->xbuf_pos);
    158   xoff = pp->xbuf_pos;
    159   pp->xbuf_pos = 0;
    160   if ( (NULL != last_escape) &&
    161        (((size_t) (value_end - last_escape)) < sizeof (pp->xbuf)) )
    162   {
    163     mhd_assert (value_end >= last_escape);
    164     pp->xbuf_pos = (size_t) (value_end - last_escape);
    165     memcpy (pp->xbuf,
    166             last_escape,
    167             (size_t) (value_end - last_escape));
    168     value_end = last_escape;
    169   }
    170   while ( (value_start != value_end) ||
    171           (pp->must_ikvi) ||
    172           (xoff > 0) )
    173   {
    174     size_t delta = (size_t) (value_end - value_start);
    175     bool cut = false;
    176     size_t clen = 0;
    177 
    178     mhd_assert (value_end >= value_start);
    179 
    180     if (delta > XBUF_SIZE - xoff)
    181       delta = XBUF_SIZE - xoff;
    182     /* move (additional) input into processing buffer */
    183     if (0 != delta)
    184     {
    185       memcpy (&xbuf[xoff],
    186               value_start,
    187               delta);
    188       xoff += delta;
    189       value_start += delta;
    190     }
    191     /* find if escape sequence is at the end of the processing buffer;
    192        if so, exclude those from processing (reduce delta to point at
    193        end of processed region) */
    194     if ( (xoff > 0) &&
    195          ('%' == xbuf[xoff - 1]) )
    196     {
    197       cut = (xoff != XBUF_SIZE);
    198       xoff--;
    199       if (cut)
    200       {
    201         /* move escape sequence into buffer for next function invocation */
    202         pp->xbuf[0] = '%';
    203         pp->xbuf_pos = 1;
    204       }
    205       else
    206       {
    207         /* just skip escape sequence for next loop iteration */
    208         delta = xoff;
    209         clen = 1;
    210       }
    211     }
    212     else if ( (xoff > 1) &&
    213               ('%' == xbuf[xoff - 2]) )
    214     {
    215       cut = (xoff != XBUF_SIZE);
    216       xoff -= 2;
    217       if (cut)
    218       {
    219         /* move escape sequence into buffer for next function invocation */
    220         memcpy (pp->xbuf,
    221                 &xbuf[xoff],
    222                 2);
    223         pp->xbuf_pos = 2;
    224       }
    225       else
    226       {
    227         /* just skip escape sequence for next loop iteration */
    228         delta = xoff;
    229         clen = 2;
    230       }
    231     }
    232     mhd_assert (xoff < sizeof (xbuf));
    233     /* unescape */
    234     xbuf[xoff] = '\0';        /* 0-terminate in preparation */
    235     if (0 != xoff)
    236     {
    237       MHD_unescape_plus (xbuf);
    238       xoff = MHD_http_unescape (xbuf);
    239     }
    240     /* finally: call application! */
    241     if (pp->must_ikvi || (0 != xoff) )
    242     {
    243       pp->must_ikvi = false;
    244       if (MHD_NO == pp->ikvi (pp->cls,
    245                               MHD_POSTDATA_KIND,
    246                               (const char *) &pp[1],      /* key */
    247                               NULL,
    248                               NULL,
    249                               NULL,
    250                               xbuf,
    251                               pp->value_offset,
    252                               xoff))
    253       {
    254         pp->state = PP_Error;
    255         return;
    256       }
    257     }
    258     pp->value_offset += xoff;
    259     if (cut)
    260       break;
    261     if (0 != clen)
    262     {
    263       xbuf[delta] = '%';        /* undo 0-termination */
    264       memmove (xbuf,
    265                &xbuf[delta],
    266                clen);
    267     }
    268     xoff = clen;
    269   }
    270 }
    271 
    272 
    273 /**
    274  * Process url-encoded POST data.
    275  *
    276  * @param pp post processor context
    277  * @param post_data upload data
    278  * @param post_data_len number of bytes in @a post_data
    279  * @return #MHD_YES on success, #MHD_NO if there was an error processing the data
    280  */
    281 static enum MHD_Result
    282 post_process_urlencoded (struct MHD_PostProcessor *pp,
    283                          const char *post_data,
    284                          size_t post_data_len)
    285 {
    286   char *kbuf = (char *) &pp[1];
    287   size_t poff;
    288   const char *start_key = NULL;
    289   const char *end_key = NULL;
    290   const char *start_value = NULL;
    291   const char *end_value = NULL;
    292   const char *last_escape = NULL;
    293 
    294   mhd_assert (PP_Callback != pp->state);
    295 
    296   poff = 0;
    297   while ( ( (poff < post_data_len) ||
    298             (pp->state == PP_Callback) ) &&
    299           (pp->state != PP_Error) )
    300   {
    301     switch (pp->state)
    302     {
    303     case PP_Error:
    304       /* clearly impossible as per while loop invariant */
    305       abort ();
    306       break; /* Unreachable */
    307     case PP_Init:
    308       /* initial phase */
    309       mhd_assert (NULL == start_key);
    310       mhd_assert (NULL == end_key);
    311       mhd_assert (NULL == start_value);
    312       mhd_assert (NULL == end_value);
    313       switch (post_data[poff])
    314       {
    315       case '=':
    316         /* Case: (no key)'=' */
    317         /* Empty key with value */
    318         pp->state = PP_Error;
    319         continue;
    320       case '&':
    321         /* Case: (no key)'&' */
    322         /* Empty key without value */
    323         poff++;
    324         continue;
    325       case '\n':
    326       case '\r':
    327         /* Case: (no key)'\n' or (no key)'\r' */
    328         pp->state = PP_Done;
    329         poff++;
    330         break;
    331       default:
    332         /* normal character, key start, advance! */
    333         pp->state = PP_ProcessKey;
    334         start_key = &post_data[poff];
    335         pp->must_ikvi = true;
    336         poff++;
    337         continue;
    338       }
    339       break; /* end PP_Init */
    340     case PP_ProcessKey:
    341       /* key phase */
    342       mhd_assert (NULL == start_value);
    343       mhd_assert (NULL == end_value);
    344       mhd_assert (NULL != start_key || 0 == poff);
    345       mhd_assert (0 != poff || NULL == start_key);
    346       mhd_assert (NULL == end_key);
    347       switch (post_data[poff])
    348       {
    349       case '=':
    350         /* Case: 'key=' */
    351         if (0 != poff)
    352           end_key = &post_data[poff];
    353         poff++;
    354         pp->state = PP_ProcessValue;
    355         break;
    356       case '&':
    357         /* Case: 'key&' */
    358         if (0 != poff)
    359           end_key = &post_data[poff];
    360         poff++;
    361         pp->state = PP_Callback;
    362         break;
    363       case '\n':
    364       case '\r':
    365         /* Case: 'key\n' or 'key\r' */
    366         if (0 != poff)
    367           end_key = &post_data[poff];
    368         /* No advance here, 'PP_Done' will be selected by next 'PP_Init' phase */
    369         pp->state = PP_Callback;
    370         break;
    371       default:
    372         /* normal character, advance! */
    373         if (0 == poff)
    374           start_key = post_data;
    375         poff++;
    376         break;
    377       }
    378       mhd_assert (NULL == end_key || NULL != start_key);
    379       break; /* end PP_ProcessKey */
    380     case PP_ProcessValue:
    381       if (NULL == start_value)
    382         start_value = &post_data[poff];
    383       switch (post_data[poff])
    384       {
    385       case '=':
    386         /* case 'key==' */
    387         pp->state = PP_Error;
    388         continue;
    389       case '&':
    390         /* case 'value&' */
    391         end_value = &post_data[poff];
    392         poff++;
    393         if (pp->must_ikvi ||
    394             (start_value != end_value) )
    395         {
    396           pp->state = PP_Callback;
    397         }
    398         else
    399         {
    400           pp->buffer_pos = 0;
    401           pp->value_offset = 0;
    402           pp->state = PP_Init;
    403           start_value = NULL;
    404           end_value = NULL;
    405         }
    406         continue;
    407       case '\n':
    408       case '\r':
    409         /* Case: 'value\n' or 'value\r' */
    410         end_value = &post_data[poff];
    411         if (pp->must_ikvi ||
    412             (start_value != end_value) )
    413           pp->state = PP_Callback; /* No poff advance here to set PP_Done in the next iteration */
    414         else
    415         {
    416           poff++;
    417           pp->state = PP_Done;
    418         }
    419         break;
    420       case '%':
    421         last_escape = &post_data[poff];
    422         poff++;
    423         break;
    424       case '0':
    425       case '1':
    426       case '2':
    427       case '3':
    428       case '4':
    429       case '5':
    430       case '6':
    431       case '7':
    432       case '8':
    433       case '9':
    434         /* character, may be part of escaping */
    435         poff++;
    436         continue;
    437       default:
    438         /* normal character, no more escaping! */
    439         last_escape = NULL;
    440         poff++;
    441         continue;
    442       }
    443       break; /* end PP_ProcessValue */
    444     case PP_Done:
    445       switch (post_data[poff])
    446       {
    447       case '\n':
    448       case '\r':
    449         poff++;
    450         continue;
    451       }
    452       /* unexpected data at the end, fail! */
    453       pp->state = PP_Error;
    454       break;
    455     case PP_Callback:
    456       mhd_assert ((NULL != end_key) || (NULL == start_key));
    457       if (1)
    458       {
    459         const size_t key_len = (size_t) (end_key - start_key);
    460         mhd_assert (end_key >= start_key);
    461         if (0 != key_len)
    462         {
    463           if ( (pp->buffer_pos + key_len >= pp->buffer_size) ||
    464                (pp->buffer_pos + key_len < pp->buffer_pos) )
    465           {
    466             /* key too long, cannot parse! */
    467             pp->state = PP_Error;
    468             continue;
    469           }
    470           /* compute key, if we have not already */
    471           memcpy (&kbuf[pp->buffer_pos],
    472                   start_key,
    473                   key_len);
    474           pp->buffer_pos += key_len;
    475           start_key = NULL;
    476           end_key = NULL;
    477           pp->must_unescape_key = true;
    478         }
    479       }
    480 #ifdef _DEBUG
    481       else
    482         mhd_assert (0 != pp->buffer_pos);
    483 #endif /* _DEBUG */
    484       if (pp->must_unescape_key)
    485       {
    486         kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
    487         MHD_unescape_plus (kbuf);
    488         MHD_http_unescape (kbuf);
    489         pp->must_unescape_key = false;
    490       }
    491       process_value (pp,
    492                      start_value,
    493                      end_value,
    494                      NULL);
    495       if (PP_Error == pp->state)
    496         continue;
    497       pp->value_offset = 0;
    498       start_value = NULL;
    499       end_value = NULL;
    500       pp->buffer_pos = 0;
    501       pp->state = PP_Init;
    502       break;
    503     case PP_NextBoundary:
    504     case PP_ProcessEntryHeaders:
    505     case PP_PerformCheckMultipart:
    506     case PP_ProcessValueToBoundary:
    507     case PP_PerformCleanup:
    508     case PP_Nested_Init:
    509     case PP_Nested_PerformMarking:
    510     case PP_Nested_ProcessEntryHeaders:
    511     case PP_Nested_ProcessValueToBoundary:
    512     case PP_Nested_PerformCleanup:
    513     default:
    514       MHD_PANIC (_ ("internal error.\n")); /* should never happen! */
    515     }
    516     mhd_assert ((end_key == NULL) || (start_key != NULL));
    517     mhd_assert ((end_value == NULL) || (start_value != NULL));
    518   }
    519 
    520   mhd_assert (PP_Callback != pp->state);
    521 
    522   if (PP_Error == pp->state)
    523   {
    524     /* State in error, returning failure */
    525     return MHD_NO;
    526   }
    527 
    528   /* save remaining data for next iteration */
    529   if (NULL != start_key)
    530   {
    531     size_t key_len;
    532     mhd_assert ((PP_ProcessKey == pp->state) || (NULL != end_key));
    533     if (NULL == end_key)
    534       end_key = &post_data[poff];
    535     mhd_assert (end_key >= start_key);
    536     key_len = (size_t) (end_key - start_key);
    537     mhd_assert (0 != key_len); /* it must be always non-zero here */
    538     if ( (pp->buffer_pos + key_len >= pp->buffer_size) ||
    539          (pp->buffer_pos + key_len < pp->buffer_pos) )
    540     {
    541       pp->state = PP_Error;
    542       return MHD_NO;
    543     }
    544     memcpy (&kbuf[pp->buffer_pos],
    545             start_key,
    546             key_len);
    547     pp->buffer_pos += key_len;
    548     pp->must_unescape_key = true;
    549     start_key = NULL;
    550     end_key = NULL;
    551   }
    552   if ( (NULL != start_value) &&
    553        (PP_ProcessValue == pp->state) )
    554   {
    555     /* compute key, if we have not already */
    556     if (pp->must_unescape_key)
    557     {
    558       kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
    559       MHD_unescape_plus (kbuf);
    560       MHD_http_unescape (kbuf);
    561       pp->must_unescape_key = false;
    562     }
    563     if (NULL == end_value)
    564       end_value = &post_data[poff];
    565     if ( (NULL != last_escape) &&
    566          (2 < (end_value - last_escape)) )
    567       last_escape = NULL;
    568     process_value (pp,
    569                    start_value,
    570                    end_value,
    571                    last_escape);
    572     pp->must_ikvi = false;
    573   }
    574   if (PP_Error == pp->state)
    575   {
    576     /* State in error, returning failure */
    577     return MHD_NO;
    578   }
    579   return MHD_YES;
    580 }
    581 
    582 
    583 /**
    584  * If the given line matches the prefix, strdup the
    585  * rest of the line into the suffix ptr.
    586  *
    587  * @param prefix prefix to match
    588  * @param prefix_len length of @a prefix
    589  * @param line line to match prefix in
    590  * @param suffix set to a copy of the rest of the line, starting at the end of the match
    591  * @return #MHD_YES if there was a match, #MHD_NO if not
    592  */
    593 static int
    594 try_match_header (const char *prefix,
    595                   size_t prefix_len,
    596                   char *line,
    597                   char **suffix)
    598 {
    599   if (NULL != *suffix)
    600     return MHD_NO;
    601   if (MHD_str_equal_caseless_n_ (prefix,
    602                                  line,
    603                                  prefix_len))
    604   {
    605     *suffix = strdup (&line[prefix_len]);
    606     return MHD_YES;
    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         const char *bnd;
   1115         char *nested;
   1116 
   1117         bnd = strstr (pp->content_type,
   1118                       "boundary=");
   1119         if (NULL == bnd)
   1120         {
   1121           pp->state = PP_Error;
   1122           return MHD_NO;
   1123         }
   1124         /* Note: 'bnd' points into 'pp->content_type', which is released
   1125            below, so the copy must be taken first.  It must also be
   1126            taken into a local: assigning the 'strstr()' result to
   1127            'pp->nested_boundary' first would overwrite -- and leak -- a
   1128            boundary already owned by this post processor.  That happens
   1129            whenever this state is reached twice without passing through
   1130            PP_PerformCleanup, i.e. for every additional nested
   1131            "multipart/mixed" part, and the leaked block is as long as
   1132            the boundary the client chose. */
   1133         nested = strdup (&bnd[MHD_STATICSTR_LEN_ ("boundary=")]);
   1134         if (NULL == nested)
   1135         {
   1136           /* out of memory */
   1137           pp->state = PP_Error;
   1138           return MHD_NO;
   1139         }
   1140         if (NULL != pp->nested_boundary)
   1141           free (pp->nested_boundary);
   1142         pp->nested_boundary = nested;
   1143         /* free old content type, we will need that field
   1144            for the content type of the nested elements */
   1145         free (pp->content_type);
   1146         pp->content_type = NULL;
   1147         pp->nlen = strlen (pp->nested_boundary);
   1148         pp->state = PP_Nested_Init;
   1149         state_changed = 1;
   1150         break;
   1151       }
   1152       pp->state = PP_ProcessValueToBoundary;
   1153       pp->value_offset = 0;
   1154       state_changed = 1;
   1155       break;
   1156     case PP_ProcessValueToBoundary:
   1157       if (MHD_NO == process_value_to_boundary (pp,
   1158                                                &ioff,
   1159                                                pp->boundary,
   1160                                                pp->blen,
   1161                                                PP_PerformCleanup,
   1162                                                PP_Done))
   1163       {
   1164         if (pp->state == PP_Error)
   1165           return MHD_NO;
   1166         break;
   1167       }
   1168       break;
   1169     case PP_PerformCleanup:
   1170       /* clean up state of one multipart form-data element! */
   1171       pp->have = NE_none;
   1172       free_unmarked (pp);
   1173       if (NULL != pp->nested_boundary)
   1174       {
   1175         free (pp->nested_boundary);
   1176         pp->nested_boundary = NULL;
   1177       }
   1178       pp->state = PP_ProcessEntryHeaders;
   1179       state_changed = 1;
   1180       break;
   1181     case PP_Nested_Init:
   1182       if (NULL == pp->nested_boundary)
   1183       {
   1184         pp->state = PP_Error;
   1185         return MHD_NO;
   1186       }
   1187       if (MHD_NO == find_boundary (pp,
   1188                                    pp->nested_boundary,
   1189                                    pp->nlen,
   1190                                    &ioff,
   1191                                    PP_Nested_PerformMarking,
   1192                                    PP_NextBoundary /* or PP_Error? */))
   1193       {
   1194         if (pp->state == PP_Error)
   1195           return MHD_NO;
   1196         goto END;
   1197       }
   1198       break;
   1199     case PP_Nested_PerformMarking:
   1200       /* remember what headers were given
   1201          globally */
   1202       pp->have = NE_none;
   1203       if (NULL != pp->content_name)
   1204         pp->have |= NE_content_name;
   1205       if (NULL != pp->content_type)
   1206         pp->have |= NE_content_type;
   1207       if (NULL != pp->content_filename)
   1208         pp->have |= NE_content_filename;
   1209       if (NULL != pp->content_transfer_encoding)
   1210         pp->have |= NE_content_transfer_encoding;
   1211       pp->state = PP_Nested_ProcessEntryHeaders;
   1212       state_changed = 1;
   1213       break;
   1214     case PP_Nested_ProcessEntryHeaders:
   1215       pp->value_offset = 0;
   1216       if (MHD_NO ==
   1217           process_multipart_headers (pp,
   1218                                      &ioff,
   1219                                      PP_Nested_ProcessValueToBoundary))
   1220       {
   1221         if (pp->state == PP_Error)
   1222           return MHD_NO;
   1223         else
   1224           goto END;
   1225       }
   1226       state_changed = 1;
   1227       break;
   1228     case PP_Nested_ProcessValueToBoundary:
   1229       if (MHD_NO == process_value_to_boundary (pp,
   1230                                                &ioff,
   1231                                                pp->nested_boundary,
   1232                                                pp->nlen,
   1233                                                PP_Nested_PerformCleanup,
   1234                                                PP_NextBoundary))
   1235       {
   1236         if (pp->state == PP_Error)
   1237           return MHD_NO;
   1238         break;
   1239       }
   1240       break;
   1241     case PP_Nested_PerformCleanup:
   1242       free_unmarked (pp);
   1243       pp->state = PP_Nested_ProcessEntryHeaders;
   1244       state_changed = 1;
   1245       break;
   1246     case PP_ProcessKey:
   1247     case PP_ProcessValue:
   1248     case PP_Callback:
   1249     default:
   1250       MHD_PANIC (_ ("internal error.\n")); /* should never happen! */
   1251     }
   1252 AGAIN:
   1253     if (ioff > 0)
   1254     {
   1255       memmove (buf,
   1256                &buf[ioff],
   1257                pp->buffer_pos - ioff);
   1258       pp->buffer_pos -= ioff;
   1259       ioff = 0;
   1260       state_changed = 1;
   1261     }
   1262   }
   1263 END:
   1264   if (0 != ioff)
   1265   {
   1266     memmove (buf,
   1267              &buf[ioff],
   1268              pp->buffer_pos - ioff);
   1269     pp->buffer_pos -= ioff;
   1270   }
   1271   if (poff < post_data_len)
   1272   {
   1273     pp->state = PP_Error;
   1274     return MHD_NO;              /* serious error */
   1275   }
   1276   return MHD_YES;
   1277 }
   1278 
   1279 
   1280 _MHD_EXTERN enum MHD_Result
   1281 MHD_post_process (struct MHD_PostProcessor *pp,
   1282                   const char *post_data,
   1283                   size_t post_data_len)
   1284 {
   1285   if (0 == post_data_len)
   1286     return MHD_YES;
   1287   if (NULL == pp)
   1288     return MHD_NO;
   1289   if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
   1290                                  pp->encoding,
   1291                                  MHD_STATICSTR_LEN_ (
   1292                                    MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
   1293     return post_process_urlencoded (pp,
   1294                                     post_data,
   1295                                     post_data_len);
   1296   if (MHD_str_equal_caseless_n_ (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA,
   1297                                  pp->encoding,
   1298                                  MHD_STATICSTR_LEN_ (
   1299                                    MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
   1300     return post_process_multipart (pp,
   1301                                    post_data,
   1302                                    post_data_len);
   1303   /* this should never be reached */
   1304   return MHD_NO;
   1305 }
   1306 
   1307 
   1308 _MHD_EXTERN enum MHD_Result
   1309 MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
   1310 {
   1311   enum MHD_Result ret;
   1312 
   1313   if (NULL == pp)
   1314     return MHD_YES;
   1315   if (PP_ProcessValue == pp->state)
   1316   {
   1317     /* key without terminated value left at the end of the
   1318        buffer; fake receiving a termination character to
   1319        ensure it is also processed */
   1320     post_process_urlencoded (pp,
   1321                              "\n",
   1322                              1);
   1323   }
   1324   /* These internal strings need cleaning up since
   1325      the post-processing may have been interrupted
   1326      at any stage */
   1327   if ( (pp->xbuf_pos > 0) ||
   1328        ( (pp->state != PP_Done) &&
   1329          (pp->state != PP_Init) ) )
   1330     ret = MHD_NO;
   1331   else
   1332     ret = MHD_YES;
   1333   pp->have = NE_none;
   1334   free_unmarked (pp);
   1335   if (NULL != pp->nested_boundary)
   1336     free (pp->nested_boundary);
   1337   free (pp);
   1338   return ret;
   1339 }
   1340 
   1341 
   1342 /* end of postprocessor.c */