Kannel: Open Source WAP and SMS gateway  svn-r5335
mime.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * mime.c - Implement MIME multipart/related handling
59  *
60  * References:
61  * RFC 2387 (The MIME Multipart/Related Content-type)
62  * RFC 2025 (Multipurpose Internet Mail Extensions [MIME])
63  *
64  * See gwlib/mime.h for more details on the implementation.
65  *
66  * Stipe Tolj <stolj@kannel.org>
67  */
68 
69 #include <string.h>
70 #include <limits.h>
71 #include <ctype.h>
72 
73 #include "gwlib/gwlib.h"
74 #include "gwlib/mime.h"
75 
76 struct MIMEEntity {
80  struct MIMEEntity *start; /* in case multipart/related */
81 };
82 
83 /********************************************************************
84  * Creation and destruction routines.
85  */
86 
88 {
89  MIMEEntity *e;
90 
91  e = gw_malloc(sizeof(MIMEEntity));
94  e->body = NULL;
95  e->start = NULL;
96 
97  return e;
98 }
99 
100 void static mime_entity_destroy_item(void *e)
101 {
103 }
104 
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 }
118 
119 
120 
121 /********************************************************************
122  * Helper routines. Some are derived from gwlib/http.[ch]
123  */
124 
125 /*
126  * Read some headers, i.e., until the first empty line (read and discard
127  * the empty line as well). Return -1 for error, 0 for all headers read.
128  */
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 }
158 
159 /* This function checks that there is a boundary parameter in the headers
160  * for a multipart MIME object. If not, it is inserted and passed back to caller
161  * in the variable boundary_elem.
162  */
163 static void fix_boundary_element(List *headers, Octstr **boundary_elem)
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
209 }
210 
211 
212 /********************************************************************
213  * Mapping function from other data types, mainly Octstr and HTTP.
214  */
215 
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 */
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  }
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 */
266  octstr_append(mime, body);
267 
269  }
270 
271  octstr_append(mime, octstr_imm("\r\n--"));
272  octstr_append(mime, boundary);
273  octstr_append(mime, octstr_imm("--\r\n"));
274 
276 
277 finished:
278 
279  return mime;
280 }
281 
283 {
284  Octstr *start;
285  int len;
286 
287  if (!content_type)
288  return NULL;
289 
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 }
299 
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 }
326 
327 /*
328  * This routine is used for mime_[http|octstr]_to_entity() in order to
329  * reduce code duplication. Basically the only difference is how the headers
330  * are parsed or passed to the resulting MIMEEntity representation.
331  */
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;
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() */
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);
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. */
441 
442  }
443 
445  octstr_destroy(value);
448 
449  return e;
450 }
451 
452 
454 {
455  gw_assert(mime != NULL);
456 
457  return mime_something_to_entity(mime, NULL);
458 }
459 
460 
462 {
463  gw_assert(headers != NULL && body != NULL);
464 
466 }
467 
468 
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 
480 
481  return headers;
482 }
483 
484 
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);
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);
507  return NULL;
508  }
509 
510  /* the rest is the body */
512 
513  octstr_destroy(os);
516 
517  return body;
518 }
519 
520 /* Make a copy of a mime object. recursively. */
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 }
534 
535 /* Replace top-level MIME headers: Old ones removed completetly */
537 {
538  gw_assert(e != NULL);
539  gw_assert(headers != NULL);
540 
543  e->start = NULL; /* clear it, since header change means it could have changed.*/
544 }
545 
546 
547 /* Get number of body parts. Returns 0 if this is not
548  * a multipart object.
549  */
551 {
552  gw_assert(e != NULL);
553  return e->multiparts ? gwlist_len(e->multiparts) : 0;
554 }
555 
556 
557 /* Append a new part to list of body parts. Copy is made
558  * Note that if it was not multipart, this action makes it so!
559  */
561 {
562  gw_assert(e != NULL);
563  gw_assert(part != NULL);
564 
566 }
567 
568 
569 /* Get part i in list of body parts. Copy is made*/
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 }
581 
582 
583 /* Remove part i in list of body parts. */
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 }
599 
600 /* Replace part i in list of body parts. Old one will be deleted */
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 }
617 
618 /* Change body element of non-multipart entity.
619  * We don't check that object is multi part. Result is just that
620  * body will be ignored.
621  */
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 }
631 
632 /* Returns (copy of) the 'start' element of a multi-part entity. */
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)
670  }
671 
672  return (e->start) ? mime_entity_duplicate(e->start) : NULL;
673 }
674 
675 /********************************************************************
676  * Routines for debugging purposes.
677  */
678 
679 static void mime_entity_dump_real(MIMEEntity *m, unsigned int level)
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 
692  debug("mime.dump",0,"%sContent-Type `%s'", octstr_get_cstr(prefix),
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);
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 }
715 
716 
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 }
724 
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
void mime_entity_set_body(MIMEEntity *e, Octstr *body)
Definition: mime.c:622
MIMEEntity * mime_entity_get_part(MIMEEntity *e, int i)
Definition: mime.c:570
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2886
gw_assert(wtls_machine->packet_to_send !=NULL)
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:1504
void mime_entity_replace_part(MIMEEntity *e, int i, MIMEEntity *newpart)
Definition: mime.c:601
long gwlist_len(List *list)
Definition: list.c:166
List * mime_entity_headers(MIMEEntity *m)
Definition: mime.c:469
void * gwlist_get(List *list, long pos)
Definition: list.c:292
Octstr * parse_get_line(ParseContext *context)
Definition: parse.c:282
Octstr * body
Definition: mime.c:79
static char * boundary
Definition: test_ppg.c:97
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:3225
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:1511
MIMEEntity * mime_entity_create(void)
Definition: mime.c:87
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * charset
Definition: test_ota.c:68
MIMEEntity * mime_multipart_start_elem(MIMEEntity *e)
Definition: mime.c:633
static void fix_boundary_element(List *headers, Octstr **boundary_elem)
Definition: mime.c:163
void http_destroy_headers(List *headers)
Definition: http.c:2879
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
void gwlist_delete(List *list, long pos, long count)
Definition: list.c:232
Octstr * mime_entity_to_octstr(MIMEEntity *m)
Definition: mime.c:216
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1527
static void mime_entity_destroy_item(void *e)
Definition: mime.c:100
void mime_entity_destroy(MIMEEntity *e)
Definition: mime.c:105
List * http_create_empty_headers(void)
Definition: http.c:2872
static MIMEEntity * mime_something_to_entity(Octstr *mime, List *headers)
Definition: mime.c:332
static int cid_matches(List *headers, Octstr *start)
Definition: mime.c:300
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
Octstr * mime_entity_body(MIMEEntity *m)
Definition: mime.c:485
MIMEEntity * mime_http_to_entity(List *headers, Octstr *body)
Definition: mime.c:461
Octstr * http_get_header_parameter(Octstr *value, Octstr *parameter)
Definition: http.c:3531
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
void octstr_destroy_item(void *os)
Definition: octstr.c:336
const char * content_type
Definition: fakewap.c:249
void mime_replace_headers(MIMEEntity *e, List *headers)
Definition: mime.c:536
static int read_mime_headers(ParseContext *context, List *headers)
Definition: mime.c:129
void mime_entity_dump(MIMEEntity *m)
Definition: mime.c:717
void gwlist_insert(List *list, long pos, void *item)
Definition: list.c:214
Octstr * http_header_value(List *headers, Octstr *name)
Definition: http.c:2932
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
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:726
long http_header_remove_all(List *headers, char *name)
Definition: http.c:3135
int octstr_str_ncompare(const Octstr *ostr, const char *str, long n)
Definition: octstr.c:999
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2507
List * http_header_duplicate(List *headers)
Definition: http.c:2969
#define gwlist_create()
Definition: list.h:136
void mime_entity_add_part(MIMEEntity *e, MIMEEntity *part)
Definition: mime.c:560
MIMEEntity * mime_octstr_to_entity(Octstr *mime)
Definition: mime.c:453
void mime_entity_remove_part(MIMEEntity *e, int i)
Definition: mime.c:584
Octstr * parse_get_rest(ParseContext *context)
Definition: parse.c:329
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
MIMEEntity * mime_entity_duplicate(MIMEEntity *e)
Definition: mime.c:521
ParseContext * parse_context_create(Octstr *str)
Definition: parse.c:74
Definition: list.c:102
static int start
int mime_entity_num_parts(MIMEEntity *e)
Definition: mime.c:550
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.