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;
172 if ( (parts = (struct sspm_part *)
173 malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
174 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
178 memset(parts,0,sizeof(parts));
180 sspm_parse_mime(parts,
181 NUM_PARTS, /* Max parts */
182 icalmime_local_action_map, /* Actions */
184 data, /* data for get_string*/
185 0 /* First header */);
189 for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){
192 char mimetype[TMPSZ];
193 char* major = sspm_major_type_string(parts[i].header.major);
194 char* minor = sspm_minor_type_string(parts[i].header.minor);
196 if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){
197 assert(parts[i].header.minor_text !=0);
198 minor = parts[i].header.minor_text;
201 sprintf(mimetype,"%s/%s",major,minor);
203 comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT);
206 /* HACK Handle Error */
210 if(parts[i].header.error!=SSPM_NO_ERROR){
214 if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){
215 str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line";
218 if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){
219 str = "Got the wrong boundary for the opening of a MULTIPART part.";
222 if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){
223 str = "Got a multipart header that did not specify a boundary";
226 if(parts[i].header.error==SSPM_NO_HEADER_ERROR){
227 str = "Did not get a header for the part. Is there a blank\
228 line between the header and the previous boundary\?";
232 if(parts[i].header.error_text != 0){
233 snprintf((char*)temp,256,
234 "%s: %s",str,parts[i].header.error_text);
236 strcpy((char*)temp,str);
239 icalcomponent_add_property
241 icalproperty_vanew_xlicerror(
243 icalparameter_new_xlicerrortype(
244 ICAL_XLICERRORTYPE_MIMEPARSEERROR),
248 if(parts[i].header.major != SSPM_NO_MAJOR_TYPE &&
249 parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){
251 icalcomponent_add_property(comp,
252 icalproperty_new_xlicmimecontenttype((char*)
253 icalmemory_strdup(mimetype)));
257 if (parts[i].header.encoding != SSPM_NO_ENCODING){
259 icalcomponent_add_property(comp,
260 icalproperty_new_xlicmimeencoding(
261 sspm_encoding_string(parts[i].header.encoding)));
264 if (parts[i].header.filename != 0){
265 icalcomponent_add_property(comp,
266 icalproperty_new_xlicmimefilename(parts[i].header.filename));
269 if (parts[i].header.content_id != 0){
270 icalcomponent_add_property(comp,
271 icalproperty_new_xlicmimecid(parts[i].header.content_id));
274 if (parts[i].header.charset != 0){
275 icalcomponent_add_property(comp,
276 icalproperty_new_xlicmimecharset(parts[i].header.charset));
279 /* Add iCal components as children of the component */
280 if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
281 parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE &&
284 icalcomponent_add_component(comp,
285 (icalcomponent*)parts[i].data);
288 } else if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
289 parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE &&
292 /* Add other text components as "DESCRIPTION" properties */
294 icalcomponent_add_property(comp,
295 icalproperty_new_description(
296 (char*)icalmemory_strdup((char*)parts[i].data)));
302 if(root!= 0 && parts[i].level == 0){
303 /* We've already assigned the root, but there is another
304 part at the root level. This is probably a parse
306 icalcomponent_free(comp);
310 if(parts[i].level == last_level && last_level != 0){
311 icalerror_assert(parent!=0,"No parent for adding component");
313 icalcomponent_add_component(parent,comp);
315 } else if (parts[i].level == last_level && last_level == 0 &&
321 } else if (parts[i].level > last_level){
324 icalcomponent_add_component(parent,comp);
326 last_level = parts[i].level;
328 } else if (parts[i].level < last_level){
330 parent = icalcomponent_get_parent(parent);
331 icalcomponent_add_component(parent,comp);
333 last_level = parts[i].level;
339 last_level = parts[i].level;
340 assert(parts[i].data == 0);
343 sspm_free_parts(parts,NUM_PARTS);
351 int icalmime_test(char* (*get_string)(char *s, size_t size, void *d),
355 struct sspm_part *parts;
358 if ( (parts = (struct sspm_part *)
359 malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
360 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
364 memset(parts,0,sizeof(parts));
366 sspm_parse_mime(parts,
367 NUM_PARTS, /* Max parts */
368 icalmime_local_action_map, /* Actions */
370 data, /* data for get_string*/
371 0 /* First header */);
373 for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ;
375 if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){
376 parts[i].data = icalmemory_strdup(
377 icalcomponent_as_ical_string((icalcomponent*)parts[i].data));
381 sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org");