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