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