Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
mime.c File Reference
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include "gwlib/gwlib.h"
#include "gwlib/mime.h"

Go to the source code of this file.

Data Structures

struct  MIMEEntity
 

Functions

MIMEEntitymime_entity_create (void)
 
static void mime_entity_destroy_item (void *e)
 
void mime_entity_destroy (MIMEEntity *e)
 
static int read_mime_headers (ParseContext *context, List *headers)
 
static void fix_boundary_element (List *headers, Octstr **boundary_elem)
 
Octstrmime_entity_to_octstr (MIMEEntity *m)
 
static Octstrget_start_param (Octstr *content_type)
 
static int cid_matches (List *headers, Octstr *start)
 
static 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)
 
static void mime_entity_dump_real (MIMEEntity *m, unsigned int level)
 
void mime_entity_dump (MIMEEntity *m)
 

Function Documentation

static 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().

301 {
302  Octstr *cid = http_header_value(headers, octstr_imm("Content-ID"));
303  char *cid_str;
304  int cid_len;
305  int ret;
306 
307  if (cid == NULL)
308  return 0;
309 
310  /* First, strip the <> if any. XXX some mime coders produce such messiness! */
311  cid_str = octstr_get_cstr(cid);
312  cid_len = octstr_len(cid);
313  if (cid_str[0] == '<') {
314  cid_str+=1;
315  cid_len-=2;
316  }
317  if (start != NULL && cid != NULL &&
318  (octstr_compare(start, cid) == 0 || octstr_str_ncompare(start, cid_str, cid_len) == 0))
319  ret = 1;
320  else
321  ret = 0;
322 
323  octstr_destroy(cid);
324  return ret;
325 }
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Octstr * http_header_value(List *headers, Octstr *name)
Definition: http.c:2909
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
int octstr_str_ncompare(const Octstr *ostr, const char *str, long n)
Definition: octstr.c:997
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
static void fix_boundary_element ( List headers,
Octstr **  boundary_elem 
)
static

Definition at line 163 of file mime.c.

References boundary, 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().

164 {
165  Octstr *value, *boundary;
166  long len;
167 
168  /*
169  * Check if we have an boundary parameter already in the
170  * Content-Type header. If no, add one, otherwise parse which one
171  * we should use.
172  * XXX this can be abstracted as function in gwlib/http.[ch].
173  */
174  value = http_header_value(headers, octstr_imm("Content-Type"));
175  boundary = value ? http_get_header_parameter(value, octstr_imm("boundary")) : NULL;
176 
177  if (value == NULL) {
178  /* we got here because it is multi-part, so... */
179  value = octstr_create("multipart/mixed");
180  http_header_add(headers, "Content-Type", "multipart/mixed");
181  }
182  if (boundary == NULL) {
183  Octstr *v;
184  boundary = octstr_format("_boundary_%d_%ld_%c_%c_bd%d",
185  random(), (long) time(NULL), 'A' + (random() % 26),
186  'a' + (random() % 26), random());
187 
188  octstr_format_append(value, "; boundary=%S", boundary);
189 
190  http_header_remove_all(headers, "Content-Type");
191  http_header_add(headers, "Content-Type", octstr_get_cstr(value));
192  if ((v = http_header_value(headers, octstr_imm("MIME-Version"))) == NULL)
193  http_header_add(headers, "MIME-Version", "1.0");
194  else
195  octstr_destroy(v);
196  }
197  else if ((len = octstr_len(boundary)) > 0 &&
198  octstr_get_char(boundary, 0) == '"' &&
199  octstr_get_char(boundary, len - 1) == '"') {
200  octstr_delete(boundary, 0, 1);
201  octstr_delete(boundary, len - 2, 1);
202  }
203 
204  octstr_destroy(value);
205  if (boundary_elem)
206  *boundary_elem = boundary;
207  else
208  octstr_destroy(boundary);
209 }
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2863
static char * boundary
Definition: test_ppg.c:97
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
Octstr * http_get_header_parameter(Octstr *value, Octstr *parameter)
Definition: http.c:3508
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
Octstr * http_header_value(List *headers, Octstr *name)
Definition: http.c:2909
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
long http_header_remove_all(List *headers, char *name)
Definition: http.c:3112
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2505
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static 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(), octstr_len(), and start.

Referenced by mime_multipart_start_elem(), and mime_something_to_entity().

283 {
284  Octstr *start;
285  int len;
286 
287  if (!content_type)
288  return NULL;
289 
290  start = http_get_header_parameter(content_type, octstr_imm("start"));
291  if (start && (len = octstr_len(start)) > 0 &&
292  octstr_get_char(start, 0) == '"' && octstr_get_char(start, len-1) == '"') {
293  octstr_delete(start, 0, 1);
294  octstr_delete(start, len-2, 1);
295  }
296 
297  return start;
298 }
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
Octstr * http_get_header_parameter(Octstr *value, Octstr *parameter)
Definition: http.c:3508
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static int start
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.

561 {
562  gw_assert(e != NULL);
563  gw_assert(part != NULL);
564 
566 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
List * multiparts
Definition: mime.c:78
gw_assert(wtls_machine->packet_to_send!=NULL)
MIMEEntity * mime_entity_duplicate(MIMEEntity *e)
Definition: mime.c:521
Octstr* mime_entity_body ( MIMEEntity m)

Definition at line 485 of file mime.c.

References MIMEEntity::body, debug(), gw_assert(), MIMEEntity::headers, 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(), and read_mime_headers().

486 {
487  Octstr *os, *body;
489  MIMEEntity *e;
490 
491  gw_assert(m != NULL && m->headers != NULL);
492 
493  /* For non-multipart, return body directly. */
494  if (mime_entity_num_parts(m) == 0)
495  return octstr_duplicate(m->body);
496 
497  os = mime_entity_to_octstr(m);
498  context = parse_context_create(os);
499  e = mime_entity_create();
500 
501  /* parse the headers up to the body */
502  if ((read_mime_headers(context, e->headers) != 0) || e->headers == NULL) {
503  debug("mime.parse",0,"Failed to read MIME headers in Octstr block:");
504  octstr_dump(os, 0);
506  parse_context_destroy(context);
507  return NULL;
508  }
509 
510  /* the rest is the body */
511  body = parse_get_rest(context);
512 
513  octstr_destroy(os);
515  parse_context_destroy(context);
516 
517  return body;
518 }
Definition: parse.c:65
Octstr * body
Definition: mime.c:79
MIMEEntity * mime_entity_create(void)
Definition: mime.c:87
Octstr * mime_entity_to_octstr(MIMEEntity *m)
Definition: mime.c:216
void mime_entity_destroy(MIMEEntity *e)
Definition: mime.c:105
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
static int read_mime_headers(ParseContext *context, List *headers)
Definition: mime.c:129
void parse_context_destroy(ParseContext *context)
Definition: parse.c:88
Definition: octstr.c:118
List * headers
Definition: mime.c:77
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
Octstr * parse_get_rest(ParseContext *context)
Definition: parse.c:329
ParseContext * parse_context_create(Octstr *str)
Definition: parse.c:74
int mime_entity_num_parts(MIMEEntity *e)
Definition: mime.c:550
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().

88 {
89  MIMEEntity *e;
90 
91  e = gw_malloc(sizeof(MIMEEntity));
94  e->body = NULL;
95  e->start = NULL;
96 
97  return e;
98 }
Octstr * body
Definition: mime.c:79
List * multiparts
Definition: mime.c:78
List * http_create_empty_headers(void)
Definition: http.c:2849
struct MIMEEntity * start
Definition: mime.c:80
List * headers
Definition: mime.c:77
#define gwlist_create()
Definition: list.h:136
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().

106 {
107  gw_assert(e != NULL);
108 
109  if (e->headers != NULL)
111  if (e->multiparts != NULL)
113  octstr_destroy(e->body);
114  e->start = NULL; /* will be destroyed on it's own via gwlist_destroy */
115 
116  gw_free(e);
117 }
Octstr * body
Definition: mime.c:79
List * multiparts
Definition: mime.c:78
static void mime_entity_destroy_item(void *e)
Definition: mime.c:100
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
void octstr_destroy_item(void *os)
Definition: octstr.c:334
gw_assert(wtls_machine->packet_to_send!=NULL)
struct MIMEEntity * start
Definition: mime.c:80
List * headers
Definition: mime.c:77
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
static 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().

101 {
103 }
void mime_entity_destroy(MIMEEntity *e)
Definition: mime.c:105
void mime_entity_dump ( MIMEEntity m)

Definition at line 717 of file mime.c.

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

Referenced by main().

718 {
719  gw_assert(m != NULL && m->headers != NULL);
720 
721  debug("mms",0,"Dumping MIMEEntity at address %p", m);
722  mime_entity_dump_real(m, 0);
723 }
static void mime_entity_dump_real(MIMEEntity *m, unsigned int level)
Definition: mime.c:679
gw_assert(wtls_machine->packet_to_send!=NULL)
List * headers
Definition: mime.c:77
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
static 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(), 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().

680 {
681  long i, items;
682  Octstr *prefix, *type, *charset;
683  unsigned int j;
684 
685  gw_assert(m != NULL && m->headers != NULL);
686 
687  prefix = octstr_create("");
688  for (j = 0; j < level * 2; j++)
689  octstr_append_cstr(prefix, " ");
690 
691  http_header_get_content_type(m->headers, &type, &charset);
692  debug("mime.dump",0,"%sContent-Type `%s'", octstr_get_cstr(prefix),
693  octstr_get_cstr(type));
694  if (m->start != NULL) {
695  Octstr *cid = http_header_value(m->start->headers, octstr_imm("Content-ID"));
696  debug("mime.dump",0,"%sRelated to Content-ID <%s> MIMEEntity at address `%p'",
697  octstr_get_cstr(prefix), octstr_get_cstr(cid), m->start);
698  octstr_destroy(cid);
699  }
700  items = gwlist_len(m->multiparts);
701  debug("mime.dump",0,"%sBody contains %ld MIME entities, size %ld", octstr_get_cstr(prefix),
702  items, (items == 0 && m->body) ? octstr_len(m->body) : -1);
703 
704  octstr_destroy(prefix);
705  octstr_destroy(type);
706  octstr_destroy(charset);
707 
708  for (i = 0; i < items; i++) {
709  MIMEEntity *e = gwlist_get(m->multiparts, i);
710 
711  mime_entity_dump_real(e, level + 1);
712  }
713 
714 }
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
Octstr * body
Definition: mime.c:79
int type
Definition: smsc_cimd2.c:215
List * multiparts
Definition: mime.c:78
void http_header_get_content_type(List *headers, Octstr **type, Octstr **charset)
Definition: http.c:3202
static void mime_entity_dump_real(MIMEEntity *m, unsigned int level)
Definition: mime.c:679
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1509
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * charset
Definition: test_ota.c:68
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
gw_assert(wtls_machine->packet_to_send!=NULL)
Octstr * http_header_value(List *headers, Octstr *name)
Definition: http.c:2909
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
struct MIMEEntity * start
Definition: mime.c:80
List * headers
Definition: mime.c:77
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
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().

522 {
523  MIMEEntity *copy = mime_entity_create();
524  int i, n;
525 
526  mime_replace_headers(copy, e->headers);
527  copy->body = e->body ? octstr_duplicate(e->body) : NULL;
528 
529  for (i = 0, n = gwlist_len(e->multiparts); i < n; i++)
530  gwlist_append(copy->multiparts,
532  return copy;
533 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
Octstr * body
Definition: mime.c:79
List * multiparts
Definition: mime.c:78
MIMEEntity * mime_entity_create(void)
Definition: mime.c:87
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void mime_replace_headers(MIMEEntity *e, List *headers)
Definition: mime.c:536
List * headers
Definition: mime.c:77
MIMEEntity * mime_entity_duplicate(MIMEEntity *e)
Definition: mime.c:521
MIMEEntity* mime_entity_get_part ( MIMEEntity e,
int  i 
)

Definition at line 570 of file mime.c.

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

571 {
572  MIMEEntity *m;
573  gw_assert(e != NULL);
574  gw_assert(i >= 0);
576 
577  m = gwlist_get(e->multiparts, i);
578  gw_assert(m);
579  return mime_entity_duplicate(m);
580 }
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
List * multiparts
Definition: mime.c:78
gw_assert(wtls_machine->packet_to_send!=NULL)
MIMEEntity * mime_entity_duplicate(MIMEEntity *e)
Definition: mime.c:521
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(), and mime_entity_num_parts().

470 {
471  List *headers;
472 
473  gw_assert(m != NULL && m->headers != NULL);
474 
475  /* Need a fixup before hand over. */
476  if (mime_entity_num_parts(m) > 0)
477  fix_boundary_element(m->headers, NULL);
478 
479  headers = http_header_duplicate(m->headers);
480 
481  return headers;
482 }
static void fix_boundary_element(List *headers, Octstr **boundary_elem)
Definition: mime.c:163
gw_assert(wtls_machine->packet_to_send!=NULL)
List * headers
Definition: mime.c:77
List * http_header_duplicate(List *headers)
Definition: http.c:2946
Definition: list.c:102
int mime_entity_num_parts(MIMEEntity *e)
Definition: mime.c:550
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().

551 {
552  gw_assert(e != NULL);
553  return e->multiparts ? gwlist_len(e->multiparts) : 0;
554 }
long gwlist_len(List *list)
Definition: list.c:166
List * multiparts
Definition: mime.c:78
gw_assert(wtls_machine->packet_to_send!=NULL)
void mime_entity_remove_part ( MIMEEntity e,
int  i 
)

Definition at line 584 of file mime.c.

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

585 {
586  MIMEEntity *m;
587 
588  gw_assert(e != NULL);
589  gw_assert(i >= 0);
591 
592 
593  m = gwlist_get(e->multiparts, i);
594  gwlist_delete(e->multiparts, i, 1);
595  if (m == e->start) e->start = NULL;
596 
598 }
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
List * multiparts
Definition: mime.c:78
void gwlist_delete(List *list, long pos, long count)
Definition: list.c:232
void mime_entity_destroy(MIMEEntity *e)
Definition: mime.c:105
gw_assert(wtls_machine->packet_to_send!=NULL)
struct MIMEEntity * start
Definition: mime.c:80
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(), gwlist_len(), mime_entity_destroy(), mime_entity_duplicate(), MIMEEntity::multiparts, and MIMEEntity::start.

602 {
603 
604  MIMEEntity *m;
605 
606  gw_assert(e != NULL);
607  gw_assert(i >= 0);
609 
610  m = gwlist_get(e->multiparts, i);
611  gwlist_delete(e->multiparts, i, 1);
613  if (m == e->start) e->start = NULL;
614 
616 }
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
List * multiparts
Definition: mime.c:78
void gwlist_delete(List *list, long pos, long count)
Definition: list.c:232
void mime_entity_destroy(MIMEEntity *e)
Definition: mime.c:105
gw_assert(wtls_machine->packet_to_send!=NULL)
void gwlist_insert(List *list, long pos, void *item)
Definition: list.c:214
struct MIMEEntity * start
Definition: mime.c:80
MIMEEntity * mime_entity_duplicate(MIMEEntity *e)
Definition: mime.c:521
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.

623 {
624  gw_assert(e != NULL);
625  gw_assert(body != NULL);
626 
627  if (e->body)
628  octstr_destroy(e->body);
629  e->body = octstr_duplicate(body);
630 }
Octstr * body
Definition: mime.c:79
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
Octstr* mime_entity_to_octstr ( MIMEEntity m)

Definition at line 216 of file mime.c.

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

Referenced by main(), mime_entity_body(), and mime_entity_to_octstr().

217 {
218  Octstr *mime, *boundary = NULL;
219  List *headers;
220  long i;
221 
222  gw_assert(m != NULL && m->headers != NULL);
223 
224  mime = octstr_create("");
225 
226  /*
227  * First of all check if we have further MIME entity dependencies,
228  * which means we have further MIMEEntities in our m->multiparts
229  * list. If no, then add headers and body and return. This is the
230  * easy case. Otherwise we have to loop inside our entities.
231  */
232  if (gwlist_len(m->multiparts) == 0) {
233  for (i = 0; i < gwlist_len(m->headers); i++) {
234  octstr_append(mime, gwlist_get(m->headers, i));
235  octstr_append(mime, octstr_imm("\r\n"));
236  }
237  octstr_append(mime, octstr_imm("\r\n"));
238  if (m->body != NULL)
239  octstr_append(mime, m->body);
240  goto finished;
241  }
242 
243  /* This call ensures boundary exists, and returns it */
244  fix_boundary_element(m->headers, &boundary);
245  headers = http_header_duplicate(m->headers);
246 
247  /* headers */
248  for (i = 0; i < gwlist_len(headers); i++) {
249  octstr_append(mime, gwlist_get(headers, i));
250  octstr_append(mime, octstr_imm("\r\n"));
251  }
252  http_destroy_headers(headers);
253  octstr_append(mime, octstr_imm("\r\n")); /* Mark end of headers. */
254 
255  /* loop through all MIME multipart entities of this entity */
256  for (i = 0; i < gwlist_len(m->multiparts); i++) {
257  MIMEEntity *e = gwlist_get(m->multiparts, i);
258  Octstr *body;
259 
260  octstr_append(mime, octstr_imm("\r\n--"));
261  octstr_append(mime, boundary);
262  octstr_append(mime, octstr_imm("\r\n"));
263 
264  /* call ourself to produce the MIME entity body */
265  body = mime_entity_to_octstr(e);
266  octstr_append(mime, body);
267 
268  octstr_destroy(body);
269  }
270 
271  octstr_append(mime, octstr_imm("\r\n--"));
272  octstr_append(mime, boundary);
273  octstr_append(mime, octstr_imm("--\r\n"));
274 
275  octstr_destroy(boundary);
276 
277 finished:
278 
279  return mime;
280 }
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
Octstr * body
Definition: mime.c:79
static char * boundary
Definition: test_ppg.c:97
List * multiparts
Definition: mime.c:78
static void fix_boundary_element(List *headers, Octstr **boundary_elem)
Definition: mime.c:163
void http_destroy_headers(List *headers)
Definition: http.c:2856
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Octstr * mime_entity_to_octstr(MIMEEntity *m)
Definition: mime.c:216
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
gw_assert(wtls_machine->packet_to_send!=NULL)
Definition: octstr.c:118
List * headers
Definition: mime.c:77
List * http_header_duplicate(List *headers)
Definition: http.c:2946
Definition: list.c:102
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().

462 {
463  gw_assert(headers != NULL && body != NULL);
464 
465  return mime_something_to_entity(body, headers);
466 }
static MIMEEntity * mime_something_to_entity(Octstr *mime, List *headers)
Definition: mime.c:332
gw_assert(wtls_machine->packet_to_send!=NULL)
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(), MIMEEntity::start, and start.

634 {
635  gw_assert(e != NULL);
636 
637  /* If e->start element is not yet set, set it as follows:
638  * - if content type is not set, then set it to NULL
639  * - if the start element is not set but this is a multipart object, set
640  * it to first multipart element, else set it to null
641  * - if the start element of the content type is set, find a matching object
642  * and set e->start accordingly.
643  * Finally, return a copy of it.
644  */
645  if (!e->start) {
646  Octstr *ctype = http_header_value(e->headers, octstr_imm("Content-Type"));
647  Octstr *start = get_start_param(ctype);
648  int i;
649 
650  if (!ctype)
651  e->start = NULL;
652  else if (!start) {
653  if (gwlist_len(e->multiparts) > 0)
654  e->start = gwlist_get(e->multiparts, 0);
655  else
656  e->start = NULL;
657  } else
658  for (i = 0; i < gwlist_len(e->multiparts); i++) {
659  MIMEEntity *x = gwlist_get(e->multiparts, i);
660  if (cid_matches(x->headers, start)) {
661  e->start = x;
662  break;
663  }
664  }
665 
666  if (ctype)
667  octstr_destroy(ctype);
668  if (start)
669  octstr_destroy(start);
670  }
671 
672  return (e->start) ? mime_entity_duplicate(e->start) : NULL;
673 }
static Octstr * get_start_param(Octstr *content_type)
Definition: mime.c:282
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
List * multiparts
Definition: mime.c:78
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
static int cid_matches(List *headers, Octstr *start)
Definition: mime.c:300
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
Octstr * http_header_value(List *headers, Octstr *name)
Definition: http.c:2909
Definition: octstr.c:118
struct MIMEEntity * start
Definition: mime.c:80
List * headers
Definition: mime.c:77
MIMEEntity * mime_entity_duplicate(MIMEEntity *e)
Definition: mime.c:521
static int start
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().

454 {
455  gw_assert(mime != NULL);
456 
457  return mime_something_to_entity(mime, NULL);
458 }
static MIMEEntity * mime_something_to_entity(Octstr *mime, List *headers)
Definition: mime.c:332
gw_assert(wtls_machine->packet_to_send!=NULL)
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().

537 {
538  gw_assert(e != NULL);
539  gw_assert(headers != NULL);
540 
542  e->headers = http_header_duplicate(headers);
543  e->start = NULL; /* clear it, since header change means it could have changed.*/
544 }
void http_destroy_headers(List *headers)
Definition: http.c:2856
gw_assert(wtls_machine->packet_to_send!=NULL)
struct MIMEEntity * start
Definition: mime.c:80
List * headers
Definition: mime.c:77
List * http_header_duplicate(List *headers)
Definition: http.c:2946
static MIMEEntity* mime_something_to_entity ( Octstr mime,
List headers 
)
static

Definition at line 332 of file mime.c.

References MIMEEntity::body, boundary, 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(), 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(), read_mime_headers(), MIMEEntity::start, and start.

Referenced by mime_http_to_entity(), and mime_octstr_to_entity().

333 {
334  MIMEEntity *e;
336  Octstr *value, *boundary, *start;
337  int len = 0;
338 
339  gw_assert(mime != NULL);
340 
341  value = boundary = start = NULL;
342  context = parse_context_create(mime);
343  e = mime_entity_create();
344 
345  /* parse the headers up to the body. If we have headers already passed
346  * from our caller, then duplicate them and continue */
347  if (headers != NULL) {
348  /* we have some headers to duplicate, first ensure we destroy
349  * the list from the previous creation inside mime_entity_create() */
351  e->headers = http_header_duplicate(headers);
352  } else {
353  /* parse the headers out of the mime block */
354  if ((read_mime_headers(context, e->headers) != 0) || e->headers == NULL) {
355  debug("mime.parse",0,"Failed to read MIME headers in Octstr block:");
356  octstr_dump(mime, 0);
358  parse_context_destroy(context);
359  return NULL;
360  }
361  }
362 
363  /*
364  * Now check if the body is a multipart. This is indicated by an 'boundary'
365  * parameter in the 'Content-Type' value. If yes, call ourself for the
366  * multipart entities after parsing them.
367  */
368  value = http_header_value(e->headers, octstr_imm("Content-Type"));
369  boundary = http_get_header_parameter(value, octstr_imm("boundary"));
370  start = get_start_param(value);
371 
372  /* Beware that we need *unquoted* strings to compare against in the
373  * following parsing sections. */
374  if (boundary && (len = octstr_len(boundary)) > 0 &&
375  octstr_get_char(boundary, 0) == '"' && octstr_get_char(boundary, len-1) == '"') {
376  octstr_delete(boundary, 0, 1);
377  octstr_delete(boundary, len-2, 1);
378 
379  }
380 
381  if (boundary != NULL) {
382  /* we have a multipart block as body, parse the boundary blocks */
383  Octstr *entity, *seperator, *os;
384 
385  /* loop by all boundary blocks we have in the body */
386  seperator = octstr_create("--");
387  octstr_append(seperator, boundary);
388  while ((entity = parse_get_seperated_block(context, seperator)) != NULL) {
389  MIMEEntity *m;
390  int del2 = 0;
391 
392  /* we have still linefeeds at the beginning and end that we
393  * need to remove, these are from the separator.
394  * We check if it is LF only or CRLF! */
395  del2 = (octstr_get_char(entity, 0) == '\r');
396  if (del2)
397  octstr_delete(entity, 0, 2);
398  else
399  octstr_delete(entity, 0, 1);
400 
401  /* we assume the same mechanism applies to beginning and end --
402  * seems reasonable! */
403  if (del2)
404  octstr_delete(entity, octstr_len(entity) - 2, 2);
405  else
406  octstr_delete(entity, octstr_len(entity) - 1, 1);
407 
408  debug("mime.parse",0,"MIME multipart: Parsing entity:");
409  octstr_dump(entity, 0);
410 
411  /* call ourself for this MIME entity and inject to list */
412  if ((m = mime_octstr_to_entity(entity))) {
413  gwlist_append(e->multiparts, m);
414 
415  /* check if this entity is our start entity (in terms of related)
416  * and set our start pointer to it */
417  if (cid_matches(m->headers, start)) {
418  /* set only if none has been set before */
419  e->start = (e->start == NULL) ? m : e->start;
420  }
421  }
422 
423  octstr_destroy(entity);
424  }
425  /* ok, we parsed all blocks, we expect to see now the end boundary */
426  octstr_append_cstr(seperator, "--");
427  os = parse_get_line(context);
428  if (os != NULL && octstr_compare(os, seperator) != 0) {
429  debug("mime.parse",0,"Failed to see end boundary, parsed line is '%s'.",
430  octstr_get_cstr(os));
431  }
432 
433  octstr_destroy(seperator);
434  octstr_destroy(os);
435  }
436  else {
437 
438  /* we don't have boundaries, so this is no multipart block,
439  * pass the body to the MIME entity. */
440  e->body = parse_get_rest(context);
441 
442  }
443 
444  parse_context_destroy(context);
445  octstr_destroy(value);
446  octstr_destroy(boundary);
447  octstr_destroy(start);
448 
449  return e;
450 }
Octstr * parse_get_seperated_block(ParseContext *context, Octstr *seperator)
Definition: parse.c:303
static Octstr * get_start_param(Octstr *content_type)
Definition: mime.c:282
Definition: parse.c:65
void gwlist_append(List *list, void *item)
Definition: list.c:179
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
Octstr * parse_get_line(ParseContext *context)
Definition: parse.c:282
Octstr * body
Definition: mime.c:79
static char * boundary
Definition: test_ppg.c:97
List * multiparts
Definition: mime.c:78
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1509
MIMEEntity * mime_entity_create(void)
Definition: mime.c:87
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void http_destroy_headers(List *headers)
Definition: http.c:2856
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
void mime_entity_destroy(MIMEEntity *e)
Definition: mime.c:105
static int cid_matches(List *headers, Octstr *start)
Definition: mime.c:300
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
Octstr * http_get_header_parameter(Octstr *value, Octstr *parameter)
Definition: http.c:3508
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
gw_assert(wtls_machine->packet_to_send!=NULL)
static int read_mime_headers(ParseContext *context, List *headers)
Definition: mime.c:129
Octstr * http_header_value(List *headers, Octstr *name)
Definition: http.c:2909
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
void parse_context_destroy(ParseContext *context)
Definition: parse.c:88
Definition: octstr.c:118
struct MIMEEntity * start
Definition: mime.c:80
List * headers
Definition: mime.c:77
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
List * http_header_duplicate(List *headers)
Definition: http.c:2946
MIMEEntity * mime_octstr_to_entity(Octstr *mime)
Definition: mime.c:453
Octstr * parse_get_rest(ParseContext *context)
Definition: parse.c:329
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
ParseContext * parse_context_create(Octstr *str)
Definition: parse.c:74
static int start
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
static 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(), and parse_get_line().

Referenced by mime_entity_body(), and mime_something_to_entity().

130 {
131  Octstr *line, *prev;
132 
133  if (gwlist_len(headers) == 0)
134  prev = NULL;
135  else
136  prev = gwlist_get(headers, gwlist_len(headers) - 1);
137 
138  for (;;) {
139  line = parse_get_line(context);
140  if (line == NULL) {
141  return -1;
142  }
143  if (octstr_len(line) == 0) {
144  octstr_destroy(line);
145  break;
146  }
147  if (isspace(octstr_get_char(line, 0)) && prev != NULL) {
148  octstr_append(prev, line);
149  octstr_destroy(line);
150  } else {
151  gwlist_append(headers, line);
152  prev = line;
153  }
154  }
155 
156  return 0;
157 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
Octstr * parse_get_line(ParseContext *context)
Definition: parse.c:282
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.