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