1 /**
2  * @file
3  * Representation of the body of an email
4  *
5  * @authors
6  * Copyright (C) 2017 Richard Russon <rich@flatcap.org>
7  *
8  * @copyright
9  * This program is free software: you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License as published by the Free Software
11  * Foundation, either version 2 of the License, or (at your option) any later
12  * version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 /**
24  * @page email_body Body of an Email
25  *
26  * Representation of the body of an email
27  */
28 
29 #include "config.h"
30 #include <stdbool.h>
31 #include <unistd.h>
32 #include "mutt/lib.h"
33 #include "body.h"
34 #include "email.h"
35 #include "envelope.h"
36 #include "mime.h"
37 #include "parameter.h"
38 
39 /**
40  * mutt_body_new - Create a new Body
41  * @retval ptr Newly allocated Body
42  */
mutt_body_new(void)43 struct Body *mutt_body_new(void)
44 {
45   struct Body *p = mutt_mem_calloc(1, sizeof(struct Body));
46 
47   p->disposition = DISP_ATTACH;
48   p->use_disp = true;
49   TAILQ_INIT(&p->parameter);
50   return p;
51 }
52 
53 /**
54  * mutt_body_free - Free a Body
55  * @param[out] ptr Body to free
56  */
mutt_body_free(struct Body ** ptr)57 void mutt_body_free(struct Body **ptr)
58 {
59   if (!ptr)
60     return;
61 
62   struct Body *a = *ptr, *b = NULL;
63 
64   while (a)
65   {
66     b = a;
67     a = a->next;
68 
69     mutt_param_free(&b->parameter);
70     if (b->filename)
71     {
72       if (b->unlink)
73         unlink(b->filename);
74       mutt_debug(LL_DEBUG1, "%sunlinking %s\n", b->unlink ? "" : "not ", b->filename);
75     }
76 
77     FREE(&b->filename);
78     FREE(&b->d_filename);
79     FREE(&b->charset);
80     FREE(&b->content);
81     FREE(&b->xtype);
82     FREE(&b->subtype);
83     FREE(&b->language);
84     FREE(&b->description);
85     FREE(&b->form_name);
86 
87     if (b->email)
88     {
89       /* Don't free twice (b->email->body = b->parts) */
90       b->email->body = NULL;
91       email_free(&b->email);
92     }
93 
94     mutt_env_free(&b->mime_headers);
95     mutt_body_free(&b->parts);
96     FREE(&b);
97   }
98 
99   *ptr = NULL;
100 }
101 
102 /**
103  * mutt_body_cmp_strict - Strictly compare two email Body's
104  * @param b1 First Body
105  * @param b2 Second Body
106  * @retval true Body's are strictly identical
107  */
mutt_body_cmp_strict(const struct Body * b1,const struct Body * b2)108 bool mutt_body_cmp_strict(const struct Body *b1, const struct Body *b2)
109 {
110   if (!b1 || !b2)
111     return false;
112 
113   if ((b1->type != b2->type) || (b1->encoding != b2->encoding) ||
114       !mutt_str_equal(b1->subtype, b2->subtype) ||
115       !mutt_str_equal(b1->description, b2->description) ||
116       !mutt_param_cmp_strict(&b1->parameter, &b2->parameter) || (b1->length != b2->length))
117   {
118     return false;
119   }
120   return true;
121 }
122 
123 /**
124  * mutt_body_get_charset - Get a body's character set
125  * @param b      Body to examine
126  * @param buf    Buffer for the result
127  * @param buflen Length of the buffer
128  * @retval ptr  Buffer containing character set
129  * @retval NULL On error, or if not a text type
130  */
mutt_body_get_charset(struct Body * b,char * buf,size_t buflen)131 char *mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
132 {
133   char *p = NULL;
134 
135   if (b && (b->type != TYPE_TEXT))
136     return NULL;
137 
138   if (b)
139     p = mutt_param_get(&b->parameter, "charset");
140 
141   if (p)
142     mutt_ch_canonical_charset(buf, buflen, p);
143   else
144     mutt_str_copy(buf, "us-ascii", buflen);
145 
146   return buf;
147 }
148