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