aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-01-12 15:07:46 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-01-12 15:07:46 +0000
commitb23b5cad0cff93314190431693106e3f29ba29da (patch)
tree980f694f3105a81f4985cee3c675338f2fb8a9eb
parentf3fe35899c9749e4eb8000ccebb8e1348def28d6 (diff)
downloadmailfromd-b23b5cad0cff93314190431693106e3f29ba29da.tar.gz
mailfromd-b23b5cad0cff93314190431693106e3f29ba29da.tar.bz2
* src/prog.c (instr_header): Improve trace output.
* pmult/pmult.c: Implement recipient and header modifications. * configure.ac: Link libmta/libcstrr.a (for pmult). * TODO: Update. * gacopyz/server.c (gacopyz_srv_send_command): Do not bail out on message modification responses. * gacopyz/gacopyz.c (gacopyz_header_command): Improve trace output. git-svn-id: file:///svnroot/mailfromd/branches/gmach@1557 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog11
-rw-r--r--TODO2
-rw-r--r--configure.ac1
-rw-r--r--gacopyz/gacopyz.c2
-rw-r--r--gacopyz/server.c13
-rw-r--r--pmult/pmult.c306
-rw-r--r--src/prog.c2
7 files changed, 323 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 1af4fd53..b3e44fc6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,17 @@
2008-01-12 Sergey Poznyakoff <gray@gnu.org.ua>
+ * src/prog.c (instr_header): Improve trace output.
+ * pmult/pmult.c: Implement recipient and header modifications.
+ * configure.ac: Link libmta/libcstrr.a (for pmult).
+ * TODO: Update.
+
+ * gacopyz/server.c (gacopyz_srv_send_command): Do not bail out on
+ message modification responses.
+ * gacopyz/gacopyz.c (gacopyz_header_command): Improve trace output.
+
* src/gram.y (DELETE string): Initialize hdr.value.
* src/drivers.c (code_type_header): Value can be NULL.
-
+
* pmult/pmult.c: Implement most of the SMTP functionality.
* src/mailfromd.h, lib/libmf.h (dict_init, dict_install)
diff --git a/TODO b/TODO
index 69e37dd7..b78c0be1 100644
--- a/TODO
+++ b/TODO
@@ -2,6 +2,8 @@ Mailfromd TODO list.
* Language:
+** Clarify the `delete' semantics.
+
** Implement \U, \L, \E and other GNU extensions to the replacement strings.
** Various items by Jan (ref <Pine.LNX.4.58.0610112345080.2162@cedric.unob.cz>)
diff --git a/configure.ac b/configure.ac
index 25a9cb66..f0c3da18 100644
--- a/configure.ac
+++ b/configure.ac
@@ -549,6 +549,7 @@ if test "$enable_pmilter" = yes; then
libmta/librcbcomm.a\
libmta/librcb.a\
libmta/libmtar.a\
+ libmta/libcstrr.a\
libcheck/libcheck.a\
librepl/libreplr.a"
diff --git a/gacopyz/gacopyz.c b/gacopyz/gacopyz.c
index f20a506f..4e28161b 100644
--- a/gacopyz/gacopyz.c
+++ b/gacopyz/gacopyz.c
@@ -1587,7 +1587,7 @@ gacopyz_header_command(SMFICTX *ctx, unsigned char cmd,
memcpy(cptr, headerv, lenv);
cptr += lenv;
- TRACE(ctx, cmd, bufsize, buf);
+ TRACE(ctx, cmd, sizeof hptr->buf + bufsize, buf);
hptr->hdr.cmd = cmd;
hptr->hdr.size = htonl(bufsize + 1);
diff --git a/gacopyz/server.c b/gacopyz/server.c
index 36868b7f..554b3398 100644
--- a/gacopyz/server.c
+++ b/gacopyz/server.c
@@ -1031,6 +1031,19 @@ gacopyz_srv_send_command(gacopyz_srv_t srv, unsigned char cmd,
srv->state = srv_msgproc;
break;
+ case SMFIR_ADDRCPT:
+ case SMFIR_DELRCPT:
+ case SMFIR_REPLBODY:
+ case SMFIR_CHGHEADER:
+ case SMFIR_ADDHEADER:
+ case SMFIR_INSHEADER:
+ srv->resp_ptr = srv->buf;
+ srv->resp_size = size;
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "action=%s, unhandled response=%c",
+ cp->action, rcmd);
+ break;
+
default:
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
"action=%s, bogus response=%c",
diff --git a/pmult/pmult.c b/pmult/pmult.c
index 3f804a54..4b80295c 100644
--- a/pmult/pmult.c
+++ b/pmult/pmult.c
@@ -85,12 +85,24 @@ struct pmult_client
/* List of configured clients: */
mu_list_t /* of struct pmult_client */ client_list;
+enum pmult_msg_state
+ {
+ pmult_msg_state_initial,
+ pmult_msg_state_headers,
+ pmult_msg_state_cr1,
+ pmult_msg_state_crlf1,
+ pmult_msg_state_cr2,
+ pmult_msg_state_body
+ };
+
struct pmult_priv_data
{
mu_debug_t debug;
mu_list_t /* of gacopyz_srv_t */ srvlist;
unsigned nrcpt;
unsigned nbadrcpts;
+ mu_stream_t hdrstream;
+ enum pmult_msg_state state;
};
@@ -532,24 +544,47 @@ while (0)
#define MSG_REJECT "550 5.7.1 Command rejected\r\n"
#define MSG_SHUTDOWN "421 4.7.0 pmult closing connection\r\n"
+const char *
+hdrcommname (int rc)
+{
+ switch (rc)
+ {
+ case SMFIR_CHGHEADER:
+ return "chgheader";
+
+ case SMFIR_ADDHEADER:
+ return "addheader";
+
+ case SMFIR_INSHEADER:
+ return "insheader";
+ }
+ return "unknown";
+}
+
static int
pmult_std_reply (struct pmult_priv_data *p, pmse_ctx_P pmse_ctx,
gacopyz_srv_t gsrv, int rc,
const char *ident, const char *arg)
{
+ char *buf;
+ char *cp;
+ size_t size;
+
+ if (!arg)
+ arg = "";
+
switch (rc)
{
+ case SMFIR_CONTINUE:
+ break;
+
case SMFIR_REPLYCODE:
- {
- char *msg;
- size_t size;
- gacopyz_srv_reply (gsrv, &msg, &size);
- MU_DEBUG3 (p->debug, MU_DEBUG_TRACE2,
- "%s=%s, reply=%s",
- ident, arg, msg);
- SM_VERBOSE (sm_pmfi_setreply (pmse_ctx, msg));
- return (msg[0] == '4') ? SMTP_R_TEMP : SMTP_R_PERM;
- }
+ gacopyz_srv_reply (gsrv, &buf, &size);
+ MU_DEBUG3 (p->debug, MU_DEBUG_TRACE2,
+ "%s=%s, reply=%s",
+ ident, arg, buf);
+ SM_VERBOSE (sm_pmfi_setreply (pmse_ctx, buf));
+ return (buf[0] == '4') ? SMTP_R_TEMP : SMTP_R_PERM;
case SMFIR_REJECT:
MU_DEBUG3 (p->debug, MU_DEBUG_TRACE2,
@@ -577,11 +612,96 @@ pmult_std_reply (struct pmult_priv_data *p, pmse_ctx_P pmse_ctx,
ident, arg, MSG_SHUTDOWN);
SM_VERBOSE (sm_pmfi_setreply (pmse_ctx, MSG_SHUTDOWN));
return SMTP_R_SSD;
+
+ case SMFIR_ADDRCPT:
+ gacopyz_srv_reply (gsrv, &buf, &size);
+ MU_DEBUG3 (p->debug, MU_DEBUG_TRACE2,
+ "%s=%s, addrcpt=%s",
+ ident, arg, buf);
+ /* FIXME-MF: Not implemented in mailfromd */
+ SM_VERBOSE (sm_pmfi_rcpt_add (pmse_ctx, buf, NULL));
+ break;
+
+ case SMFIR_DELRCPT:
+ gacopyz_srv_reply (gsrv, &buf, &size);
+ MU_DEBUG3 (p->debug, MU_DEBUG_TRACE2,
+ "%s=%s, delrcpt=%s",
+ ident, arg, buf);
+ /* FIXME-MF: Not implemented in mailfromd */
+ /* FIXME: Index is always 0 */
+ SM_VERBOSE (sm_pmfi_rcpt_del (pmse_ctx, buf, 0));
+ break;
+
+ case SMFIR_CHGHEADER:
+ case SMFIR_ADDHEADER:
+ case SMFIR_INSHEADER:
+ {
+ char *header;
+ uint type;
+ uint32_t idx = 0;
+
+ gacopyz_srv_reply (gsrv, &buf, &size);
+ if (rc != SMFIR_ADDHEADER)
+ {
+ idx = ntohl (*(uint32_t*)buf);
+ buf += sizeof (uint32_t);
+ }
+ cp = memchr (buf, 0, size);
+ if (!cp)
+ {
+ mu_diag_output (MU_DIAG_NOTICE, "Malformed CHGHEADER command");
+ break;
+ }
+ cp++;
+ MU_DEBUG6 (p->debug, MU_DEBUG_TRACE2,
+ "%s=%s, %s=%u '%s','%s'\n",
+ ident, arg, hdrcommname (rc), idx, buf, cp);
+
+ header = malloc (size + 5);
+ if (!header)
+ {
+ mu_error ("%s", mu_strerror (ENOMEM));
+ return SMTP_R_ACCEPT;
+ }
+ strcpy (header, buf);
+ strcat (header, ": ");
+ strcat (header, cp);
+ strcat (header, "\r\n");
+
+ switch (rc)
+ {
+ case SMFIR_CHGHEADER:
+ /* FIXME: REMOVE does not work unless full header contents is
+ supplied. */
+ type = (*cp == 0) ? SM_HDRMOD_T_REMOVE : SM_HDRMOD_T_REPLACE;
+ break;
+
+ case SMFIR_ADDHEADER:
+ type = SM_HDRMOD_T_APPEND;
+ break;
+
+ case SMFIR_INSHEADER:
+ type = SM_HDRMOD_T_INSERT;
+ }
+ SM_VERBOSE (sm_pmfi_hdr_mod (pmse_ctx, type, idx, header));
+ free (header);
+ }
+ break;
+
+ case SMFIR_REPLBODY:
+ /* FIXME */
+
+ default:
+ if (isascii (rc) && isprint (rc))
+ mu_diag_output (MU_DIAG_WARNING, _("Unsupported reply code: %c (%d)"),
+ rc, rc);
+ else
+ mu_diag_output (MU_DIAG_WARNING, _("Unsupported reply code: (%d)"),
+ rc);
}
return SMTP_R_CONT;
}
-
typedef sfsistat_T (*pmult_runfun_t) (pmse_ctx_P, gacopyz_srv_t, void *);
static sfsistat_T
@@ -631,6 +751,7 @@ pmult_free (struct pmult_priv_data *p)
mu_list_destroy (&p->srvlist);
unprotect ();
+ mu_stream_destroy (&p->hdrstream, NULL);
mu_debug_destroy (&p->debug, NULL);
free (p);
}
@@ -1078,6 +1199,148 @@ rf_body (pmse_ctx_P pmse_ctx, gacopyz_srv_t gsrv, void *data)
return status == SMTP_R_CONT ? SMTP_R_OK : status;
}
+static int
+collect_headers (struct pmult_priv_data *p, unsigned char *buf, size_t len,
+ size_t *poff)
+{
+ int rc;
+ size_t off = 0;
+
+ if (p->state == pmult_msg_state_initial)
+ {
+ mu_memory_stream_create (&p->hdrstream, NULL, MU_STREAM_NO_CHECK);
+ p->state = pmult_msg_state_headers;
+ }
+
+ for (;;)
+ {
+ if (p->state == pmult_msg_state_headers)
+ {
+ for (; off < len; off++)
+ if (buf[off] == '\r')
+ {
+ off++;
+ p->state = pmult_msg_state_cr1;
+ break;
+ }
+ }
+
+ if (off == len)
+ break;
+
+ if (p->state == pmult_msg_state_cr1 && buf[off] == '\n')
+ {
+ p->state = pmult_msg_state_crlf1;
+ off++;
+ }
+
+ if (off == len)
+ break;
+
+ if (p->state == pmult_msg_state_crlf1)
+ {
+ if (buf[off] == '\r')
+ {
+ p->state = pmult_msg_state_cr2;
+ off++;
+ }
+ else
+ p->state = pmult_msg_state_headers;
+ }
+
+ if (off == len)
+ break;
+
+ if (p->state == pmult_msg_state_cr2 && buf[off] == '\n')
+ {
+ p->state = pmult_msg_state_body;
+ off++;
+ break;
+ }
+ }
+
+ rc = mu_stream_sequential_write (p->hdrstream, buf, off);
+ if (rc)
+ {
+ mu_error ("mu_stream_sequential_write: %s", mu_strerror (rc));
+ return 1;
+ }
+ *poff = off;
+ return 0;
+}
+
+struct header
+{
+ const char *name;
+ const char *value;
+};
+
+static sfsistat_T
+rf_header (pmse_ctx_P pmse_ctx, gacopyz_srv_t gsrv, void *data)
+{
+ struct pmult_priv_data *p = sm_pmfi_get_ctx_se (pmse_ctx);
+ struct header *hp = data;
+ int rc = gacopyz_srv_header (gsrv, (char*)hp->name, (char*)hp->value);
+ pmult_std_reply (p, pmse_ctx, gsrv, rc, "header", NULL);
+ /* FIXME: do I need to analyze its return? */
+ return SMTP_R_OK;
+}
+
+static sfsistat_T
+rf_eoh (pmse_ctx_P pmse_ctx, gacopyz_srv_t gsrv, void *data)
+{
+ struct pmult_priv_data *p = sm_pmfi_get_ctx_se (pmse_ctx);
+ int rc = gacopyz_srv_eoh (gsrv);
+ pmult_std_reply (p, pmse_ctx, gsrv, rc, "eoh", NULL);
+ /* FIXME: do I need to analyze its return? */
+ return SMTP_R_OK;
+}
+
+static int
+process_headers (pmse_ctx_P pmse_ctx, struct pmult_priv_data *p)
+{
+ mu_header_t hdr;
+ mu_off_t size;
+ size_t count, i;
+ int rc;
+ mu_transport_t tbuf;
+
+ /* FIXME-MU: This could be largely simplified if mu_header_t had
+ a _set_stream method. */
+ rc = mu_stream_size (p->hdrstream, &size);
+ if (rc)
+ {
+ mu_error (_("Cannot get the size of the header stream: %s"),
+ mu_strerror (rc));
+ return 1;
+ }
+ mu_stream_get_transport (p->hdrstream, &tbuf);
+ rc = mu_header_create (&hdr, (char*) tbuf, size, NULL);
+ if (rc)
+ {
+ mu_error (_("Cannot create header: %s"), mu_strerror (rc));
+ return 1;
+ }
+
+ /* FIXME-MU: mu_header_get_iterator would be in place here. */
+ mu_header_get_field_count (hdr, &count);
+ for (i = 1; i <= count; i++)
+ {
+ struct header h;
+ if (mu_header_sget_field_name (hdr, i, &h.name)
+ || mu_header_sget_field_value (hdr, i, &h.value))
+ continue;
+ pmult_runlist (p, rf_header, pmse_ctx, &h, NULL);
+ }
+ pmult_runlist (p, rf_eoh, pmse_ctx, NULL, NULL);
+
+ mu_header_destroy (&hdr, mu_header_get_owner (hdr));
+ return 0;
+}
+
+#define EOM_MARK "\r\n.\r\n"
+#define EOM_MARK_LEN (sizeof (EOM_MARK) - 1)
+
static sfsistat_T
pmult_msg (pmse_ctx_P pmse_ctx, unsigned char *buf, size_t len)
{
@@ -1093,6 +1356,27 @@ pmult_msg (pmse_ctx_P pmse_ctx, unsigned char *buf, size_t len)
MU_DEBUG1 (p->debug, MU_DEBUG_TRACE1, "BODY %lu\n",
(unsigned long) len);
}
+
+ if (p->state != pmult_msg_state_body)
+ {
+ size_t off;
+ int rc = collect_headers (p, buf, len, &off);
+ if (rc)
+ return SMTP_R_ACCEPT; /* Better safe than sorry. */
+ if (p->state != pmult_msg_state_body)
+ return SMTP_R_OK; /* See comment to rf_body */
+ if (process_headers (pmse_ctx, p))
+ return SMTP_R_ACCEPT;
+ len -= off;
+ buf += off;
+ }
+
+ /* FIXME: This is not enough, the marker can be split between two
+ successive calls. */
+ if (len >= EOM_MARK_LEN
+ && memcmp (buf + len - EOM_MARK_LEN, EOM_MARK, EOM_MARK_LEN) == 0)
+ len -= 3;
+
bc.ident = "body";
bc.srvfun = gacopyz_srv_body;
bc.size = len;
diff --git a/src/prog.c b/src/prog.c
index 7305b518..2956e656 100644
--- a/src/prog.c
+++ b/src/prog.c
@@ -1359,7 +1359,7 @@ instr_header(eval_environ_t env)
adjust_stack(env, 1);
if (PROG_TRACE_ENGINE)
- prog_trace(env, "HEADER %d %s %s",
+ prog_trace(env, "HEADER %d '%s' '%s'",
hdr->opcode, hdr->name, hdr->value);
trace("%s%s:%lu: %s %s %s",

Return to:

Send suggestions and report system problems to the System administrator.