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