2 /*======================================================================
4 CREATOR: eric 26 July 2000
10 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of either:
15 The LGPL as published by the Free Software Foundation, version
16 2.1, available at: http://www.fsf.org/copyleft/lesser.html
20 The Mozilla Public License Version 1.0. You may obtain a copy of
21 the License at http://www.mozilla.org/MPL/
23 The Original Code is eric. The Initial Developer of the Original
27 ======================================================================*/
30 #include "icalerror.h"
31 #include "icalmemory.h"
34 #include <string.h> /* For strdup */
35 #include <stdio.h> /* for snprintf*/
42 /* These *_part routines are called by the MIME parser via the
52 void* icalmime_text_new_part()
57 struct text_part* impl;
59 if ( ( impl = (struct text_part*)
60 malloc(sizeof(struct text_part))) == 0) {
64 impl->buf = icalmemory_new_buffer(BUF_SIZE);
65 impl->buf_pos = impl->buf;
66 impl->buf_size = BUF_SIZE;
70 void icalmime_text_add_line(void *part,
71 struct sspm_header *header,
72 char* line, size_t size)
74 struct text_part* impl = (struct text_part*) part;
76 icalmemory_append_string(&(impl->buf),&(impl->buf_pos),
77 &(impl->buf_size),line);
81 void* icalmime_textcalendar_end_part(void* part)
84 struct text_part* impl = (struct text_part*) part;
85 icalcomponent *c = icalparser_parse_string(impl->buf);
87 icalmemory_free_buffer(impl->buf);
94 void* icalmime_text_end_part(void* part)
96 struct text_part* impl = ( struct text_part*) part;
99 icalmemory_add_tmp_buffer(impl->buf);
107 void icalmime_text_free_part(void *part)
113 /* Ignore Attachments for now */
115 void* icalmime_attachment_new_part()
119 void icalmime_attachment_add_line(void *part, struct sspm_header *header,
120 char* line, size_t size)
128 void* icalmime_attachment_end_part(void* part)
133 void icalmime_attachment_free_part(void *part)
140 struct sspm_action_map icalmime_local_action_map[] =
142 {SSPM_TEXT_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_textcalendar_end_part,icalmime_text_free_part},
143 {SSPM_TEXT_MAJOR_TYPE,SSPM_ANY_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part},
144 {SSPM_TEXT_MAJOR_TYPE,SSPM_PLAIN_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part},
145 {SSPM_APPLICATION_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
146 {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
147 {SSPM_AUDIO_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
148 {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
149 {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,0,0,0,0}
152 #define NUM_PARTS 100 /* HACK. Hard Limit */
156 struct sspm_part* icalmime_make_part(icalcomponent* comp)
162 char* icalmime_as_mime_string(char* icalcomponent);
164 icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size,
168 struct sspm_part *parts;
170 icalcomponent *root=0, *parent=0, *comp=0, *last = 0;
171 size_t alloc_len = NUM_PARTS * sizeof(struct sspm_part);
173 if ( (parts = (struct sspm_part *)
174 malloc(alloc_len))==0) {
175 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
179 memset(parts, 0, alloc_len);
181 sspm_parse_mime(parts,
182 NUM_PARTS, /* Max parts */
183 icalmime_local_action_map, /* Actions */
185 data, /* data for get_string*/
186 0 /* First header */);
190 for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){
193 char mimetype[TMPSZ];
194 char* major = sspm_major_type_string(parts[i].header.major);
195 char* minor = sspm_minor_type_string(parts[i].header.minor);
197 if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){
198 assert(parts[i].header.minor_text !=0);
199 minor = parts[i].header.minor_text;
202 sprintf(mimetype,"%s/%s",major,minor);
204 comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT);
207 /* HACK Handle Error */
211 if(parts[i].header.error!=SSPM_NO_ERROR){
215 if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){
216 str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line";
219 if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){
220 str = "Got the wrong boundary for the opening of a MULTIPART part.";
223 if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){
224 str = "Got a multipart header that did not specify a boundary";
227 if(parts[i].header.error==SSPM_NO_HEADER_ERROR){
228 str = "Did not get a header for the part. Is there a blank\
229 line between the header and the previous boundary\?";
233 if(parts[i].header.error_text != 0){
234 snprintf((char*)temp,256,
235 "%s: %s",str,parts[i].header.error_text);
237 strncpy((char*)temp,str, 255);
240 icalcomponent_add_property
242 icalproperty_vanew_xlicerror(
244 icalparameter_new_xlicerrortype(
245 ICAL_XLICERRORTYPE_MIMEPARSEERROR),
249 if(parts[i].header.major != SSPM_NO_MAJOR_TYPE &&
250 parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){
252 icalcomponent_add_property(comp,
253 icalproperty_new_xlicmimecontenttype((char*)
254 icalmemory_strdup(mimetype)));
258 if (parts[i].header.encoding != SSPM_NO_ENCODING){
260 icalcomponent_add_property(comp,
261 icalproperty_new_xlicmimeencoding(
262 sspm_encoding_string(parts[i].header.encoding)));
265 if (parts[i].header.filename != 0){
266 icalcomponent_add_property(comp,
267 icalproperty_new_xlicmimefilename(parts[i].header.filename));
270 if (parts[i].header.content_id != 0){
271 icalcomponent_add_property(comp,
272 icalproperty_new_xlicmimecid(parts[i].header.content_id));
275 if (parts[i].header.charset != 0){
276 icalcomponent_add_property(comp,
277 icalproperty_new_xlicmimecharset(parts[i].header.charset));
280 /* Add iCal components as children of the component */
281 if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
282 parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE &&
285 icalcomponent_add_component(comp,
286 (icalcomponent*)parts[i].data);
289 } else if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
290 parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE &&
293 /* Add other text components as "DESCRIPTION" properties */
295 icalcomponent_add_property(comp,
296 icalproperty_new_description(
297 (char*)icalmemory_strdup((char*)parts[i].data)));
303 if(root!= 0 && parts[i].level == 0){
304 /* We've already assigned the root, but there is another
305 part at the root level. This is probably a parse
307 icalcomponent_free(comp);
311 if(parts[i].level == last_level && last_level != 0){
312 icalerror_assert(parent!=0,"No parent for adding component");
314 icalcomponent_add_component(parent,comp);
316 } else if (parts[i].level == last_level && last_level == 0 &&
322 } else if (parts[i].level > last_level){
325 icalcomponent_add_component(parent,comp);
327 last_level = parts[i].level;
329 } else if (parts[i].level < last_level){
331 parent = icalcomponent_get_parent(parent);
332 icalcomponent_add_component(parent,comp);
334 last_level = parts[i].level;
340 last_level = parts[i].level;
341 assert(parts[i].data == 0);
344 sspm_free_parts(parts,NUM_PARTS);
352 int icalmime_test(char* (*get_string)(char *s, size_t size, void *d),
356 struct sspm_part *parts;
358 size_t alloc_len = NUM_PARTS * sizeof(struct sspm_part);
360 if ( (parts = (struct sspm_part *)
361 malloc(alloc_len))==0) {
362 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
366 memset(parts,0,alloc_len);
368 sspm_parse_mime(parts,
369 NUM_PARTS, /* Max parts */
370 icalmime_local_action_map, /* Actions */
372 data, /* data for get_string*/
373 0 /* First header */);
375 for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ;
377 if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){
378 parts[i].data = icalmemory_strdup(
379 icalcomponent_as_ical_string((icalcomponent*)parts[i].data));
383 sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org");