diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-07-13 14:42:40 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-07-13 15:07:02 +0300 |
commit | f8fc2081dffd950ab1c6082e4a32f0096bd7415d (patch) | |
tree | cdbfdf9d5b0996ee1b4f00d06c71901fb418cce9 /mail | |
parent | 0517ca033b3222afc09f5b70626c38280c749c14 (diff) | |
download | mailutils-f8fc2081dffd950ab1c6082e4a32f0096bd7415d.tar.gz mailutils-f8fc2081dffd950ab1c6082e4a32f0096bd7415d.tar.bz2 |
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.
Diffstat (limited to 'mail')
-rw-r--r-- | mail/Makefile.am | 1 | ||||
-rw-r--r-- | mail/decode.c | 136 | ||||
-rw-r--r-- | mail/mail.h | 26 | ||||
-rw-r--r-- | mail/struct.c | 71 | ||||
-rw-r--r-- | mail/table.c | 2 | ||||
-rw-r--r-- | mail/util.c | 28 |
6 files changed, 209 insertions, 55 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am index a47694bc5..bcd482df0 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -84,6 +84,7 @@ mail_SOURCES = \ shell.c\ size.c\ source.c\ + struct.c\ summary.c\ table.c\ tag.c\ diff --git a/mail/decode.c b/mail/decode.c index 369ed7626..1b951fbc2 100644 --- a/mail/decode.c +++ b/mail/decode.c @@ -33,7 +33,8 @@ struct decode_closure static int print_stream (mu_stream_t, FILE *); static int display_message (mu_message_t, msgset_t *msgset, void *closure); -static int display_message0 (mu_message_t, const msgset_t *, int); +static int display_submessage (struct mime_descend_closure *closure, + void *data); static int get_content_encoding (mu_header_t hdr, char **value); static void run_metamail (const char *mailcap, mu_message_t mesg); @@ -59,12 +60,20 @@ display_message (mu_message_t mesg, msgset_t *msgset, void *arg) { struct decode_closure *closure = arg; mu_attribute_t attr = NULL; - + struct mime_descend_closure mclos; + mu_message_get_attribute (mesg, &attr); if (mu_attribute_is_deleted (attr)) return 1; - display_message0 (mesg, msgset, closure->select_hdr); + mclos.hints = closure->select_hdr ? MDHINT_SELECTED_HEADERS : 0; + mclos.msgset = msgset; + mclos.message = mesg; + mclos.type = NULL; + mclos.encoding = NULL; + mclos.parent = NULL; + + mime_descend (&mclos, display_submessage, NULL); /* Mark enclosing message as read */ if (mu_mailbox_get_message (mbox, msgset->msg_part[0], &mesg) == 0) @@ -112,9 +121,23 @@ display_headers (FILE *out, mu_message_t mesg, } } +size_t +fprint_msgset (FILE *fp, const msgset_t *msgset) +{ + int i; + size_t n = 0; + + n = fprintf (fp, "%d", msgset->msg_part[0]); + for (i = 1; i < msgset->npart; i++) + n += fprintf (fp, "[%d", msgset->msg_part[i]); + for (i = 1; i < msgset->npart; i++) + n += fprintf (fp, "]"); + return n; +} + static void display_part_header (FILE *out, const msgset_t *msgset, - char *type, char *encoding) + const char *type, const char *encoding) { int size = util_screen_columns () - 3; unsigned int i; @@ -124,11 +147,8 @@ display_part_header (FILE *out, const msgset_t *msgset, fputc ('-', out); fputc ('+', out); fputc ('\n', out); - fprintf (out, _("| Message=%d"), msgset->msg_part[0]); - for (i = 1; i < msgset->npart; i++) - fprintf (out, "[%d", msgset->msg_part[i]); - for (i = 1; i < msgset->npart; i++) - fprintf (out, "]"); + fprintf (out, "%s", _("| Message=")); + fprint_msgset (out, msgset); fprintf (out, "\n"); fprintf (out, _("| Type=%s\n"), type); @@ -140,38 +160,49 @@ display_part_header (FILE *out, const msgset_t *msgset, fputc ('\n', out); } -static int -display_message0 (mu_message_t mesg, const msgset_t *msgset, - int select_hdr) +int +mime_descend (struct mime_descend_closure *closure, + mime_descend_fn fun, void *data) { + int status = 0; size_t nparts = 0; mu_header_t hdr = NULL; char *type; char *encoding; int ismime = 0; - char *tmp; + struct mime_descend_closure subclosure; - mu_message_get_header (mesg, &hdr); - util_get_content_type (hdr, &type); + mu_message_get_header (closure->message, &hdr); + util_get_content_type (hdr, &type, NULL); get_content_encoding (hdr, &encoding); - mu_message_is_multipart (mesg, &ismime); + closure->type = type; + closure->encoding = encoding; + + subclosure.hints = 0; + subclosure.parent = closure; + + mu_message_is_multipart (closure->message, &ismime); if (ismime) { unsigned int j; - - mu_message_get_num_parts (mesg, &nparts); + + mu_message_get_num_parts (closure->message, &nparts); for (j = 1; j <= nparts; j++) { mu_message_t message = NULL; - if (mu_message_get_part (mesg, j, &message) == 0) + if (mu_message_get_part (closure->message, j, &message) == 0) { - msgset_t *set = msgset_expand (msgset_dup (msgset), + msgset_t *set = msgset_expand (msgset_dup (closure->msgset), msgset_make_1 (j)); - display_message0 (message, set, 0); + subclosure.msgset = set; + subclosure.message = message; + status = mime_descend (&subclosure, fun, data); msgset_free (set); + if (status) + break; } } } @@ -179,14 +210,36 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, { mu_message_t submsg = NULL; - if (mu_message_unencapsulate (mesg, &submsg, NULL) == 0) - display_message0 (submsg, msgset, select_hdr); + if (mu_message_unencapsulate (closure->message, &submsg, NULL) == 0) + { + subclosure.hints = MDHINT_SELECTED_HEADERS; + subclosure.msgset = closure->msgset; + subclosure.message = submsg; + status = mime_descend (&subclosure, fun, data); + } } - else if (mailvar_get (&tmp, "metamail", mailvar_type_string, 0) == 0) + else + status = fun (closure, data); + + closure->type = NULL; + closure->encoding = NULL; + + free (type); + free (encoding); + + return status; +} + +static int +display_submessage (struct mime_descend_closure *closure, void *data) +{ + char *tmp; + + if (mailvar_get (&tmp, "metamail", mailvar_type_string, 0) == 0) { /* If `metamail' is set to a string, treat it as command line of external metamail program. */ - run_metamail (tmp, mesg); + run_metamail (tmp, closure->message); } else { @@ -197,19 +250,20 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, mu_stream_t stream = NULL; mu_header_t hdr = NULL; - mu_message_get_body (mesg, &body); - mu_message_get_header (mesg, &hdr); + mu_message_get_body (closure->message, &body); + mu_message_get_header (closure->message, &hdr); mu_body_get_stream (body, &b_stream); /* Can we decode. */ - if (mu_filter_create(&d_stream, b_stream, encoding, - MU_FILTER_DECODE, MU_STREAM_READ) == 0) + if (mu_filter_create(&d_stream, b_stream, closure->encoding, + MU_FILTER_DECODE, MU_STREAM_READ) == 0) stream = d_stream; else stream = b_stream; - - display_part_header (ofile, msgset, type, encoding); - + + display_part_header (ofile, closure->msgset, + closure->type, closure->encoding); + /* If `metamail' is set to true, enable internal mailcap support */ if (mailvar_get (NULL, "metamail", mailvar_type_boolean, 0) == 0) @@ -225,33 +279,31 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset, builtin_display = display_stream_mailcap (NULL, stream, hdr, no_ask, interactive, 0, debug); } - + if (builtin_display) { size_t lines = 0; int pagelines = util_get_crt (); FILE *out; - mu_message_lines (mesg, &lines); + mu_message_lines (closure->message, &lines); if (pagelines && lines > pagelines) out = popen (getenv ("PAGER"), "w"); else out = ofile; - - display_headers (out, mesg, msgset, select_hdr); - + + display_headers (out, closure->message, closure->msgset, + closure->hints & MDHINT_SELECTED_HEADERS); + print_stream (stream, out); - + if (out != ofile) pclose (out); } if (d_stream) mu_stream_destroy (&d_stream, NULL); } - - free (type); - free (encoding); - + return 0; } diff --git a/mail/mail.h b/mail/mail.h index b6e4c3901..54e4ce199 100644 --- a/mail/mail.h +++ b/mail/mail.h @@ -242,6 +242,7 @@ extern int mail_eq (int argc, char **argv); /* command = */ extern int mail_setenv (int argc, char **argv); extern int mail_envelope (int argc, char **argv); extern int print_envelope (msgset_t *mspec, mu_message_t msg, void *data); +extern int mail_struct (int argc, char **argv); extern int if_cond (void); @@ -307,6 +308,27 @@ extern int msgset_member (msgset_t *set, size_t n); extern msgset_t *msgset_negate (msgset_t *set); extern size_t msgset_count (msgset_t *set); + +#define MDHINT_SELECTED_HEADERS 0x1 + +struct mime_descend_closure +{ + int hints; + const msgset_t *msgset; + mu_message_t message; + const char *type; + const char *encoding; + const struct mime_descend_closure *parent; +}; + +typedef int (*mime_descend_fn) (struct mime_descend_closure *closure, + void *data); + +extern int mime_descend (struct mime_descend_closure *closure, + mime_descend_fn fun, void *data); + + + extern int util_do_command (const char *cmd, ...) MU_PRINTFLIKE(1,2); extern int util_foreach_msg (int argc, char **argv, int flags, @@ -369,7 +391,7 @@ extern int util_tempfile (char **namep); extern void util_msgset_iterate (msgset_t *msgset, int (*fun) (mu_message_t, msgset_t *, void *), void *closure); -extern int util_get_content_type (mu_header_t hdr, char **value); +extern int util_get_content_type (mu_header_t hdr, char **value, char **args); extern int util_get_hdr_value (mu_header_t hdr, const char *name, char **value); extern int util_merge_addresses (char **addr_str, const char *value); extern int util_header_expand (mu_header_t *hdr); @@ -383,6 +405,8 @@ void util_mark_read (mu_message_t msg); const char *util_url_to_string (mu_url_t url); +size_t fprint_msgset (FILE *fp, const msgset_t *msgset); + int is_address_field (const char *name); extern int ml_got_interrupt (void); diff --git a/mail/struct.c b/mail/struct.c new file mode 100644 index 000000000..8d22b41d9 --- /dev/null +++ b/mail/struct.c @@ -0,0 +1,71 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2009 Free Software Foundation, Inc. + + GNU Mailutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Mailutils is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ + +#include "mail.h" + +#define PART_WIDTH 8 + +static int +show_part (struct mime_descend_closure *closure, void *data) +{ + size_t width; + size_t size = 0; + + width = fprint_msgset (ofile, closure->msgset); + for (; width < 5; width++) + fputc (' ', ofile); + + fprintf (ofile, " %-25s", closure->type); + + mu_message_size (closure->message, &size); + if (size < 1024) + fprintf (ofile, " %4lu", (unsigned long) size); + else if (size < 1024*1024) + fprintf (ofile, "%4luK", (unsigned long) size / 1024); + else + fprintf (ofile, "%4luM", (unsigned long) size / 1024 / 1024); + + fprintf (ofile, "\n"); + return 0; +} + +static int +show_struct (msgset_t *msgset, mu_message_t msg, void *data) +{ + struct mime_descend_closure mclos; + + mclos.hints = 0; + mclos.msgset = msgset; + mclos.message = msg; + mclos.type = NULL; + mclos.encoding = NULL; + mclos.parent = NULL; + + mime_descend (&mclos, show_part, NULL); + + /* Mark enclosing message as read */ + if (mu_mailbox_get_message (mbox, msgset->msg_part[0], &msg) == 0) + util_mark_read (msg); + + return 0; +} + +int +mail_struct (int argc, char **argv) +{ + return util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT, + show_struct, NULL); +} diff --git a/mail/table.c b/mail/table.c index 363090897..ead4bfeec 100644 --- a/mail/table.c +++ b/mail/table.c @@ -136,6 +136,8 @@ static const struct mail_command_entry mail_command_table[] = { mail_size, msglist_compl }, { "so", "source", "so[urce] file", 0, mail_source, NULL }, + { "st", "struct", "st[ruct] [msglist]", 0, + mail_struct, NULL }, { "su", "summary", "su[mmary]", 0, mail_summary, no_compl }, { "T", "Type", "T[ype] [msglist]", 0, diff --git a/mail/util.c b/mail/util.c index 5faea748a..95ec9b61c 100644 --- a/mail/util.c +++ b/mail/util.c @@ -793,7 +793,7 @@ util_descend_subparts (mu_message_t mesg, msgset_t *msgset, mu_message_t *part) mu_header_t hdr = NULL; mu_message_get_header (mesg, &hdr); - util_get_content_type (hdr, &type); + util_get_content_type (hdr, &type, NULL); if (mu_c_strncasecmp (type, "message/rfc822", strlen (type)) == 0) { if (mu_message_unencapsulate (mesg, &submsg, NULL)) @@ -839,12 +839,12 @@ util_msgset_iterate (msgset_t *msgset, return; if (util_descend_subparts (mesg, msgset, &mesg) == 0) - (*fun)(mesg, msgset, closure); + (*fun) (mesg, msgset, closure); } } int -util_get_content_type (mu_header_t hdr, char **value) +util_get_content_type (mu_header_t hdr, char **value, char **args) { char *type = NULL; util_get_hdr_value (hdr, MU_HEADER_CONTENT_TYPE, &type); @@ -854,6 +854,17 @@ util_get_content_type (mu_header_t hdr, char **value) free (type); type = strdup ("text/plain"); /* Default. */ } + else + { + char *p; + p = strchr (type, ';'); + if (p) + { + *p++ = 0; + if (args) + *args = p; + } + } *value = type; return 0; } @@ -861,16 +872,9 @@ util_get_content_type (mu_header_t hdr, char **value) int util_get_hdr_value (mu_header_t hdr, const char *name, char **value) { - int status = mu_header_aget_value (hdr, name, value); + int status = mu_header_aget_value_unfold (hdr, name, value); if (status == 0) - { - /* Remove the newlines. */ - char *nl; - while ((nl = strchr (*value, '\n')) != NULL) - { - *nl = ' '; - } - } + mu_rtrim_class (*value, MU_CTYPE_SPACE); return status; } |