4 * This is a really bad attempt at writing a parser to handle multipart
5 * messages -- in the case of WebCit, a form containing uploaded files.
12 #include <sys/types.h>
20 void extract_key(char *target, char *source, char *key) {
23 strcpy(target, source);
24 for (a=0; a<strlen(target); ++a) {
25 if ((!strncasecmp(&target[a], key, strlen(key)))
26 && (target[a+strlen(key)]=='=')) {
27 strcpy(target, &target[a+strlen(key)+1]);
28 if (target[0]==34) strcpy(target, &target[1]);
29 for (b=0; b<strlen(target); ++b)
30 if (target[b]==34) target[b]=0;
40 * The very back end for the component handler
41 * (This function expects to be fed CONTENT ONLY, no headers)
43 void do_something_with_it(char *content, int length, char *content_type,
44 char *content_disposition) {
48 extract_key(name, content_disposition, " name");
49 extract_key(filename, content_disposition, "filename");
51 /* Nested multipart gets recursively fed back into the parser */
52 if (!strncasecmp(content_type, "multipart", 9)) {
53 mime_parser(content, length, content_type);
56 /**** OTHERWISE, HERE'S WHERE WE HANDLE THE STUFF!! ****
57 * Later we'll want to do this with a callback. We'll also want to
58 * handle content-transfer-encoding before passing control to callback
59 * functions. For now, though ... it's just a hardcoded WebCit tie-in.
62 else if (strlen(name)>0) {
70 * Take a part, figure out its length, and do something with it
71 * (This function expects to be fed HEADERS+CONTENT)
73 void handle_part(char *content, int part_length, char *supplied_content_type) {
74 char content_type[256];
75 char content_disposition[256];
78 int crlf = 0; /* set to 1 for crlf-style newlines */
81 strcpy(content_type, supplied_content_type);
83 /* Strip off any leading blank lines. */
85 while ((!strncmp(start, "\r", 1)) || (!strncmp(start, "\n", 1))) {
90 /* At this point all we have left is the headers and the content. */
94 buf[strlen(buf)+1] = 0;
95 if (strlen(buf)<((sizeof buf)-1)) {
96 strncpy(&buf[strlen(buf)], start, 1);
100 } while((buf[strlen(buf)-1] != 10) && (part_length>0));
101 if (part_length <= 0) return;
102 buf[strlen(buf)-1] = 0;
103 if (buf[strlen(buf)-1]==13) {
104 buf[strlen(buf)-1] = 0;
107 if (!strncasecmp(buf, "Content-type: ", 14)) {
108 strcpy(content_type, &buf[14]);
110 if (!strncasecmp(buf, "Content-disposition: ", 21)) {
111 strcpy(content_disposition, &buf[21]);
113 } while (strlen(buf)>0);
115 if (crlf) actual_length = part_length - 2;
116 else actual_length = part_length - 1;
118 /* Now that we've got this component isolated, what to do with it? */
119 do_something_with_it(start, actual_length,
120 content_type, content_disposition);
126 * Break out the components of a multipart message
127 * (This function expects to be fed CONTENT ONLY, no headers)
129 void mime_parser(char *content, int ContentLength, char *ContentType) {
132 int have_boundary = 0;
136 int bytes_processed = 0;
139 /* If it's not multipart, don't process it as multipart */
140 if (strncasecmp(ContentType, "multipart", 9)) {
141 do_something_with_it(content, ContentLength, ContentType, "");
145 /* Figure out what the boundary is */
146 strcpy(boundary, ContentType);
147 for (a=0; a<strlen(boundary); ++a) {
148 if (!strncasecmp(&boundary[a], "boundary=", 9)) {
151 strcpy(&boundary[2], &boundary[a+9]);
155 if ((boundary[a]==13) || (boundary[a]==10)) {
160 /* We can't process multipart messages without a boundary. */
161 if (have_boundary == 0) return;
162 strcpy(endary, boundary);
163 strcat(endary, "--");
167 /* Seek to the beginning of the next boundary */
168 while (bytes_processed < ContentLength) {
169 /* && (strncasecmp(ptr, boundary, strlen(boundary))) ) { */
171 if (strncasecmp(ptr, boundary, strlen(boundary))) {
176 /* See if we're at the end */
177 if (!strncasecmp(ptr, endary, strlen(endary))) {
181 /* Seek to the end of the boundary string */
182 if (!strncasecmp(ptr, boundary, strlen(boundary))) {
183 while ( (bytes_processed < ContentLength)
184 && (strncasecmp(ptr, "\n", 1)) ) {
190 while ( (bytes_processed < ContentLength)
191 && (strncasecmp(ptr, boundary, strlen(boundary))) ) {
196 handle_part(beginning, part_length, "");
197 /* Back off so we can see the next boundary */