]> code.citadel.org Git - citadel.git/blob - webcit/mime_parser.c
* Wrote mime_parser.c for handling of image uploads. This will also
[citadel.git] / webcit / mime_parser.c
1 /*
2  * mime_parser.c
3  *
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.
6  */
7
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <signal.h>
12 #include <sys/types.h>
13 #include <ctype.h>
14 #include <string.h>
15 #include "webcit.h"
16 #include "child.h"
17
18 /*
19  * Take a part, figure out its length, and do something with it
20  */
21 void process_part(char *content, int part_length) {
22         FILE *fp;
23         char filename[256];
24         static char partno = 0;
25         char *start;
26         char buf[512];
27         int crlf = 0;   /* set to 1 for crlf-style newlines */
28         int actual_length;
29
30         fprintf(stderr, "MIME: process_part() called with a length o' %d\n",
31                 part_length);
32
33         /* Strip off any leading blank lines. */
34         start = content;
35         while ((!strncmp(start, "\r", 1)) || (!strncmp(start, "\n", 1))) {
36                 ++start;
37                 --part_length;
38                 }
39
40         /* At this point all we have left is the headers and the content. */
41         do {
42                 strcpy(buf, "");
43                 do {
44                         buf[strlen(buf)+1] = 0;
45                         strncpy(&buf[strlen(buf)], start, 1);
46                         ++start;
47                         --part_length;
48                         } while((buf[strlen(buf)-1] != 10) && (part_length>0));
49                 if (part_length <= 0) return;
50                 buf[strlen(buf)-1] = 0;
51                 if (buf[strlen(buf)-1]==13) {
52                         buf[strlen(buf)-1] = 0;
53                         crlf = 1;
54                         }
55                 fprintf(stderr, "MIME: <%s>\n", buf);
56                 } while (strlen(buf)>0);
57         fprintf(stderr, "MIME: done processing headers\n");
58         
59         if (crlf) actual_length = part_length - 2;
60         else actual_length = part_length - 1;
61         
62         sprintf(filename, "content.%04x.%04x", getpid(), ++partno);
63         fp = fopen(filename, "wb");
64         fwrite(start, actual_length, 1, fp);
65         fclose(fp);
66         }
67
68         
69 /*
70  * Main function of parser
71  */
72 void mime_parser(char *content, int ContentLength, char *ContentType) {
73         char boundary[256];
74         char endary[256];
75         int have_boundary = 0;
76         int a;
77         char *ptr;
78         char *beginning;
79         int bytes_processed = 0;
80         int part_length;
81
82         fprintf(stderr, "MIME: ContentLength: %d, ContentType: %s\n",
83                 ContentLength, ContentType);
84
85         /* Figure out what the boundary is */
86         strcpy(boundary, ContentType);
87         for (a=0; a<strlen(boundary); ++a) {
88                 if (!strncasecmp(&boundary[a], "boundary=", 9)) {
89                         boundary[0]='-';
90                         boundary[1]='-';
91                         strcpy(&boundary[2], &boundary[a+9]);
92                         have_boundary = 1;
93                         a = 0;
94                         }
95                 if ((boundary[a]==13) || (boundary[a]==10)) {
96                         boundary[a] = 0;
97                         }
98                 }
99
100         /* We can't process multipart messages without a boundary. */
101         if (have_boundary == 0) return;
102         strcpy(endary, boundary);
103         strcat(endary, "--");
104         fprintf(stderr, "MIME: boundary is %s\n", boundary);
105         fprintf(stderr, "MIME:   endary is %s\n", endary);
106
107         ptr = content;
108
109         /* Seek to the beginning of the next boundary */
110         while (bytes_processed < ContentLength) {
111               /* && (strncasecmp(ptr, boundary, strlen(boundary))) ) { */
112
113                 if (strncasecmp(ptr, boundary, strlen(boundary))) {
114                         ++ptr;
115                         ++bytes_processed;
116                         }
117
118                 /* See if we're at the end */
119                 if (!strncasecmp(ptr, endary, strlen(endary))) {
120                         fprintf(stderr, "MIME: the end.\n");
121                         return;
122                         }
123
124                 /* Seek to the end of the boundary string */
125                 if (!strncasecmp(ptr, boundary, strlen(boundary))) {
126                         fprintf(stderr, "MIME: founda bounda\n");
127                         while ( (bytes_processed < ContentLength)
128                               && (strncasecmp(ptr, "\n", 1)) ) {
129                                 ++ptr;
130                                 ++bytes_processed;
131                                 }
132                         beginning = ptr;
133                         part_length = 0;
134                         while ( (bytes_processed < ContentLength)
135                           && (strncasecmp(ptr, boundary, strlen(boundary))) ) {
136                                 ++ptr;
137                                 ++bytes_processed;
138                                 ++part_length;
139                                 }
140                         process_part(beginning, part_length);
141                         /* Back off so we can see the next boundary */
142                         --ptr;
143                         --bytes_processed;
144                         }
145                 }
146         }