Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

mime.c File Reference

#include <string.h>
#include <limits.h>
#include <ctype.h>
#include "gwlib/gwlib.h"
#include "gwlib/mime.h"

Include dependency graph for mime.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  MIMEEntity

Functions

MIMEEntitymime_entity_create (void)
void mime_entity_destroy_item (void *e)
void mime_entity_destroy (MIMEEntity *e)
int read_mime_headers (ParseContext *context, List *headers)
void fix_boundary_element (List *headers, Octstr **boundary_elem)
Octstrmime_entity_to_octstr (MIMEEntity *m)
Octstrget_start_param (Octstr *content_type)
int cid_matches (List *headers, Octstr *start)
MIMEEntitymime_something_to_entity (Octstr *mime, List *headers)
MIMEEntitymime_octstr_to_entity (Octstr *mime)
MIMEEntitymime_http_to_entity (List *headers, Octstr *body)
Listmime_entity_headers (MIMEEntity *m)
Octstrmime_entity_body (MIMEEntity *m)
MIMEEntitymime_entity_duplicate (MIMEEntity *e)
void mime_replace_headers (MIMEEntity *e, List *headers)
int mime_entity_num_parts (MIMEEntity *e)
void mime_entity_add_part (MIMEEntity *e, MIMEEntity *part)
MIMEEntitymime_entity_get_part (MIMEEntity *e, int i)
void mime_entity_remove_part (MIMEEntity *e, int i)
void mime_entity_replace_part (MIMEEntity *e, int i, MIMEEntity *newpart)
void mime_entity_set_body (MIMEEntity *e, Octstr *body)
MIMEEntitymime_multipart_start_elem (MIMEEntity *e)
void mime_entity_dump_real (MIMEEntity *m, unsigned int level)
void mime_entity_dump (MIMEEntity *m)


Function Documentation

int cid_matches List headers,
Octstr start
[static]
 

Definition at line 300 of file mime.c.

References http_header_value(), octstr_compare(), octstr_destroy(), octstr_get_cstr, octstr_imm(), octstr_len(), and octstr_str_ncompare().

Referenced by mime_multipart_start_elem(), and mime_something_to_entity().

00301 {
00302      Octstr *cid = http_header_value(headers, octstr_imm("Content-ID"));
00303      char *cid_str;
00304      int cid_len;
00305      int ret;
00306 
00307      if (cid == NULL) 
00308          return 0;
00309      
00310      /* First, strip the <> if any. XXX some mime coders produce such messiness! */
00311      cid_str = octstr_get_cstr(cid);
00312      cid_len = octstr_len(cid);
00313      if (cid_str[0] == '<') {
00314          cid_str+=1;
00315      cid_len-=2;
00316      }
00317      if (start != NULL && cid != NULL  && 
00318      (octstr_compare(start, cid) == 0 || octstr_str_ncompare(start, cid_str, cid_len) == 0)) 
00319       ret = 1;
00320      else 
00321       ret = 0;
00322 
00323      octstr_destroy(cid);
00324      return ret;
00325 }

Here is the call graph for this function:

void fix_boundary_element List headers,
Octstr **  boundary_elem
[static]
 

Definition at line 163 of file mime.c.

References http_get_header_parameter(), http_header_add(), http_header_remove_all(), http_header_value(), octstr_create, octstr_delete(), octstr_destroy(), octstr_format(), octstr_format_append(), octstr_get_char(), octstr_get_cstr, octstr_imm(), and octstr_len().

Referenced by mime_entity_headers(), and mime_entity_to_octstr().

00164 {
00165     Octstr *value, *boundary;
00166     long len;
00167     
00168      /* 
00169       * Check if we have an boundary parameter already in the 
00170       * Content-Type header. If no, add one, otherwise parse which one 
00171       * we should use.
00172       * XXX this can be abstracted as function in gwlib/http.[ch].
00173       */
00174      value = http_header_value(headers, octstr_imm("Content-Type"));
00175      boundary = value ? http_get_header_parameter(value, octstr_imm("boundary")) : NULL;
00176 
00177      if (value == NULL) {
00178         /* we got here because it is multi-part, so... */
00179         value = octstr_create("multipart/mixed");
00180         http_header_add(headers, "Content-Type", "multipart/mixed");
00181      }
00182      if (boundary == NULL) {
00183         Octstr *v;
00184         boundary = octstr_format("_boundary_%d_%ld_%c_%c_bd%d", 
00185                                  random(), (long) time(NULL), 'A' + (random() % 26), 
00186                                  'a' + (random() % 26), random());
00187            
00188         octstr_format_append(value, "; boundary=%S", boundary);
00189       
00190         http_header_remove_all(headers, "Content-Type");
00191         http_header_add(headers, "Content-Type", octstr_get_cstr(value));
00192         if ((v = http_header_value(headers, octstr_imm("MIME-Version"))) == NULL)
00193             http_header_add(headers, "MIME-Version", "1.0");
00194         else
00195             octstr_destroy(v);
00196     } 
00197     else if ((len = octstr_len(boundary)) > 0 &&
00198              octstr_get_char(boundary, 0) == '"' && 
00199              octstr_get_char(boundary, len - 1) == '"') {
00200         octstr_delete(boundary, 0, 1);
00201         octstr_delete(boundary, len - 2, 1);      
00202     }
00203 
00204     octstr_destroy(value);
00205     if (boundary_elem)
00206         *boundary_elem = boundary;
00207     else
00208         octstr_destroy(boundary);
00209 }

Here is the call graph for this function:

Octstr* get_start_param Octstr content_type  )  [static]
 

Definition at line 282 of file mime.c.

References http_get_header_parameter(), octstr_delete(), octstr_get_char(), octstr_imm(), and octstr_len().

Referenced by mime_multipart_start_elem(), and mime_something_to_entity().

00283 {
00284      Octstr *start;
00285      int len;
00286 
00287      if (!content_type)
00288       return NULL;
00289 
00290      start = http_get_header_parameter(content_type, octstr_imm("start"));
00291      if (start && (len = octstr_len(start)) > 0 &&
00292      octstr_get_char(start, 0) == '"' && octstr_get_char(start, len-1) == '"') {
00293       octstr_delete(start, 0, 1);
00294       octstr_delete(start, len-2, 1);
00295      }
00296      
00297      return start;  
00298 }

Here is the call graph for this function:

void mime_entity_add_part MIMEEntity e,
MIMEEntity part
 

Definition at line 560 of file mime.c.

References gw_assert, gwlist_append(), mime_entity_duplicate(), and MIMEEntity::multiparts.

00561 {
00562      gw_assert(e != NULL);
00563      gw_assert(part != NULL);
00564      
00565      gwlist_append(e->multiparts, mime_entity_duplicate(part));
00566 }

Here is the call graph for this function:

Octstr* mime_entity_body MIMEEntity m  ) 
 

Definition at line 485 of file mime.c.

References MIMEEntity::body, debug(), gw_assert, MIMEEntity::headers, m, mime_entity_create(), mime_entity_destroy(), mime_entity_num_parts(), mime_entity_to_octstr(), octstr_destroy(), octstr_dump, octstr_duplicate, parse_context_create(), parse_context_destroy(), parse_get_rest(), ParseContext, and read_mime_headers().

00486 {
00487     Octstr *os, *body;
00488     ParseContext *context;
00489     MIMEEntity *e;
00490 
00491     gw_assert(m != NULL && m->headers != NULL);
00492 
00493     /* For non-multipart, return body directly. */
00494     if (mime_entity_num_parts(m) == 0)
00495      return octstr_duplicate(m->body);
00496 
00497     os = mime_entity_to_octstr(m);
00498     context = parse_context_create(os);
00499     e = mime_entity_create();
00500 
00501     /* parse the headers up to the body */
00502     if ((read_mime_headers(context, e->headers) != 0) || e->headers == NULL) {
00503         debug("mime.parse",0,"Failed to read MIME headers in Octstr block:");
00504         octstr_dump(os, 0);
00505         mime_entity_destroy(e);
00506         parse_context_destroy(context);
00507         return NULL;
00508     }
00509 
00510     /* the rest is the body */
00511     body = parse_get_rest(context);
00512 
00513     octstr_destroy(os);
00514     mime_entity_destroy(e);
00515     parse_context_destroy(context);
00516 
00517     return body;
00518 }

Here is the call graph for this function:

MIMEEntity* mime_entity_create void   ) 
 

Definition at line 87 of file mime.c.

References MIMEEntity::body, gwlist_create, MIMEEntity::headers, http_create_empty_headers(), MIMEEntity::multiparts, and MIMEEntity::start.

Referenced by mime_entity_body(), mime_entity_duplicate(), and mime_something_to_entity().

00088 {
00089     MIMEEntity *e;
00090 
00091     e = gw_malloc(sizeof(MIMEEntity));
00092     e->headers = http_create_empty_headers();
00093     e->multiparts = gwlist_create();
00094     e->body = NULL;
00095     e->start = NULL;
00096 
00097     return e;
00098 }

Here is the call graph for this function:

void mime_entity_destroy MIMEEntity e  ) 
 

Definition at line 105 of file mime.c.

References MIMEEntity::body, gw_assert, gwlist_destroy(), MIMEEntity::headers, mime_entity_destroy_item(), MIMEEntity::multiparts, octstr_destroy(), octstr_destroy_item(), and MIMEEntity::start.

Referenced by main(), mime_entity_body(), mime_entity_destroy_item(), mime_entity_remove_part(), mime_entity_replace_part(), and mime_something_to_entity().

00106 {
00107     gw_assert(e != NULL);
00108 
00109     if (e->headers != NULL)
00110         gwlist_destroy(e->headers, octstr_destroy_item);
00111     if (e->multiparts != NULL)
00112         gwlist_destroy(e->multiparts, mime_entity_destroy_item);
00113     octstr_destroy(e->body);
00114     e->start = NULL; /* will be destroyed on it's own via gwlist_destroy */
00115   
00116     gw_free(e);
00117 }    

Here is the call graph for this function:

void mime_entity_destroy_item void *  e  )  [static]
 

Definition at line 100 of file mime.c.

References mime_entity_destroy().

Referenced by mime_entity_destroy().

00101 {
00102     mime_entity_destroy(e);
00103 }

Here is the call graph for this function:

void mime_entity_dump MIMEEntity m  ) 
 

Definition at line 717 of file mime.c.

References debug(), gw_assert, MIMEEntity::headers, m, and mime_entity_dump_real().

Referenced by main().

00718 {
00719     gw_assert(m != NULL && m->headers != NULL);
00720 
00721     debug("mms",0,"Dumping MIMEEntity at address %p", m);
00722     mime_entity_dump_real(m, 0);
00723 }

Here is the call graph for this function:

void mime_entity_dump_real MIMEEntity m,
unsigned int  level
[static]
 

Definition at line 679 of file mime.c.

References MIMEEntity::body, charset, debug(), gw_assert, gwlist_get(), gwlist_len(), MIMEEntity::headers, http_header_get_content_type(), http_header_value(), m, MIMEEntity::multiparts, octstr_append_cstr(), octstr_create, octstr_destroy(), octstr_get_cstr, octstr_imm(), octstr_len(), MIMEEntity::start, and type.

Referenced by mime_entity_dump().

00680 {
00681     long i, items;
00682     Octstr *prefix, *type, *charset;
00683     unsigned int j;
00684 
00685     gw_assert(m != NULL && m->headers != NULL);
00686 
00687     prefix = octstr_create("");
00688     for (j = 0; j < level * 2; j++)
00689         octstr_append_cstr(prefix, " ");
00690 
00691     http_header_get_content_type(m->headers, &type, &charset);
00692     debug("mime.dump",0,"%sContent-Type `%s'", octstr_get_cstr(prefix),
00693           octstr_get_cstr(type));
00694     if (m->start != NULL) {
00695         Octstr *cid = http_header_value(m->start->headers, octstr_imm("Content-ID"));
00696         debug("mime.dump",0,"%sRelated to Content-ID <%s> MIMEEntity at address `%p'", 
00697               octstr_get_cstr(prefix), octstr_get_cstr(cid), m->start);
00698         octstr_destroy(cid);
00699     }
00700     items = gwlist_len(m->multiparts);
00701     debug("mime.dump",0,"%sBody contains %ld MIME entities, size %ld", octstr_get_cstr(prefix),
00702           items, (items == 0 && m->body) ? octstr_len(m->body) : -1);
00703 
00704     octstr_destroy(prefix);
00705     octstr_destroy(type);
00706     octstr_destroy(charset);
00707 
00708     for (i = 0; i < items; i++) {
00709         MIMEEntity *e = gwlist_get(m->multiparts, i);
00710 
00711         mime_entity_dump_real(e, level + 1);
00712     }
00713 
00714 }

Here is the call graph for this function:

MIMEEntity* mime_entity_duplicate MIMEEntity e  ) 
 

Definition at line 521 of file mime.c.

References MIMEEntity::body, gwlist_append(), gwlist_get(), gwlist_len(), MIMEEntity::headers, mime_entity_create(), mime_entity_duplicate(), mime_replace_headers(), MIMEEntity::multiparts, and octstr_duplicate.

Referenced by mime_entity_add_part(), mime_entity_duplicate(), mime_entity_get_part(), mime_entity_replace_part(), and mime_multipart_start_elem().

00522 {
00523      MIMEEntity *copy = mime_entity_create();
00524      int i, n;
00525      
00526      mime_replace_headers(copy, e->headers);
00527      copy->body = e->body ? octstr_duplicate(e->body) : NULL;
00528      
00529      for (i = 0, n = gwlist_len(e->multiparts); i < n; i++)
00530       gwlist_append(copy->multiparts, 
00531             mime_entity_duplicate(gwlist_get(e->multiparts, i)));
00532      return copy;
00533 }

Here is the call graph for this function:

MIMEEntity* mime_entity_get_part MIMEEntity e,
int  i
 

Definition at line 570 of file mime.c.

References gw_assert, gwlist_get(), m, mime_entity_duplicate(), and MIMEEntity::multiparts.

00571 {
00572      MIMEEntity *m;
00573      gw_assert(e != NULL);
00574      gw_assert(i >= 0);
00575      gw_assert(i < gwlist_len(e->multiparts));
00576 
00577      m = gwlist_get(e->multiparts, i);
00578      gw_assert(m);
00579      return mime_entity_duplicate(m);
00580 }

Here is the call graph for this function:

List* mime_entity_headers MIMEEntity m  ) 
 

Definition at line 469 of file mime.c.

References fix_boundary_element(), gw_assert, MIMEEntity::headers, http_header_duplicate(), m, and mime_entity_num_parts().

00470 {
00471     List *headers;
00472 
00473     gw_assert(m != NULL && m->headers != NULL);
00474 
00475     /* Need a fixup before hand over. */
00476     if (mime_entity_num_parts(m) > 0)
00477        fix_boundary_element(m->headers, NULL);
00478 
00479     headers = http_header_duplicate(m->headers);
00480 
00481     return headers;
00482 }

Here is the call graph for this function:

int mime_entity_num_parts MIMEEntity e  ) 
 

Definition at line 550 of file mime.c.

References gw_assert, gwlist_len(), and MIMEEntity::multiparts.

Referenced by mime_entity_body(), and mime_entity_headers().

00551 {
00552      gw_assert(e != NULL);
00553      return e->multiparts ? gwlist_len(e->multiparts) : 0;
00554 }

Here is the call graph for this function:

void mime_entity_remove_part MIMEEntity e,
int  i
 

Definition at line 584 of file mime.c.

References gw_assert, gwlist_delete(), gwlist_get(), m, mime_entity_destroy(), MIMEEntity::multiparts, and MIMEEntity::start.

00585 {
00586      MIMEEntity *m;
00587 
00588      gw_assert(e != NULL);
00589      gw_assert(i >= 0);
00590      gw_assert(i < gwlist_len(e->multiparts));
00591      
00592      
00593      m = gwlist_get(e->multiparts, i);
00594      gwlist_delete(e->multiparts, i, 1);
00595      if (m == e->start) e->start = NULL;
00596 
00597      mime_entity_destroy(m);
00598 }

Here is the call graph for this function:

void mime_entity_replace_part MIMEEntity e,
int  i,
MIMEEntity newpart
 

Definition at line 601 of file mime.c.

References gw_assert, gwlist_delete(), gwlist_get(), gwlist_insert(), m, mime_entity_destroy(), mime_entity_duplicate(), MIMEEntity::multiparts, and MIMEEntity::start.

00602 {
00603 
00604      MIMEEntity *m;
00605      
00606      gw_assert(e != NULL);
00607      gw_assert(i >= 0);
00608      gw_assert(i < gwlist_len(e->multiparts));
00609      
00610      m = gwlist_get(e->multiparts, i);
00611      gwlist_delete(e->multiparts, i, 1);
00612      gwlist_insert(e->multiparts, i, mime_entity_duplicate(newpart));
00613      if (m == e->start) e->start = NULL;
00614 
00615      mime_entity_destroy(m);
00616 }

Here is the call graph for this function:

void mime_entity_set_body MIMEEntity e,
Octstr body
 

Definition at line 622 of file mime.c.

References MIMEEntity::body, gw_assert, octstr_destroy(), and octstr_duplicate.

00623 {
00624      gw_assert(e != NULL);
00625      gw_assert(body != NULL);
00626 
00627      if (e->body)
00628       octstr_destroy(e->body);
00629      e->body = octstr_duplicate(body);
00630 }

Here is the call graph for this function:

Octstr* mime_entity_to_octstr MIMEEntity m  ) 
 

Definition at line 216 of file mime.c.

References MIMEEntity::body, fix_boundary_element(), gw_assert, gwlist_get(), gwlist_len(), MIMEEntity::headers, http_destroy_headers(), http_header_duplicate(), m, MIMEEntity::multiparts, octstr_append(), octstr_create, octstr_destroy(), and octstr_imm().

Referenced by main(), and mime_entity_body().

00217 {
00218     Octstr *mime, *boundary = NULL;
00219     List *headers;
00220     long i;
00221 
00222     gw_assert(m != NULL && m->headers != NULL);
00223 
00224     mime = octstr_create("");
00225 
00226     /* 
00227      * First of all check if we have further MIME entity dependencies,
00228      * which means we have further MIMEEntities in our m->multiparts
00229      * list. If no, then add headers and body and return. This is the
00230      * easy case. Otherwise we have to loop inside our entities.
00231      */
00232     if (gwlist_len(m->multiparts) == 0) {
00233         for (i = 0; i < gwlist_len(m->headers); i++) {
00234             octstr_append(mime, gwlist_get(m->headers, i));
00235             octstr_append(mime, octstr_imm("\r\n"));
00236         }
00237         octstr_append(mime, octstr_imm("\r\n"));
00238         if (m->body != NULL)
00239             octstr_append(mime, m->body);
00240         goto finished;
00241     }
00242 
00243     /* This call ensures boundary exists, and returns it */
00244     fix_boundary_element(m->headers, &boundary);
00245     headers = http_header_duplicate(m->headers);
00246 
00247     /* headers */
00248     for (i = 0; i < gwlist_len(headers); i++) {
00249         octstr_append(mime, gwlist_get(headers, i));
00250         octstr_append(mime, octstr_imm("\r\n"));
00251     }
00252     http_destroy_headers(headers);
00253     octstr_append(mime, octstr_imm("\r\n")); /* Mark end of headers. */
00254 
00255     /* loop through all MIME multipart entities of this entity */
00256     for (i = 0; i < gwlist_len(m->multiparts); i++) {
00257         MIMEEntity *e = gwlist_get(m->multiparts, i);
00258         Octstr *body;
00259 
00260         octstr_append(mime, octstr_imm("\r\n--"));
00261         octstr_append(mime, boundary);
00262         octstr_append(mime, octstr_imm("\r\n"));
00263 
00264         /* call ourself to produce the MIME entity body */
00265         body = mime_entity_to_octstr(e);
00266         octstr_append(mime, body);
00267 
00268         octstr_destroy(body);
00269     }
00270 
00271     octstr_append(mime, octstr_imm("\r\n--"));
00272     octstr_append(mime, boundary);
00273     octstr_append(mime, octstr_imm("--\r\n"));
00274 
00275     octstr_destroy(boundary);
00276 
00277 finished:
00278 
00279     return mime;
00280 }

Here is the call graph for this function:

MIMEEntity* mime_http_to_entity List headers,
Octstr body
 

Definition at line 461 of file mime.c.

References gw_assert, and mime_something_to_entity().

00462 {
00463     gw_assert(headers != NULL && body != NULL);
00464 
00465     return mime_something_to_entity(body, headers);
00466 }

Here is the call graph for this function:

MIMEEntity* mime_multipart_start_elem MIMEEntity e  ) 
 

Definition at line 633 of file mime.c.

References cid_matches(), get_start_param(), gw_assert, gwlist_get(), gwlist_len(), MIMEEntity::headers, http_header_value(), mime_entity_duplicate(), MIMEEntity::multiparts, octstr_destroy(), octstr_imm(), and MIMEEntity::start.

00634 {
00635      gw_assert(e != NULL);
00636      
00637     /* If e->start element is not yet set, set it as follows:
00638      * - if content type is not set, then set it to NULL
00639      * - if the start element is not set but this is a multipart object, set
00640      *   it to first multipart element, else set it to null
00641      * - if the start element of the content type is set, find a matching object
00642      *    and set e->start accordingly.
00643      * Finally, return a copy of it.
00644      */
00645      if (!e->start) {
00646       Octstr *ctype = http_header_value(e->headers, octstr_imm("Content-Type"));
00647       Octstr *start = get_start_param(ctype);
00648       int i;
00649       
00650       if (!ctype)
00651            e->start = NULL;
00652       else if (!start) {
00653            if (gwlist_len(e->multiparts) > 0) 
00654             e->start = gwlist_get(e->multiparts, 0); 
00655            else 
00656             e->start = NULL;
00657       } else 
00658            for (i = 0; i < gwlist_len(e->multiparts); i++) {
00659             MIMEEntity *x = gwlist_get(e->multiparts, i);
00660             if (cid_matches(x->headers, start)) {
00661              e->start = x;
00662              break;
00663             }
00664            }
00665       
00666       if (ctype)
00667            octstr_destroy(ctype);
00668       if (start)
00669            octstr_destroy(start);
00670      }
00671      
00672      return (e->start) ? mime_entity_duplicate(e->start) : NULL;
00673 }

Here is the call graph for this function:

MIMEEntity* mime_octstr_to_entity Octstr mime  ) 
 

Definition at line 453 of file mime.c.

References gw_assert, and mime_something_to_entity().

Referenced by main(), and mime_something_to_entity().

00454 {
00455     gw_assert(mime != NULL);
00456 
00457     return mime_something_to_entity(mime, NULL);
00458 }

Here is the call graph for this function:

void mime_replace_headers MIMEEntity e,
List headers
 

Definition at line 536 of file mime.c.

References gw_assert, MIMEEntity::headers, http_destroy_headers(), http_header_duplicate(), and MIMEEntity::start.

Referenced by mime_entity_duplicate().

00537 {
00538      gw_assert(e != NULL);
00539      gw_assert(headers != NULL);
00540 
00541      http_destroy_headers(e->headers);
00542      e->headers = http_header_duplicate(headers);
00543      e->start = NULL; /* clear it, since header change means it could have changed.*/
00544 }

Here is the call graph for this function:

MIMEEntity* mime_something_to_entity Octstr mime,
List headers
[static]
 

Definition at line 332 of file mime.c.

References MIMEEntity::body, cid_matches(), debug(), get_start_param(), gw_assert, gwlist_append(), MIMEEntity::headers, http_destroy_headers(), http_get_header_parameter(), http_header_duplicate(), http_header_value(), m, mime_entity_create(), mime_entity_destroy(), mime_octstr_to_entity(), MIMEEntity::multiparts, octstr_append(), octstr_append_cstr(), octstr_compare(), octstr_create, octstr_delete(), octstr_destroy(), octstr_dump, octstr_get_char(), octstr_get_cstr, octstr_imm(), octstr_len(), parse_context_create(), parse_context_destroy(), parse_get_line(), parse_get_rest(), parse_get_seperated_block(), ParseContext, read_mime_headers(), and MIMEEntity::start.

Referenced by mime_http_to_entity(), and mime_octstr_to_entity().

00333 {
00334     MIMEEntity *e;
00335     ParseContext *context;
00336     Octstr *value, *boundary, *start;
00337     int len = 0;
00338 
00339     gw_assert(mime != NULL);
00340 
00341     value = boundary = start = NULL;
00342     context = parse_context_create(mime);
00343     e = mime_entity_create();
00344     
00345     /* parse the headers up to the body. If we have headers already passed 
00346      * from our caller, then duplicate them and continue */
00347     if (headers != NULL) {
00348         /* we have some headers to duplicate, first ensure we destroy
00349          * the list from the previous creation inside mime_entity_create() */
00350         http_destroy_headers(e->headers);
00351         e->headers = http_header_duplicate(headers);
00352     } else {
00353         /* parse the headers out of the mime block */
00354         if ((read_mime_headers(context, e->headers) != 0) || e->headers == NULL) {
00355             debug("mime.parse",0,"Failed to read MIME headers in Octstr block:");
00356             octstr_dump(mime, 0);
00357             mime_entity_destroy(e);
00358             parse_context_destroy(context);
00359             return NULL;
00360         }
00361     }
00362 
00363     /* 
00364      * Now check if the body is a multipart. This is indicated by an 'boundary'
00365      * parameter in the 'Content-Type' value. If yes, call ourself for the 
00366      * multipart entities after parsing them.
00367      */
00368     value = http_header_value(e->headers, octstr_imm("Content-Type"));
00369     boundary = http_get_header_parameter(value, octstr_imm("boundary"));
00370     start = get_start_param(value);
00371 
00372     /* Beware that we need *unquoted* strings to compare against in the
00373      * following parsing sections. */
00374     if (boundary && (len = octstr_len(boundary)) > 0 &&
00375         octstr_get_char(boundary, 0) == '"' && octstr_get_char(boundary, len-1) == '"') {
00376         octstr_delete(boundary, 0, 1);
00377         octstr_delete(boundary, len-2, 1);
00378 
00379     }
00380 
00381     if (boundary != NULL) {
00382         /* we have a multipart block as body, parse the boundary blocks */
00383         Octstr *entity, *seperator, *os;
00384         
00385         /* loop by all boundary blocks we have in the body */
00386         seperator = octstr_create("--");
00387         octstr_append(seperator, boundary);
00388         while ((entity = parse_get_seperated_block(context, seperator)) != NULL) {
00389             MIMEEntity *m;
00390             int del2 = 0;
00391         
00392             /* we have still linefeeds at the beginning and end that we 
00393              * need to remove, these are from the separator. 
00394              * We check if it is LF only or CRLF! */
00395             del2 = (octstr_get_char(entity, 0) == '\r');
00396             if (del2) 
00397                 octstr_delete(entity, 0, 2);          
00398             else
00399                 octstr_delete(entity, 0, 1);
00400 
00401             /* we assume the same mechanism applies to beginning and end -- 
00402              * seems reasonable! */
00403             if (del2)
00404                 octstr_delete(entity, octstr_len(entity) - 2, 2);
00405             else
00406                 octstr_delete(entity, octstr_len(entity) - 1, 1);
00407 
00408             debug("mime.parse",0,"MIME multipart: Parsing entity:");
00409             octstr_dump(entity, 0);
00410 
00411             /* call ourself for this MIME entity and inject to list */
00412             if ((m = mime_octstr_to_entity(entity))) {
00413                 gwlist_append(e->multiparts, m);
00414          
00415                 /* check if this entity is our start entity (in terms of related)
00416                  * and set our start pointer to it */
00417                 if (cid_matches(m->headers, start)) {
00418                     /* set only if none has been set before */
00419                     e->start = (e->start == NULL) ? m : e->start;
00420                 }
00421             }
00422 
00423             octstr_destroy(entity);
00424         }
00425         /* ok, we parsed all blocks, we expect to see now the end boundary */
00426         octstr_append_cstr(seperator, "--");
00427         os = parse_get_line(context);
00428         if (os != NULL && octstr_compare(os, seperator) != 0) {
00429             debug("mime.parse",0,"Failed to see end boundary, parsed line is '%s'.",
00430                   octstr_get_cstr(os));
00431         }
00432 
00433         octstr_destroy(seperator);
00434         octstr_destroy(os);
00435     }
00436     else {
00437 
00438         /* we don't have boundaries, so this is no multipart block, 
00439          * pass the body to the MIME entity. */
00440         e->body = parse_get_rest(context);
00441 
00442     }
00443 
00444     parse_context_destroy(context);
00445     octstr_destroy(value);
00446     octstr_destroy(boundary);
00447     octstr_destroy(start);
00448 
00449     return e;
00450 }

Here is the call graph for this function:

int read_mime_headers ParseContext context,
List headers
[static]
 

Definition at line 129 of file mime.c.

References gwlist_append(), gwlist_get(), gwlist_len(), octstr_append(), octstr_destroy(), octstr_get_char(), octstr_len(), parse_get_line(), and ParseContext.

Referenced by mime_entity_body(), and mime_something_to_entity().

00130 {
00131     Octstr *line, *prev;
00132 
00133     if (gwlist_len(headers) == 0)
00134         prev = NULL;
00135     else
00136         prev = gwlist_get(headers, gwlist_len(headers) - 1);
00137 
00138     for (;;) {
00139         line = parse_get_line(context);
00140         if (line == NULL) {
00141             return -1;
00142         }
00143         if (octstr_len(line) == 0) {
00144             octstr_destroy(line);
00145             break;
00146         }
00147         if (isspace(octstr_get_char(line, 0)) && prev != NULL) {
00148             octstr_append(prev, line);
00149             octstr_destroy(line);
00150         } else {
00151             gwlist_append(headers, line);
00152             prev = line;
00153         }
00154     }
00155 
00156     return 0;
00157 }

Here is the call graph for this function:

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.