summaryrefslogtreecommitdiff
path: root/mail
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-07-13 14:42:40 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-07-13 15:07:02 +0300
commitf8fc2081dffd950ab1c6082e4a32f0096bd7415d (patch)
treecdbfdf9d5b0996ee1b4f00d06c71901fb418cce9 /mail
parent0517ca033b3222afc09f5b70626c38280c749c14 (diff)
downloadmailutils-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.am1
-rw-r--r--mail/decode.c136
-rw-r--r--mail/mail.h26
-rw-r--r--mail/struct.c71
-rw-r--r--mail/table.c2
-rw-r--r--mail/util.c28
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;
}

Return to:

Send suggestions and report system problems to the System administrator.