Commit c1d1ab07 c1d1ab07c72070d2ca92f729ab2454ad0b06f0ae by Sergey Poznyakoff

Bugfix.

* imap4d/append.c: Add a comment.
* imap4d/imap4d.h (imap4d_child_signal_setup): New proto.
* libmu_sieve/extensions/pipe.c (sieve_action_pipe): Use
mu_stream_copy, rewrite error handling.
* libmu_sieve/extensions/spamd.c (spamd_send_message): se
mu_stream_copy.
(spamd_test): Honor dry-run mode.
* libmu_sieve/extensions/vacation.c (build_mime): Remove
misleading FIXME. Use mu_stream_copy.
* libmu_sieve/extensions/moderator.c (moderator_message_get_part): Use
mu_body_get_streamref.
* examples/header.c (hstream): New global.
(cmd_load, cmd_free, cmd_remove, cmd_insert): Discard hstream.
(cmd_readline): Use hstream. Obtain it using mu_stream_readline.
* libproto/mbox/mbox.c (mbox_envelope_date): Remove trailing
newline from the obtained envelope line.
* mailbox/amd.c (amd_body_stream_seek): Allow for off == size
(imprtant for empty bodies).
1 parent 3ffda3e1
......@@ -28,6 +28,7 @@
char *file;
mu_header_t header;
mu_iterator_t iterator;
mu_stream_t hstream;
char *ps[] = { "> ", ". " };
int interactive;
......@@ -124,6 +125,7 @@ cmd_load (int argc, char **argv)
{
if (check_args (argv[0], argc, 2, 2))
return;
mu_stream_destroy (&hstream);
mu_header_destroy (&header);
load_file (argv[1]);
}
......@@ -134,6 +136,7 @@ cmd_free (int argc, char **argv)
if (check_args (argv[0], argc, 1, 1))
return;
mu_iterator_destroy (&iterator);
mu_stream_destroy (&hstream);
mu_header_destroy (&header);
}
......@@ -211,6 +214,7 @@ cmd_remove (int argc, char **argv)
status = mu_header_remove (header, fn, num);
if (status)
mu_error ("%u: %s: %s", line_num, argv[0], mu_strerror (status));
mu_stream_destroy (&hstream);
}
/* insert header value [ref [num] [before|after] [replace]] */
......@@ -260,6 +264,7 @@ cmd_insert (int argc, char **argv)
}
status = mu_header_insert (header, argv[1], argv[2],
ref, num, flags);
mu_stream_destroy (&hstream);
if (status)
mu_error ("%u: %s: %s", line_num, argv[0], mu_strerror (status));
}
......@@ -289,6 +294,7 @@ cmd_write (int argc, char **argv)
break;
}
mu_stream_destroy (&str);
mu_stream_destroy (&hstream);
}
void
......@@ -341,18 +347,19 @@ void
cmd_readline (int argc, char **argv)
{
char *buf;
size_t size;
mu_stream_t stream;
size_t size = 128;
size_t nbytes;
if (check_args (argv[0], argc, 1, 2))
return;
size = atoi (argv[1]);
if (argc == 2)
size = atoi (argv[1]);
buf = malloc (size);
if (!buf)
abort ();
mu_header_get_stream (header, &stream);
mu_stream_readline (stream, buf, size, &nbytes);
if (!hstream)
mu_header_get_streamref (header, &hstream);
mu_stream_readline (hstream, buf, size, &nbytes);
printf ("\"%*.*s\"", (int) nbytes, (int) nbytes, buf);
free (buf);
}
......
......@@ -45,6 +45,7 @@ _append_sender (mu_envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
return 0;
}
/* FIXME: Why not use mu_message_size instead? */
static int
_append_size (mu_message_t msg, size_t *psize)
{
......
......@@ -322,6 +322,7 @@ extern char *namespace_checkfullpath (const char *name, const char *pattern,
const char *delim, int *pns);
int imap4d_session_setup (char *username);
int imap4d_session_setup0 (void);
void imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo));
/* Capability functions */
extern void imap4d_capability_add (const char *str);
......
......@@ -213,7 +213,7 @@ moderator_message_get_part (mu_sieve_machine_t mach,
free (value);
mu_message_get_body (tmp, &body);
mu_body_get_stream (body, &str);
mu_body_get_streamref (body, &str);
rc = mu_stream_to_message (str, pmsg);
if (rc)
......@@ -223,6 +223,7 @@ moderator_message_get_part (mu_sieve_machine_t mach,
mu_strerror (rc));
return 1;
}
mu_stream_destroy (&str);
}
else if (value)
{
......
......@@ -21,9 +21,9 @@
The pipe action executes a shell command specified by its
argument and pipes the entire message to its standard input.
The envelope of the message is included, if the :envelope tag is given.
Notes/FIXME: 1. it would be nice to implement meta-variables in
<program call> which would expand to various
<program call> which would expand to various
items from the message being handled.
2. :mime tag could be useful too.
*/
......@@ -41,38 +41,6 @@
#include <regex.h>
#include <mailutils/sieve.h>
#define ASSERT(expr, diag, ec) \
if (!(expr)) \
{ \
if (ec) \
mu_sieve_error (mach, "%lu: %s: %s", \
(unsigned long) mu_sieve_get_message_num (mach), \
diag, \
mu_strerror (ec)); \
else \
mu_sieve_error (mach, "%lu: %s", \
(unsigned long) mu_sieve_get_message_num (mach), \
diag); \
mu_sieve_abort (mach); \
}
#define ASSERT2(expr, diag, arg, ec) \
if (!(expr)) \
{ \
if (ec) \
mu_sieve_error (mach, "%lu: `%s': %s: %s", \
(unsigned long) mu_sieve_get_message_num (mach), \
arg, \
diag, \
mu_strerror (ec)); \
else \
mu_sieve_error (mach, "%lu: `%s': %s", \
(unsigned long) mu_sieve_get_message_num (mach), \
arg, \
diag); \
mu_sieve_abort (mach); \
}
int
sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
......@@ -81,12 +49,25 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
mu_sieve_value_t *val;
char *cmd;
mu_stream_t mstr, pstr;
char buf[512];
size_t n;
mu_envelope_t env;
const char *error_diag = NULL;
const char *error_arg = NULL;
#define ONERR(rc, diag, arg) \
if (rc) \
{ \
error_diag = diag; \
error_arg = arg; \
break; \
}
val = mu_sieve_value_get (args, 0);
ASSERT (val, _("cannot get command!"), 0);
if (!val)
{
mu_sieve_error (mach, "%lu: %s",
(unsigned long) mu_sieve_get_message_num (mach),
_("cannot get command!"));
mu_sieve_abort (mach);
}
cmd = val->v.string;
mu_sieve_log_action (mach, "PIPE", NULL);
......@@ -104,49 +85,64 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
msg = mu_sieve_get_message (mach);
mu_message_get_envelope (msg, &env);
rc = mu_message_get_stream (msg, &mstr);
ASSERT (rc == 0, _("cannot get message stream"), rc);
rc = mu_prog_stream_create (&pstr, cmd, MU_STREAM_WRITE);
ASSERT2 (rc == 0, _("cannot create command stream"), cmd, rc);
rc = mu_stream_open (pstr);
ASSERT2 (rc == 0, _("cannot open command stream"), cmd, rc);
if (mu_sieve_tag_lookup (tags, "envelope", &val))
do
{
char *p;
rc = mu_envelope_aget_sender (env, &p);
ASSERT (rc == 0, _("cannot get envelope sender"), rc);
rc = mu_stream_write (pstr, "From ", 5, NULL);
ASSERT (rc == 0, _("stream write failed"), rc);
mu_stream_write (pstr, p, strlen (p), NULL);
free (p);
rc = mu_stream_write (pstr, " ", 1, NULL);
ASSERT (rc == 0, _("stream write failed"), rc);
rc = mu_envelope_aget_date (env, &p);
ASSERT (rc == 0, _("cannot get envelope date"), rc);
rc = mu_stream_write (pstr, p, strlen (p), NULL);
ASSERT (rc == 0, _("stream write failed"), rc);
free (p);
rc = mu_stream_write (pstr, "\n", 1, NULL);
ASSERT (rc == 0, _("stream write failed"), rc);
rc = mu_message_get_streamref (msg, &mstr);
ONERR (rc, _("cannot get message stream"), NULL);
rc = mu_prog_stream_create (&pstr, cmd, MU_STREAM_WRITE);
ONERR (rc, _("cannot create command stream"), cmd);
rc = mu_stream_open (pstr);
ONERR (rc, _("cannot open command stream"), cmd);
if (mu_sieve_tag_lookup (tags, "envelope", &val))
{
char *p;
rc = mu_envelope_aget_sender (env, &p);
ONERR (rc, _("cannot get envelope sender"), NULL);
rc = mu_stream_write (pstr, "From ", 5, NULL);
ONERR (rc, _("stream write failed"), NULL);
mu_stream_write (pstr, p, strlen (p), NULL);
free (p);
rc = mu_stream_write (pstr, " ", 1, NULL);
ONERR (rc, _("stream write failed"), NULL);
rc = mu_envelope_aget_date (env, &p);
ONERR (rc, _("cannot get envelope date"), NULL);
rc = mu_stream_write (pstr, p, strlen (p), NULL);
ONERR (rc, _("stream write failed"), NULL);
free (p);
rc = mu_stream_write (pstr, "\n", 1, NULL);
ONERR (rc, _("stream write failed"), NULL);
}
rc = mu_stream_copy (pstr, mstr, 0);
ONERR (rc, _("command failed"), cmd);
}
rc = mu_stream_seek (mstr, 0, SEEK_SET, NULL);
while (rc == 0
&& mu_stream_read (mstr, buf, sizeof buf, &n) == 0
&& n > 0)
rc = mu_stream_write (pstr, buf, n, NULL);
while (0);
mu_stream_destroy (&mstr);
mu_stream_close (pstr);
mu_stream_destroy (&pstr);
if (rc)
{
if (error_arg)
mu_sieve_error (mach, "%lu: %s: %s: %s",
(unsigned long) mu_sieve_get_message_num (mach),
error_diag,
error_arg,
mu_strerror (rc));
else
mu_sieve_error (mach, "%lu: %s: %s",
(unsigned long) mu_sieve_get_message_num (mach),
error_diag,
mu_strerror (rc));
mu_sieve_abort (mach);
}
ASSERT2 (rc == 0, _("command failed"), cmd, rc);
return 0;
}
......@@ -155,9 +151,9 @@ static mu_sieve_tag_def_t pipe_tags[] = {
{ "envelope", SVT_VOID },
{ NULL }
};
static mu_sieve_tag_group_t pipe_tag_groups[] = {
{ pipe_tags, NULL },
{ pipe_tags, NULL },
{ NULL }
};
......@@ -173,4 +169,3 @@ SIEVE_EXPORT (pipe, init) (mu_sieve_machine_t mach)
return mu_sieve_register_action (mach, "pipe", sieve_action_pipe,
pipe_args, pipe_tag_groups, 1);
}
......
......@@ -34,6 +34,8 @@
#include <mailutils/sieve.h>
#include <mailutils/mu_auth.h>
#include <mailutils/nls.h>
#include <mailutils/filter.h>
#include <mailutils/stream.h>
#define DEFAULT_SPAMD_PORT 783
......@@ -98,29 +100,28 @@ spamd_send_command (mu_stream_t stream, const char *fmt, ...)
mu_stream_writeline (stream, buf, n);
}
static void
static int
spamd_send_message (mu_stream_t stream, mu_message_t msg)
{
size_t size;
char buf[512];
mu_stream_t mstr;
int rc;
mu_stream_t mstr, flt;
mu_message_get_stream (msg, &mstr);
mu_stream_seek (mstr, 0, SEEK_SET, NULL);
while (mu_stream_readline (mstr, buf, sizeof (buf), &size) == 0
&& size > 0)
rc = mu_message_get_streamref (msg, &mstr);
if (rc)
return rc;
rc = mu_filter_create (&flt, mstr, "rfc822", MU_FILTER_ENCODE,
MU_STREAM_READ|MU_STREAM_SEEK|MU_STREAM_NO_CLOSE);
if (rc)
{
char *nl = NULL;
if (buf[size-1] == '\n')
{
size--;
nl = "\r\n";
}
mu_stream_write (stream, buf, size, NULL);
if (nl)
mu_stream_write (stream, nl, 2, NULL);
mu_stream_destroy (&mstr);
return rc;
}
rc = mu_stream_copy (stream, flt, 0);
mu_stream_destroy (&mstr);
mu_stream_destroy (&flt);
return rc;
}
static size_t
......@@ -284,6 +285,9 @@ spamd_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
(u_long) mu_sieve_get_message_num (mach));
}
if (mu_sieve_is_dry_run (mach))
return 0;
if (mu_sieve_tag_lookup (tags, "host", &arg))
host = arg->v.string;
else
......
......@@ -42,7 +42,6 @@
/* Build a mime response message from original message MSG. TEXT
is the message text.
FIXME: This is for future use, when I add :mime tag
*/
static int
build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime,
......@@ -50,25 +49,25 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime,
{
mu_mime_t mime = NULL;
mu_message_t newmsg;
mu_stream_t stream, input, save_input = NULL;
mu_stream_t stream, input;
mu_header_t hdr;
mu_body_t body;
char buf[512];
char *header = "Content-Type: text/plain;charset=" MU_SIEVE_CHARSET "\n"
"Content-Transfer-Encoding: 8bit\n\n";
const char *header =
"Content-Type: text/plain;charset=" MU_SIEVE_CHARSET "\n"
"Content-Transfer-Encoding: 8bit\n\n";
int rc;
size_t n;
mu_mime_create (&mime, NULL, 0);
mu_message_create (&newmsg, NULL);
mu_message_get_body (newmsg, &body);
mu_body_get_stream (body, &stream);
if ((rc = mu_memory_stream_create (&input, MU_STREAM_RDWR)))
{
mu_sieve_error (mach,
_("cannot create temporary stream: %s"),
mu_strerror (rc));
mu_mime_destroy (&mime);
mu_message_destroy (&newmsg, NULL);
return 1;
}
......@@ -77,6 +76,9 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime,
mu_sieve_error (mach,
_("cannot open temporary stream: %s"),
mu_strerror (rc));
mu_mime_destroy (&mime);
mu_message_destroy (&newmsg, NULL);
mu_stream_destroy (&input);
return 1;
}
......@@ -91,19 +93,37 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime,
{
header = "Content-Type: text/plain;charset=" MU_SIEVE_CHARSET "\n"
"Content-Transfer-Encoding: base64\n\n";
save_input = input;
input = fstr;
}
}
while (rc == 0
&& mu_stream_read (input, buf, sizeof buf, &n) == 0
&& n > 0)
rc = mu_stream_write (stream, buf, n, NULL);
rc = mu_body_get_streamref (body, &stream);
if (rc)
{
mu_sieve_error (mach,
_("cannot get input body stream: %s"),
mu_strerror (rc));
mu_mime_destroy (&mime);
mu_message_destroy (&newmsg, NULL);
mu_stream_destroy (&input);
return 1;
}
mu_stream_seek (input, 0, MU_SEEK_SET, NULL);
rc = mu_stream_copy (stream, input, 0);
if (rc)
{
mu_sieve_error (mach,
_("stream copy failed: %s"),
mu_strerror (rc));
mu_mime_destroy (&mime);
mu_message_destroy (&newmsg, NULL);
mu_stream_destroy (&input);
mu_stream_destroy (&stream);
return 1;
}
mu_stream_destroy (&input);
if (save_input)
mu_stream_destroy (&save_input);
mu_header_create (&hdr, header, strlen (header));
mu_message_set_header (newmsg, hdr, NULL);
......
......@@ -382,7 +382,8 @@ mbox_envelope_date (mu_envelope_t envelope, char *buf, size_t len,
&n);
if (status)
return status;
mu_rtrim_cset (buffer, "\r\n");
/* Format: "From [sender] [date]" */
/* strlen ("From ") == 5 */
if (n > 5 && (s = strchr (buffer + 5, ' ')) != NULL)
......
......@@ -1710,7 +1710,7 @@ amd_body_stream_seek (mu_stream_t str, mu_off_t off, mu_off_t *presult)
amd_body_size (amdstr->body, &size);
if (off < 0 || off >= size)
if (off < 0 || off > size)
return ESPIPE;
amdstr->off = off;
......