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