1 /**
2 * @file
3 * Manipulate multipart Emails
4 *
5 * @authors
6 * Copyright (C) 1996-2002,2009-2012 Michael R. Elkins <me@mutt.org>
7 * Copyright (C) 2019 Pietro Cerutti <gahr@gahr.ch>
8 *
9 * @copyright
10 * This program is free software: you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free Software
12 * Foundation, either version 2 of the License, or (at your option) any later
13 * version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /**
25 * @page send_multipart Manipulate multipart Emails
26 *
27 * Manipulate multipart Emails
28 */
29
30 #include "config.h"
31 #include <stddef.h>
32 #include <stdbool.h>
33 #include "mutt/lib.h"
34 #include "email/lib.h"
35 #include "multipart.h"
36 #include "sendlib.h"
37
38 /**
39 * get_toplevel_encoding - Find the most restrictive encoding type
40 * @param a Body to examine
41 * @retval num Encoding type, e.g. #ENC_7BIT
42 */
get_toplevel_encoding(struct Body * a)43 static int get_toplevel_encoding(struct Body *a)
44 {
45 int e = ENC_7BIT;
46
47 for (; a; a = a->next)
48 {
49 if (a->encoding == ENC_BINARY)
50 return ENC_BINARY;
51 if (a->encoding == ENC_8BIT)
52 e = ENC_8BIT;
53 }
54
55 return e;
56 }
57
58 /**
59 * check_boundary - Check for duplicate boundary
60 * @param boundary Boundary to look for
61 * @param b Body parts to check
62 * @retval true Duplicate found
63 */
check_boundary(const char * boundary,struct Body * b)64 static bool check_boundary(const char *boundary, struct Body *b)
65 {
66 char *p = NULL;
67
68 if (b->parts && check_boundary(boundary, b->parts))
69 return true;
70
71 if (b->next && check_boundary(boundary, b->next))
72 return true;
73
74 p = mutt_param_get(&b->parameter, "boundary");
75 if (p && mutt_str_equal(p, boundary))
76 {
77 return true;
78 }
79 return false;
80 }
81
82 /**
83 * mutt_generate_boundary - Create a unique boundary id for a MIME part
84 * @param pl MIME part
85 */
mutt_generate_boundary(struct ParameterList * pl)86 void mutt_generate_boundary(struct ParameterList *pl)
87 {
88 char rs[MUTT_RANDTAG_LEN + 1];
89
90 mutt_rand_base32(rs, sizeof(rs) - 1);
91 rs[MUTT_RANDTAG_LEN] = 0;
92 mutt_param_set(pl, "boundary", rs);
93 }
94
95 /**
96 * mutt_make_multipart - Create a multipart email
97 * @param b Body of email to start
98 * @retval ptr Newly allocated Body
99 */
mutt_make_multipart(struct Body * b)100 struct Body *mutt_make_multipart(struct Body *b)
101 {
102 struct Body *new_body = mutt_body_new();
103 new_body->type = TYPE_MULTIPART;
104 new_body->subtype = mutt_str_dup("mixed");
105 new_body->encoding = get_toplevel_encoding(b);
106 do
107 {
108 mutt_generate_boundary(&new_body->parameter);
109 if (check_boundary(mutt_param_get(&new_body->parameter, "boundary"), b))
110 mutt_param_delete(&new_body->parameter, "boundary");
111 } while (!mutt_param_get(&new_body->parameter, "boundary"));
112 new_body->use_disp = false;
113 new_body->disposition = DISP_INLINE;
114 new_body->parts = b;
115
116 return new_body;
117 }
118
119 /**
120 * mutt_remove_multipart - Extract the multipart body if it exists
121 * @param b Body to alter
122 * @retval ptr The parts of the Body
123 *
124 * @note The original Body is freed
125 */
mutt_remove_multipart(struct Body * b)126 struct Body *mutt_remove_multipart(struct Body *b)
127 {
128 struct Body *t = NULL;
129
130 if (b->parts)
131 {
132 t = b;
133 b = b->parts;
134 t->parts = NULL;
135 mutt_body_free(&t);
136 }
137 return b;
138 }
139