summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2005-03-12 19:18:55 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2005-03-12 19:18:55 +0000
commit4e6c7e6e3f5a8906c5229390b45c2c9b3aa090df (patch)
tree9b175f494e057e444cf732dfda58c196b5cd56b8 /lib
parent060730686c03584575b5497a3b765ab963b2e690 (diff)
downloadmailutils-4e6c7e6e3f5a8906c5229390b45c2c9b3aa090df.tar.gz
mailutils-4e6c7e6e3f5a8906c5229390b45c2c9b3aa090df.tar.bz2
Routines for displaying MIME messages.
Diffstat (limited to 'lib')
-rw-r--r--lib/mailcap.c660
1 files changed, 660 insertions, 0 deletions
diff --git a/lib/mailcap.c b/lib/mailcap.c
new file mode 100644
index 000000000..8e0d65f97
--- /dev/null
+++ b/lib/mailcap.c
@@ -0,0 +1,660 @@
1/* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2005 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21#include <mailutils/mailutils.h>
22#include <xalloc.h>
23#include <fnmatch.h>
24#define obstack_chunk_alloc malloc
25#define obstack_chunk_free free
26#include <obstack.h>
27#include <sys/wait.h>
28
29/* Default mailcap path, the $HOME/.mailcap: entry is prepended to it */
30#define DEFAULT_MAILCAP \
31 "/usr/local/etc/mailcap:"\
32 "/usr/etc/mailcap:"\
33 "/etc/mailcap:"\
34 "/etc/mail/mailcap:"\
35 "/usr/public/lib/mailcap"
36
37#define FLAGS_DRY_RUN 0x0001
38#define FLAGS_INTERACTIVE 0x0002
39
40struct mime_context
41{
42 stream_t input;
43 header_t hdr;
44 char *content_type_buffer;
45 char *content_type;
46 list_t values;
47 char *temp_file;
48 int unlink_temp_file;
49
50 char *no_ask_str;
51 list_t no_ask_types;
52 int debug_level;
53 int flags;
54};
55
56#define DEBUG(c,l,f) if ((c)->debug_level > (l)) printf f
57
58static void
59mime_context_fill (struct mime_context *ctx, const char *file,
60 stream_t input, header_t hdr, const char *no_ask,
61 int interactive, int dry_run, int debug_level)
62{
63 char *p, *sp;
64
65 memset (ctx, 0, sizeof *ctx);
66 ctx->input = input;
67 ctx->hdr = hdr;
68 header_aget_value (hdr, MU_HEADER_CONTENT_TYPE, &ctx->content_type_buffer);
69 ctx->content_type = strtok_r (ctx->content_type_buffer, ";", &sp);
70 ctx->temp_file = file ? strdup (file) : NULL;
71 ctx->unlink_temp_file = 0;
72
73 if (interactive)
74 ctx->flags |= FLAGS_INTERACTIVE;
75 if (dry_run)
76 ctx->flags |= FLAGS_DRY_RUN;
77 ctx->debug_level = debug_level;
78
79 list_create (&ctx->values);
80 while ((p = strtok_r (NULL, ";", &sp)))
81 list_append (ctx->values, p);
82
83 if (no_ask)
84 {
85 ctx->no_ask_str = xstrdup (no_ask);
86 list_create (&ctx->no_ask_types);
87 for (p = strtok_r (ctx->no_ask_str, ",", &sp); p;
88 p = strtok_r (NULL, ",", &sp))
89 list_append (ctx->no_ask_types, p);
90 }
91}
92
93static void
94mime_context_release (struct mime_context *ctx)
95{
96 free (ctx->content_type_buffer);
97 if (ctx->unlink_temp_file)
98 unlink (ctx->temp_file);
99 free (ctx->temp_file);
100 list_destroy (&ctx->values);
101 free (ctx->no_ask_str);
102 list_destroy (&ctx->no_ask_types);
103}
104
105static int
106mime_context_do_not_ask (struct mime_context *ctx)
107{
108 int rc = 0;
109
110 if (ctx->no_ask_types)
111 {
112 iterator_t itr;
113 list_get_iterator (ctx->no_ask_types, &itr);
114 for (iterator_first (itr); !rc && !iterator_is_done (itr);
115 iterator_next (itr))
116 {
117 char *p;
118 iterator_current (itr, (void**)&p);
119 rc = fnmatch (p, ctx->content_type, FNM_CASEFOLD) == 0;
120 }
121 iterator_destroy (&itr);
122 }
123 return rc;
124}
125
126int
127dry_run_p (struct mime_context *ctx)
128{
129 return ctx->flags & FLAGS_DRY_RUN;
130}
131
132int
133interactive_p (struct mime_context *ctx)
134{
135 return ctx->flags & FLAGS_INTERACTIVE;
136}
137
138static void
139mime_context_get_content_type (struct mime_context *ctx, char **ptr)
140{
141 *ptr = ctx->content_type;
142}
143
144static void
145mime_context_get_input (struct mime_context *ctx, stream_t *pinput)
146{
147 *pinput = ctx->input;
148}
149
150static void
151mime_context_get_content_type_value (struct mime_context *ctx,
152 char *name, size_t len,
153 char **ptr, size_t *plen)
154{
155 iterator_t itr = NULL;
156
157 list_get_iterator (ctx->values, &itr);
158 for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr))
159 {
160 char *item, *p;
161
162 iterator_current (itr, (void**) &item);
163 p = strchr (item, '=');
164 if (p - item == len && strncasecmp (item, name, len) == 0)
165 {
166 *ptr = ++p;
167 *plen = strlen (*ptr);
168 if (**ptr == '"')
169 {
170 ++*ptr;
171 *plen -= 2;
172 }
173 break;
174 }
175 }
176 iterator_destroy (&itr);
177}
178
179static void
180mime_context_write_input (struct mime_context *ctx, int fd)
181{
182 stream_t input;
183 char buf[512];
184 size_t n;
185 int status;
186
187 mime_context_get_input (ctx, &input);
188 stream_seek (input, 0, SEEK_SET);
189 while ((status = stream_sequential_read (input, buf, sizeof buf, &n)) == 0
190 && n)
191 write (fd, buf, n);
192}
193
194static int
195mime_context_get_temp_file (struct mime_context *ctx, char **ptr)
196{
197 if (!ctx->temp_file)
198 {
199 int fd = mu_tempfile (NULL, &ctx->temp_file);
200 if (fd == -1)
201 return -1;
202 mime_context_write_input (ctx, fd);
203 close (fd);
204 ctx->unlink_temp_file = 1;
205 }
206 *ptr = ctx->temp_file;
207 return 0;
208}
209
210
211static struct obstack expand_stack;
212
213static int
214expand_string (struct mime_context *ct, char **pstr)
215{
216 char *p, *s;
217 int rc = 0;
218
219 for (p = *pstr; *p; )
220 {
221 switch (p[0])
222 {
223 case '%':
224 switch (p[1])
225 {
226 case 's':
227 mime_context_get_temp_file (ct, &s);
228 obstack_grow (&expand_stack, s, strlen (s));
229 rc = 1;
230 p += 2;
231 break;
232
233 case 't':
234 mime_context_get_content_type (ct, &s);
235 obstack_grow (&expand_stack, s, strlen (s));
236 p += 2;
237 break;
238
239 case '{':
240 {
241 size_t n;
242 char *q = ++p;