/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999-2021 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 . */
#if defined(HAVE_CONFIG_H)
# include
#endif
#include "muscript.h"
#include "muscript_priv.h"
struct sieve_log_data
{
char *user;
char *hdr;
};
static void
_sieve_action_log (mu_sieve_machine_t mach,
const char *action, const char *fmt, va_list ap)
{
struct sieve_log_data *ldat = mu_sieve_get_data (mach);
int pfx = 0;
mu_stream_t stream;
mu_message_t msg = mu_sieve_get_message (mach);
mu_sieve_get_diag_stream (mach, &stream);
mu_stream_printf (stream, "\033s<%d>\033O<%d>", MU_LOG_NOTICE,
MU_LOGMODE_LOCUS);
if (ldat)
{
if (ldat->user)
mu_stream_printf (stream, _("(user %s) "), ldat->user);
if (ldat->hdr)
{
mu_header_t hdr = NULL;
char *val = NULL;
mu_message_get_header (msg, &hdr);
if (mu_header_aget_value (hdr, ldat->hdr, &val) == 0
|| mu_header_aget_value (hdr, MU_HEADER_MESSAGE_ID, &val) == 0)
{
pfx = 1;
mu_stream_printf (stream, _("%s on msg %s"), action, val);
free (val);
}
}
}
if (!pfx)
{
size_t uid = 0;
mu_message_get_uid (msg, &uid);
mu_stream_printf (stream, _("%s on msg uid %lu"), action,
(unsigned long) uid);
}
if (fmt && strlen (fmt))
{
mu_stream_printf (stream, "; ");
mu_stream_vprintf (stream, fmt, ap);
}
mu_stream_printf (stream, "\n");
mu_stream_unref (stream);
}
static void
sieve_setenv (mu_sieve_machine_t mach, const char **env)
{
if (env)
{
char *buffer = NULL;
size_t buflen = 0;
size_t i;
char *p;
for (i = 0; env[i]; i++)
{
if (buflen < strlen (env[i]) + 1)
{
buflen = strlen (env[i]) + 1;
buffer = mu_realloc (buffer, buflen);
}
strcpy (buffer, env[i]);
p = strchr (buffer, '=');
if (!p)
continue;
*p++ = 0;
mu_sieve_set_environ (mach, buffer, p);
}
free (buffer);
}
}
static int
sieve_init (const char *prog, const char **env, mu_script_descr_t *pdescr)
{
int rc;
mu_sieve_machine_t mach;
rc = mu_sieve_machine_create (&mach);
if (rc == 0)
{
if (mu_script_sieve_log)
mu_sieve_set_logger (mach, _sieve_action_log);
sieve_setenv (mach, env);
rc = mu_sieve_compile (mach, prog);
}
*pdescr = (mu_script_descr_t) mach;
return rc;
}
static int
sieve_log_enable (mu_script_descr_t descr, const char *name, const char *hdr)
{
mu_sieve_machine_t mach = (mu_sieve_machine_t) descr;
struct sieve_log_data *ldat;
size_t size = 0;
char *p;
if (name)
size += strlen (name) + 1;
if (hdr)
size += strlen (hdr) + 1;
if (size)
{
ldat = calloc (1, sizeof (*ldat) + size);
if (!ldat)
return ENOMEM;
p = (char *) (ldat + 1);
if (name)
{
ldat->user = p;
p = mu_stpcpy (p, name) + 1;
}
if (hdr)
{
ldat->hdr = p;
strcpy (p, hdr);
}
mu_sieve_set_data (mach, ldat);
}
mu_sieve_set_logger (mach, _sieve_action_log);
return 0;
}
static int
sieve_done (mu_script_descr_t descr)
{
mu_sieve_machine_t mach = (mu_sieve_machine_t) descr;
void *p = mu_sieve_get_data (mach);
free (p);
mu_sieve_machine_destroy (&mach);
return 0;
}
static int
sieve_proc (mu_script_descr_t descr, mu_message_t msg)
{
return mu_sieve_message ((mu_sieve_machine_t) descr, msg);
}
struct mu_script_fun mu_script_sieve = {
"sieve",
"sv\0siv\0sieve\0",
sieve_init,
sieve_done,
sieve_proc,
sieve_log_enable
};