Commit 78712199 787121995cef1f77d279df9b70a9eb1f4fb35325 by Sergey Poznyakoff

Fix all FIXMEs from b2c1b1ff. Revise attachment API.

* include/mailutils/message.h (mu_message_save_attachment)
(mu_message_encapsulate, mu_message_unencapsulate): Change type
of the last argument.
(mu_mime_io_buffer_create,mu_mime_io_buffer_destroy)
(mu_mime_io_buffer_set_size,mu_mime_io_buffer_get_size)
(mu_mime_io_buffer_set_charset,mu_mime_io_buffer_sget_charset)
(mu_mime_io_buffer_aget_charset): New prototypes.
(mu_mimehdr_get_disp,mu_mimehdr_aget_disp): Remove unneeded
parameter.
* include/mailutils/types.hin (mu_mime_io_buffer_t): New type.
* mailbox/attachment.c (_msg_info): Rename structure to
_mu_mime_io_buffer.
<header_buf,header_len,mu_header_size>: Remove unreferenced members.
<refcnt,bufsize,charset>: New members.
<ioffset,ooffset>: Change type to size_t.
(mu_mime_io_buffer_create,mu_mime_io_buffer_destroy)
(mu_mime_io_buffer_set_size,mu_mime_io_buffer_get_size)
(mu_mime_io_buffer_set_charset,mu_mime_io_buffer_sget_charset)
(mu_mime_io_buffer_aget_charset): New functions.
(mu_message_save_attachment)
(mu_message_encapsulate, mu_message_unencapsulate): Take
mu_mime_io_buffer_t as the last argument.
* mailbox/mimehdr.c (mu_mimehdr_get_disp): Remove unneeded
parameter.
(mu_mimehdr_aget_disp): Remove unneeded parameter. Store
return value into pvalue.

* examples/mimetest.c (message_display_parts): Use
mu_mimehdr_aget_disp and mu_mime_io_buffer_* functions.
* mailbox/testsuite/Mime: Update.

* mh/mhn.c (options, opt_handler): New option --charset.
(store_handler): Use mu_message_aget_decoded_attachment_name.
1 parent d02e8bf4
......@@ -35,7 +35,7 @@ void message_display_parts(mu_message_t msg, int indent);
const char *from;
const char *subject;
const char *charset = "UTF-8";
const char *charset;
int print_attachments;
int indent_level = 4;
......@@ -180,8 +180,6 @@ message_display_parts (mu_message_t msg, int indent)
size_t nparts, nsubparts;
mu_message_t part;
mu_header_t hdr;
const char *type;
const char *encoding;
mu_stream_t str;
mu_body_t body;
int offset, ismulti;
......@@ -200,24 +198,34 @@ message_display_parts (mu_message_t msg, int indent)
for (j = 1; j <= nparts; j++)
{
int status;
const char *hvalue;
char *type = NULL;
const char *encoding = "";
MU_ASSERT (mu_message_get_part (msg, j, &part));
MU_ASSERT (mu_message_get_header (part, &hdr));
status = mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE, &type);
status = mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE,
&hvalue);
if (status == MU_ERR_NOENT)
type = "";
/* nothing */;
else if (status != 0)
mu_error ("Cannot get header value: %s", mu_strerror (status));
else
{
type = "";
mu_error ("Cannot get header value: %s", mu_strerror (status));
status = mu_mimehdr_aget_disp (hvalue, &type);
if (status)
mu_error ("Cannot extract content type field: %s",
mu_strerror (status));
}
printf ("%*.*sType of part %d = %s\n", indent, indent, "", j, type);
printf ("%*.*sType of part %d = %s\n", indent, indent, "",
j, type ? type : "");
print_message_part_sizes (part, indent);
if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING,
&encoding))
encoding = "";
ismulti = 0;
if ((type[0]
&& mu_c_strncasecmp (type, "message/rfc822", strlen (type)) == 0)
if ((type
&& mu_c_strcasecmp (type, "message/rfc822") == 0)
|| (mu_message_is_multipart (part, &ismulti) == 0 && ismulti))
{
if (!ismulti)
......@@ -232,23 +240,21 @@ message_display_parts (mu_message_t msg, int indent)
indent, indent, "", from, subject);
printf ("%*.*sBegin\n", indent, indent, "");
MU_ASSERT (mu_message_get_num_parts (part, &nsubparts));
message_display_parts (part, indent+indent_level);
message_display_parts (part, indent + indent_level);
mu_message_destroy (&part, NULL);
}
else if (type[0] == '\0'
|| (mu_c_strncasecmp (type, "text/plain", strlen ("text/plain")) ==
0)
|| (mu_c_strncasecmp (type, "text/html", strlen ("text/html")) ==
0))
{
printf ("%*.*sText Message\n", indent, indent, "");
else if (!type
|| (mu_c_strcasecmp (type, "text/plain") == 0)
|| (mu_c_strcasecmp (type, "text/html")) == 0)
{
printf ("%*.*sText Message\n", indent, indent, "");
printf ("%*.*sBegin\n", indent, indent, "");
mu_message_get_body (part, &body);
mu_body_get_stream (body, &str);
mu_filter_create (&str, str, encoding, 0, 0);
offset = 0;
while (mu_stream_readline (str, buf, sizeof (buf), offset, &nbytes) ==
0 && nbytes)
while (mu_stream_readline (str, buf, sizeof (buf),
offset, &nbytes) == 0 && nbytes)
{
printf ("%*.*s%s", indent, indent, "", buf);
offset += nbytes;
......@@ -268,13 +274,22 @@ message_display_parts (mu_message_t msg, int indent)
printf ("%*.*sAttachment - saving [%s]\n", indent, indent, "",
fname);
printf ("%*.*sBegin\n", indent, indent, "");
/*FIXME: What is the 'data' argument for? */
mu_message_save_attachment (part, fname, NULL);
if (charset)
{
mu_mime_io_buffer_t info;
mu_mime_io_buffer_create (&info);
mu_mime_io_buffer_set_charset (info, charset);
MU_ASSERT (mu_message_save_attachment (part, NULL, info));
mu_mime_io_buffer_destroy (&info);
}
else
MU_ASSERT (mu_message_save_attachment (part, fname, NULL));
if (print_attachments)
print_file (fname, indent);
free (fname);
}
printf ("\n%*.*sEnd\n", indent, indent, "");
free (type);
}
}
......
......@@ -113,21 +113,35 @@ extern int mu_message_create_attachment (const char *content_type,
const char *filename,
mu_message_t *newmsg);
extern int mu_message_save_attachment (mu_message_t msg,
const char *filename, void **data);
const char *filename,
mu_mime_io_buffer_t buf);
extern int mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg,
void **data);
mu_mime_io_buffer_t buf);
extern int mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
void **data);
mu_mime_io_buffer_t buf);
extern int mu_mime_io_buffer_create (mu_mime_io_buffer_t *pinfo);
extern void mu_mime_io_buffer_destroy (mu_mime_io_buffer_t *pinfo);
extern void mu_mime_io_buffer_set_size (mu_mime_io_buffer_t info, size_t size);
extern void mu_mime_io_buffer_get_size (mu_mime_io_buffer_t info,
size_t *psize);
extern int mu_mime_io_buffer_set_charset (mu_mime_io_buffer_t info,
const char *charset);
extern void mu_mime_io_buffer_sget_charset (mu_mime_io_buffer_t info,
const char **charset);
extern int mu_mime_io_buffer_aget_charset (mu_mime_io_buffer_t info,
const char **charset);
/* Bit values for *pflags in functions below */
#define MU_MIMEHDR_MULTILINE 0x01 /* Parameter was multiline */
#define MU_MIMEHDR_CSINFO 0x02 /* Parameter contains charset/language
info */
extern int mu_mimehdr_get_disp (const char *str, const char *param,
char *buf, size_t bufsz, size_t *retsz);
extern int mu_mimehdr_aget_disp (const char *str, const char *param,
char **pvalue);
extern int mu_mimehdr_get_disp (const char *str, char *buf, size_t bufsz,
size_t *retsz);
extern int mu_mimehdr_aget_disp (const char *str, char **pvalue);
extern int mu_mimehdr_get_param (const char *str, const char *param,
char *buf, size_t bufsz, size_t *retsz,
int *pflags);
......
......@@ -113,6 +113,7 @@ typedef struct _mu_m_server *mu_m_server_t;
typedef struct _mu_opool *mu_opool_t;
typedef struct _mu_progmailer *mu_progmailer_t;
typedef struct _mu_secret *mu_secret_t;
typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t;
#define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
#define MU_FOLDER_ATTRIBUTE_FILE 0x002
......
......@@ -47,17 +47,17 @@
#define BUF_SIZE 2048
struct _msg_info
struct _mu_mime_io_buffer
{
unsigned int refcnt;
char *buf;
size_t bufsize;
size_t nbytes;
char *header_buf;
int header_len;
int mu_header_size;
char *charset;
mu_header_t hdr;
mu_message_t msg;
int ioffset;
int ooffset;
size_t ioffset;
size_t ooffset;
mu_stream_t stream; /* output file/decoding stream for saving attachment */
mu_stream_t fstream; /* output file stream for saving attachment */
};
......@@ -139,58 +139,131 @@ mu_message_create_attachment (const char *content_type, const char *encoding,
return ret;
}
int
mu_mime_io_buffer_create (mu_mime_io_buffer_t *pinfo)
{
mu_mime_io_buffer_t info;
if ((info = calloc (1, sizeof (*info))) == NULL)
return ENOMEM;
info->refcnt = 1;
info->bufsize = BUF_SIZE;
*pinfo = info;
return 0;
}
static int
_attachment_setup (struct _msg_info **info, mu_message_t msg,
mu_stream_t *stream, void **data)
void
mu_mime_io_buffer_set_size (mu_mime_io_buffer_t info, size_t size)
{
int sfl, ret;
mu_body_t body;
info->bufsize = size;
}
if ((ret = mu_message_get_body (msg, &body)) != 0 ||
(ret = mu_body_get_stream (body, stream)) != 0)
return ret;
mu_stream_get_flags (*stream, &sfl);
if (data == NULL && (sfl & MU_STREAM_NONBLOCK))
return EINVAL;
if (data)
*info = *data;
if (*info == NULL)
{
if ((*info = calloc (1, sizeof (struct _msg_info))) == NULL)
return ENOMEM;
}
if (((*info)->buf = malloc (BUF_SIZE)) == NULL)
void
mu_mime_io_buffer_get_size (mu_mime_io_buffer_t info, size_t *psize)
{
*psize = info->bufsize;
}
int
mu_mime_io_buffer_set_charset (mu_mime_io_buffer_t info, const char *charset)
{
char *cp = strdup (charset);
if (!cp)
return ENOMEM;
free (info->charset);
info->charset = cp;
return 0;
}
void
mu_mime_io_buffer_sget_charset (mu_mime_io_buffer_t info, const char **charset)
{
*charset = info->charset;
}
int
mu_mime_io_buffer_aget_charset (mu_mime_io_buffer_t info, const char **charset)
{
*charset = strdup (info->charset);
if (!charset)
return ENOMEM;
return 0;
}
void
mu_mime_io_buffer_destroy (mu_mime_io_buffer_t *pinfo)
{
if (pinfo && *pinfo)
{
free (*info);
return ENOMEM;
mu_mime_io_buffer_t info = *pinfo;
free (info->charset);
free (info->buf);
free (info);
*pinfo = NULL;
}
return 0;
}
static void
_attachment_free (struct _msg_info *info, int free_message)
_attachment_free (struct _mu_mime_io_buffer *info, int free_message)
{
if (info->buf)
free (info->buf);
if (info->header_buf)
free (info->header_buf);
if (free_message)
{
if (info->msg)
mu_message_destroy (&(info->msg), NULL);
mu_message_destroy (&info->msg, NULL);
else if (info->hdr)
mu_header_destroy (&(info->hdr), NULL);
mu_header_destroy (&info->hdr, NULL);
}
info->msg = NULL;
info->hdr = NULL;
info->ioffset = 0;
info->ooffset = 0;
info->stream = NULL;
info->fstream = NULL;
if (--info->refcnt == 0)
{
free (info->charset);
free (info->buf);
free (info);
}
free (info);
}
static int
_attachment_setup (mu_mime_io_buffer_t *pinfo, mu_message_t msg,
mu_stream_t *stream)
{
int ret;
mu_body_t body;
mu_mime_io_buffer_t info;
if ((ret = mu_message_get_body (msg, &body)) != 0 ||
(ret = mu_body_get_stream (body, stream)) != 0)
return ret;
if (*pinfo)
{
info = *pinfo;
info->refcnt++;
}
else
{
ret = mu_mime_io_buffer_create (&info);
if (ret)
return ret;
}
if (!info->buf && ((info->buf = malloc (info->bufsize)) == NULL))
{
_attachment_free (info, 0);
return ENOMEM;
}
*pinfo = info;
return 0;
}
int
mu_message_save_attachment (mu_message_t msg, const char *filename,
void **data)
mu_mime_io_buffer_t info)
{
mu_stream_t istream;
struct _msg_info *info = NULL;
int ret;
size_t size;
size_t nbytes;
......@@ -201,15 +274,15 @@ mu_message_save_attachment (mu_message_t msg, const char *filename,
if (msg == NULL)
return EINVAL;
if ((ret = _attachment_setup (&info, msg, &istream, data)) != 0)
if ((ret = _attachment_setup (&info, msg, &istream)) != 0)
return ret;
if (ret == 0 && (ret = mu_message_get_header (msg, &hdr)) == 0)
{
if (filename == NULL)
{
/* FIXME: Charset info is ignored */
ret = mu_message_aget_attachment_name (msg, &partname, NULL);
ret = mu_message_aget_decoded_attachment_name (msg, info->charset,
&partname, NULL);
if (partname)
fname = partname;
}
......@@ -248,12 +321,12 @@ mu_message_save_attachment (mu_message_t msg, const char *filename,
if (info->stream && istream)
{
if (info->nbytes)
memmove (info->buf, info->buf + (BUF_SIZE - info->nbytes),
memmove (info->buf, info->buf + (info->bufsize - info->nbytes),
info->nbytes);
while ((ret == 0 && info->nbytes)
||
((ret =
mu_stream_read (info->stream, info->buf, BUF_SIZE,
mu_stream_read (info->stream, info->buf, info->bufsize,
info->ioffset, &info->nbytes)) == 0
&& info->nbytes))
{
......@@ -274,9 +347,10 @@ mu_message_save_attachment (mu_message_t msg, const char *filename,
mu_stream_close (info->fstream);
mu_stream_destroy (&info->stream, NULL);
mu_stream_destroy (&info->fstream, NULL);
_attachment_free (info, ret);
}
_attachment_free (info, ret); /* FIXME: or 0? */
/* Free fname if we allocated it. */
if (partname)
free (partname);
......@@ -285,11 +359,11 @@ mu_message_save_attachment (mu_message_t msg, const char *filename,
}
int
mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, void **data)
mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg,
mu_mime_io_buffer_t info)
{
mu_stream_t istream, ostream;
const char *header;
struct _msg_info *info = NULL;
int ret = 0;
size_t nbytes;
mu_body_t body;
......@@ -299,16 +373,16 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, void **data)
if (newmsg == NULL)
return MU_ERR_OUT_PTR_NULL;
if ((ret = _attachment_setup (&info, msg, &ostream, data)) != 0)
if ((ret = _attachment_setup (&info, msg, &ostream)) != 0)
return ret;
if (info->msg == NULL
&& (ret = mu_message_create (&(info->msg), NULL)) == 0)
&& (ret = mu_message_create (&info->msg, NULL)) == 0)
{
header =
"Content-Type: message/rfc822\nContent-Transfer-Encoding: 7bit\n\n";
if ((ret =
mu_header_create (&(info->hdr), header, strlen (header),
mu_header_create (&info->hdr, header, strlen (header),
msg)) == 0)
ret = mu_message_set_header (info->msg, info->hdr, NULL);
}
......@@ -318,12 +392,12 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, void **data)
(ret = mu_body_get_stream (body, &ostream)) == 0)
{
if (info->nbytes)
memmove (info->buf, info->buf + (BUF_SIZE - info->nbytes),
memmove (info->buf, info->buf + (info->bufsize - info->nbytes),
info->nbytes);
while ((ret == 0 && info->nbytes)
||
((ret =
mu_stream_read (istream, info->buf, BUF_SIZE,
mu_stream_read (istream, info->buf, info->bufsize,
info->ioffset, &info->nbytes)) == 0
&& info->nbytes))
{
......@@ -342,27 +416,27 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, void **data)
}
if (ret == 0)
*newmsg = info->msg;
if (ret != EAGAIN && info)
_attachment_free (info, ret);
_attachment_free (info, ret && ret != EAGAIN);
return ret;
}
#define MESSAGE_RFC822_STR "message/rfc822"
int
mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
void **data)
mu_mime_io_buffer_t info)
{
size_t size, nbytes;
int ret = 0;
mu_header_t hdr;
mu_stream_t istream, ostream;
struct _msg_info *info = NULL;
if (msg == NULL)
return EINVAL;
if (newmsg == NULL)
return MU_ERR_OUT_PTR_NULL;
if ((data == NULL || *data == NULL)
if (info == NULL /* FIXME: not needed? */
&& (ret = mu_message_get_header (msg, &hdr)) == 0)
{
mu_header_get_value (hdr, "Content-Type", NULL, 0, &size);
......@@ -373,9 +447,8 @@ mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
return ENOMEM;
mu_header_get_value (hdr, "Content-Type", content_type, size + 1,
0);
ret =
mu_c_strncasecmp (content_type, "message/rfc822",
strlen ("message/rfc822"));
ret = mu_c_strncasecmp (content_type, MESSAGE_RFC822_STR,
sizeof (MESSAGE_RFC822_STR) - 1);
free (content_type);
if (ret != 0)
return EINVAL;
......@@ -383,20 +456,21 @@ mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
else
return EINVAL;
}
if ((ret = _attachment_setup (&info, msg, &istream, data)) != 0)
if ((ret = _attachment_setup (&info, msg, &istream)) != 0)
return ret;
if (info->msg == NULL)
ret = mu_message_create (&(info->msg), NULL);
ret = mu_message_create (&info->msg, NULL);
if (ret == 0)
{
mu_message_get_stream (info->msg, &ostream);
if (info->nbytes)
memmove (info->buf, info->buf + (BUF_SIZE - info->nbytes),
memmove (info->buf, info->buf + (info->bufsize - info->nbytes),
info->nbytes);
while ((ret == 0 && info->nbytes)
||
((ret =
mu_stream_read (istream, info->buf, BUF_SIZE, info->ioffset,
mu_stream_read (istream, info->buf,
info->bufsize, info->ioffset,
&info->nbytes)) == 0 && info->nbytes))
{
info->ioffset += info->nbytes;
......@@ -413,7 +487,6 @@ mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
}
if (ret == 0)
*newmsg = info->msg;
if (ret != EAGAIN && info)
_attachment_free (info, ret);
_attachment_free (info, ret && ret != EAGAIN);
return ret;
}
......
......@@ -332,8 +332,7 @@ _header_get_param (const char *field_body,
value, and `type/subtype' part, if it is a Content-Type value.
*/
int
mu_mimehdr_get_disp (const char *str, const char *param,
char *buf, size_t bufsz, size_t *retsz)
mu_mimehdr_get_disp (const char *str, char *buf, size_t bufsz, size_t *retsz)
{
char *p = strchr (str, ';');
size_t size;
......@@ -350,7 +349,7 @@ mu_mimehdr_get_disp (const char *str, const char *param,
/* Same as mu_mimehdr_get_disp, but allocates memory */
int
mu_mimehdr_aget_disp (const char *str, const char *param, char **pvalue)
mu_mimehdr_aget_disp (const char *str, char **pvalue)
{
char *p = strchr (str, ';');
size_t size;
......@@ -363,6 +362,7 @@ mu_mimehdr_aget_disp (const char *str, const char *param, char **pvalue)
return ENOMEM;
memcpy (p, str, size);
p[size] = 0;
*pvalue = p;
return 0;
}
......
......@@ -83,7 +83,7 @@ From: Sergey Poznyakoff <gray@Mirddin.farlep.net>
Subject: Simple MIME
Number of parts in message - 2
Total message size - 1626/42
Type of part 1 = text/plain; name="msg.1"; charset="us-ascii"
Type of part 1 = text/plain
Message part size - 371/13: 141/4, 230/9
Text Message
Begin
......@@ -98,7 +98,7 @@ And welcome little fishes in
With gently smiling jaws!
End
Type of part 2 = application/octet-stream; name="msg.21"
Type of part 2 = application/octet-stream
Message part size - 645/11: 183/5, 462/6
Attachment - saving [msg.21]
Begin
......@@ -119,7 +119,7 @@ From: Sergey Poznyakoff <gray@Mirddin.farlep.net>
Subject: Nested MIME
Number of parts in message - 2
Total message size - 3484/84
Type of part 1 = text/plain; name="msg.21"; charset="us-ascii"
Type of part 1 = text/plain
Message part size - 496/14: 155/4, 341/10
Text Message
Begin
......@@ -135,11 +135,11 @@ Why, I do it again and again.'
End
Type of part 2 = multipart/mixed; boundary="----- =_aaaaaaaaaa1"
Type of part 2 = multipart/mixed
Message part size - 2378/52: 114/3, 2264/49
Encapsulated message :
Begin
Type of part 1 = application/octet-stream; name="msg.22"
Type of part 1 = application/octet-stream
Message part size - 663/12: 184/5, 479/7
Attachment - saving [msg.22]
Begin
......@@ -154,11 +154,11 @@ By the use of this ointment--one shilling the box--
Allow me to sell you a couple?'
End
Type of part 2 = multipart/mixed; boundary="----- =_aaaaaaaaaa2"
Type of part 2 = multipart/mixed
Message part size - 1531/32: 114/3, 1417/29
Encapsulated message :
Begin
Type of part 1 = application/octet-stream; name="msg.23"
Type of part 1 = application/octet-stream
Message part size - 668/12: 185/5, 483/7
Attachment - saving [msg.23]
Begin
......@@ -173,7 +173,7 @@ And the muscular strength, which it gave to my jaw,
Has lasted the rest of my life.'
End
Type of part 2 = application/octet-stream; name="msg.24"
Type of part 2 = application/octet-stream
Message part size - 679/12: 184/5, 495/7
Attachment - saving [msg.24]
Begin
......@@ -197,13 +197,13 @@ From: Sergey Poznyakoff <gray@Mirddin.farlep.net>
Subject: Empty MIME Parts
Number of parts in message - 2
Total message size - 914/27
Type of part 1 = text/plain; name="empty"; charset="us-ascii"
Type of part 1 = text/plain
Message part size - 143/4: 143/4, 0/0
Text Message
Begin
End
Type of part 2 = text/plain; name="single.line"; charset="us-ascii"
Type of part 2 = text/plain
Message part size - 156/5: 155/4, 1/1
Text Message
Begin
......
......@@ -55,7 +55,8 @@ enum mh_arg {
ARG_BUILD,
ARG_CC,
ARG_CFLAGS,
ARG_CHANGECUR,
ARG_CHANGECUR,
ARG_CHARSET,
ARG_CHECK,
ARG_CHUNKSIZE,
ARG_CLEAR,
......
......@@ -74,16 +74,18 @@ static struct argp_option options[] = {
{"auto", ARG_AUTO, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("use filenames from the content headers"), 31},
{"noauto", ARG_NOAUTO, NULL, OPTION_HIDDEN, "", 31 },
{"charset", ARG_CHARSET, N_("NAME"), 0,
N_("use this charset to represent attachment file names"), 31},
{N_("Other options"), 0, NULL, OPTION_DOC, NULL, 40},
{"part", ARG_PART, N_("PART"), 0,
N_("limit the scope of the operation to the given part"), 41},
{"type", ARG_TYPE, N_("CONTENT"), 0,
N_("operate on message part with given multipart content"), 41 },
{"verbose", ARG_VERBOSE, N_("BOOL"), OPTION_ARG_OPTIONAL,
{"verbose", ARG_VERBOSE, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("print additional information"), 41 },
{"noverbose", ARG_NOVERBOSE, NULL, OPTION_HIDDEN, "", 41 },
{"quiet", ARG_QUIET, 0, 0,
{"noverbose", ARG_NOVERBOSE, NULL, OPTION_HIDDEN, "", 41 },
{"quiet", ARG_QUIET, 0, 0,
N_("be quiet")},
{"license", ARG_LICENSE, 0, 0,
N_("display software license"), -1},
......@@ -144,6 +146,8 @@ static char *content_type;
static char *content_subtype;
static char *input_file;
static int width = 80;
static char *charset; /* Charset for output file names. NULL means
no recoding is necessary. */
static mh_msgset_t msgset;
static mu_mailbox_t mbox;
......@@ -397,6 +401,10 @@ opt_handler (int key, char *arg, struct argp_state *state)
mh_license (argp_program_version);
break;
case ARG_CHARSET:
charset = arg;
break;
default:
return ARGP_ERR_UNKNOWN;
}
......@@ -1589,14 +1597,21 @@ store_handler (mu_message_t msg, msg_part_t part, char *type, char *encoding,
if (mode_options & OPT_AUTO)
{
char *val;
/* FIXME: Take into account CS/Lang info and recode the value
if necessary */
if (mu_message_aget_attachment_name (msg, &val, NULL) == 0)
int rc = mu_message_aget_decoded_attachment_name (msg, charset,
&val, NULL);
if (rc == 0)
{
name = normalize_path (dir, val);
free (val);
}
else if (rc != MU_ERR_NOENT)
{
char *pstr = msg_part_format (part);
mu_diag_output (MU_DIAG_WARNING,
_("%s: cannot decode attachment name: %s"),
pstr, mu_strerror (rc));
free (pstr);
}
}
if (!name)
......