diff --git a/rhizome.h b/rhizome.h index 580149de..94588cee 100644 --- a/rhizome.h +++ b/rhizome.h @@ -346,6 +346,25 @@ typedef struct rhizome_http_request { /* Boundary string for POST multipart form requests */ char boundary_string[1024]; int boundary_string_length; + /* File currently being written to while decoding POST multipart form */ + FILE *field_file; + /* Which fields have been seen in POST multipart form */ + int fields_seen; + /* The seen fields bitmap above shares values with the actual Rhizome Direct + state machine. The state numbers (and thus bitmap values for the various + fields) are listed here. + + To avoid confusion, we should not use single bit values for states that do + not correspond directly to a particular field. + Doesn't really matter what they are apart from not having exactly one bit set. + In fact, the only reason to not have exactly one bit set is so that we keep as + many bits available for field types as possible. + */ +#define RD_MIME_STATE_MANIFESTHEADERS (1<<0) +#define RD_MIME_STATE_DATAHEADERS (1<<1) +#define RD_MIME_STATE_INITIAL 0 +#define RD_MIME_STATE_PARTHEADERS 0xffff0000 +#define RD_MIME_STATE_BODY 0xffff0001 /* The source specification data which are used in different ways by different request types */ diff --git a/rhizome_direct.c b/rhizome_direct.c index 5dfb9d7d..a9055c2b 100644 --- a/rhizome_direct.c +++ b/rhizome_direct.c @@ -119,11 +119,6 @@ int rhizome_direct_form_received(rhizome_http_request *r) return rhizome_server_simple_http_response(r, 204, "Move along. Nothing to see."); } -#define RD_MIME_STATE_INITIAL 0 -#define RD_MIME_STATE_PARTHEADERS 1 -#define RD_MIME_STATE_MANIFESTHEADERS 2 -#define RD_MIME_STATE_DATAHEADERS 3 -#define RD_MIME_STATE_BODY 99 int rhizome_direct_process_mime_line(rhizome_http_request *r,char *buffer) { @@ -149,7 +144,6 @@ int rhizome_direct_process_mime_line(rhizome_http_request *r,char *buffer) then. In the meantime, we will have something that meets our immediate needs for Rhizome Direct and a variety of use cases. */ - DEBUGF("mime line: %s",buffer); /* Regardless of the state of the parser, the presence of boundary lines is significant, so lets just check once, and remember the result. @@ -165,22 +159,28 @@ int rhizome_direct_process_mime_line(rhizome_http_request *r,char *buffer) int blankLine=0; if (!strcmp(buffer,"\r\n")) blankLine=1; + DEBUGF("mime state: 0x%x, blankLine=%d, EOF=%d", + r->source_flags,blankLine,endOfForm); switch(r->source_flags) { case RD_MIME_STATE_INITIAL: + DEBUGF("mime line: %s",r->request); if (boundaryLine) r->source_flags=RD_MIME_STATE_PARTHEADERS; break; case RD_MIME_STATE_PARTHEADERS: case RD_MIME_STATE_MANIFESTHEADERS: case RD_MIME_STATE_DATAHEADERS: + DEBUGF("mime line: %s",r->request); if (blankLine) { /* End of headers */ if (r->source_flags!=RD_MIME_STATE_PARTHEADERS) { /* Open manifest or data file handle, and begin writing to it. */ + /* XXX not implemented */ + r->source_flags=RD_MIME_STATE_BODY; } else { /* unknown part: complain */ rhizome_server_simple_http_response - (r, 400, "<html><h1>Unsupported form field</h1></html>\r\n"); + (r, 400, "<html><h1>Unsupported form field or missing content-disposition line in mime part</h1></html>\r\n"); return -1; } } else { @@ -190,12 +190,30 @@ int rhizome_direct_process_mime_line(rhizome_http_request *r,char *buffer) "Content-Disposition: form-data; name=\"%[^\"]\";" " filename=\"%[^\"]\"",field,name)==2) { + if (r->source_flags!=RD_MIME_STATE_PARTHEADERS) + { + /* Multiple content-disposition lines. This is very naughty. */ + rhizome_server_simple_http_response + (r, 400, "<html><h1>Malformed multi-part form POST: Multiple content-disposition lines in single MIME encoded part.</h1></html>\r\n"); + return -1; + } DEBUGF("Found form part '%s' name '%s'",field,name); if (!strcasecmp(field,"manifest")) r->source_flags=RD_MIME_STATE_MANIFESTHEADERS; if (!strcasecmp(field,"data")) r->source_flags=RD_MIME_STATE_DATAHEADERS; - } + if (r->source_flags!=RD_MIME_STATE_PARTHEADERS) + r->fields_seen|=r->source_flags; + } else if (blankLine) { + if (r->source_flags==RD_MIME_STATE_PARTHEADERS) + { + /* Multiple content-disposition lines. This is very naughty. */ + rhizome_server_simple_http_response + (r, 400, "<html><h1>Malformed multi-part form POST: Missing content-disposition lines in MIME encoded part.</h1></html>\r\n"); + return -1; + } + r->source_flags=RD_MIME_STATE_BODY; + } } break; case RD_MIME_STATE_BODY: