Add test for loading one mimepart from the mimestructure; decode its content inside.
[citadel.git] / libcitadel / tests / mimeparser_test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <dirent.h>
8 #include <errno.h>
9
10 #include <fcntl.h>
11
12 #include <unistd.h>
13 #include <stddef.h>
14
15
16 #include "../lib/libcitadel.h"
17
18 /* shamelesly copied from msgbase.h */
19 struct ma_info {
20         int is_ma;              /* Set to 1 if we are using this stuff */
21         int freeze;             /* Freeze the replacement chain because we're
22                                  * digging through a subsection */
23         int did_print;          /* One alternative has been displayed */
24         char chosen_part[128];  /* Which part of a m/a did we choose? */
25         const char *printme;
26         int chosen_pref;        /* Chosen part preference level (lower is better) */
27         int use_fo_hooks;       /* Use fixed output hooks */
28         int dont_decode;        /* should we call the decoder or not? */
29 };
30
31
32 /*
33  * Callback function for mime parser that simply lists the part
34  */
35 static void list_this_part(char *name, 
36                            char *filename, 
37                            char *partnum, 
38                            char *disp,
39                            void *content, 
40                            char *cbtype, 
41                            char *cbcharset, 
42                            size_t length, 
43                            char *encoding,
44                            char *cbid, 
45                            void *cbuserdata)
46 {
47         struct ma_info *ma;
48         
49         ma = (struct ma_info *)cbuserdata;
50         if (ma->is_ma == 0) {
51                 printf("part=%s|%s|%s|%s|%s|%ld|%s|%s\n",
52                         name, 
53                         filename, 
54                         partnum, 
55                         disp, 
56                         cbtype, 
57                         (long)length, 
58                         cbid, 
59                         cbcharset);
60         }
61 }
62
63 /* 
64  * Callback function for multipart prefix
65  */
66 static void list_this_pref(char *name, 
67                            char *filename, 
68                            char *partnum, 
69                            char *disp,
70                            void *content, 
71                            char *cbtype, 
72                            char *cbcharset, 
73                            size_t length, 
74                            char *encoding,
75                            char *cbid, 
76                            void *cbuserdata)
77 {
78         struct ma_info *ma;
79         
80         ma = (struct ma_info *)cbuserdata;
81         if (!strcasecmp(cbtype, "multipart/alternative")) {
82                 ++ma->is_ma;
83         }
84
85         if (ma->is_ma == 0) {
86                 printf("pref=%s|%s\n", partnum, cbtype);
87         }
88 }
89
90 /* 
91  * Callback function for multipart sufffix
92  */
93 static void list_this_suff(char *name, 
94                            char *filename, 
95                            char *partnum, 
96                            char *disp,
97                            void *content, 
98                            char *cbtype, 
99                            char *cbcharset, 
100                            size_t length, 
101                            char *encoding,
102                            char *cbid, 
103                            void *cbuserdata)
104 {
105         struct ma_info *ma;
106         
107         ma = (struct ma_info *)cbuserdata;
108         if (ma->is_ma == 0) {
109                 printf("suff=%s|%s\n", partnum, cbtype);
110         }
111         if (!strcasecmp(cbtype, "multipart/alternative")) {
112                 --ma->is_ma;
113         }
114 }
115
116
117 /*
118  * Callback function for mime parser that opens a section for downloading
119  */
120 static void mime_download(char *name, 
121                           char *filename, 
122                           char *partnum, 
123                           char *disp,
124                           void *content, 
125                           char *cbtype, 
126                           char *cbcharset, 
127                           size_t length,
128                           char *encoding, 
129                           char *cbid, 
130                           void *cbuserdata)
131 {
132         int rc = 0;
133
134         /* Silently go away if there's already a download open. */
135
136         struct ma_info *ma;
137         
138         ma = (struct ma_info *)cbuserdata;
139
140         if ((!IsEmptyStr(partnum) && (!strcasecmp(ma->printme, partnum)))) {
141                 char *decoded = NULL;
142                 size_t bytes_decoded;
143                 rc = mime_decode_now (content, 
144                                       length,
145                                       encoding,
146                                       &decoded,
147                                       &bytes_decoded);
148                 if ((rc < 0) || (decoded == NULL)) {
149                         printf("failed to decode content\n");
150                         return;
151                 }
152                 rc = write(STDOUT_FILENO, content, length);
153                 free(decoded);
154         }
155 }
156
157
158
159 /*
160  * Callback function for mime parser that outputs a section all at once.
161  * We can specify the desired section by part number *or* content-id.
162  * /
163 void mime_spew_section(char *name, 
164                        char *filename, 
165                        char *partnum, 
166                        char *disp,
167                        void *content, 
168                        char *cbtype, 
169                        char *cbcharset, 
170                        size_t length,
171                        char *encoding, 
172                        char *cbid, 
173                        void *cbuserdata)
174 {
175         int *found_it = (int *)cbuserdata;
176
177         if (
178                 (!IsEmptyStr(partnum) && (!strcasecmp(CC->download_desired_section, partnum)))
179         ||      (!IsEmptyStr(cbid) && (!strcasecmp(CC->download_desired_section, cbid)))
180         ) {
181                 *found_it = 1;
182                 printf("%d %d|-1|%s|%s|%s\n",
183                         BINARY_FOLLOWS,
184                         (int)length,
185                         filename,
186                         cbtype,
187                         cbcharset
188                 );
189                 fwrite(STDOUT, content, length);
190         }
191 }
192
193 */
194
195
196
197
198 int main(int argc, char* argv[])
199 {
200         char a;
201         int fd;
202         char *filename = NULL;
203         struct stat statbuf;
204         const char *Err;
205
206         StrBuf *MimeBuf;
207         long MimeLen;
208         char *MimeStr;
209         struct ma_info ma;
210         int do_proto = 0;
211         int dont_decode = 1;
212
213         setvbuf(stdout, NULL, _IONBF, 0);
214         memset(&ma, 0, sizeof(struct ma_info));
215
216         while ((a = getopt(argc, argv, "dpf:P:")) != EOF)
217         {
218                 switch (a) {
219                 case 'f':
220                         filename = optarg;
221                         break;
222                 case 'p':
223                         do_proto = 1;
224                         break;
225                 case 'd':
226                         dont_decode = 0;
227                         break;
228                 case 'P':
229                         ma.printme = optarg;
230                 }
231         }
232         StartLibCitadel(8);
233
234         if (filename == NULL) {
235                 printf("Filename requried! -f\n");
236                 return 1;
237         }
238         fd = open(filename, 0);
239         if (fd < 0) {
240                 printf("Error opening file [%s] %d [%s]\n", filename, errno, strerror(errno));
241                 return 1;
242         }
243         if (fstat(fd, &statbuf) == -1) {
244                 printf("Error stating file [%s] %d [%s]\n", filename, errno, strerror(errno));
245                 return 1;
246         }
247         MimeBuf = NewStrBufPlain(NULL, statbuf.st_size + 1);
248         if (StrBufReadBLOB(MimeBuf, &fd, 1, statbuf.st_size, &Err) < 0) {
249                 printf("Error reading file [%s] %d [%s] [%s]\n", filename, errno, strerror(errno), Err);
250                 FreeStrBuf(&MimeBuf);
251                 return 1;
252         }
253         MimeLen = StrLength(MimeBuf);
254         MimeStr = SmashStrBuf(&MimeBuf);
255
256         if (ma.printme == NULL)
257                 mime_parser(MimeStr, MimeStr + MimeLen,
258                             (do_proto ? *list_this_part : NULL),
259                             (do_proto ? *list_this_pref : NULL),
260                             (do_proto ? *list_this_suff : NULL),
261                             (void *)&ma, dont_decode);
262         else 
263                 mime_parser(MimeStr, MimeStr + MimeLen,
264                             *mime_download, NULL, NULL, (void *)&ma, dont_decode);
265
266         free(MimeStr);
267         return 0;
268 }