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