]> code.citadel.org Git - citadel.git/blob - citadel/mime_parser.c
Added the ability to supply both start and end pointers to mime_parser()
[citadel.git] / citadel / mime_parser.c
1 /*
2  * mime_parser.c
3  *
4  * This is a really bad attempt at writing a parser to handle MIME-encoded
5  * messages.
6  *
7  * Copyright (c) 1998-1999 by Art Cancro
8  * This code is distributed under the terms of the GNU General Public License.
9  *
10  */
11
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <stdio.h>
15 #include <signal.h>
16 #include <sys/types.h>
17 #include <ctype.h>
18 #include <string.h>
19 #include "mime_parser.h"
20
21
22
23 void extract_key(char *target, char *source, char *key) {
24         int a, b;
25
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;
34                         return;
35                         }
36                 }
37         strcpy(target, "");
38         }
39
40
41
42         /**** OTHERWISE, HERE'S WHERE WE HANDLE THE STUFF!! *****
43
44         CallBack(name, filename, "", content, content_type, length);
45
46         **** END OF STUFF-HANDLER ****/
47
48
49 /* 
50  * Utility function to "readline" from memory
51  * (returns new pointer)
52  */
53 char *memreadline(char *start, char *buf, int maxlen) {
54         char ch;
55         char *ptr;
56
57         ptr = start;
58         bzero(buf, maxlen);
59
60         while(1) {
61                 ch = *ptr++;
62                 if ((ch==10)||(ch==0)) {
63                         if (strlen(buf)>0)
64                                 if (buf[strlen(buf)-1]==13)
65                                         buf[strlen(buf)-1] = 0;
66                         return ptr;
67                         }
68                 if (strlen(buf) < (maxlen-1)) {
69                         buf[strlen(buf)+1] = 0;
70                         buf[strlen(buf)] = ch;
71                         }
72                 }
73         }
74
75
76
77 /*
78  * Break out the components of a multipart message
79  * (This function expects to be fed HEADERS + CONTENT)
80  * Note: NULL can be supplied as content_end; in this case, the message is
81  * considered to have ended when the parser encounters a 0x00 byte.
82  */
83 void mime_parser(char *content_start, char *content_end,
84                 void (*CallBack)
85                         (char *cbname,
86                         char *cbfilename,
87                         char *cbencoding,
88                         void *cbcontent,
89                         char *cbtype,
90                         size_t cblength)
91                 ) {
92
93         char *ptr;
94         char *part_start, *part_end;
95         char buf[256];
96         char header[256];
97         char boundary[256];
98         char content_type[256];
99         char encoding[256];
100         int content_length;
101         int i;
102
103         ptr = content_start;
104         bzero(boundary, sizeof boundary);
105         bzero(content_type, sizeof content_type);
106         bzero(encoding, sizeof encoding);
107         content_length = 0;
108
109         /* Learn interesting things from the headers */
110         strcpy(header, "");
111         do {
112                 ptr = memreadline(ptr, buf, sizeof buf);
113                 if (*ptr == 0) return; /* premature end of message */
114                 if (content_end != NULL)
115                         if (ptr >= content_end) return;
116
117                 for (i=0; i<strlen(buf); ++i)
118                         if (isspace(buf[i])) buf[i]=' ';
119                 if (!isspace(buf[0])) {
120                         if (!strncasecmp(header, "Content-type: ", 14))
121                                 strcpy(content_type, &header[14]);
122                         if (!strncasecmp(header, "Content-length: ", 16))
123                                 content_length = atoi(&header[16]);
124                         if (!strncasecmp(header,
125                                 "Content-transfer-encoding: ", 27))
126                                         strcpy(encoding, &header[27]);
127                         if (strlen(boundary)==0)
128                                 extract_key(boundary, header, "boundary");
129                         strcpy(header, "");
130                         }
131                 if ((strlen(header)+strlen(buf)+2)<sizeof(header))
132                         strcat(header, buf);
133                 } while ((strlen(buf) > 0) && (*ptr != 0));
134
135         cprintf("Content type is <%s>\n", content_type);
136         cprintf("Encoding is <%s>\n", encoding);
137         cprintf("Content length is %d\n", content_length);
138         cprintf("Boundary is <%s>\n", boundary);
139
140
141         /* If this is a multipart message, then recursively process it */
142         if (strlen(boundary)>0) {
143                 }
144         
145
146         }