Back to index

lightning-sunbird  0.9+nobinonly
icalmime.c
Go to the documentation of this file.
00001 /* -*- Mode: C -*-*/
00002 /*======================================================================
00003  FILE: icalmime.c
00004  CREATOR: eric 26 July 2000
00005 
00006 
00007  $Id: icalmime.c,v 1.8 2005/01/24 12:49:11 acampi Exp $
00008  $Locker:  $
00009 
00010  (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
00011 
00012  This program is free software; you can redistribute it and/or modify
00013  it under the terms of either: 
00014 
00015     The LGPL as published by the Free Software Foundation, version
00016     2.1, available at: http://www.fsf.org/copyleft/lesser.html
00017 
00018   Or:
00019 
00020     The Mozilla Public License Version 1.0. You may obtain a copy of
00021     the License at http://www.mozilla.org/MPL/
00022 
00023  The Original Code is eric. The Initial Developer of the Original
00024  Code is Eric Busboom
00025 
00026 
00027 ======================================================================*/
00028 
00029 #include "icalmime.h"
00030 #include "icalerror.h"
00031 #include "icalmemory.h"
00032 #include "sspm.h"
00033 #include "stdlib.h"
00034 #include <string.h> /* For strdup */
00035 #include <stdio.h> /* for snprintf*/
00036 
00037 #ifdef DMALLOC
00038 #include "dmalloc.h"
00039 #endif
00040 
00041 #ifdef WIN32
00042 #define snprintf      _snprintf
00043 #define strcasecmp    stricmp
00044 #endif
00045 
00046 /* These *_part routines are called by the MIME parser via the
00047    local_action_map */
00048 
00049 struct text_part
00050 {
00051        char* buf;
00052        char* buf_pos;
00053        size_t buf_size;
00054 };
00055 
00056 void* icalmime_text_new_part()
00057 {
00058 
00059 #define BUF_SIZE 2048
00060 
00061     struct text_part* impl;
00062 
00063     if ( ( impl = (struct text_part*)
00064           malloc(sizeof(struct text_part))) == 0) {
00065        return 0;
00066     }
00067 
00068     impl->buf =  icalmemory_new_buffer(BUF_SIZE);
00069     impl->buf_pos = impl->buf;
00070     impl->buf_size = BUF_SIZE;
00071 
00072     return impl;    
00073 }
00074 void icalmime_text_add_line(void *part, 
00075                          struct sspm_header *header, 
00076                          char* line, size_t size)
00077 {
00078     struct text_part* impl = (struct text_part*) part;
00079 
00080     icalmemory_append_string(&(impl->buf),&(impl->buf_pos),
00081                           &(impl->buf_size),line);
00082     
00083 }
00084 
00085 void* icalmime_textcalendar_end_part(void* part)
00086 {
00087 
00088     struct text_part* impl = (struct text_part*) part;
00089     icalcomponent *c = icalparser_parse_string(impl->buf);
00090 
00091     icalmemory_free_buffer(impl->buf);
00092     free(impl);
00093 
00094     return c;
00095 
00096 }
00097 
00098 void* icalmime_text_end_part(void* part)
00099 {
00100     struct text_part* impl = ( struct text_part*) part;
00101 
00102     icalmemory_add_tmp_buffer(impl->buf);
00103     free(impl);
00104 
00105     return impl->buf;
00106 }
00107 
00108 void icalmime_text_free_part(void *part)
00109 {
00110     part = part;
00111 }
00112 
00113 
00114 /* Ignore Attachments for now */
00115 
00116 void* icalmime_attachment_new_part()
00117 {
00118     return 0;
00119 }
00120 void icalmime_attachment_add_line(void *part, struct sspm_header *header, 
00121                               char* line, size_t size)
00122 {
00123     part = part;
00124     header = header;
00125     line = line;
00126     size = size;
00127 }
00128 
00129 void* icalmime_attachment_end_part(void* part)
00130 {
00131     return 0;
00132 }
00133 
00134 void icalmime_attachment_free_part(void *part)
00135 {
00136 }
00137 
00138 
00139 
00140 
00141 struct sspm_action_map icalmime_local_action_map[] = 
00142 {
00143     {SSPM_TEXT_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_textcalendar_end_part,icalmime_text_free_part},
00144     {SSPM_TEXT_MAJOR_TYPE,SSPM_ANY_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part},
00145     {SSPM_TEXT_MAJOR_TYPE,SSPM_PLAIN_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part},
00146     {SSPM_APPLICATION_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
00147     {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
00148     {SSPM_AUDIO_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
00149     {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
00150    {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,0,0,0,0}
00151 };
00152 
00153 #define NUM_PARTS 100 /* HACK. Hard Limit */
00154 
00155 
00156 
00157 struct sspm_part* icalmime_make_part(icalcomponent* comp)
00158 {
00159     comp = comp;
00160     return 0;
00161 }
00162 
00163 char* icalmime_as_mime_string(char* icalcomponent);
00164 
00165 icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size, 
00166                                                  void *d),
00167                             void *data)
00168 {
00169     struct sspm_part *parts;
00170     int i, last_level=0;
00171     icalcomponent *root=0, *parent=0, *comp=0, *last = 0;
00172 
00173     if ( (parts = (struct sspm_part *)
00174          malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
00175        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
00176        return 0;
00177     }
00178 
00179     memset(parts,0,sizeof(parts));
00180 
00181     sspm_parse_mime(parts, 
00182                   NUM_PARTS, /* Max parts */
00183                   icalmime_local_action_map, /* Actions */ 
00184                   get_string,
00185                   data, /* data for get_string*/
00186                   0 /* First header */);
00187 
00188 
00189 
00190     for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){
00191 
00192 #define TMPSZ 1024
00193        char mimetype[TMPSZ];                            
00194        char* major = sspm_major_type_string(parts[i].header.major);
00195        char* minor = sspm_minor_type_string(parts[i].header.minor);
00196 
00197        if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){
00198            assert(parts[i].header.minor_text !=0);
00199            minor = parts[i].header.minor_text;
00200        }
00201        
00202        snprintf(mimetype,sizeof(mimetype),"%s/%s",major,minor);
00203 
00204        comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT);
00205 
00206        if(comp == 0){
00207            /* HACK Handle Error */
00208            assert(0);
00209        }
00210 
00211        if(parts[i].header.error!=SSPM_NO_ERROR){
00212            char *str = "Unknown error";
00213            char temp[256];
00214 
00215            if(parts[i].header.error==SSPM_MALFORMED_HEADER_ERROR){
00216               str = "Malformed header, possibly due to input not in MIME format";
00217            }
00218 
00219            if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){
00220               str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line";
00221            }
00222 
00223            if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){
00224               str = "Got the wrong boundary for the opening of a MULTIPART part.";
00225            }
00226 
00227            if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){
00228               str = "Got a multipart header that did not specify a boundary";
00229            }
00230 
00231            if(parts[i].header.error==SSPM_NO_HEADER_ERROR){
00232               str = "Did not get a header for the part. Is there a blank\
00233 line between the header and the previous boundary\?";
00234 
00235            }
00236 
00237            if(parts[i].header.error_text != 0){
00238               snprintf(temp,sizeof(temp),
00239                       "%s: %s",str,parts[i].header.error_text);
00240            } else {
00241               strcpy(temp,str);
00242            }
00243 
00244            icalcomponent_add_property
00245               (comp,
00246                icalproperty_vanew_xlicerror(
00247                    temp,
00248                    icalparameter_new_xlicerrortype(
00249                       ICAL_XLICERRORTYPE_MIMEPARSEERROR),
00250                    0));  
00251        }
00252 
00253        if(parts[i].header.major != SSPM_NO_MAJOR_TYPE &&
00254           parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){
00255 
00256            icalcomponent_add_property(comp,
00257               icalproperty_new_xlicmimecontenttype((char*)
00258                             icalmemory_strdup(mimetype)));
00259 
00260        }
00261 
00262        if (parts[i].header.encoding != SSPM_NO_ENCODING){
00263 
00264            icalcomponent_add_property(comp,
00265               icalproperty_new_xlicmimeencoding(
00266                  sspm_encoding_string(parts[i].header.encoding)));
00267        }
00268 
00269        if (parts[i].header.filename != 0){
00270            icalcomponent_add_property(comp,
00271               icalproperty_new_xlicmimefilename(parts[i].header.filename));
00272        }
00273 
00274        if (parts[i].header.content_id != 0){
00275            icalcomponent_add_property(comp,
00276               icalproperty_new_xlicmimecid(parts[i].header.content_id));
00277        }
00278 
00279        if (parts[i].header.charset != 0){
00280            icalcomponent_add_property(comp,
00281               icalproperty_new_xlicmimecharset(parts[i].header.charset));
00282        }
00283 
00284        /* Add iCal components as children of the component */
00285        if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
00286           parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE &&
00287           parts[i].data != 0){
00288 
00289            icalcomponent_add_component(comp,
00290                                    (icalcomponent*)parts[i].data);
00291            parts[i].data = 0;
00292 
00293        } else        if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
00294           parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE &&
00295           parts[i].data != 0){
00296 
00297            /* Add other text components as "DESCRIPTION" properties */
00298 
00299            icalcomponent_add_property(comp,
00300                icalproperty_new_description(
00301                  (char*)icalmemory_strdup((char*)parts[i].data)));
00302 
00303            parts[i].data = 0;
00304        }
00305        
00306 
00307        if(root!= 0 && parts[i].level == 0){
00308            /* We've already assigned the root, but there is another
00309                part at the root level. This is probably a parse
00310                error*/
00311            icalcomponent_free(comp);
00312            continue;
00313        }
00314 
00315        if(parts[i].level == last_level && last_level != 0){
00316            icalerror_assert(parent!=0,"No parent for adding component");
00317 
00318            icalcomponent_add_component(parent,comp);
00319 
00320        } else if (parts[i].level == last_level && last_level == 0 &&
00321            root == 0) {
00322 
00323            root = comp;
00324            parent = comp;
00325 
00326        } else if (parts[i].level > last_level){      
00327 
00328            parent = last;
00329            icalcomponent_add_component(parent,comp);
00330 
00331            last_level = parts[i].level;
00332 
00333        } else if (parts[i].level < last_level){
00334 
00335            parent = icalcomponent_get_parent(parent);
00336            icalcomponent_add_component(parent,comp);
00337 
00338            last_level = parts[i].level;
00339        } else { 
00340            assert(0);
00341        }
00342 
00343        last = comp;
00344        last_level = parts[i].level;
00345        assert(parts[i].data == 0);
00346     }
00347 
00348     sspm_free_parts(parts,NUM_PARTS);
00349     free(parts);
00350 
00351     return root;
00352 }
00353 
00354 
00355 
00356 int icalmime_test(char* (*get_string)(char *s, size_t size, void *d),
00357                 void *data)
00358 {
00359     char *out;
00360     struct sspm_part *parts;
00361     int i;
00362 
00363     if ( (parts = (struct sspm_part *)
00364          malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
00365        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
00366        return 0;
00367     }
00368 
00369     memset(parts,0,sizeof(parts));
00370 
00371     sspm_parse_mime(parts, 
00372                   NUM_PARTS, /* Max parts */
00373                   icalmime_local_action_map, /* Actions */ 
00374                   get_string,
00375                   data, /* data for get_string*/
00376                   0 /* First header */);
00377 
00378    for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; 
00379        i++){
00380        if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){
00381           parts[i].data = icalmemory_strdup(
00382               icalcomponent_as_ical_string((icalcomponent*)parts[i].data));
00383        }
00384    }
00385 
00386     sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org");
00387 
00388     printf("%s\n",out);
00389 
00390     return 0;
00391 
00392 }
00393 
00394