move smap/nospam into the mime module.
[apps/madmutt.git] / lib-mime / mime.cpkg
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or (at
5  *  your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful, but
8  *  WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15  *  MA 02110-1301, USA.
16  *
17  *  Copyright © 2006 Pierre Habouzit
18  */
19 /*
20  * Copyright notice from original mutt:
21  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
22  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
23  */
24
25 #include <lib-lib/lib-lib.h>
26 #include <lib-lua/lib-lua.h>
27 #include "mime.h"
28 @import "../lib-lua/base.cpkg"
29
30 #define BOUNDARYLEN 16
31 const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t";
32
33 const char *BodyTypes[] = {
34     "x-unknown",
35     "audio",
36     "application",
37     "image",
38     "message",
39     "model",
40     "multipart",
41     "text",
42     "video",
43 };
44
45 const char *BodyEncodings[] = {
46     "x-unknown",
47     "7bit",
48     "8bit",
49     "quoted-printable",
50     "base64",
51     "binary",
52     "x-uuencoded",
53 };
54
55 rx_t *SpamList = NULL, *NoSpamList = NULL;
56
57 @package Mime {
58     /*
59      ** .pp
60      ** ``$spam_separator'' controls what happens when multiple spam headers
61      ** are matched: if \fIunset\fP, each successive header will overwrite any
62      ** previous matches value for the spam label. If \fIset\fP, each successive
63      ** match will append to the previous, using ``$spam_separator'' as a
64      ** separator.
65      */
66     string_t spam_separator = m_strdup(",");
67
68     void spam(rx_t rx, const string_t tpl) {
69         rx_set_template(rx, tpl);
70         rx_list_append(&SpamList, rx);
71         RETURN();
72     };
73
74     void nospam(rx_t rx) {
75         if (!m_strcmp(rx->pattern, "*")) {
76             rx_list_wipe(&SpamList);
77             rx_list_wipe(&NoSpamList);
78             rx_delete(&rx);
79         } else {
80             rx_list_append(&NoSpamList, rx);
81         }
82         RETURN();
83     };
84 };
85
86 /****************************************************************************/
87 /* rfc822 header parameters                                                 */
88 /****************************************************************************/
89
90 char *parameter_getval(parameter_t *parm, const char *s)
91 {
92     while (parm) {
93         if (!ascii_strcasecmp(parm->attribute, s))
94             return parm->value;
95         parm = parm->next;
96     }
97     return NULL;
98 }
99
100 void parameter_setval(parameter_t **p, const char *attribute, const char *value)
101 {
102     while (*p) {
103         if (!ascii_strcasecmp(attribute, (*p)->attribute)) {
104             if (value) {
105                 m_strreplace(&(*p)->value, value);
106             } else {
107                 parameter_t *q = parameter_list_pop(p);
108                 parameter_delete(&q);
109             }
110             return;
111         }
112         p = &(*p)->next;
113     }
114
115     if (value) {
116         (*p) = parameter_new();
117         (*p)->attribute = m_strdup(attribute);
118         (*p)->value = m_strdup(value);
119     }
120 }
121
122 void parameter_delval(parameter_t **p, const char *attribute)
123 {
124     while (*p) {
125         if (!ascii_strcasecmp(attribute, (*p)->attribute)) {
126             parameter_t *q = parameter_list_pop(p);
127             parameter_delete(&q);
128             return;
129         }
130
131         p = &(*p)->next;
132     }
133 }
134
135 int parameter_equal(const parameter_t *p1, const parameter_t *p2)
136 {
137     while (p1 && p2) {
138         if (m_strcmp(p1->attribute, p2->attribute)
139         ||  m_strcmp(p1->value, p2->value))
140             return 0;
141
142         p1 = p1->next;
143         p2 = p2->next;
144     }
145
146     if (p1 || p2)
147         return 0;
148
149     return 1;
150 }
151
152 void parameter_set_boundary(parameter_t **parm)
153 {
154     char rs[BOUNDARYLEN + 1];
155     int i;
156
157     for (i = 0; i < BOUNDARYLEN; i++) {
158         rs[i] = __m_b64chars[lrand48() % sizeof(__m_b64chars)];
159     }
160     rs[BOUNDARYLEN] = '\0';
161
162     parameter_setval(parm, "boundary", rs);
163 }
164
165
166 /****************************************************************************/
167 /* XXX                                                                      */
168 /****************************************************************************/
169
170 void envelope_wipe(ENVELOPE *p)
171 {
172     address_list_wipe(&p->return_path);
173     address_list_wipe(&p->from);
174     address_list_wipe(&p->to);
175     address_list_wipe(&p->cc);
176     address_list_wipe(&p->bcc);
177     address_list_wipe(&p->sender);
178     address_list_wipe(&p->reply_to);
179     address_list_wipe(&p->mail_followup_to);
180
181     p_delete(&p->list_post);
182     p_delete(&p->subject);
183     /* real_subj is just an offset to subject and shouldn't be freed */
184     p_delete(&p->message_id);
185     p_delete(&p->supersedes);
186     p_delete(&p->date);
187     p_delete(&p->x_label);
188     p_delete(&p->organization);
189 #ifdef USE_NNTP
190     p_delete(&p->newsgroups);
191     p_delete(&p->xref);
192     p_delete(&p->followup_to);
193     p_delete(&p->x_comment_to);
194 #endif
195
196     mutt_buffer_free (&p->spam);
197     string_list_wipe(&p->references);
198     string_list_wipe(&p->in_reply_to);
199     string_list_wipe(&p->userhdrs);
200 }
201
202 void body_wipe(BODY *b)
203 {
204     if (b->parameter)
205         parameter_list_wipe(&b->parameter);
206
207     if (b->unlink && b->filename) {
208         unlink (b->filename);
209     }
210
211     p_delete(&b->filename);
212     p_delete(&b->content);
213     p_delete(&b->xtype);
214     p_delete(&b->subtype);
215     p_delete(&b->description);
216     p_delete(&b->form_name);
217
218     if (b->hdr) {
219         /* Don't free twice (b->hdr->content = b->parts) */
220         b->hdr->content = NULL;
221         header_delete(&b->hdr);
222     }
223
224     if (b->parts)
225         body_list_wipe(&b->parts);
226 }
227
228 void header_wipe(HEADER *h)
229 {
230     envelope_delete(&h->env);
231     body_list_wipe(&h->content);
232     p_delete(&h->maildir_flags);
233     p_delete(&h->tree);
234     p_delete(&h->path);
235     string_list_wipe(&h->chain);
236     p_delete(&h->data);
237 }
238
239
240 /****************************************************************************/
241 /* misc functions                                                           */
242 /****************************************************************************/
243
244 int mutt_is_message_type(BODY *b)
245 {
246     int tok;
247
248     if (b->type != TYPEMESSAGE)
249         return 0;
250
251     tok = mime_which_token(b->subtype, -1);
252     return tok == MIME_RFC822 || tok == MIME_NEWS;
253 }
254
255 int mutt_is_text_part(BODY * b)
256 {
257     char *s = b->subtype;
258
259     if (mutt_is_application_pgp(b))
260         return 0;
261
262     switch (b->type) {
263       case TYPETEXT:
264         return 1;
265
266       case TYPEMESSAGE:
267         return mime_which_token(s, -1) == MIME_DELIVERY_STATUS;
268
269       case TYPEAPPLICATION:
270         return mime_which_token(s, -1) == MIME_PGP_KEYS;
271
272       default:
273         return 0;
274     }
275 }
276
277 /* vim:set ft=c: */