1 | |
---|
2 | /* |
---|
3 | * mhlistsbr.c -- routines to list information about the |
---|
4 | * -- contents of MIME messages |
---|
5 | * |
---|
6 | * $Id: mhlistsbr.c,v 1.1.1.1 1999-02-07 18:14:14 danw Exp $ |
---|
7 | */ |
---|
8 | |
---|
9 | #include <h/mh.h> |
---|
10 | #include <fcntl.h> |
---|
11 | #include <h/signals.h> |
---|
12 | #include <errno.h> |
---|
13 | #include <signal.h> |
---|
14 | #include <zotnet/mts/mts.h> |
---|
15 | #include <zotnet/tws/tws.h> |
---|
16 | #include <h/mime.h> |
---|
17 | #include <h/mhparse.h> |
---|
18 | |
---|
19 | extern int errno; |
---|
20 | |
---|
21 | /* mhmisc.c */ |
---|
22 | int part_ok (CT, int); |
---|
23 | int type_ok (CT, int); |
---|
24 | void flush_errors (void); |
---|
25 | |
---|
26 | /* |
---|
27 | * prototypes |
---|
28 | */ |
---|
29 | void list_all_messages (CT *, int, int, int, int); |
---|
30 | int list_switch (CT, int, int, int, int); |
---|
31 | int list_content (CT, int, int, int, int); |
---|
32 | |
---|
33 | /* |
---|
34 | * static prototypes |
---|
35 | */ |
---|
36 | static void list_single_message (CT, int, int, int); |
---|
37 | static int list_debug (CT); |
---|
38 | static int list_multi (CT, int, int, int, int); |
---|
39 | static int list_partial (CT, int, int, int, int); |
---|
40 | static int list_external (CT, int, int, int, int); |
---|
41 | static int list_application (CT, int, int, int, int); |
---|
42 | static int list_encoding (CT); |
---|
43 | |
---|
44 | |
---|
45 | /* |
---|
46 | * various formats for -list option |
---|
47 | */ |
---|
48 | #define LSTFMT1 "%4s %-5s %-24s %5s %-36s\n" |
---|
49 | #define LSTFMT2a "%4d " |
---|
50 | #define LSTFMT2b "%-5s %-24.24s " |
---|
51 | #define LSTFMT2c1 "%5lu" |
---|
52 | #define LSTFMT2c2 "%4lu%c" |
---|
53 | #define LSTFMT2c3 "huge " |
---|
54 | #define LSTFMT2c4 " " |
---|
55 | #define LSTFMT2d1 " %-36.36s" |
---|
56 | #define LSTFMT2d2 "\t %-65.65s\n" |
---|
57 | |
---|
58 | |
---|
59 | /* |
---|
60 | * Top level entry point to list group of messages |
---|
61 | */ |
---|
62 | |
---|
63 | void |
---|
64 | list_all_messages (CT *cts, int headers, int realsize, int verbose, int debug) |
---|
65 | { |
---|
66 | CT ct, *ctp; |
---|
67 | |
---|
68 | if (headers) |
---|
69 | printf (LSTFMT1, "msg", "part", "type/subtype", "size", "description"); |
---|
70 | |
---|
71 | for (ctp = cts; *ctp; ctp++) { |
---|
72 | ct = *ctp; |
---|
73 | list_single_message (ct, realsize, verbose, debug); |
---|
74 | } |
---|
75 | |
---|
76 | flush_errors (); |
---|
77 | } |
---|
78 | |
---|
79 | |
---|
80 | /* |
---|
81 | * Entry point to list a single message |
---|
82 | */ |
---|
83 | |
---|
84 | static void |
---|
85 | list_single_message (CT ct, int realsize, int verbose, int debug) |
---|
86 | { |
---|
87 | if (type_ok (ct, 1)) { |
---|
88 | umask (ct->c_umask); |
---|
89 | list_switch (ct, 1, realsize, verbose, debug); |
---|
90 | if (ct->c_fp) { |
---|
91 | fclose (ct->c_fp); |
---|
92 | ct->c_fp = NULL; |
---|
93 | } |
---|
94 | if (ct->c_ceclosefnx) |
---|
95 | (*ct->c_ceclosefnx) (ct); |
---|
96 | } |
---|
97 | } |
---|
98 | |
---|
99 | |
---|
100 | /* |
---|
101 | * Primary switching routine to list information about a content |
---|
102 | */ |
---|
103 | |
---|
104 | int |
---|
105 | list_switch (CT ct, int toplevel, int realsize, int verbose, int debug) |
---|
106 | { |
---|
107 | switch (ct->c_type) { |
---|
108 | case CT_MULTIPART: |
---|
109 | return list_multi (ct, toplevel, realsize, verbose, debug); |
---|
110 | break; |
---|
111 | |
---|
112 | case CT_MESSAGE: |
---|
113 | switch (ct->c_subtype) { |
---|
114 | case MESSAGE_PARTIAL: |
---|
115 | return list_partial (ct, toplevel, realsize, verbose, debug); |
---|
116 | break; |
---|
117 | |
---|
118 | case MESSAGE_EXTERNAL: |
---|
119 | return list_external (ct, toplevel, realsize, verbose, debug); |
---|
120 | break; |
---|
121 | |
---|
122 | case MESSAGE_RFC822: |
---|
123 | default: |
---|
124 | return list_content (ct, toplevel, realsize, verbose, debug); |
---|
125 | break; |
---|
126 | } |
---|
127 | break; |
---|
128 | |
---|
129 | case CT_TEXT: |
---|
130 | case CT_AUDIO: |
---|
131 | case CT_IMAGE: |
---|
132 | case CT_VIDEO: |
---|
133 | return list_content (ct, toplevel, realsize, verbose, debug); |
---|
134 | break; |
---|
135 | |
---|
136 | case CT_APPLICATION: |
---|
137 | return list_application (ct, toplevel, realsize, verbose, debug); |
---|
138 | break; |
---|
139 | |
---|
140 | default: |
---|
141 | /* list_debug (ct); */ |
---|
142 | adios (NULL, "unknown content type %d", ct->c_type); |
---|
143 | break; |
---|
144 | } |
---|
145 | |
---|
146 | return 0; /* NOT REACHED */ |
---|
147 | } |
---|
148 | |
---|
149 | |
---|
150 | #define empty(s) ((s) ? (s) : "") |
---|
151 | |
---|
152 | /* |
---|
153 | * Method for listing information about a simple/generic content |
---|
154 | */ |
---|
155 | |
---|
156 | int |
---|
157 | list_content (CT ct, int toplevel, int realsize, int verbose, int debug) |
---|
158 | { |
---|
159 | unsigned long size; |
---|
160 | char *cp, buffer[BUFSIZ]; |
---|
161 | CI ci = &ct->c_ctinfo; |
---|
162 | |
---|
163 | printf (toplevel > 0 ? LSTFMT2a : toplevel < 0 ? "part " : " ", |
---|
164 | atoi (r1bindex (empty (ct->c_file), '/'))); |
---|
165 | snprintf (buffer, sizeof(buffer), "%s/%s", empty (ci->ci_type), |
---|
166 | empty (ci->ci_subtype)); |
---|
167 | printf (LSTFMT2b, empty (ct->c_partno), buffer); |
---|
168 | |
---|
169 | if (ct->c_cesizefnx && realsize) |
---|
170 | size = (*ct->c_cesizefnx) (ct); |
---|
171 | else |
---|
172 | size = ct->c_end - ct->c_begin; |
---|
173 | |
---|
174 | /* find correct scale for size (Kilo/Mega/Giga/Tera) */ |
---|
175 | for (cp = " KMGT"; size > 9999; size >>= 10) |
---|
176 | if (!*++cp) |
---|
177 | break; |
---|
178 | |
---|
179 | /* print size of this body part */ |
---|
180 | switch (*cp) { |
---|
181 | case ' ': |
---|
182 | if (size > 0 || ct->c_encoding != CE_EXTERNAL) |
---|
183 | printf (LSTFMT2c1, size); |
---|
184 | else |
---|
185 | printf (LSTFMT2c4); |
---|
186 | break; |
---|
187 | |
---|
188 | default: |
---|
189 | printf (LSTFMT2c2, size, *cp); |
---|
190 | break; |
---|
191 | |
---|
192 | case '\0': |
---|
193 | printf (LSTFMT2c3); |
---|
194 | } |
---|
195 | |
---|
196 | /* print Content-Description */ |
---|
197 | if (ct->c_descr) { |
---|
198 | char *dp; |
---|
199 | |
---|
200 | dp = trimcpy (cp = add (ct->c_descr, NULL)); |
---|
201 | free (cp); |
---|
202 | printf (LSTFMT2d1, dp); |
---|
203 | free (dp); |
---|
204 | } |
---|
205 | |
---|
206 | printf ("\n"); |
---|
207 | |
---|
208 | /* |
---|
209 | * If verbose, print any RFC-822 comments in the |
---|
210 | * Content-Type line. |
---|
211 | */ |
---|
212 | if (verbose && ci->ci_comment) { |
---|
213 | char *dp; |
---|
214 | |
---|
215 | dp = trimcpy (cp = add (ci->ci_comment, NULL)); |
---|
216 | free (cp); |
---|
217 | snprintf (buffer, sizeof(buffer), "(%s)", dp); |
---|
218 | free (dp); |
---|
219 | printf (LSTFMT2d2, buffer); |
---|
220 | } |
---|
221 | |
---|
222 | if (debug) |
---|
223 | list_debug (ct); |
---|
224 | |
---|
225 | return OK; |
---|
226 | } |
---|
227 | |
---|
228 | |
---|
229 | /* |
---|
230 | * Print debugging information about a content |
---|
231 | */ |
---|
232 | |
---|
233 | static int |
---|
234 | list_debug (CT ct) |
---|
235 | { |
---|
236 | char **ap, **ep; |
---|
237 | CI ci = &ct->c_ctinfo; |
---|
238 | |
---|
239 | fflush (stdout); |
---|
240 | fprintf (stderr, " partno \"%s\"\n", empty (ct->c_partno)); |
---|
241 | |
---|
242 | /* print MIME-Version line */ |
---|
243 | if (ct->c_vrsn) |
---|
244 | fprintf (stderr, " %s:%s\n", VRSN_FIELD, ct->c_vrsn); |
---|
245 | |
---|
246 | /* print Content-Type line */ |
---|
247 | if (ct->c_ctline) |
---|
248 | fprintf (stderr, " %s:%s\n", TYPE_FIELD, ct->c_ctline); |
---|
249 | |
---|
250 | /* print parsed elements of content type */ |
---|
251 | fprintf (stderr, " type \"%s\"\n", empty (ci->ci_type)); |
---|
252 | fprintf (stderr, " subtype \"%s\"\n", empty (ci->ci_subtype)); |
---|
253 | fprintf (stderr, " comment \"%s\"\n", empty (ci->ci_comment)); |
---|
254 | fprintf (stderr, " magic \"%s\"\n", empty (ci->ci_magic)); |
---|
255 | |
---|
256 | /* print parsed parameters attached to content type */ |
---|
257 | fprintf (stderr, " parameters\n"); |
---|
258 | for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) |
---|
259 | fprintf (stderr, " %s=\"%s\"\n", *ap, *ep); |
---|
260 | |
---|
261 | /* print internal flags for type/subtype */ |
---|
262 | fprintf (stderr, " type 0x%x subtype 0x%x params 0x%x\n", |
---|
263 | ct->c_type, ct->c_subtype, (unsigned int) ct->c_ctparams); |
---|
264 | |
---|
265 | fprintf (stderr, " showproc \"%s\"\n", empty (ct->c_showproc)); |
---|
266 | fprintf (stderr, " termproc \"%s\"\n", empty (ct->c_termproc)); |
---|
267 | fprintf (stderr, " storeproc \"%s\"\n", empty (ct->c_storeproc)); |
---|
268 | |
---|
269 | /* print transfer encoding information */ |
---|
270 | if (ct->c_celine) |
---|
271 | fprintf (stderr, " %s:%s", ENCODING_FIELD, ct->c_celine); |
---|
272 | |
---|
273 | /* print internal flags for transfer encoding */ |
---|
274 | fprintf (stderr, " transfer encoding 0x%x params 0x%x\n", |
---|
275 | ct->c_encoding, (unsigned int) ct->c_cefile); |
---|
276 | |
---|
277 | /* print Content-ID */ |
---|
278 | if (ct->c_id) |
---|
279 | fprintf (stderr, " %s:%s", ID_FIELD, ct->c_id); |
---|
280 | |
---|
281 | /* print Content-Description */ |
---|
282 | if (ct->c_descr) |
---|
283 | fprintf (stderr, " %s:%s", DESCR_FIELD, ct->c_descr); |
---|
284 | |
---|
285 | fprintf (stderr, " read fp 0x%x file \"%s\" begin %ld end %ld\n", |
---|
286 | (unsigned int) ct->c_fp, empty (ct->c_file), |
---|
287 | ct->c_begin, ct->c_end); |
---|
288 | |
---|
289 | /* print more information about transfer encoding */ |
---|
290 | list_encoding (ct); |
---|
291 | |
---|
292 | return OK; |
---|
293 | } |
---|
294 | |
---|
295 | #undef empty |
---|
296 | |
---|
297 | |
---|
298 | /* |
---|
299 | * list content information for type "multipart" |
---|
300 | */ |
---|
301 | |
---|
302 | static int |
---|
303 | list_multi (CT ct, int toplevel, int realsize, int verbose, int debug) |
---|
304 | { |
---|
305 | struct multipart *m = (struct multipart *) ct->c_ctparams; |
---|
306 | struct part *part; |
---|
307 | |
---|
308 | /* list the content for toplevel of this multipart */ |
---|
309 | list_content (ct, toplevel, realsize, verbose, debug); |
---|
310 | |
---|
311 | /* now list for all the subparts */ |
---|
312 | for (part = m->mp_parts; part; part = part->mp_next) { |
---|
313 | CT p = part->mp_part; |
---|
314 | |
---|
315 | if (part_ok (p, 1) && type_ok (p, 1)) |
---|
316 | list_switch (p, 0, realsize, verbose, debug); |
---|
317 | } |
---|
318 | |
---|
319 | return OK; |
---|
320 | } |
---|
321 | |
---|
322 | |
---|
323 | /* |
---|
324 | * list content information for type "message/partial" |
---|
325 | */ |
---|
326 | |
---|
327 | static int |
---|
328 | list_partial (CT ct, int toplevel, int realsize, int verbose, int debug) |
---|
329 | { |
---|
330 | struct partial *p = (struct partial *) ct->c_ctparams; |
---|
331 | |
---|
332 | list_content (ct, toplevel, realsize, verbose, debug); |
---|
333 | if (verbose) { |
---|
334 | printf ("\t [message %s, part %d", p->pm_partid, p->pm_partno); |
---|
335 | if (p->pm_maxno) |
---|
336 | printf (" of %d", p->pm_maxno); |
---|
337 | printf ("]\n"); |
---|
338 | } |
---|
339 | |
---|
340 | return OK; |
---|
341 | } |
---|
342 | |
---|
343 | |
---|
344 | /* |
---|
345 | * list content information for type "message/external" |
---|
346 | */ |
---|
347 | |
---|
348 | static int |
---|
349 | list_external (CT ct, int toplevel, int realsize, int verbose, int debug) |
---|
350 | { |
---|
351 | struct exbody *e = (struct exbody *) ct->c_ctparams; |
---|
352 | |
---|
353 | /* |
---|
354 | * First list the information for the |
---|
355 | * message/external content itself. |
---|
356 | */ |
---|
357 | list_content (ct, toplevel, realsize, verbose, debug); |
---|
358 | |
---|
359 | if (verbose) { |
---|
360 | if (e->eb_name) |
---|
361 | printf ("\t name=\"%s\"\n", e->eb_name); |
---|
362 | if (e->eb_dir) |
---|
363 | printf ("\t directory=\"%s\"\n", e->eb_dir); |
---|
364 | if (e->eb_site) |
---|
365 | printf ("\t site=\"%s\"\n", e->eb_site); |
---|
366 | if (e->eb_server) |
---|
367 | printf ("\t server=\"%s\"\n", e->eb_server); |
---|
368 | if (e->eb_subject) |
---|
369 | printf ("\t subject=\"%s\"\n", e->eb_subject); |
---|
370 | |
---|
371 | /* This must be defined */ |
---|
372 | printf ("\t access-type=\"%s\"\n", e->eb_access); |
---|
373 | |
---|
374 | if (e->eb_mode) |
---|
375 | printf ("\t mode=\"%s\"\n", e->eb_mode); |
---|
376 | if (e->eb_permission) |
---|
377 | printf ("\t permission=\"%s\"\n", e->eb_permission); |
---|
378 | |
---|
379 | if (e->eb_flags == NOTOK) |
---|
380 | printf ("\t [service unavailable]\n"); |
---|
381 | } |
---|
382 | |
---|
383 | /* |
---|
384 | * Now list the information for the external content |
---|
385 | * to which this content points. |
---|
386 | */ |
---|
387 | list_content (e->eb_content, 0, realsize, verbose, debug); |
---|
388 | |
---|
389 | return OK; |
---|
390 | } |
---|
391 | |
---|
392 | |
---|
393 | /* |
---|
394 | * list content information for type "application" |
---|
395 | */ |
---|
396 | |
---|
397 | static int |
---|
398 | list_application (CT ct, int toplevel, int realsize, int verbose, int debug) |
---|
399 | { |
---|
400 | list_content (ct, toplevel, realsize, verbose, debug); |
---|
401 | if (verbose) { |
---|
402 | char **ap, **ep; |
---|
403 | CI ci = &ct->c_ctinfo; |
---|
404 | |
---|
405 | for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) |
---|
406 | printf ("\t %s=\"%s\"\n", *ap, *ep); |
---|
407 | } |
---|
408 | |
---|
409 | return OK; |
---|
410 | } |
---|
411 | |
---|
412 | |
---|
413 | /* |
---|
414 | * list information about the Content-Transfer-Encoding |
---|
415 | * used by a content. |
---|
416 | */ |
---|
417 | |
---|
418 | static int |
---|
419 | list_encoding (CT ct) |
---|
420 | { |
---|
421 | CE ce; |
---|
422 | |
---|
423 | if ((ce = ct->c_cefile)) |
---|
424 | fprintf (stderr, " decoded fp 0x%x file \"%s\"\n", |
---|
425 | (unsigned int) ce->ce_fp, ce->ce_file ? ce->ce_file : ""); |
---|
426 | |
---|
427 | return OK; |
---|
428 | } |
---|