]> diplodocus.org Git - nmh/blob - uip/mhmisc.c
decode_rfc2047(): Stop unused-variable warning if HAVE_ICONV false.
[nmh] / uip / mhmisc.c
1 /* mhmisc.c -- misc routines to process MIME messages
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "sbr/read_yes_or_no_if_tty.h"
10 #include "sbr/concat.h"
11 #include "sbr/error.h"
12 #include "h/mime.h"
13 #include "h/mhparse.h"
14 #include "h/utils.h"
15 #include "sbr/makedir.h"
16 #include "mhmisc.h"
17
18 extern int debugsw;
19
20 /*
21 * limit actions to specified parts or content types
22 */
23 int npart = 0;
24 int ntype = 0;
25 char *parts[NPARTS + 1];
26 char *types[NTYPES + 1];
27
28 bool userrs;
29
30 static char *errs = NULL;
31
32
33 int
34 part_ok (CT ct)
35 {
36 char **ap;
37 int len;
38
39 /* a part is "ok", i.e., should be processed, if:
40 - there were no -part arguments
41 - this part is a multipart
42 */
43 if (npart == 0 || ct->c_type == CT_MULTIPART) {
44 return 1;
45 }
46
47 /* or if:
48 - this part is a an exact match for any -part option
49 - this part is a sub-part of any -part option
50 */
51 for (ap = parts; *ap; ap++) {
52 len = strlen(*ap);
53 if (!strncmp (*ap, ct->c_partno, len) &&
54 (!ct->c_partno[len] || ct->c_partno[len] == '.' )) {
55 return 1;
56 }
57 }
58
59 return 0;
60 }
61
62 int
63 part_exact(CT ct)
64 {
65 char **ap;
66
67 if (!ct->c_partno)
68 return 0;
69
70 for (ap = parts; *ap; ap++) {
71 if (!strcmp (*ap, ct->c_partno)) {
72 return 1;
73 }
74 }
75
76 return 0;
77 }
78
79
80 int
81 type_ok (CT ct, int sP)
82 {
83 char **ap;
84 char buffer[BUFSIZ];
85 CI ci = &ct->c_ctinfo;
86
87 if (ntype == 0 || (ct->c_type == CT_MULTIPART && (sP || ct->c_subtype)))
88 return 1;
89
90 snprintf (buffer, sizeof(buffer), "%s/%s", ci->ci_type, ci->ci_subtype);
91 for (ap = types; *ap; ap++)
92 if (!strcasecmp (*ap, ci->ci_type) || !strcasecmp (*ap, buffer))
93 return 1;
94
95 return 0;
96 }
97
98
99 /*
100 * Returns true if the content has a disposition of "inline".
101 *
102 * Technically we should check parent content to see if they have
103 * disposition to use as a default, but we don't right now. Maybe
104 * later ....
105 */
106
107 int
108 is_inline(CT ct)
109 {
110 /*
111 * If there isn't any disposition at all, it's "inline". Obviously
112 * if it's "inline", then it's inline. RFC 2183 says if it's an unknown
113 * disposition, treat it as 'attachment'.
114 */
115
116 if (! ct->c_dispo_type || strcasecmp(ct->c_dispo_type, "inline") == 0)
117 return 1;
118 return 0;
119 }
120
121 int
122 make_intermediates (char *file)
123 {
124 char *cp;
125
126 for (cp = file + 1; (cp = strchr(cp, '/')); cp++) {
127 struct stat st;
128
129 *cp = '\0';
130 if (stat (file, &st) == NOTOK) {
131 int answer;
132 char *ep;
133 if (errno != ENOENT) {
134 advise (file, "error on directory");
135 losing_directory:
136 *cp = '/';
137 return NOTOK;
138 }
139
140 ep = concat ("Create directory \"", file, "\"? ", NULL);
141 answer = read_yes_or_no_if_tty (ep);
142 free (ep);
143
144 if (!answer)
145 goto losing_directory;
146 if (!makedir (file)) {
147 inform("unable to create directory %s", file);
148 goto losing_directory;
149 }
150 }
151
152 *cp = '/';
153 }
154
155 return OK;
156 }
157
158
159 /*
160 * Construct error message for content
161 */
162
163 void
164 content_error (char *what, CT ct, char *fmt, ...)
165 {
166 va_list arglist;
167 int len, buflen;
168 char *bp, buffer[BUFSIZ];
169 CI ci;
170
171 bp = buffer;
172 buflen = sizeof(buffer);
173
174 if (userrs && invo_name && *invo_name) {
175 snprintf (bp, buflen, "%s: ", invo_name);
176 len = strlen (bp);
177 bp += len;
178 buflen -= len;
179 }
180
181 va_start (arglist, fmt);
182
183 vsnprintf (bp, buflen, fmt, arglist);
184 len = strlen (bp);
185 bp += len;
186 buflen -= len;
187
188 ci = &ct->c_ctinfo;
189
190 if (what) {
191 char *s;
192
193 if (*what) {
194 snprintf (bp, buflen, " %s: ", what);
195 len = strlen (bp);
196 bp += len;
197 buflen -= len;
198 }
199
200 if ((s = strerror (errno)))
201 snprintf (bp, buflen, "%s", s);
202 else
203 snprintf (bp, buflen, "Error %d", errno);
204
205 len = strlen (bp);
206 bp += len;
207 buflen -= len;
208 }
209
210 /* Now add content type and subtype */
211 snprintf (bp, buflen, "\n (content %s/%s",
212 ci->ci_type, ci->ci_subtype);
213 len = strlen (bp);
214 bp += len;
215 buflen -= len;
216
217 /* Now add the message/part number */
218 if (ct->c_file) {
219 snprintf (bp, buflen, " in message %s", ct->c_file);
220 len = strlen (bp);
221 bp += len;
222 buflen -= len;
223
224 if (ct->c_partno) {
225 snprintf (bp, buflen, ", part %s", ct->c_partno);
226 len = strlen (bp);
227 bp += len;
228 buflen -= len;
229 }
230 }
231
232 snprintf (bp, buflen, ")");
233 len = strlen (bp);
234 bp += len;
235 buflen -= len;
236
237 if (userrs) {
238 *bp++ = '\n';
239 *bp = '\0';
240 buflen--;
241
242 errs = add (buffer, errs);
243 } else {
244 inform("%s", buffer);
245 }
246
247 va_end(arglist);
248 }
249
250
251 void
252 flush_errors (void)
253 {
254 if (errs) {
255 fflush (stdout);
256 fputs(errs, stderr);
257 free (errs);
258 errs = NULL;
259 }
260 }