mail: implement struct command.
* NEWS, doc/texinfo/programs.texi: Document struct command. * mail/struct.c: New file. * mail/Makefile.am (mail_SOURCES): Add struct.c * mail/decode.c (fprint_msgset, mime_descend): New functions. Rewrite the rest using mime_descend. * mail/mail.h (mail_struct): New function. (MDHINT_SELECTED_HEADERS): New define. (struct mime_descend_closure, mime_descend_fn): New types. (mime_descend): New proto. (util_get_content_type): Get two arguments. * mail/table.c (mail_command_table): Add st[ruct]. * mail/util.c (util_get_content_type): Get two arguments. All callers updated. (util_get_hdr_value): use mu_header_aget_value_unfold and mu_rtrim_class.
Showing
8 changed files
with
235 additions
and
56 deletions
1 | GNU mailutils NEWS -- history of user-visible changes. 2009-07-12 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2009-07-13 |
2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, | 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, |
3 | 2008, 2009 Free Software Foundation, Inc. | 3 | 2008, 2009 Free Software Foundation, Inc. |
4 | See the end of file for copying conditions. | 4 | See the end of file for copying conditions. |
... | @@ -53,6 +53,15 @@ is also allowed. | ... | @@ -53,6 +53,15 @@ is also allowed. |
53 | The -F option (record outgoing messages in a file named after the | 53 | The -F option (record outgoing messages in a file named after the |
54 | first recipient) is implemented. | 54 | first recipient) is implemented. |
55 | 55 | ||
56 | ** struct command | ||
57 | |||
58 | The st[ruct] command allows to list message MIME structures, e.g.: | ||
59 | |||
60 | & struct 2 | ||
61 | 2[1] text/plain 513 | ||
62 | 2[2] application/octal-stream 247K | ||
63 | 2[3] text/x-diff 31K | ||
64 | |||
56 | ** error locations | 65 | ** error locations |
57 | 66 | ||
58 | Diagnostic messages issued while processing `source' command | 67 | Diagnostic messages issued while processing `source' command | ... | ... |
... | @@ -2878,6 +2878,7 @@ Displays current mailbox summary. E.g.: | ... | @@ -2878,6 +2878,7 @@ Displays current mailbox summary. E.g.: |
2878 | @kyindex Print, mail command | 2878 | @kyindex Print, mail command |
2879 | @kyindex Type, mail command | 2879 | @kyindex Type, mail command |
2880 | @kyindex decode, mail command | 2880 | @kyindex decode, mail command |
2881 | @kyindex struct, mail command | ||
2881 | @kyindex top, mail command | 2882 | @kyindex top, mail command |
2882 | @kyindex pipe, mail command | 2883 | @kyindex pipe, mail command |
2883 | @kyindex |, mail command | 2884 | @kyindex |, mail command |
... | @@ -2926,6 +2927,21 @@ defaults to five. | ... | @@ -2926,6 +2927,21 @@ defaults to five. |
2926 | Pipe the contents of specified messages through @var{shell-command}. If | 2927 | Pipe the contents of specified messages through @var{shell-command}. If |
2927 | @var{shell-command} is empty but the string variable @code{cmd} is set, | 2928 | @var{shell-command} is empty but the string variable @code{cmd} is set, |
2928 | the value of this variable is used as a command name. | 2929 | the value of this variable is used as a command name. |
2930 | @item struct [@var{msglist}] | ||
2931 | Prints the @acronym{MIME} structure of each message from | ||
2932 | @var{msglist}. Empty @var{msglist} means current message. | ||
2933 | |||
2934 | Example: | ||
2935 | |||
2936 | @smallexample | ||
2937 | @cartouche | ||
2938 | & struct 2 | ||
2939 | 2 multipart/mixed 14k | ||
2940 | 2[1] text/plain 296 | ||
2941 | 2[2] application/octet-stream 5k | ||
2942 | 2[3] text/x-diff 31k | ||
2943 | @end cartouche | ||
2944 | @end smallexample | ||
2929 | @end table | 2945 | @end table |
2930 | 2946 | ||
2931 | @node Marking Messages | 2947 | @node Marking Messages | ... | ... |
... | @@ -33,7 +33,8 @@ struct decode_closure | ... | @@ -33,7 +33,8 @@ struct decode_closure |
33 | 33 | ||
34 | static int print_stream (mu_stream_t, FILE *); | 34 | static int print_stream (mu_stream_t, FILE *); |
35 | static int display_message (mu_message_t, msgset_t *msgset, void *closure); | 35 | static int display_message (mu_message_t, msgset_t *msgset, void *closure); |
36 | static int display_message0 (mu_message_t, const msgset_t *, int); | 36 | static int display_submessage (struct mime_descend_closure *closure, |
37 | void *data); | ||
37 | static int get_content_encoding (mu_header_t hdr, char **value); | 38 | static int get_content_encoding (mu_header_t hdr, char **value); |
38 | static void run_metamail (const char *mailcap, mu_message_t mesg); | 39 | static void run_metamail (const char *mailcap, mu_message_t mesg); |
39 | 40 | ||
... | @@ -59,12 +60,20 @@ display_message (mu_message_t mesg, msgset_t *msgset, void *arg) | ... | @@ -59,12 +60,20 @@ display_message (mu_message_t mesg, msgset_t *msgset, void *arg) |
59 | { | 60 | { |
60 | struct decode_closure *closure = arg; | 61 | struct decode_closure *closure = arg; |
61 | mu_attribute_t attr = NULL; | 62 | mu_attribute_t attr = NULL; |
62 | 63 | struct mime_descend_closure mclos; | |
64 | |||
63 | mu_message_get_attribute (mesg, &attr); | 65 | mu_message_get_attribute (mesg, &attr); |
64 | if (mu_attribute_is_deleted (attr)) | 66 | if (mu_attribute_is_deleted (attr)) |
65 | return 1; | 67 | return 1; |
66 | 68 | ||
67 | display_message0 (mesg, msgset, closure->select_hdr); | 69 | mclos.hints = closure->select_hdr ? MDHINT_SELECTED_HEADERS : 0; |
70 | mclos.msgset = msgset; | ||
71 | mclos.message = mesg; | ||
72 | mclos.type = NULL; | ||
73 | mclos.encoding = NULL; | ||
74 | mclos.parent = NULL; | ||
75 | |||
76 | mime_descend (&mclos, display_submessage, NULL); | ||
68 | 77 | ||
69 | /* Mark enclosing message as read */ | 78 | /* Mark enclosing message as read */ |
70 | if (mu_mailbox_get_message (mbox, msgset->msg_part[0], &mesg) == 0) | 79 | if (mu_mailbox_get_message (mbox, msgset->msg_part[0], &mesg) == 0) |
... | @@ -112,9 +121,23 @@ display_headers (FILE *out, mu_message_t mesg, | ... | @@ -112,9 +121,23 @@ display_headers (FILE *out, mu_message_t mesg, |
112 | } | 121 | } |
113 | } | 122 | } |
114 | 123 | ||
124 | size_t | ||
125 | fprint_msgset (FILE *fp, const msgset_t *msgset) | ||
126 | { | ||
127 | int i; | ||
128 | size_t n = 0; | ||
129 | |||
130 | n = fprintf (fp, "%d", msgset->msg_part[0]); | ||
131 | for (i = 1; i < msgset->npart; i++) | ||
132 | n += fprintf (fp, "[%d", msgset->msg_part[i]); | ||
133 | for (i = 1; i < msgset->npart; i++) | ||
134 | n += fprintf (fp, "]"); | ||
135 | return n; | ||
136 | } | ||
137 | |||
115 | static void | 138 | static void |
116 | display_part_header (FILE *out, const msgset_t *msgset, | 139 | display_part_header (FILE *out, const msgset_t *msgset, |
117 | char *type, char *encoding) | 140 | const char *type, const char *encoding) |
118 | { | 141 | { |
119 | int size = util_screen_columns () - 3; | 142 | int size = util_screen_columns () - 3; |
120 | unsigned int i; | 143 | unsigned int i; |
... | @@ -124,11 +147,8 @@ display_part_header (FILE *out, const msgset_t *msgset, | ... | @@ -124,11 +147,8 @@ display_part_header (FILE *out, const msgset_t *msgset, |
124 | fputc ('-', out); | 147 | fputc ('-', out); |
125 | fputc ('+', out); | 148 | fputc ('+', out); |
126 | fputc ('\n', out); | 149 | fputc ('\n', out); |
127 | fprintf (out, _("| Message=%d"), msgset->msg_part[0]); | 150 | fprintf (out, "%s", _("| Message=")); |
128 | for (i = 1; i < msgset->npart; i++) | 151 | fprint_msgset (out, msgset); |
129 | fprintf (out, "[%d", msgset->msg_part[i]); | ||
130 | for (i = 1; i < msgset->npart; i++) | ||
131 | fprintf (out, "]"); | ||
132 | fprintf (out, "\n"); | 152 | fprintf (out, "\n"); |
133 | 153 | ||
134 | fprintf (out, _("| Type=%s\n"), type); | 154 | fprintf (out, _("| Type=%s\n"), type); |
... | @@ -140,38 +160,49 @@ display_part_header (FILE *out, const msgset_t *msgset, | ... | @@ -140,38 +160,49 @@ display_part_header (FILE *out, const msgset_t *msgset, |
140 | fputc ('\n', out); | 160 | fputc ('\n', out); |
141 | } | 161 | } |
142 | 162 | ||
143 | static int | 163 | int |
144 | display_message0 (mu_message_t mesg, const msgset_t *msgset, | 164 | mime_descend (struct mime_descend_closure *closure, |
145 | int select_hdr) | 165 | mime_descend_fn fun, void *data) |
146 | { | 166 | { |
167 | int status = 0; | ||
147 | size_t nparts = 0; | 168 | size_t nparts = 0; |
148 | mu_header_t hdr = NULL; | 169 | mu_header_t hdr = NULL; |
149 | char *type; | 170 | char *type; |
150 | char *encoding; | 171 | char *encoding; |
151 | int ismime = 0; | 172 | int ismime = 0; |
152 | char *tmp; | 173 | struct mime_descend_closure subclosure; |
153 | 174 | ||
154 | mu_message_get_header (mesg, &hdr); | 175 | mu_message_get_header (closure->message, &hdr); |
155 | util_get_content_type (hdr, &type); | 176 | util_get_content_type (hdr, &type, NULL); |
156 | get_content_encoding (hdr, &encoding); | 177 | get_content_encoding (hdr, &encoding); |
157 | 178 | ||
158 | mu_message_is_multipart (mesg, &ismime); | 179 | closure->type = type; |
180 | closure->encoding = encoding; | ||
181 | |||
182 | subclosure.hints = 0; | ||
183 | subclosure.parent = closure; | ||
184 | |||
185 | mu_message_is_multipart (closure->message, &ismime); | ||
159 | if (ismime) | 186 | if (ismime) |
160 | { | 187 | { |
161 | unsigned int j; | 188 | unsigned int j; |
162 | 189 | ||
163 | mu_message_get_num_parts (mesg, &nparts); | 190 | mu_message_get_num_parts (closure->message, &nparts); |
164 | 191 | ||
165 | for (j = 1; j <= nparts; j++) | 192 | for (j = 1; j <= nparts; j++) |
166 | { | 193 | { |
167 | mu_message_t message = NULL; | 194 | mu_message_t message = NULL; |
168 | 195 | ||
169 | if (mu_message_get_part (mesg, j, &message) == 0) | 196 | if (mu_message_get_part (closure->message, j, &message) == 0) |
170 | { | 197 | { |
171 | msgset_t *set = msgset_expand (msgset_dup (msgset), | 198 | msgset_t *set = msgset_expand (msgset_dup (closure->msgset), |
172 | msgset_make_1 (j)); | 199 | msgset_make_1 (j)); |
173 | display_message0 (message, set, 0); | 200 | subclosure.msgset = set; |
201 | subclosure.message = message; | ||
202 | status = mime_descend (&subclosure, fun, data); | ||
174 | msgset_free (set); | 203 | msgset_free (set); |
204 | if (status) | ||
205 | break; | ||
175 | } | 206 | } |
176 | } | 207 | } |
177 | } | 208 | } |
... | @@ -179,14 +210,36 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, | ... | @@ -179,14 +210,36 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, |
179 | { | 210 | { |
180 | mu_message_t submsg = NULL; | 211 | mu_message_t submsg = NULL; |
181 | 212 | ||
182 | if (mu_message_unencapsulate (mesg, &submsg, NULL) == 0) | 213 | if (mu_message_unencapsulate (closure->message, &submsg, NULL) == 0) |
183 | display_message0 (submsg, msgset, select_hdr); | 214 | { |
215 | subclosure.hints = MDHINT_SELECTED_HEADERS; | ||
216 | subclosure.msgset = closure->msgset; | ||
217 | subclosure.message = submsg; | ||
218 | status = mime_descend (&subclosure, fun, data); | ||
219 | } | ||
184 | } | 220 | } |
185 | else if (mailvar_get (&tmp, "metamail", mailvar_type_string, 0) == 0) | 221 | else |
222 | status = fun (closure, data); | ||
223 | |||
224 | closure->type = NULL; | ||
225 | closure->encoding = NULL; | ||
226 | |||
227 | free (type); | ||
228 | free (encoding); | ||
229 | |||
230 | return status; | ||
231 | } | ||
232 | |||
233 | static int | ||
234 | display_submessage (struct mime_descend_closure *closure, void *data) | ||
235 | { | ||
236 | char *tmp; | ||
237 | |||
238 | if (mailvar_get (&tmp, "metamail", mailvar_type_string, 0) == 0) | ||
186 | { | 239 | { |
187 | /* If `metamail' is set to a string, treat it as command line | 240 | /* If `metamail' is set to a string, treat it as command line |
188 | of external metamail program. */ | 241 | of external metamail program. */ |
189 | run_metamail (tmp, mesg); | 242 | run_metamail (tmp, closure->message); |
190 | } | 243 | } |
191 | else | 244 | else |
192 | { | 245 | { |
... | @@ -197,19 +250,20 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, | ... | @@ -197,19 +250,20 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, |
197 | mu_stream_t stream = NULL; | 250 | mu_stream_t stream = NULL; |
198 | mu_header_t hdr = NULL; | 251 | mu_header_t hdr = NULL; |
199 | 252 | ||
200 | mu_message_get_body (mesg, &body); | 253 | mu_message_get_body (closure->message, &body); |
201 | mu_message_get_header (mesg, &hdr); | 254 | mu_message_get_header (closure->message, &hdr); |
202 | mu_body_get_stream (body, &b_stream); | 255 | mu_body_get_stream (body, &b_stream); |
203 | 256 | ||
204 | /* Can we decode. */ | 257 | /* Can we decode. */ |
205 | if (mu_filter_create(&d_stream, b_stream, encoding, | 258 | if (mu_filter_create(&d_stream, b_stream, closure->encoding, |
206 | MU_FILTER_DECODE, MU_STREAM_READ) == 0) | 259 | MU_FILTER_DECODE, MU_STREAM_READ) == 0) |
207 | stream = d_stream; | 260 | stream = d_stream; |
208 | else | 261 | else |
209 | stream = b_stream; | 262 | stream = b_stream; |
210 | 263 | ||
211 | display_part_header (ofile, msgset, type, encoding); | 264 | display_part_header (ofile, closure->msgset, |
212 | 265 | closure->type, closure->encoding); | |
266 | |||
213 | /* If `metamail' is set to true, enable internal mailcap | 267 | /* If `metamail' is set to true, enable internal mailcap |
214 | support */ | 268 | support */ |
215 | if (mailvar_get (NULL, "metamail", mailvar_type_boolean, 0) == 0) | 269 | if (mailvar_get (NULL, "metamail", mailvar_type_boolean, 0) == 0) |
... | @@ -225,33 +279,31 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, | ... | @@ -225,33 +279,31 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, |
225 | builtin_display = display_stream_mailcap (NULL, stream, hdr, no_ask, | 279 | builtin_display = display_stream_mailcap (NULL, stream, hdr, no_ask, |
226 | interactive, 0, debug); | 280 | interactive, 0, debug); |
227 | } | 281 | } |
228 | 282 | ||
229 | if (builtin_display) | 283 | if (builtin_display) |
230 | { | 284 | { |
231 | size_t lines = 0; | 285 | size_t lines = 0; |
232 | int pagelines = util_get_crt (); | 286 | int pagelines = util_get_crt (); |
233 | FILE *out; | 287 | FILE *out; |
234 | 288 | ||
235 | mu_message_lines (mesg, &lines); | 289 | mu_message_lines (closure->message, &lines); |
236 | if (pagelines && lines > pagelines) | 290 | if (pagelines && lines > pagelines) |
237 | out = popen (getenv ("PAGER"), "w"); | 291 | out = popen (getenv ("PAGER"), "w"); |
238 | else | 292 | else |
239 | out = ofile; | 293 | out = ofile; |
240 | 294 | ||
241 | display_headers (out, mesg, msgset, select_hdr); | 295 | display_headers (out, closure->message, closure->msgset, |
242 | 296 | closure->hints & MDHINT_SELECTED_HEADERS); | |
297 | |||
243 | print_stream (stream, out); | 298 | print_stream (stream, out); |
244 | 299 | ||
245 | if (out != ofile) | 300 | if (out != ofile) |
246 | pclose (out); | 301 | pclose (out); |
247 | } | 302 | } |
248 | if (d_stream) | 303 | if (d_stream) |
249 | mu_stream_destroy (&d_stream, NULL); | 304 | mu_stream_destroy (&d_stream, NULL); |
250 | } | 305 | } |
251 | 306 | ||
252 | free (type); | ||
253 | free (encoding); | ||
254 | |||
255 | return 0; | 307 | return 0; |
256 | } | 308 | } |
257 | 309 | ... | ... |
... | @@ -242,6 +242,7 @@ extern int mail_eq (int argc, char **argv); /* command = */ | ... | @@ -242,6 +242,7 @@ extern int mail_eq (int argc, char **argv); /* command = */ |
242 | extern int mail_setenv (int argc, char **argv); | 242 | extern int mail_setenv (int argc, char **argv); |
243 | extern int mail_envelope (int argc, char **argv); | 243 | extern int mail_envelope (int argc, char **argv); |
244 | extern int print_envelope (msgset_t *mspec, mu_message_t msg, void *data); | 244 | extern int print_envelope (msgset_t *mspec, mu_message_t msg, void *data); |
245 | extern int mail_struct (int argc, char **argv); | ||
245 | 246 | ||
246 | extern int if_cond (void); | 247 | extern int if_cond (void); |
247 | 248 | ||
... | @@ -307,6 +308,27 @@ extern int msgset_member (msgset_t *set, size_t n); | ... | @@ -307,6 +308,27 @@ extern int msgset_member (msgset_t *set, size_t n); |
307 | extern msgset_t *msgset_negate (msgset_t *set); | 308 | extern msgset_t *msgset_negate (msgset_t *set); |
308 | extern size_t msgset_count (msgset_t *set); | 309 | extern size_t msgset_count (msgset_t *set); |
309 | 310 | ||
311 | |||
312 | #define MDHINT_SELECTED_HEADERS 0x1 | ||
313 | |||
314 | struct mime_descend_closure | ||
315 | { | ||
316 | int hints; | ||
317 | const msgset_t *msgset; | ||
318 | mu_message_t message; | ||
319 | const char *type; | ||
320 | const char *encoding; | ||
321 | const struct mime_descend_closure *parent; | ||
322 | }; | ||
323 | |||
324 | typedef int (*mime_descend_fn) (struct mime_descend_closure *closure, | ||
325 | void *data); | ||
326 | |||
327 | extern int mime_descend (struct mime_descend_closure *closure, | ||
328 | mime_descend_fn fun, void *data); | ||
329 | |||
330 | |||
331 | |||
310 | extern int util_do_command (const char *cmd, ...) MU_PRINTFLIKE(1,2); | 332 | extern int util_do_command (const char *cmd, ...) MU_PRINTFLIKE(1,2); |
311 | 333 | ||
312 | extern int util_foreach_msg (int argc, char **argv, int flags, | 334 | extern int util_foreach_msg (int argc, char **argv, int flags, |
... | @@ -369,7 +391,7 @@ extern int util_tempfile (char **namep); | ... | @@ -369,7 +391,7 @@ extern int util_tempfile (char **namep); |
369 | extern void util_msgset_iterate (msgset_t *msgset, | 391 | extern void util_msgset_iterate (msgset_t *msgset, |
370 | int (*fun) (mu_message_t, msgset_t *, void *), | 392 | int (*fun) (mu_message_t, msgset_t *, void *), |
371 | void *closure); | 393 | void *closure); |
372 | extern int util_get_content_type (mu_header_t hdr, char **value); | 394 | extern int util_get_content_type (mu_header_t hdr, char **value, char **args); |
373 | extern int util_get_hdr_value (mu_header_t hdr, const char *name, char **value); | 395 | extern int util_get_hdr_value (mu_header_t hdr, const char *name, char **value); |
374 | extern int util_merge_addresses (char **addr_str, const char *value); | 396 | extern int util_merge_addresses (char **addr_str, const char *value); |
375 | extern int util_header_expand (mu_header_t *hdr); | 397 | extern int util_header_expand (mu_header_t *hdr); |
... | @@ -383,6 +405,8 @@ void util_mark_read (mu_message_t msg); | ... | @@ -383,6 +405,8 @@ void util_mark_read (mu_message_t msg); |
383 | 405 | ||
384 | const char *util_url_to_string (mu_url_t url); | 406 | const char *util_url_to_string (mu_url_t url); |
385 | 407 | ||
408 | size_t fprint_msgset (FILE *fp, const msgset_t *msgset); | ||
409 | |||
386 | int is_address_field (const char *name); | 410 | int is_address_field (const char *name); |
387 | 411 | ||
388 | extern int ml_got_interrupt (void); | 412 | extern int ml_got_interrupt (void); | ... | ... |
mail/struct.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2009 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #include "mail.h" | ||
18 | |||
19 | #define PART_WIDTH 8 | ||
20 | |||
21 | static int | ||
22 | show_part (struct mime_descend_closure *closure, void *data) | ||
23 | { | ||
24 | size_t width; | ||
25 | size_t size = 0; | ||
26 | |||
27 | width = fprint_msgset (ofile, closure->msgset); | ||
28 | for (; width < 5; width++) | ||
29 | fputc (' ', ofile); | ||
30 | |||
31 | fprintf (ofile, " %-25s", closure->type); | ||
32 | |||
33 | mu_message_size (closure->message, &size); | ||
34 | if (size < 1024) | ||
35 | fprintf (ofile, " %4lu", (unsigned long) size); | ||
36 | else if (size < 1024*1024) | ||
37 | fprintf (ofile, "%4luK", (unsigned long) size / 1024); | ||
38 | else | ||
39 | fprintf (ofile, "%4luM", (unsigned long) size / 1024 / 1024); | ||
40 | |||
41 | fprintf (ofile, "\n"); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int | ||
46 | show_struct (msgset_t *msgset, mu_message_t msg, void *data) | ||
47 | { | ||
48 | struct mime_descend_closure mclos; | ||
49 | |||
50 | mclos.hints = 0; | ||
51 | mclos.msgset = msgset; | ||
52 | mclos.message = msg; | ||
53 | mclos.type = NULL; | ||
54 | mclos.encoding = NULL; | ||
55 | mclos.parent = NULL; | ||
56 | |||
57 | mime_descend (&mclos, show_part, NULL); | ||
58 | |||
59 | /* Mark enclosing message as read */ | ||
60 | if (mu_mailbox_get_message (mbox, msgset->msg_part[0], &msg) == 0) | ||
61 | util_mark_read (msg); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | int | ||
67 | mail_struct (int argc, char **argv) | ||
68 | { | ||
69 | return util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT, | ||
70 | show_struct, NULL); | ||
71 | } |
... | @@ -136,6 +136,8 @@ static const struct mail_command_entry mail_command_table[] = { | ... | @@ -136,6 +136,8 @@ static const struct mail_command_entry mail_command_table[] = { |
136 | mail_size, msglist_compl }, | 136 | mail_size, msglist_compl }, |
137 | { "so", "source", "so[urce] file", 0, | 137 | { "so", "source", "so[urce] file", 0, |
138 | mail_source, NULL }, | 138 | mail_source, NULL }, |
139 | { "st", "struct", "st[ruct] [msglist]", 0, | ||
140 | mail_struct, NULL }, | ||
139 | { "su", "summary", "su[mmary]", 0, | 141 | { "su", "summary", "su[mmary]", 0, |
140 | mail_summary, no_compl }, | 142 | mail_summary, no_compl }, |
141 | { "T", "Type", "T[ype] [msglist]", 0, | 143 | { "T", "Type", "T[ype] [msglist]", 0, | ... | ... |
... | @@ -793,7 +793,7 @@ util_descend_subparts (mu_message_t mesg, msgset_t *msgset, mu_message_t *part) | ... | @@ -793,7 +793,7 @@ util_descend_subparts (mu_message_t mesg, msgset_t *msgset, mu_message_t *part) |
793 | mu_header_t hdr = NULL; | 793 | mu_header_t hdr = NULL; |
794 | 794 | ||
795 | mu_message_get_header (mesg, &hdr); | 795 | mu_message_get_header (mesg, &hdr); |
796 | util_get_content_type (hdr, &type); | 796 | util_get_content_type (hdr, &type, NULL); |
797 | if (mu_c_strncasecmp (type, "message/rfc822", strlen (type)) == 0) | 797 | if (mu_c_strncasecmp (type, "message/rfc822", strlen (type)) == 0) |
798 | { | 798 | { |
799 | if (mu_message_unencapsulate (mesg, &submsg, NULL)) | 799 | if (mu_message_unencapsulate (mesg, &submsg, NULL)) |
... | @@ -839,12 +839,12 @@ util_msgset_iterate (msgset_t *msgset, | ... | @@ -839,12 +839,12 @@ util_msgset_iterate (msgset_t *msgset, |
839 | return; | 839 | return; |
840 | 840 | ||
841 | if (util_descend_subparts (mesg, msgset, &mesg) == 0) | 841 | if (util_descend_subparts (mesg, msgset, &mesg) == 0) |
842 | (*fun)(mesg, msgset, closure); | 842 | (*fun) (mesg, msgset, closure); |
843 | } | 843 | } |
844 | } | 844 | } |
845 | 845 | ||
846 | int | 846 | int |
847 | util_get_content_type (mu_header_t hdr, char **value) | 847 | util_get_content_type (mu_header_t hdr, char **value, char **args) |
848 | { | 848 | { |
849 | char *type = NULL; | 849 | char *type = NULL; |
850 | util_get_hdr_value (hdr, MU_HEADER_CONTENT_TYPE, &type); | 850 | util_get_hdr_value (hdr, MU_HEADER_CONTENT_TYPE, &type); |
... | @@ -854,6 +854,17 @@ util_get_content_type (mu_header_t hdr, char **value) | ... | @@ -854,6 +854,17 @@ util_get_content_type (mu_header_t hdr, char **value) |
854 | free (type); | 854 | free (type); |
855 | type = strdup ("text/plain"); /* Default. */ | 855 | type = strdup ("text/plain"); /* Default. */ |
856 | } | 856 | } |
857 | else | ||
858 | { | ||
859 | char *p; | ||
860 | p = strchr (type, ';'); | ||
861 | if (p) | ||
862 | { | ||
863 | *p++ = 0; | ||
864 | if (args) | ||
865 | *args = p; | ||
866 | } | ||
867 | } | ||
857 | *value = type; | 868 | *value = type; |
858 | return 0; | 869 | return 0; |
859 | } | 870 | } |
... | @@ -861,16 +872,9 @@ util_get_content_type (mu_header_t hdr, char **value) | ... | @@ -861,16 +872,9 @@ util_get_content_type (mu_header_t hdr, char **value) |
861 | int | 872 | int |
862 | util_get_hdr_value (mu_header_t hdr, const char *name, char **value) | 873 | util_get_hdr_value (mu_header_t hdr, const char *name, char **value) |
863 | { | 874 | { |
864 | int status = mu_header_aget_value (hdr, name, value); | 875 | int status = mu_header_aget_value_unfold (hdr, name, value); |
865 | if (status == 0) | 876 | if (status == 0) |
866 | { | 877 | mu_rtrim_class (*value, MU_CTYPE_SPACE); |
867 | /* Remove the newlines. */ | ||
868 | char *nl; | ||
869 | while ((nl = strchr (*value, '\n')) != NULL) | ||
870 | { | ||
871 | *nl = ' '; | ||
872 | } | ||
873 | } | ||
874 | return status; | 878 | return status; |
875 | } | 879 | } |
876 | 880 | ... | ... |
-
Please register or sign in to post a comment