Diffstat (limited to 'libical/src/libical/icalmime.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libical/src/libical/icalmime.c | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/libical/src/libical/icalmime.c b/libical/src/libical/icalmime.c new file mode 100644 index 0000000..7021746 --- a/dev/null +++ b/libical/src/libical/icalmime.c | |||
@@ -0,0 +1,388 @@ | |||
1 | /* -*- Mode: C -*-*/ | ||
2 | /*====================================================================== | ||
3 | FILE: icalmime.c | ||
4 | CREATOR: eric 26 July 2000 | ||
5 | |||
6 | |||
7 | $Id$ | ||
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 | int snprintf(char *str, size_t n, char const *fmt, ...); | ||
38 | |||
39 | #ifdef DMALLOC | ||
40 | #include "dmalloc.h" | ||
41 | #endif | ||
42 | |||
43 | |||
44 | /* These *_part routines are called by the MIME parser via the | ||
45 | local_action_map */ | ||
46 | |||
47 | struct text_part | ||
48 | { | ||
49 | char* buf; | ||
50 | char* buf_pos; | ||
51 | size_t buf_size; | ||
52 | }; | ||
53 | |||
54 | void* icalmime_text_new_part() | ||
55 | { | ||
56 | |||
57 | #define BUF_SIZE 2048 | ||
58 | |||
59 | struct text_part* impl; | ||
60 | |||
61 | if ( ( impl = (struct text_part*) | ||
62 | malloc(sizeof(struct text_part))) == 0) { | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | impl->buf = icalmemory_new_buffer(BUF_SIZE); | ||
67 | impl->buf_pos = impl->buf; | ||
68 | impl->buf_size = BUF_SIZE; | ||
69 | |||
70 | return impl; | ||
71 | } | ||
72 | void icalmime_text_add_line(void *part, | ||
73 | struct sspm_header *header, | ||
74 | char* line, size_t size) | ||
75 | { | ||
76 | struct text_part* impl = (struct text_part*) part; | ||
77 | |||
78 | icalmemory_append_string(&(impl->buf),&(impl->buf_pos), | ||
79 | &(impl->buf_size),line); | ||
80 | |||
81 | } | ||
82 | |||
83 | void* icalmime_textcalendar_end_part(void* part) | ||
84 | { | ||
85 | |||
86 | struct text_part* impl = (struct text_part*) part; | ||
87 | icalcomponent *c = icalparser_parse_string(impl->buf); | ||
88 | |||
89 | icalmemory_free_buffer(impl->buf); | ||
90 | free(impl); | ||
91 | |||
92 | return c; | ||
93 | |||
94 | } | ||
95 | |||
96 | void* icalmime_text_end_part(void* part) | ||
97 | { | ||
98 | struct text_part* impl = ( struct text_part*) part; | ||
99 | |||
100 | icalmemory_add_tmp_buffer(impl->buf); | ||
101 | free(impl); | ||
102 | |||
103 | return impl->buf; | ||
104 | } | ||
105 | |||
106 | void icalmime_text_free_part(void *part) | ||
107 | { | ||
108 | part = part; | ||
109 | } | ||
110 | |||
111 | |||
112 | /* Ignore Attachments for now */ | ||
113 | |||
114 | void* icalmime_attachment_new_part() | ||
115 | { | ||
116 | return 0; | ||
117 | } | ||
118 | void icalmime_attachment_add_line(void *part, struct sspm_header *header, | ||
119 | char* line, size_t size) | ||
120 | { | ||
121 | part = part; | ||
122 | header = header; | ||
123 | line = line; | ||
124 | size = size; | ||
125 | } | ||
126 | |||
127 | void* icalmime_attachment_end_part(void* part) | ||
128 | { | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | void icalmime_attachment_free_part(void *part) | ||
133 | { | ||
134 | } | ||
135 | |||
136 | |||
137 | |||
138 | |||
139 | struct sspm_action_map icalmime_local_action_map[] = | ||
140 | { | ||
141 | {SSPM_TEXT_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_textcalendar_end_part,icalmime_text_free_part}, | ||
142 | {SSPM_TEXT_MAJOR_TYPE,SSPM_ANY_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part}, | ||
143 | {SSPM_TEXT_MAJOR_TYPE,SSPM_PLAIN_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part}, | ||
144 | {SSPM_APPLICATION_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, | ||
145 | {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, | ||
146 | {SSPM_AUDIO_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, | ||
147 | {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, | ||
148 | {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,0,0,0,0} | ||
149 | }; | ||
150 | |||
151 | #define NUM_PARTS 100 /* HACK. Hard Limit */ | ||
152 | |||
153 | |||
154 | |||
155 | struct sspm_part* icalmime_make_part(icalcomponent* comp) | ||
156 | { | ||
157 | comp = comp; | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | char* icalmime_as_mime_string(char* icalcomponent); | ||
162 | |||
163 | icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size, | ||
164 | void *d), | ||
165 | void *data) | ||
166 | { | ||
167 | struct sspm_part *parts; | ||
168 | int i, last_level=0; | ||
169 | icalcomponent *root=0, *parent=0, *comp=0, *last = 0; | ||
170 | |||
171 | if ( (parts = (struct sspm_part *) | ||
172 | malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) { | ||
173 | icalerror_set_errno(ICAL_NEWFAILED_ERROR); | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | memset(parts,0,sizeof(parts)); | ||
178 | |||
179 | sspm_parse_mime(parts, | ||
180 | NUM_PARTS, /* Max parts */ | ||
181 | icalmime_local_action_map, /* Actions */ | ||
182 | get_string, | ||
183 | data, /* data for get_string*/ | ||
184 | 0 /* First header */); | ||
185 | |||
186 | |||
187 | |||
188 | for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){ | ||
189 | |||
190 | #define TMPSZ 1024 | ||
191 | char mimetype[TMPSZ]; | ||
192 | char* major = sspm_major_type_string(parts[i].header.major); | ||
193 | char* minor = sspm_minor_type_string(parts[i].header.minor); | ||
194 | |||
195 | if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){ | ||
196 | assert(parts[i].header.minor_text !=0); | ||
197 | minor = parts[i].header.minor_text; | ||
198 | } | ||
199 | |||
200 | sprintf(mimetype,"%s/%s",major,minor); | ||
201 | |||
202 | comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT); | ||
203 | |||
204 | if(comp == 0){ | ||
205 | /* HACK Handle Error */ | ||
206 | assert(0); | ||
207 | } | ||
208 | |||
209 | if(parts[i].header.error!=SSPM_NO_ERROR){ | ||
210 | char *str; | ||
211 | char* temp[256]; | ||
212 | |||
213 | if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){ | ||
214 | str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line"; | ||
215 | } | ||
216 | |||
217 | if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){ | ||
218 | str = "Got the wrong boundary for the opening of a MULTIPART part."; | ||
219 | } | ||
220 | |||
221 | if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){ | ||
222 | str = "Got a multipart header that did not specify a boundary"; | ||
223 | } | ||
224 | |||
225 | if(parts[i].header.error==SSPM_NO_HEADER_ERROR){ | ||
226 | str = "Did not get a header for the part. Is there a blank\ | ||
227 | line between the header and the previous boundary\?"; | ||
228 | |||
229 | } | ||
230 | |||
231 | if(parts[i].header.error_text != 0){ | ||
232 | snprintf((char*)temp,256, | ||
233 | "%s: %s",str,parts[i].header.error_text); | ||
234 | } else { | ||
235 | strcpy((char*)temp,str); | ||
236 | } | ||
237 | |||
238 | icalcomponent_add_property | ||
239 | (comp, | ||
240 | icalproperty_vanew_xlicerror( | ||
241 | (char*)temp, | ||
242 | icalparameter_new_xlicerrortype( | ||
243 | ICAL_XLICERRORTYPE_MIMEPARSEERROR), | ||
244 | 0)); | ||
245 | } | ||
246 | |||
247 | if(parts[i].header.major != SSPM_NO_MAJOR_TYPE && | ||
248 | parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){ | ||
249 | |||
250 | icalcomponent_add_property(comp, | ||
251 | icalproperty_new_xlicmimecontenttype((char*) | ||
252 | icalmemory_strdup(mimetype))); | ||
253 | |||
254 | } | ||
255 | |||
256 | if (parts[i].header.encoding != SSPM_NO_ENCODING){ | ||
257 | |||
258 | icalcomponent_add_property(comp, | ||
259 | icalproperty_new_xlicmimeencoding( | ||
260 | sspm_encoding_string(parts[i].header.encoding))); | ||
261 | } | ||
262 | |||
263 | if (parts[i].header.filename != 0){ | ||
264 | icalcomponent_add_property(comp, | ||
265 | icalproperty_new_xlicmimefilename(parts[i].header.filename)); | ||
266 | } | ||
267 | |||
268 | if (parts[i].header.content_id != 0){ | ||
269 | icalcomponent_add_property(comp, | ||
270 | icalproperty_new_xlicmimecid(parts[i].header.content_id)); | ||
271 | } | ||
272 | |||
273 | if (parts[i].header.charset != 0){ | ||
274 | icalcomponent_add_property(comp, | ||
275 | icalproperty_new_xlicmimecharset(parts[i].header.charset)); | ||
276 | } | ||
277 | |||
278 | /* Add iCal components as children of the component */ | ||
279 | if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE && | ||
280 | parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE && | ||
281 | parts[i].data != 0){ | ||
282 | |||
283 | icalcomponent_add_component(comp, | ||
284 | (icalcomponent*)parts[i].data); | ||
285 | parts[i].data = 0; | ||
286 | |||
287 | } else if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE && | ||
288 | parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE && | ||
289 | parts[i].data != 0){ | ||
290 | |||
291 | /* Add other text components as "DESCRIPTION" properties */ | ||
292 | |||
293 | icalcomponent_add_property(comp, | ||
294 | icalproperty_new_description( | ||
295 | (char*)icalmemory_strdup((char*)parts[i].data))); | ||
296 | |||
297 | parts[i].data = 0; | ||
298 | } | ||
299 | |||
300 | |||
301 | if(root!= 0 && parts[i].level == 0){ | ||
302 | /* We've already assigned the root, but there is another | ||
303 | part at the root level. This is probably a parse | ||
304 | error*/ | ||
305 | icalcomponent_free(comp); | ||
306 | continue; | ||
307 | } | ||
308 | |||
309 | if(parts[i].level == last_level && last_level != 0){ | ||
310 | icalerror_assert(parent!=0,"No parent for adding component"); | ||
311 | |||
312 | icalcomponent_add_component(parent,comp); | ||
313 | |||
314 | } else if (parts[i].level == last_level && last_level == 0 && | ||
315 | root == 0) { | ||
316 | |||
317 | root = comp; | ||
318 | parent = comp; | ||
319 | |||
320 | } else if (parts[i].level > last_level){ | ||
321 | |||
322 | parent = last; | ||
323 | icalcomponent_add_component(parent,comp); | ||
324 | |||
325 | last_level = parts[i].level; | ||
326 | |||
327 | } else if (parts[i].level < last_level){ | ||
328 | |||
329 | parent = icalcomponent_get_parent(parent); | ||
330 | icalcomponent_add_component(parent,comp); | ||
331 | |||
332 | last_level = parts[i].level; | ||
333 | } else { | ||
334 | assert(0); | ||
335 | } | ||
336 | |||
337 | last = comp; | ||
338 | last_level = parts[i].level; | ||
339 | assert(parts[i].data == 0); | ||
340 | } | ||
341 | |||
342 | sspm_free_parts(parts,NUM_PARTS); | ||
343 | free(parts); | ||
344 | |||
345 | return root; | ||
346 | } | ||
347 | |||
348 | |||
349 | |||
350 | int icalmime_test(char* (*get_string)(char *s, size_t size, void *d), | ||
351 | void *data) | ||
352 | { | ||
353 | char *out; | ||
354 | struct sspm_part *parts; | ||
355 | int i; | ||
356 | |||
357 | if ( (parts = (struct sspm_part *) | ||
358 | malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) { | ||
359 | icalerror_set_errno(ICAL_NEWFAILED_ERROR); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | memset(parts,0,sizeof(parts)); | ||
364 | |||
365 | sspm_parse_mime(parts, | ||
366 | NUM_PARTS, /* Max parts */ | ||
367 | icalmime_local_action_map, /* Actions */ | ||
368 | get_string, | ||
369 | data, /* data for get_string*/ | ||
370 | 0 /* First header */); | ||
371 | |||
372 | for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; | ||
373 | i++){ | ||
374 | if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){ | ||
375 | parts[i].data = icalmemory_strdup( | ||
376 | icalcomponent_as_ical_string((icalcomponent*)parts[i].data)); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org"); | ||
381 | |||
382 | printf("%s\n",out); | ||
383 | |||
384 | return 0; | ||
385 | |||
386 | } | ||
387 | |||
388 | |||