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