ze-filter  (ze-filter-0.8.0-develop-180218)
ze-demime.c
Go to the documentation of this file.
1 /*
2  *
3  * ze-filter - Mail Server Filter for sendmail
4  *
5  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
6  *
7  * Auteur : Jose Marcio Martins da Cruz
8  * jose.marcio.mc@gmail.org
9  *
10  * Historique :
11  * Creation : janvier 2002
12  *
13  * This program is free software, but with restricted license :
14  *
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * More details about ze-filter license can be found at ze-filter
21  * web site : http://foss.jose-marcio.org
22  */
23 
24 #include <ze-sys.h>
25 
26 #include "ze-libjc.h"
27 
28 #define LOG_LEVEL 12
29 
30 #define USE_NEW_GET_BOUNDARY 1
31 
32 typedef struct
33 {
34  int int_value;
35  char *str_value;
36 }
37 VALUES;
38 
39 static VALUES mime_types[] = {
40  {MIME_TYPE_TEXT, "text"},
41  {MIME_TYPE_IMAGE, "image"},
42  {MIME_TYPE_AUDIO, "audio"},
43  {MIME_TYPE_VIDEO, "video"},
44  {MIME_TYPE_APPLICATION, "application"},
45  {MIME_TYPE_EXTENSION_TOKEN, "extension-token"},
46  {MIME_TYPE_MESSAGE, "message"},
47  {MIME_TYPE_MULTIPART, "multipart"},
48  {-1, NULL}
49 };
50 
51 static VALUES mime_encode[] = {
52  {MIME_ENCODE_NONE, ""},
53  {MIME_ENCODE_7BIT, "7bit"},
54  {MIME_ENCODE_8BIT, "8bit"},
55  {MIME_ENCODE_BASE64, "base64"},
56  {MIME_ENCODE_QUOTED_PRINTABLE, "quoted-printable"},
57  {MIME_ENCODE_OTHER, NULL}
58 };
59 
60 char *zeStrnDup(const char *s, size_t n);
61 
62 /* ****************************************************************************
63  * *
64  * *
65  **************************************************************************** */
66 static bool J_MIME_DEBUG = FALSE;
67 
68 void
70  bool v;
71 {
72  J_MIME_DEBUG = v;
73 }
74 
75 /* ****************************************************************************
76  * *
77  * *
78  **************************************************************************** */
79 
80 #ifndef MAX
81 #define MAX(a,b) ((a) > (b) ? (a) : (b))
82 #endif /* MAX */
83 #ifndef MIN
84 #define MIN(a,b) ((a) < (b) ? (a) : (b))
85 #endif /* MIN */
86 
87 #ifndef MAXLONG
88 #define MAXLONG (1 << 30)
89 #endif /* MAXLONG */
90 
91 /* ***************************************************************************
92  * *
93  * *
94  *****************************************************************************/
95 
96 static char *str_clear_right_spaces(char *);
97 
98 #define MAX_RECURSIVE_LEVEL 5
99 
100 #if 1
101 #define REGCOMP_FLAGS (REG_ICASE | REG_NEWLINE | REG_EXTENDED)
102 #else
103 #define REGCOMP_FLAGS (REG_ICASE | REG_EXTENDED)
104 #endif /* 1 */
105 
106 #define REGEXEC_FLAGS (0)
107 
108 /* ****************************************************************************
109  * *
110  * *
111  **************************************************************************** */
112 #define FREE_ALLOC() \
113  do { \
114  FREE(bodybuf); \
115  FREE(name); \
116  FREE(filename); \
117  FREE(boundary); \
118  FREE(charset); \
119  FREE(mimetype); \
120  } while (0);
121 
122 
123 #define LOG_SOB(h, txt) \
124  { \
125  char titi[80]; \
126  \
127  strlcpy(titi, txt, sizeof(titi)); \
128  ZE_MessageInfo(LOG_LEVEL, "*************** %s **************", h); \
129  ZE_MessageInfo(LOG_LEVEL, "%s",titi); \
130  ZE_MessageInfo(LOG_LEVEL, "*************"); \
131  }
132 
133 #define BADFILENAMECHARS " \t\n\r\"\'\\/$&|;,:()[]<>*{}@?"
134 
135 #define CLEANUP_FILENAME(fname) \
136  if (fname != NULL) \
137  { \
138  char *s = fname; \
139  while ((s = strpbrk(fname, BADFILENAMECHARS)) != NULL) \
140  *s = '_'; \
141  }
142 
143 #define GOTO_FIN(r) \
144  { \
145  result = (r); \
146  goto fin; \
147  }
148 
149 #define LINESZ 0x800
150 
151 /* bool(*func) (char *, size_t, char *, int, int, void *, mime_part_T *); */
152 
153 bool
154 decode_mime_buffer(id, buf, sz, level, flags, func, arg)
155  char *id;
156  char *buf;
157  size_t sz;
158  int level;
159  uint32_t *flags;
160  demime_F func;
161  void *arg;
162 {
163  bool result = TRUE;
164 
165  char *p = NULL;
166 
167  int encode = MIME_ENCODE_7BIT;
168  int type = MIME_TYPE_TEXT;
169  char *boundary = NULL;
170  char *name = NULL;
171  char *filename = NULL;
172  char *mimetype = NULL;
173  char *charset = NULL;
174 
175  char *bodyp = NULL;
176  size_t bodyl = 0;
177 
178  char *bodybuf = NULL;
179 
180  bool is_mime = FALSE;
181 
182  mime_part_T mpart;
183  rfc2822_hdr_T *hdrs = NULL;
184 
185  memset(&mpart, 0, sizeof (mpart));
186 
187  if (level > 4)
188  ZE_MessageInfo(10, "MIME recursion level seems high : %d", level);
189 
190  if (J_MIME_DEBUG)
191  {
192  char str[64];
193 
194  zeStrSet(str, '*', 60);
195  ZE_LogMsgDebug(19, "%s",str);
196  ZE_LogMsgDebug(19, "*** ENTERING...: level = %d", level);
197  }
198 
199  if ((buf == NULL) || (strlen(buf) == 0))
200  GOTO_FIN(TRUE);
201 
202  LOG_SOB("BUFFER", buf);
203 
204  if (id == NULL)
205  id = "00000000.000";
206 
207  buf += strspn(buf, " \t\n\r");
208 
209  hdrs = rfc2822_get_headers(buf, strlen(buf) + 1, &p);
210  mpart.hdrs = hdrs;
211 
212  ZE_MessageInfo(LOG_LEVEL, "Checking Content-Transfer-Encoding");
213  hdrs = rfc2822_lookup_header(mpart.hdrs, "Content-Transfer-Encoding");
214  if (hdrs != NULL)
215  {
216  char *r = NULL;
217 
218  is_mime = TRUE;
219 
220  ZE_MessageInfo(LOG_LEVEL + 1, "HDR -> Content-Transfer-Encoding... %s",
221  hdrs->value);
222  r = rfc2822_get_main_attr(hdrs);
223  if (r != NULL)
224  encode = which_mime_encoding(r);
225  FREE(r);
226  is_mime = TRUE;
227  }
228 
229  ZE_MessageInfo(LOG_LEVEL, "Checking Content-Type");
230  hdrs = rfc2822_lookup_header(mpart.hdrs, "Content-Type");
231  if (hdrs != NULL)
232  {
233  char *r = NULL;
234  int s_type = type;
235 
236  is_mime = TRUE;
237 
238  ZE_MessageInfo(LOG_LEVEL, "HDR -> Content-Type... %s", hdrs->value);
239  r = rfc2822_get_main_attr(hdrs);
240  if (r != NULL)
241  {
242  FREE(mimetype);
243  mimetype = r;
244  s_type = which_mime_type(r);
245  }
246 
247  ZE_MessageInfo(LOG_LEVEL, "TYPE : %4d %s", s_type, STRNULL(mimetype, "???"));
248  if (s_type == MIME_TYPE_TEXT)
249  {
250  char *cset = NULL;
251 
252  cset = rfc2822_get_attr(hdrs, "charset=");
253  if (cset != NULL)
254  {
255  FREE(charset);
256  charset = cset;
257  }
258  ZE_MessageInfo(LOG_LEVEL + 1, " HDR CHARSET = (%s)",
259  STRNULL(charset, "NULL"));
260  }
261 
262  if (s_type == MIME_TYPE_MULTIPART)
263  {
264  char *bound = NULL;
265 
266  ZE_MessageInfo(LOG_LEVEL, " HDR TYPE : %s", hdrs->value);
267  bound = rfc2822_get_attr(hdrs, "boundary=");
268  if (bound != NULL)
269  {
270 
271  FREE(boundary);
272  boundary = bound;
273  }
274  ZE_MessageInfo(LOG_LEVEL + 1, " HDR BOUNDARY = (%s)",
275  STRNULL(bound, "NOT FOUND"));
276  }
277 
278  /*
279  ** Other common attributes
280  */
281  {
282  char *fname;
283 
284  fname = rfc2822_get_attr(hdrs, "name=");
285  if (fname != NULL)
286  {
287  CLEANUP_FILENAME(fname);
288  FREE(name);
289  name = fname;
290  ZE_MessageInfo(LOG_LEVEL, " HDR NAME = (%s)", fname);
291  }
292 
293  fname = rfc2822_get_attr(hdrs, "filename=");
294  if (fname != NULL)
295  {
296  CLEANUP_FILENAME(fname);
297  FREE(filename);
298  filename = fname;
299  ZE_MessageInfo(LOG_LEVEL, " HDR FILENAME = (%s)", fname);
300  }
301  }
302 
303  /*
304  ** Get boundary value...
305  */
306  if (s_type == MIME_TYPE_MULTIPART)
307  {
308  if (boundary != NULL)
309  type = s_type;
310  } else
311  type = s_type;
312  }
313 
314  ZE_MessageInfo(LOG_LEVEL, "Checking Content-Disposition");
315  hdrs = rfc2822_lookup_header(mpart.hdrs, "Content-Disposition");
316  if (hdrs != NULL)
317  {
318 
319  is_mime = TRUE;
320 
321  {
322  char *fname = NULL;
323 
324  fname = rfc2822_get_attr(hdrs, "name=");
325  if (fname != NULL)
326  {
327  CLEANUP_FILENAME(fname);
328  FREE(name);
329  name = fname;
330  ZE_MessageInfo(LOG_LEVEL + 1, " HDR NAME = (%s)", fname);
331  }
332 
333  fname = rfc2822_get_attr(hdrs, "filename=");
334  if (fname != NULL)
335  {
336  CLEANUP_FILENAME(fname);
337  FREE(name);
338  name = fname;
339  ZE_MessageInfo(LOG_LEVEL + 1, " HDR FILENAME = (%s)", fname);
340  }
341  }
342  }
343 #if 1
344  hdrs = mpart.hdrs;
345  while (hdrs != NULL)
346  {
347  ZE_MessageInfo(LOG_LEVEL, "LIST->KEY : %s", hdrs->key);
348  hdrs = hdrs->next;
349  }
350 #endif
351 
352  /* debug */
353  if (J_MIME_DEBUG)
354  {
355  ZE_MessageInfo(LOG_LEVEL, "ENCODING : %5d %s", encode,
356  mime_encode_name(encode));
357  ZE_MessageInfo(LOG_LEVEL, "TYPE : %5d %s", type,
358  mime_type_name(type));
359  ZE_MessageInfo(LOG_LEVEL, "BOUNDARY : %s", STRNULL(boundary, "(null)"));
360  ZE_MessageInfo(LOG_LEVEL, "NAME : %s", STRNULL(name, "(null)"));
361  ZE_MessageInfo(LOG_LEVEL, "FILENAME : %s", STRNULL(filename, "(null)"));
362  ZE_MessageInfo(LOG_LEVEL, "CHARSET : %s", STRNULL(charset, "(null)"));
363  ZE_MessageInfo(LOG_LEVEL, "MIME : %s %s",
364  STRBOOL(is_mime, "YES", "NO "), STRNULL(mimetype, "UNKNOWN"));
365  }
366 
367  if (is_mime)
368  {
369  /* returns if body is empty... */
370  if ((p == NULL) || (*p == '\0'))
371  GOTO_FIN(FALSE);
372 
373  if ((bodybuf = strdup(p)) == NULL)
374  {
375  ZE_LogSysError("strdup error");
376  GOTO_FIN(FALSE);
377  }
378  bodyp = bodybuf;
379  /* it was strlen + 1 */
380  bodyl = strlen(bodybuf);
381  } else
382  {
383  if (level > 0)
384  {
385  if ((bodybuf = (char *) malloc(sz + 1)) == NULL)
386  {
387  ZE_LogSysError("malloc error");
388  GOTO_FIN(FALSE);
389  }
390  memset(bodybuf, 0, sz + 1);
391  memcpy(bodybuf, buf, sz);
392  bodyp = bodybuf;
393  bodyl = sz;
394  } else
395  {
396  /* returns if body is empty... */
397  if ((p == NULL) || (*p == '\0'))
398  {
399  GOTO_FIN(FALSE);
400  }
401 
402  if ((bodybuf = strdup(p)) == NULL)
403  {
404  ZE_LogSysError("strdup error");
405  GOTO_FIN(FALSE);
406  }
407  bodyp = bodybuf;
408  /* it was strlen + 1 JOE */
409  bodyl = strlen(bodybuf);
410  }
411  }
412 
413  /* Let's decode message body */
414  switch (encode)
415  {
416  case MIME_ENCODE_7BIT:
417  break;
418  case MIME_ENCODE_8BIT:
419  break;
420  case MIME_ENCODE_BINARY:
421  break;
422  case MIME_ENCODE_BASE64:
423  base64_decode(bodyp, p, &bodyl, NULL);
424  break;
426  qp_decode(bodyp, p, bodyl);
427  bodyl = strlen(bodyp);
428  break;
429  default:
430  break;
431  }
432 
433  if (J_MIME_DEBUG)
434  ZE_LogMsgInfo(LOG_LEVEL, "BODY LENGTH : %ld %ld", (long) strlen(bodyp), (long) bodyl);
435 
436  LOG_SOB("SUB BUF", bodyp);
437 
438  /* Let's process body */
439  if ((type == MIME_TYPE_MULTIPART) &&
440  (level < MAX_RECURSIVE_LEVEL) && (boundary != NULL) && is_mime)
441  {
442  char *bstrp = NULL;
443  int nboundary = 0;
444 
445  bstrp = zeStrCatDup("--", boundary);
446  if (bstrp == NULL)
447  {
448  ZE_LogSysError("zeStrCatDup(%s, %s) error", "--", boundary);
449  GOTO_FIN(FALSE);
450  }
451 
452  {
453  char *p = "";
454  size_t l = strlen(p);
455 #if 0
456  rfc2822_hdr_T *h;
457 
458  ZE_MessageInfo(10, " Listing headers...");
459  h = mpart.hdrs;
460  while (h != NULL)
461  {
462  ZE_MessageInfo(10, "LIST->KEY : %s", h->key);
463  h = h->next;
464  }
465 #endif
466  /* process part */
467  mpart.buf = p;
468  mpart.size = l;
469  mpart.level = level;
470  mpart.encode = encode;
471  mpart.type = type;
472  mpart.name = name;
473  mpart.filename = filename;
474  mpart.boundary = boundary;
475 
476  mpart.mime = STRNULL(mimetype, "unknown");
477  mpart.charset = STRNULL(charset, "unknown");
478 
479  func(p, l, id, level, type, arg, &mpart);
480  }
481 
482  {
483  char *gotcha = NULL;
484  char *p = bodyp;
485 
486  while (*p != '\0')
487  {
488  char *t = NULL;
489 
490  ZE_MessageInfo(LOG_LEVEL + 1, "Looking for Boundary : %s", bstrp);
491 
492  if ((gotcha = strstr(p, bstrp)) != NULL)
493  {
494  size_t pi = 0, pf = 0;
495 
496  nboundary++;
497 
498  pi = gotcha - p;
499  pf = pi + strlen(bstrp);
500 
501  ZE_MessageInfo(LOG_LEVEL + 1, " Gotcha : %ld <-> %ld...", pi, pf);
502 
503  if (pi == 0)
504  {
505  p += pf;
506  continue;
507  }
508 
509  if ((t = zeStrnDup(p, pi)) == NULL)
510  {
511  ZE_LogSysError("zeStrnDup error");
512  break;
513  }
514 
515  p += pf;
516  if (strncmp(p, "--", 2) == 0)
517  p += 2;
518  } else
519  {
520  ZE_MessageInfo(LOG_LEVEL + 1, " Gotcha : NOT...");
521  if ((t = strdup(p)) == NULL)
522  {
523  ZE_LogSysError("strdup error");
524  break;
525  }
526  p += strlen(p);
527  }
528 
529  ZE_MessageInfo(LOG_LEVEL + 1, " -> Boundary lookup : Gotcha = %s",
530  STRBOOL(gotcha != NULL, "YES", "NO"));
531 
532  decode_mime_buffer(id, t, strlen(t), level + 1, flags, func, arg);
533  FREE(t);
534  }
535  }
536 
537  FREE(bstrp);
538 
539  /*
540  ** handle situation when nboundary equals 0
541  */
542  if (nboundary == 0)
543  {
544  ZE_MessageInfo(10, "%s SPAM CHECK : multipart/... without boundaries",
545  STRNULL(id, "NOMSGID "));
546 #if 0
547  if (flags != NULL)
548  SET_FLAG(*flags, MIME_ERROR_UNUSED_BOUNDARY);
549 #endif
550  }
551 
552  } else
553  {
554  /* process part */
555  mpart.buf = bodyp;
556  mpart.size = bodyl;
557  mpart.level = level;
558  mpart.encode = encode;
559  mpart.type = type;
560  mpart.name = name;
561  mpart.filename = filename;
562  mpart.boundary = boundary;
563 
564  mpart.mime = STRNULL(mimetype, "unknown");
565  mpart.charset = STRNULL(charset, "unknown");
566 
567  func(bodyp, bodyl, id, level, type, arg, &mpart);
568  }
569  result = TRUE;
570 
571 fin:
572  FREE_ALLOC();
573  rfc2822_free_list(mpart.hdrs);
574  mpart.hdrs = NULL;
575 
576  return result;
577 }
578 
579 /* ****************************************************************************
580  * *
581  * *
582  **************************************************************************** */
583 bool
584 decode_mime_file(id, fname, flags, func, arg)
585  char *id;
586  char *fname;
587  uint32_t *flags;
588  demime_F func;
589  void *arg;
590 {
591  char *buf;
592  size_t sz = 0;
593 
594  if (fname == NULL)
595  return FALSE;
596 
597  buf = read_text_file(fname, &sz);
598 
599  if (buf == NULL)
600  {
601  ZE_LogMsgError(0, "Error reading %s input file", fname);
602  return FALSE;
603  }
604 
605  decode_mime_buffer(id, buf, sz, 0, flags, func, arg);
606 
607  FREE(buf);
608 
609  return TRUE;
610 }
611 
612 
613 
614 /* ****************************************************************************
615  * *
616  * *
617  **************************************************************************** */
618 int
620  char *s;
621 {
622  VALUES *p = mime_encode;
623 
624  if (s == NULL)
625  return MIME_ENCODE_OTHER;
626 
627  while (p->str_value != NULL)
628  {
629  if (strcasecmp(s, p->str_value) == 0)
630  return p->int_value;
631  p++;
632  }
633 
634  return MIME_ENCODE_OTHER;
635 }
636 
637 /* ****************************************************************************
638  * *
639  * *
640  **************************************************************************** */
641 char *
643  int n;
644 {
645  VALUES *p = mime_encode;
646 
647  while (p->str_value != NULL)
648  {
649  if (n == p->int_value)
650  return p->str_value;
651  p++;
652  }
653 
654  return "";
655 }
656 
657 /* ****************************************************************************
658  * *
659  * *
660  **************************************************************************** */
661 int
663  char *s;
664 {
665  VALUES *p = mime_types;
666  int n = strcspn(s, "/");
667 
668  if (s == NULL)
669  return MIME_TYPE_TEXT;
670 
671  while (p->str_value != NULL)
672  {
673  if (strncasecmp(s, p->str_value, n) == 0)
674  return p->int_value;
675  p++;
676  }
677 
678  return MIME_TYPE_TEXT;
679 }
680 
681 /* ****************************************************************************
682  * *
683  * *
684  **************************************************************************** */
685 char *
687  int n;
688 {
689  VALUES *p = mime_types;
690 
691  while (p->str_value != NULL)
692  {
693  if (n == p->int_value)
694  return p->str_value;
695  p++;
696  }
697 
698  return "???";
699 }
700 
701 
702 /* ****************************************************************************
703  * *
704  * *
705  **************************************************************************** */
706 static char *
708  char *s;
709 {
710 #if 1
711  return s;
712 #else
713  int n;
714 
715  if ((s == NULL) || ((n = strlen(s)) == 0))
716  return s;
717 
718  for (n--; n >= 0; n--)
719  {
720  if (s[n] != ' ')
721  break;
722  s[n] = '\0';
723  }
724  return s;
725 #endif /* 1 */
726 }
#define str_clear_right_spaces(s)
Definition: ze-rfc2822.c:35
int int_value
Definition: ze-demime.c:34
char * mime_type_name(int n)
Definition: ze-demime.c:686
#define STRBOOL(x, t, f)
Definition: macros.h:87
#define MIME_TYPE_IMAGE
Definition: ze-demime.h:35
int encode
Definition: ze-demime.h:64
char * rfc2822_get_main_attr(rfc2822_hdr_T *header)
Definition: ze-rfc2822.c:178
#define LOG_SOB(h, txt)
Definition: ze-demime.c:123
#define MIME_TYPE_EXTENSION_TOKEN
Definition: ze-demime.h:39
#define MIME_TYPE_AUDIO
Definition: ze-demime.h:36
#define MAX_RECURSIVE_LEVEL
Definition: ze-demime.c:98
#define MIME_TYPE_MESSAGE
Definition: ze-demime.h:40
#define FREE(x)
Definition: macros.h:37
char * key
Definition: ze-rfc2822.h:37
char * buf
Definition: ze-demime.h:61
#define MIME_ENCODE_7BIT
Definition: ze-demime.h:45
void set_mime_debug(bool v)
Definition: ze-demime.c:69
rfc2822_hdr_T * next
Definition: ze-rfc2822.h:39
#define STRNULL(x, r)
Definition: macros.h:81
char * zeStrnDup(const char *s, size_t n)
#define ZE_LogMsgInfo(level,...)
Definition: zeSyslog.h:110
char * value
Definition: ze-rfc2822.h:38
#define CLEANUP_FILENAME(fname)
Definition: ze-demime.c:135
int qp_decode(char *, char *, size_t)
Definition: ze-qp.c:33
#define FALSE
Definition: macros.h:160
size_t size
Definition: ze-demime.h:62
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
char * str_value
Definition: ze-demime.c:35
#define MIME_ENCODE_8BIT
Definition: ze-demime.h:46
#define MIME_TYPE_MULTIPART
Definition: ze-demime.h:41
bool decode_mime_file(char *id, char *fname, uint32_t *flags, demime_F func, void *arg)
Definition: ze-demime.c:584
#define rfc2822_free_list(head)
Definition: ze-rfc2822.h:50
char * mime
Definition: ze-demime.h:65
#define ZE_LogMsgDebug(level,...)
Definition: zeSyslog.h:109
char * zeStrSet(char *, int, int)
Definition: zeStrings.c:330
char * mime_encode_name(int n)
Definition: ze-demime.c:642
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
char * filename
Definition: ze-demime.h:68
#define MIME_TYPE_TEXT
Definition: ze-demime.h:34
#define TRUE
Definition: macros.h:157
bool decode_mime_buffer(char *id, char *buf, size_t sz, int level, uint32_t *flags, demime_F func, void *arg)
Definition: ze-demime.c:154
#define memcpy(d, s, n)
Definition: ze-sys.h:224
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define MIME_TYPE_VIDEO
Definition: ze-demime.h:37
int base64_decode(char *, char *, size_t *, size_t *)
Definition: ze-base64.c:94
int which_mime_encoding(char *s)
Definition: ze-demime.c:619
char * name
Definition: ze-demime.h:67
#define GOTO_FIN(r)
Definition: ze-demime.c:143
#define LOG_LEVEL
Definition: ze-demime.c:28
#define MIME_ENCODE_BINARY
Definition: ze-demime.h:47
#define MIME_ENCODE_OTHER
Definition: ze-demime.h:50
#define MIME_ENCODE_NONE
Definition: ze-demime.h:44
#define FREE_ALLOC()
Definition: ze-demime.c:112
int which_mime_type(char *s)
Definition: ze-demime.c:662
char * charset
Definition: ze-demime.h:70
#define MIME_ERROR_UNUSED_BOUNDARY
Definition: ze-demime.h:32
rfc2822_hdr_T * rfc2822_get_headers(char *buf, size_t size, char **nptr)
Definition: ze-rfc2822.c:64
char * rfc2822_get_attr(rfc2822_hdr_T *header, char *attr)
Definition: ze-rfc2822.c:201
long uint32_t
Definition: ze-sys.h:489
char * read_text_file(char *, size_t *)
Definition: ze-buffer.c:183
#define MIME_ENCODE_QUOTED_PRINTABLE
Definition: ze-demime.h:49
char * zeStrCatDup(char *, char *)
Definition: zeStrings.c:180
#define MIME_TYPE_APPLICATION
Definition: ze-demime.h:38
bool(* demime_F)(char *, size_t, char *, int, int, void *, mime_part_T *)
Definition: ze-demime.h:77
#define MIME_ENCODE_BASE64
Definition: ze-demime.h:48
char * boundary
Definition: ze-demime.h:69
rfc2822_hdr_T * hdrs
Definition: ze-demime.h:74
rfc2822_hdr_T * rfc2822_lookup_header(rfc2822_hdr_T *head, char *key)
Definition: ze-rfc2822.c:145