postprocessor.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007 Daniel Pittman and Christian Grothoff
00004 
00005      This library is free software; you can redistribute it and/or
00006      modify it under the terms of the GNU Lesser General Public
00007      License as published by the Free Software Foundation; either
00008      version 2.1 of the License, or (at your option) any later version.
00009 
00010      This library is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      Lesser General Public License for more details.
00014 
00015      You should have received a copy of the GNU Lesser General Public
00016      License along with this library; if not, write to the Free Software
00017      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00026 #include "internal.h"
00027 
00031 #define XBUF_SIZE 1024
00032 
00036 enum PP_State
00037 {
00038   /* general states */
00039   PP_Error,
00040   PP_Done,
00041   PP_Init,
00042 
00043   /* url encoding-states */
00044   PP_ProcessValue,
00045   PP_ExpectNewLine,
00046 
00047   /* post encoding-states  */
00048   PP_ProcessEntryHeaders,
00049   PP_PerformCheckMultipart,
00050   PP_ProcessValueToBoundary,
00051   PP_PerformCleanup,
00052 
00053   /* nested post-encoding states */
00054   PP_Nested_Init,
00055   PP_Nested_PerformMarking,
00056   PP_Nested_ProcessEntryHeaders,
00057   PP_Nested_ProcessValueToBoundary,
00058   PP_Nested_PerformCleanup,
00059 
00060 };
00061 
00062 enum RN_State
00063 {
00067   RN_Inactive = 0,
00068 
00073   RN_OptN = 1,
00074 
00079   RN_Full = 2,
00080 
00085   RN_Dash = 3,
00086 
00090   RN_Dash2 = 4,
00091 };
00092 
00098 enum NE_State
00099 {
00100   NE_none = 0,
00101   NE_content_name = 1,
00102   NE_content_type = 2,
00103   NE_content_filename = 4,
00104   NE_content_transfer_encoding = 8,
00105 };
00106 
00111 struct MHD_PostProcessor
00112 {
00113 
00118   struct MHD_Connection *connection;
00119 
00123   MHD_PostDataIterator ikvi;
00124 
00128   void *cls;
00129 
00134   const char *encoding;
00135 
00139   const char *boundary;
00140 
00144   char *nested_boundary;
00145 
00149   char *content_name;
00150 
00154   char *content_type;
00155 
00159   char *content_filename;
00160 
00164   char *content_transfer_encoding;
00165 
00170   char xbuf[8];
00171 
00175   unsigned int buffer_size;
00176 
00180   unsigned int buffer_pos;
00181 
00185   unsigned int xbuf_pos;
00186 
00190   unsigned int value_offset;
00191 
00195   size_t blen;
00196 
00200   size_t nlen;
00201 
00205   enum PP_State state;
00206 
00213   enum RN_State skip_rn;
00214 
00219   enum PP_State dash_state;
00220 
00225   enum NE_State have;
00226 
00227 };
00228 
00229 
00248 struct MHD_PostProcessor *
00249 MHD_create_post_processor (struct MHD_Connection *connection,
00250                            unsigned int buffer_size,
00251                            MHD_PostDataIterator ikvi, void *cls)
00252 {
00253   struct MHD_PostProcessor *ret;
00254   const char *encoding;
00255   const char *boundary;
00256   size_t blen;
00257 
00258   if ((buffer_size < 256) || (connection == NULL) || (ikvi == NULL))
00259     abort ();
00260   encoding = MHD_lookup_connection_value (connection,
00261                                           MHD_HEADER_KIND,
00262                                           MHD_HTTP_HEADER_CONTENT_TYPE);
00263   if (encoding == NULL)
00264     return NULL;
00265   boundary = NULL;
00266   if (0 != strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding))
00267     {
00268       if (0 !=
00269           strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding,
00270                        strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
00271         return NULL;
00272       boundary =
00273         &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)];
00274       /* Q: should this be "strcasestr"? */
00275       if (NULL != strstr (boundary, "boundary="))
00276         boundary = strstr (boundary, "boundary=") + strlen ("boundary=");
00277       else
00278         return NULL;            /* failed to determine boundary */
00279       blen = strlen (boundary);
00280       if ((blen == 0) || (blen * 2 + 2 > buffer_size))
00281         return NULL;            /* (will be) out of memory or invalid boundary */
00282     }
00283   else
00284     blen = 0;
00285   ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1);
00286   if (ret == NULL)
00287     return NULL;
00288   memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1);
00289   ret->connection = connection;
00290   ret->ikvi = ikvi;
00291   ret->cls = cls;
00292   ret->encoding = encoding;
00293   ret->buffer_size = buffer_size;
00294   ret->state = PP_Init;
00295   ret->blen = blen;
00296   ret->boundary = boundary;
00297   ret->skip_rn = RN_Inactive;
00298   return ret;
00299 }
00300 
00304 static int
00305 post_process_urlencoded (struct MHD_PostProcessor *pp,
00306                          const char *post_data, unsigned int post_data_len)
00307 {
00308   unsigned int equals;
00309   unsigned int amper;
00310   unsigned int poff;
00311   unsigned int xoff;
00312   unsigned int delta;
00313   int end_of_value_found;
00314   char *buf;
00315   char xbuf[XBUF_SIZE + 1];
00316 
00317   buf = (char *) &pp[1];
00318   poff = 0;
00319   while (poff < post_data_len)
00320     {
00321       switch (pp->state)
00322         {
00323         case PP_Error:
00324           return MHD_NO;
00325         case PP_Done:
00326           /* did not expect to receive more data */
00327           pp->state = PP_Error;
00328           return MHD_NO;
00329         case PP_Init:
00330           equals = 0;
00331           while ((equals + poff < post_data_len) &&
00332                  (post_data[equals + poff] != '='))
00333             equals++;
00334           if (equals + pp->buffer_pos > pp->buffer_size)
00335             {
00336               pp->state = PP_Error;     /* out of memory */
00337               return MHD_NO;
00338             }
00339           memcpy (&buf[pp->buffer_pos], &post_data[poff], equals);
00340           pp->buffer_pos += equals;
00341           if (equals + poff == post_data_len)
00342             return MHD_YES;     /* no '=' yet */
00343           buf[pp->buffer_pos] = '\0';   /* 0-terminate key */
00344           pp->buffer_pos = 0;   /* reset for next key */
00345           MHD_http_unescape (buf);
00346           poff += equals + 1;
00347           pp->state = PP_ProcessValue;
00348           pp->value_offset = 0;
00349           break;
00350         case PP_ProcessValue:
00351           /* obtain rest of value from previous iteration */
00352           memcpy (xbuf, pp->xbuf, pp->xbuf_pos);
00353           xoff = pp->xbuf_pos;
00354           pp->xbuf_pos = 0;
00355 
00356           /* find last position in input buffer that is part of the value */
00357           amper = 0;
00358           while ((amper + poff < post_data_len) &&
00359                  (amper < XBUF_SIZE) &&
00360                  (post_data[amper + poff] != '&') &&
00361                  (post_data[amper + poff] != '\n') &&
00362                  (post_data[amper + poff] != '\r'))
00363             amper++;
00364           end_of_value_found = ((amper + poff < post_data_len) &&
00365                                 ((post_data[amper + poff] == '&') ||
00366                                  (post_data[amper + poff] == '\n') ||
00367                                  (post_data[amper + poff] == '\r')));
00368           /* compute delta, the maximum number of bytes that we will be able to
00369              process right now (either amper-limited of xbuf-size limited) */
00370           delta = amper;
00371           if (delta > XBUF_SIZE - xoff)
00372             delta = XBUF_SIZE - xoff;
00373 
00374           /* move input into processing buffer */
00375           memcpy (&xbuf[xoff], &post_data[poff], delta);
00376           xoff += delta;
00377           poff += delta;
00378 
00379           /* find if escape sequence is at the end of the processing buffer;
00380              if so, exclude those from processing (reduce delta to point at
00381              end of processed region) */
00382           delta = xoff;
00383           if ((delta > 0) && (xbuf[delta - 1] == '%'))
00384             delta--;
00385           else if ((delta > 1) && (xbuf[delta - 2] == '%'))
00386             delta -= 2;
00387 
00388           /* if we have an incomplete escape sequence, save it to
00389              pp->xbuf for later */
00390           if (delta < xoff)
00391             {
00392               memcpy (pp->xbuf, &xbuf[delta], xoff - delta);
00393               pp->xbuf_pos = xoff - delta;
00394               xoff = delta;
00395             }
00396 
00397           /* If we have nothing to do (delta == 0) and
00398              not just because the value is empty (are
00399              waiting for more data), go for next iteration */
00400           if ((xoff == 0) && (poff == post_data_len))
00401             continue;
00402 
00403           /* unescape */
00404           xbuf[xoff] = '\0';    /* 0-terminate in preparation */
00405           MHD_http_unescape (xbuf);
00406 
00407           /* finally: call application! */
00408           if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1],    /* key */
00409                                   NULL, NULL, NULL, xbuf, pp->value_offset,
00410                                   xoff))
00411             {
00412               pp->state = PP_Error;
00413               return MHD_NO;
00414             }
00415           pp->value_offset += xoff;
00416 
00417           /* are we done with the value? */
00418           if (end_of_value_found)
00419             {
00420               /* we found the end of the value! */
00421               if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
00422                 {
00423                   pp->state = PP_ExpectNewLine;
00424                 }
00425               else
00426                 {
00427                   poff++;       /* skip '&' */
00428                   pp->state = PP_Init;
00429                 }
00430             }
00431           break;
00432         case PP_ExpectNewLine:
00433           if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
00434             {
00435               poff++;
00436               /* we are done, report error if we receive any more... */
00437               pp->state = PP_Done;
00438               return MHD_YES;
00439             }
00440           return MHD_NO;
00441         default:
00442           abort ();             /* should never happen! */
00443         }
00444     }
00445   return MHD_YES;
00446 }
00447 
00454 static int
00455 try_match_header (const char *prefix, char *line, char **suffix)
00456 {
00457   if (NULL != *suffix)
00458     return MHD_NO;
00459   while (*line != 0)
00460     {
00461       if (0 == strncasecmp (prefix, line, strlen (prefix)))
00462         {
00463           *suffix = strdup (&line[strlen (prefix)]);
00464           return MHD_YES;
00465         }
00466       ++line;
00467     }
00468   return MHD_NO;
00469 }
00470 
00471 static int
00472 find_boundary (struct MHD_PostProcessor *pp,
00473                const char *boundary,
00474                size_t blen,
00475                unsigned int *ioffptr,
00476                enum PP_State next_state, enum PP_State next_dash_state)
00477 {
00478   char *buf = (char *) &pp[1];
00479 
00480   if (pp->buffer_pos < 2 + blen)
00481     {
00482       if (pp->buffer_pos == pp->buffer_size)
00483         pp->state = PP_Error;   /* out of memory */
00484       return MHD_NO;            /* not enough data */
00485     }
00486   if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen)))
00487     {
00488       pp->state = PP_Error;
00489       return MHD_NO;            /* expected boundary */
00490     }
00491   /* remove boundary from buffer */
00492   (*ioffptr) += 2 + blen;
00493   /* next: start with headers */
00494   pp->skip_rn = RN_Dash;
00495   pp->state = next_state;
00496   pp->dash_state = next_dash_state;
00497   return MHD_YES;
00498 }
00499 
00508 static void
00509 try_get_value (const char *buf, const char *key, char **destination)
00510 {
00511   const char *spos;
00512   const char *bpos;
00513   const char *endv;
00514   size_t klen;
00515   size_t vlen;
00516 
00517   if (NULL != *destination)
00518     return;
00519   bpos = buf;
00520   klen = strlen (key);
00521   while (NULL != (spos = strstr (bpos, key)))
00522     {
00523       if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' ')))
00524         {
00525           /* no match */
00526           bpos = spos + 1;
00527           continue;
00528         }
00529       if (spos[klen + 1] != '"')
00530         return;                 /* not quoted */
00531       if (NULL == (endv = strstr (&spos[klen + 2], "\"")))
00532         return;                 /* no end-quote */
00533       vlen = endv - spos - klen - 1;
00534       *destination = malloc (vlen);
00535       if (NULL == *destination)
00536         return;                 /* out of memory */
00537       (*destination)[vlen - 1] = '\0';
00538       memcpy (*destination, &spos[klen + 2], vlen - 1);
00539       return;                   /* success */
00540     }
00541 }
00542 
00555 static int
00556 process_multipart_headers (struct MHD_PostProcessor *pp,
00557                            unsigned int *ioffptr, enum PP_State next_state)
00558 {
00559   char *buf = (char *) &pp[1];
00560   unsigned int newline;
00561 
00562   newline = 0;
00563   while ((newline < pp->buffer_pos) &&
00564          (buf[newline] != '\r') && (buf[newline] != '\n'))
00565     newline++;
00566   if (newline == pp->buffer_size)
00567     {
00568       pp->state = PP_Error;
00569       return MHD_NO;            /* out of memory */
00570     }
00571   if (newline == pp->buffer_pos)
00572     return MHD_NO;              /* will need more data */
00573   if (newline == 0)
00574     {
00575       /* empty line - end of headers */
00576       pp->skip_rn = RN_Full;
00577       pp->state = next_state;
00578       return MHD_YES;
00579     }
00580   /* got an actual header */
00581   if (buf[newline] == '\r')
00582     pp->skip_rn = RN_OptN;
00583   buf[newline] = '\0';
00584   if (0 == strncasecmp ("Content-disposition: ",
00585                         buf, strlen ("Content-disposition: ")))
00586     {
00587       try_get_value (&buf[strlen ("Content-disposition: ")],
00588                      "name", &pp->content_name);
00589       try_get_value (&buf[strlen ("Content-disposition: ")],
00590                      "filename", &pp->content_filename);
00591     }
00592   else
00593     {
00594       try_match_header ("Content-type: ", buf, &pp->content_type);
00595       try_match_header ("Content-Transfer-Encoding: ",
00596                         buf, &pp->content_transfer_encoding);
00597     }
00598   (*ioffptr) += newline + 1;
00599   return MHD_YES;
00600 }
00601 
00616 static int
00617 process_value_to_boundary (struct MHD_PostProcessor *pp,
00618                            unsigned int *ioffptr,
00619                            const char *boundary,
00620                            size_t blen,
00621                            enum PP_State next_state,
00622                            enum PP_State next_dash_state)
00623 {
00624   char *buf = (char *) &pp[1];
00625   unsigned int newline;
00626 
00627   /* all data in buf until the boundary
00628      (\r\n--+boundary) is part of the value */
00629   newline = 0;
00630   while (1)
00631     {
00632       while ((newline + 4 < pp->buffer_pos) &&
00633              (0 != memcmp ("\r\n--", &buf[newline], 4)))
00634         newline++;
00635       if (newline + pp->blen + 4 <= pp->buffer_pos)
00636         {
00637           /* can check boundary */
00638           if (0 != memcmp (&buf[newline + 4], boundary, pp->blen))
00639             {
00640               /* no boundary, "\r\n--" is part of content, skip */
00641               newline += 4;
00642               continue;
00643             }
00644           else
00645             {
00646               /* boundary found, process until newline then
00647                  skip boundary and go back to init */
00648               pp->skip_rn = RN_Dash;
00649               pp->state = next_state;
00650               pp->dash_state = next_dash_state;
00651               (*ioffptr) += pp->blen + 4;       /* skip boundary as well */
00652               break;
00653             }
00654         }
00655       else
00656         {
00657           /* cannot check for boundary, process content that
00658              we have and check again later; except, if we have
00659              no content, abort (out of memory) */
00660           if ((newline == 0) && (pp->buffer_pos == pp->buffer_size))
00661             {
00662               pp->state = PP_Error;
00663               return MHD_NO;
00664             }
00665           break;
00666         }
00667     }
00668   /* newline is either at beginning of boundary or
00669      at least at the last character that we are sure
00670      is not part of the boundary */
00671   if (MHD_NO == pp->ikvi (pp->cls,
00672                           MHD_POSTDATA_KIND,
00673                           pp->content_name,
00674                           pp->content_filename,
00675                           pp->content_type,
00676                           pp->content_transfer_encoding,
00677                           buf, pp->value_offset, newline))
00678     {
00679       pp->state = PP_Error;
00680       return MHD_NO;
00681     }
00682   pp->value_offset += newline;
00683   (*ioffptr) += newline;
00684   return MHD_YES;
00685 }
00686 
00687 static void
00688 free_unmarked (struct MHD_PostProcessor *pp)
00689 {
00690   if ((pp->content_name != NULL) && (0 == (pp->have & NE_content_name)))
00691     {
00692       free (pp->content_name);
00693       pp->content_name = NULL;
00694     }
00695   if ((pp->content_type != NULL) && (0 == (pp->have & NE_content_type)))
00696     {
00697       free (pp->content_type);
00698       pp->content_type = NULL;
00699     }
00700   if ((pp->content_filename != NULL) &&
00701       (0 == (pp->have & NE_content_filename)))
00702     {
00703       free (pp->content_filename);
00704       pp->content_filename = NULL;
00705     }
00706   if ((pp->content_transfer_encoding != NULL) &&
00707       (0 == (pp->have & NE_content_transfer_encoding)))
00708     {
00709       free (pp->content_transfer_encoding);
00710       pp->content_transfer_encoding = NULL;
00711     }
00712 }
00713 
00717 static int
00718 post_process_multipart (struct MHD_PostProcessor *pp,
00719                         const char *post_data, unsigned int post_data_len)
00720 {
00721   char *buf;
00722   unsigned int max;
00723   unsigned int ioff;
00724   unsigned int poff;
00725   int state_changed;
00726 
00727   buf = (char *) &pp[1];
00728   ioff = 0;
00729   poff = 0;
00730   state_changed = 1;
00731   while ((poff < post_data_len) ||
00732          ((pp->buffer_pos > 0) && (state_changed != 0)))
00733     {
00734       /* first, move as much input data
00735          as possible to our internal buffer */
00736       max = pp->buffer_size - pp->buffer_pos;
00737       if (max > post_data_len - poff)
00738         max = post_data_len - poff;
00739       memcpy (&buf[pp->buffer_pos], &post_data[poff], max);
00740       poff += max;
00741       pp->buffer_pos += max;
00742       if ((max == 0) && (state_changed == 0) && (poff < post_data_len))
00743         {
00744           pp->state = PP_Error;
00745           return MHD_NO;        /* out of memory */
00746         }
00747       state_changed = 0;
00748 
00749       /* first state machine for '\r'-'\n' and '--' handling */
00750       switch (pp->skip_rn)
00751         {
00752         case RN_Inactive:
00753           break;
00754         case RN_OptN:
00755           if (buf[0] == '\n')
00756             {
00757               ioff++;
00758               pp->skip_rn = RN_Inactive;
00759               goto AGAIN;
00760             }
00761         case RN_Dash:
00762           if (buf[0] == '-')
00763             {
00764               ioff++;
00765               pp->skip_rn = RN_Dash2;
00766               goto AGAIN;
00767             }
00768           pp->skip_rn = RN_Full;
00769           /* fall-through! */
00770         case RN_Full:
00771           if (buf[0] == '\r')
00772             {
00773               if ((pp->buffer_pos > 1) && (buf[1] == '\n'))
00774                 {
00775                   pp->skip_rn = RN_Inactive;
00776                   ioff += 2;
00777                 }
00778               else
00779                 {
00780                   pp->skip_rn = RN_OptN;
00781                   ioff++;
00782                 }
00783               goto AGAIN;
00784             }
00785           if (buf[0] == '\n')
00786             {
00787               ioff++;
00788               pp->skip_rn = RN_Inactive;
00789               goto AGAIN;
00790             }
00791           pp->skip_rn = RN_Inactive;
00792           pp->state = PP_Error;
00793           return MHD_NO;        /* no '\r\n' */
00794         case RN_Dash2:
00795           if (buf[0] == '-')
00796             {
00797               ioff++;
00798               pp->skip_rn = RN_Full;
00799               pp->state = pp->dash_state;
00800               goto AGAIN;
00801             }
00802           pp->state = PP_Error;
00803           break;
00804         }
00805 
00806       /* main state engine */
00807       switch (pp->state)
00808         {
00809         case PP_Error:
00810           return MHD_NO;
00811         case PP_Done:
00812           /* did not expect to receive more data */
00813           pp->state = PP_Error;
00814           return MHD_NO;
00815         case PP_Init:
00816           if (MHD_NO == find_boundary (pp,
00817                                        pp->boundary,
00818                                        pp->blen,
00819                                        &ioff,
00820                                        PP_ProcessEntryHeaders, PP_Done))
00821             {
00822               if (pp->state == PP_Error)
00823                 return MHD_NO;
00824               goto END;
00825             }
00826           break;
00827         case PP_ProcessEntryHeaders:
00828           if (MHD_NO ==
00829               process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart))
00830             {
00831               if (pp->state == PP_Error)
00832                 return MHD_NO;
00833               else
00834                 goto END;
00835             }
00836           state_changed = 1;
00837           break;
00838         case PP_PerformCheckMultipart:
00839           if ((pp->content_type != NULL) &&
00840               (0 == strncasecmp (pp->content_type,
00841                                  "multipart/mixed",
00842                                  strlen ("multipart/mixed"))))
00843             {
00844               pp->nested_boundary = strstr (pp->content_type, "boundary=");
00845               if (pp->nested_boundary == NULL)
00846                 {
00847                   pp->state = PP_Error;
00848                   return MHD_NO;
00849                 }
00850               pp->nested_boundary =
00851                 strdup (&pp->nested_boundary[strlen ("boundary=")]);
00852               if (pp->nested_boundary == NULL)
00853                 {
00854                   /* out of memory */
00855                   pp->state = PP_Error;
00856                   return MHD_NO;
00857                 }
00858               /* free old content type, we will need that field
00859                  for the content type of the nested elements */
00860               free (pp->content_type);
00861               pp->content_type = NULL;
00862               pp->nlen = strlen (pp->nested_boundary);
00863               pp->state = PP_Nested_Init;
00864               state_changed = 1;
00865               break;
00866             }
00867           pp->state = PP_ProcessValueToBoundary;
00868           pp->value_offset = 0;
00869           state_changed = 1;
00870           break;
00871         case PP_ProcessValueToBoundary:
00872           if (MHD_NO == process_value_to_boundary (pp,
00873                                                    &ioff,
00874                                                    pp->boundary,
00875                                                    pp->blen,
00876                                                    PP_PerformCleanup,
00877                                                    PP_Done))
00878             {
00879               if (pp->state == PP_Error)
00880                 return MHD_NO;
00881               break;
00882             }
00883           break;
00884         case PP_PerformCleanup:
00885           /* clean up state of one multipart form-data element! */
00886           pp->have = NE_none;
00887           free_unmarked (pp);
00888           if (pp->nested_boundary != NULL)
00889             {
00890               free (pp->nested_boundary);
00891               pp->nested_boundary = NULL;
00892             }
00893           pp->state = PP_ProcessEntryHeaders;
00894           state_changed = 1;
00895           break;
00896         case PP_Nested_Init:
00897           if (pp->nested_boundary == NULL)
00898             {
00899               pp->state = PP_Error;
00900               return MHD_NO;
00901             }
00902           if (MHD_NO == find_boundary (pp,
00903                                        pp->nested_boundary,
00904                                        pp->nlen,
00905                                        &ioff,
00906                                        PP_Nested_PerformMarking,
00907                                        PP_Init /* or PP_Error? */ ))
00908             {
00909               if (pp->state == PP_Error)
00910                 return MHD_NO;
00911               goto END;
00912             }
00913           break;
00914         case PP_Nested_PerformMarking:
00915           /* remember what headers were given
00916              globally */
00917           pp->have = NE_none;
00918           if (pp->content_name != NULL)
00919             pp->have |= NE_content_name;
00920           if (pp->content_type != NULL)
00921             pp->have |= NE_content_type;
00922           if (pp->content_filename != NULL)
00923             pp->have |= NE_content_filename;
00924           if (pp->content_transfer_encoding != NULL)
00925             pp->have |= NE_content_transfer_encoding;
00926           pp->state = PP_Nested_ProcessEntryHeaders;
00927           state_changed = 1;
00928           break;
00929         case PP_Nested_ProcessEntryHeaders:
00930           pp->value_offset = 0;
00931           if (MHD_NO ==
00932               process_multipart_headers (pp, &ioff,
00933                                          PP_Nested_ProcessValueToBoundary))
00934             {
00935               if (pp->state == PP_Error)
00936                 return MHD_NO;
00937               else
00938                 goto END;
00939             }
00940           state_changed = 1;
00941           break;
00942         case PP_Nested_ProcessValueToBoundary:
00943           if (MHD_NO == process_value_to_boundary (pp,
00944                                                    &ioff,
00945                                                    pp->nested_boundary,
00946                                                    pp->nlen,
00947                                                    PP_Nested_PerformCleanup,
00948                                                    PP_Init))
00949             {
00950               if (pp->state == PP_Error)
00951                 return MHD_NO;
00952               break;
00953             }
00954           break;
00955         case PP_Nested_PerformCleanup:
00956           free_unmarked (pp);
00957           pp->state = PP_Nested_ProcessEntryHeaders;
00958           state_changed = 1;
00959           break;
00960         default:
00961           abort ();             /* should never happen! */
00962         }
00963     AGAIN:
00964       if (ioff > 0)
00965         {
00966           memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
00967           pp->buffer_pos -= ioff;
00968           ioff = 0;
00969           state_changed = 1;
00970         }
00971     }
00972 END:
00973   if (ioff != 0)
00974     {
00975       memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
00976       pp->buffer_pos -= ioff;
00977     }
00978   if (poff < post_data_len)
00979     {
00980       pp->state = PP_Error;
00981       return MHD_NO;            /* serious error */
00982     }
00983   return MHD_YES;
00984 }
00985 
01000 int
01001 MHD_post_process (struct MHD_PostProcessor *pp,
01002                   const char *post_data, unsigned int post_data_len)
01003 {
01004   if (post_data_len == 0)
01005     return MHD_YES;
01006   if (pp == NULL)
01007     return MHD_NO;
01008   if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, pp->encoding))
01009     return post_process_urlencoded (pp, post_data, post_data_len);
01010   if (0 ==
01011       strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, pp->encoding,
01012                    strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
01013     return post_process_multipart (pp, post_data, post_data_len);
01014   /* this should never be reached */
01015   return MHD_NO;
01016 }
01017 
01021 int
01022 MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
01023 {
01024   int ret;
01025 
01026   /* These internal strings need cleaning up since
01027      the post-processing may have been interrupted
01028      at any stage */
01029   if ((pp->xbuf_pos > 0) || (pp->state != PP_Done))
01030     ret = MHD_NO;
01031   else
01032     ret = MHD_YES;
01033   pp->have = NE_none;
01034   free_unmarked (pp);
01035   if (pp->nested_boundary != NULL)
01036     free (pp->nested_boundary);
01037   free (pp);
01038   return ret;
01039 }
01040 
01041 /* end of postprocessor.c */

Generated on Sun Nov 16 16:53:06 2008 for GNU libmicrohttpd by  doxygen 1.5.1