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