1 /* -*- Mode: C -*-*/
2 /*======================================================================
3 FILE: icalmime.c
4 CREATOR: eric 26 July 2000
5
6
7 $Id: icalmime.c,v 1.14 2008-01-29 22:25:05 dothebart Exp $
8 $Locker: $
9
10 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of either:
14
15 The LGPL as published by the Free Software Foundation, version
16 2.1, available at: http://www.fsf.org/copyleft/lesser.html
17
18 Or:
19
20 The Mozilla Public License Version 1.0. You may obtain a copy of
21 the License at http://www.mozilla.org/MPL/
22
23 The Original Code is eric. The Initial Developer of the Original
24 Code is Eric Busboom
25
26
27 ======================================================================*/
28
29 #include "icalmime.h"
30 #include "icalerror.h"
31 #include "icalmemory.h"
32 #include "sspm.h"
33 #include "stdlib.h"
34 #include <string.h> /* For strdup */
35 #include <stdio.h> /* for snprintf*/
36
37 #ifdef DMALLOC
38 #include "dmalloc.h"
39 #endif
40
41 #ifdef WIN32
42 #if defined(_MSC_VER) && (_MSC_VER < 1900)
43 #define snprintf _snprintf
44 #endif
45 #define strcasecmp stricmp
46 #endif
47
48 /* These *_part routines are called by the MIME parser via the
49 local_action_map */
50
51 struct text_part
52 {
53 char* buf;
54 char* buf_pos;
55 size_t buf_size;
56 };
57
icalmime_text_new_part(void)58 void* icalmime_text_new_part(void)
59 {
60
61 #define BUF_SIZE 2048
62
63 struct text_part* impl;
64
65 if ( ( impl = (struct text_part*)
66 malloc(sizeof(struct text_part))) == 0) {
67 return 0;
68 }
69
70 impl->buf = icalmemory_new_buffer(BUF_SIZE);
71 impl->buf_pos = impl->buf;
72 impl->buf_size = BUF_SIZE;
73
74 return impl;
75 }
icalmime_text_add_line(void * part,struct sspm_header * header,const char * line,size_t size)76 void icalmime_text_add_line(void *part,
77 struct sspm_header *header,
78 const char* line, size_t size)
79 {
80 struct text_part* impl = (struct text_part*) part;
81 (void)header;
82 (void)size;
83
84 icalmemory_append_string(&(impl->buf),&(impl->buf_pos),
85 &(impl->buf_size),line);
86
87 }
88
icalmime_textcalendar_end_part(void * part)89 void* icalmime_textcalendar_end_part(void* part)
90 {
91
92 struct text_part* impl = (struct text_part*) part;
93 icalcomponent *c = icalparser_parse_string(impl->buf);
94
95 icalmemory_free_buffer(impl->buf);
96 free(impl);
97
98 return c;
99
100 }
101
icalmime_text_end_part_r(void * part)102 void* icalmime_text_end_part_r(void* part)
103 {
104 char *buf;
105 struct text_part* impl = ( struct text_part*) part;
106
107 buf = impl->buf;
108 free(impl);
109
110 return buf;
111 }
112
icalmime_text_end_part(void * part)113 void* icalmime_text_end_part(void* part)
114 {
115 void *buf;
116 buf = icalmime_text_end_part_r(part);
117 icalmemory_add_tmp_buffer(buf);
118 return buf;
119 }
120
121
icalmime_text_free_part(void * part)122 void icalmime_text_free_part(void *part)
123 {
124 part = part;
125 }
126
127
128 /* Ignore Attachments for now */
129
icalmime_attachment_new_part(void)130 void* icalmime_attachment_new_part(void)
131 {
132 return 0;
133 }
icalmime_attachment_add_line(void * part,struct sspm_header * header,const char * line,size_t size)134 void icalmime_attachment_add_line(void *part, struct sspm_header *header,
135 const char* line, size_t size)
136 {
137 (void)part;
138 (void)header;
139 (void)line;
140 (void)size;
141 }
142
icalmime_attachment_end_part(void * part)143 void* icalmime_attachment_end_part(void* part)
144 {
145 (void)part;
146 return 0;
147 }
148
icalmime_attachment_free_part(void * part)149 void icalmime_attachment_free_part(void *part)
150 {
151 (void)part;
152 }
153
154
155
156
157 static const struct sspm_action_map icalmime_local_action_map[] =
158 {
159 {SSPM_TEXT_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_textcalendar_end_part,icalmime_text_free_part},
160 {SSPM_TEXT_MAJOR_TYPE,SSPM_ANY_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part_r,icalmime_text_free_part},
161 {SSPM_TEXT_MAJOR_TYPE,SSPM_PLAIN_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part_r,icalmime_text_free_part},
162 {SSPM_APPLICATION_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
163 {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
164 {SSPM_AUDIO_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
165 {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
166 {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,0,0,0,0}
167 };
168
169 #define NUM_PARTS 100 /* HACK. Hard Limit */
170
171
172
icalmime_make_part(icalcomponent * comp)173 struct sspm_part* icalmime_make_part(icalcomponent* comp)
174 {
175 comp = comp;
176 return 0;
177 }
178
179 char* icalmime_as_mime_string(char* icalcomponent);
180
icalmime_parse(char * (* get_string)(char * s,size_t size,void * d),void * data)181 icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size,
182 void *d),
183 void *data)
184 {
185 struct sspm_part *parts;
186 int i, last_level=0;
187 icalcomponent *root=0, *parent=0, *comp=0, *last = 0;
188
189 if ( (parts = (struct sspm_part *)
190 malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
191 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
192 return 0;
193 }
194
195 memset(parts,0,sizeof(NUM_PARTS*sizeof(struct sspm_part)));
196
197 sspm_parse_mime(parts,
198 NUM_PARTS, /* Max parts */
199 icalmime_local_action_map, /* Actions */
200 get_string,
201 data, /* data for get_string*/
202 0 /* First header */);
203
204
205
206 for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){
207
208 #define TMPSZ 1024
209 char mimetype[TMPSZ];
210 const char* major = sspm_major_type_string(parts[i].header.major);
211 const char* minor = sspm_minor_type_string(parts[i].header.minor);
212
213 if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){
214 assert(parts[i].header.minor_text !=0);
215 minor = parts[i].header.minor_text;
216 }
217
218 snprintf(mimetype,sizeof(mimetype),"%s/%s",major,minor);
219
220 comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT);
221
222 if(comp == 0){
223 /* HACK Handle Error */
224 assert(0);
225 }
226
227 if(parts[i].header.error!=SSPM_NO_ERROR){
228 const char *str="Unknown error";
229 char temp[256];
230 if(parts[i].header.error==SSPM_MALFORMED_HEADER_ERROR){
231 str = "Malformed header, possibly due to input not in MIME format";
232 }
233
234 if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){
235 str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line";
236 }
237
238 if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){
239 str = "Got the wrong boundary for the opening of a MULTIPART part.";
240 }
241
242 if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){
243 str = "Got a multipart header that did not specify a boundary";
244 }
245
246 if(parts[i].header.error==SSPM_NO_HEADER_ERROR){
247 str = "Did not get a header for the part. Is there a blank\
248 line between the header and the previous boundary\?";
249
250 }
251
252 if(parts[i].header.error_text != 0){
253 snprintf(temp,256,
254 "%s: %s",str,parts[i].header.error_text);
255 } else {
256 strcpy(temp,str);
257 }
258
259 icalcomponent_add_property
260 (comp,
261 icalproperty_vanew_xlicerror(
262 temp,
263 icalparameter_new_xlicerrortype(
264 ICAL_XLICERRORTYPE_MIMEPARSEERROR),
265 0));
266 }
267
268 if(parts[i].header.major != SSPM_NO_MAJOR_TYPE &&
269 parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){
270
271 icalcomponent_add_property(comp,
272 icalproperty_new_xlicmimecontenttype((char*)
273 icalmemory_strdup(mimetype)));
274
275 }
276
277 if (parts[i].header.encoding != SSPM_NO_ENCODING){
278
279 icalcomponent_add_property(comp,
280 icalproperty_new_xlicmimeencoding(
281 sspm_encoding_string(parts[i].header.encoding)));
282 }
283
284 if (parts[i].header.filename != 0){
285 icalcomponent_add_property(comp,
286 icalproperty_new_xlicmimefilename(parts[i].header.filename));
287 }
288
289 if (parts[i].header.content_id != 0){
290 icalcomponent_add_property(comp,
291 icalproperty_new_xlicmimecid(parts[i].header.content_id));
292 }
293
294 if (parts[i].header.charset != 0){
295 icalcomponent_add_property(comp,
296 icalproperty_new_xlicmimecharset(parts[i].header.charset));
297 }
298
299 /* Add iCal components as children of the component */
300 if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
301 parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE &&
302 parts[i].data != 0){
303
304 icalcomponent_add_component(comp,
305 (icalcomponent*)parts[i].data);
306 parts[i].data = 0;
307
308 } else if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
309 parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE &&
310 parts[i].data != 0){
311
312 /* Add other text components as "DESCRIPTION" properties */
313
314 icalcomponent_add_property(comp,
315 icalproperty_new_description(
316 (char*)icalmemory_strdup((char*)parts[i].data)));
317
318 parts[i].data = 0;
319 }
320
321
322 if(root!= 0 && parts[i].level == 0){
323 /* We've already assigned the root, but there is another
324 part at the root level. This is probably a parse
325 error*/
326 icalcomponent_free(comp);
327 continue;
328 }
329
330 if(parts[i].level == last_level && last_level != 0){
331 icalerror_assert(parent!=0,"No parent for adding component");
332
333 icalcomponent_add_component(parent,comp);
334
335 } else if (parts[i].level == last_level && last_level == 0 &&
336 root == 0) {
337
338 root = comp;
339 parent = comp;
340
341 } else if (parts[i].level > last_level){
342
343 parent = last;
344 icalcomponent_add_component(parent,comp);
345
346 last_level = parts[i].level;
347
348 } else if (parts[i].level < last_level){
349
350 if (parent)
351 parent = icalcomponent_get_parent(parent);
352 icalcomponent_add_component(parent,comp);
353
354 last_level = parts[i].level;
355 } else {
356 assert(0);
357 }
358
359 last = comp;
360 last_level = parts[i].level;
361 assert(parts[i].data == 0);
362 }
363
364 sspm_free_parts(parts,NUM_PARTS);
365 free(parts);
366
367 return root;
368 }
369
370
371
icalmime_test(char * (* get_string)(char * s,size_t size,void * d),void * data)372 int icalmime_test(char* (*get_string)(char *s, size_t size, void *d),
373 void *data)
374 {
375 char *out;
376 struct sspm_part *parts;
377 int i;
378
379 if ( (parts = (struct sspm_part *)
380 malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
381 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
382 return 0;
383 }
384
385 memset(parts,0,sizeof(NUM_PARTS*sizeof(struct sspm_part)));
386
387 sspm_parse_mime(parts,
388 NUM_PARTS, /* Max parts */
389 icalmime_local_action_map, /* Actions */
390 get_string,
391 data, /* data for get_string*/
392 0 /* First header */);
393
394 for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ;
395 i++){
396 if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){
397 parts[i].data =
398 icalcomponent_as_ical_string_r((icalcomponent*)parts[i].data);
399 }
400 }
401
402 sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org");
403
404 printf("%s\n",out);
405 free(out);
406
407 return 0;
408
409 }
410
411
412