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