4 * This is a really bad attempt at writing a parser to handle MIME-encoded
7 * Copyright (c) 1998-1999 by Art Cancro
8 * This code is distributed under the terms of the GNU General Public License.
16 #include <sys/types.h>
19 #include "mime_parser.h"
23 void extract_key(char *target, char *source, char *key) {
26 strcpy(target, source);
27 for (a=0; a<strlen(target); ++a) {
28 if ((!strncasecmp(&target[a], key, strlen(key)))
29 && (target[a+strlen(key)]=='=')) {
30 strcpy(target, &target[a+strlen(key)+1]);
31 if (target[0]==34) strcpy(target, &target[1]);
32 for (b=0; b<strlen(target); ++b)
33 if (target[b]==34) target[b]=0;
42 /**** OTHERWISE, HERE'S WHERE WE HANDLE THE STUFF!! *****
44 CallBack(name, filename, "", content, content_type, length);
46 **** END OF STUFF-HANDLER ****/
50 * Utility function to "readline" from memory
51 * (returns new pointer)
53 char *memreadline(char *start, char *buf, int maxlen) {
62 if ((ch==10)||(ch==0)) {
64 if (buf[strlen(buf)-1]==13)
65 buf[strlen(buf)-1] = 0;
68 if (strlen(buf) < (maxlen-1)) {
69 buf[strlen(buf)+1] = 0;
70 buf[strlen(buf)] = ch;
76 * Given a message or message-part body and a length, handle any necessary
77 * decoding and pass the request up the stack.
79 void mime_decode(char *partnum,
80 char *part_start, size_t length,
81 char *content_type, char *encoding,
91 cprintf("part=%s, type=%s, length=%d, encoding=%s\n",
92 partnum, content_type, length, encoding);
97 * Break out the components of a multipart message
98 * (This function expects to be fed HEADERS + CONTENT)
99 * Note: NULL can be supplied as content_end; in this case, the message is
100 * considered to have ended when the parser encounters a 0x00 byte.
102 void the_mime_parser(char *partnum,
103 char *content_start, char *content_end,
114 char *part_start, *part_end;
120 char content_type[256];
126 char nested_partnum[256];
129 bzero(boundary, sizeof boundary);
130 bzero(content_type, sizeof content_type);
131 bzero(encoding, sizeof encoding);
133 /* Learn interesting things from the headers */
136 ptr = memreadline(ptr, buf, sizeof buf);
137 if (*ptr == 0) return; /* premature end of message */
138 if (content_end != NULL)
139 if (ptr >= content_end) return;
141 for (i=0; i<strlen(buf); ++i)
142 if (isspace(buf[i])) buf[i]=' ';
143 if (!isspace(buf[0])) {
144 if (!strncasecmp(header, "Content-type: ", 14))
145 strcpy(content_type, &header[14]);
146 if (!strncasecmp(header,
147 "Content-transfer-encoding: ", 27))
148 strcpy(encoding, &header[27]);
149 if (strlen(boundary)==0)
150 extract_key(boundary, header, "boundary");
153 if ((strlen(header)+strlen(buf)+2)<sizeof(header))
155 } while ((strlen(buf) > 0) && (*ptr != 0));
157 for (i=0; i<strlen(content_type); ++i)
158 if (content_type[i]==';') content_type[i] = 0;
160 if (strlen(boundary) > 0) {
167 /* If this is a multipart message, then recursively process it */
170 sprintf(startary, "--%s", boundary);
171 sprintf(endary, "--%s--", boundary);
174 ptr = memreadline(ptr, buf, sizeof buf);
175 if (*ptr == 0) return; /* premature end of message */
176 if (content_end != NULL)
177 if (ptr >= content_end) return;
178 if ((!strcasecmp(buf, startary))
179 ||(!strcasecmp(buf, endary))) {
180 if (part_start != NULL) {
181 sprintf(nested_partnum, "%s.%d",
182 partnum, ++part_seq);
183 the_mime_parser(nested_partnum,
184 part_start, part_end,
189 } while (strcasecmp(buf, endary));
192 /* If it's not a multipart message, then do something with it */
196 while ((*ptr != 0)&&((content_end==NULL)||(ptr<content_end))) {
202 content_type, encoding, CallBack);
208 * Entry point for the MIME parser.
209 * (This function expects to be fed HEADERS + CONTENT)
210 * Note: NULL can be supplied as content_end; in this case, the message is
211 * considered to have ended when the parser encounters a 0x00 byte.
213 void mime_parser(char *content_start, char *content_end,
223 the_mime_parser("1", content_start, content_end, CallBack);