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