--- lmtp2nntp.c 2001/08/07 09:21:49 1.10
+++ lmtp2nntp.c 2001/08/07 14:58:02 1.11
@@ -52,6 +52,8 @@
static lmtp_rc_t lmtp_cb_rset (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
static lmtp_rc_t lmtp_cb_quit (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
+static lmtp_rc_t prepareheader(void *ctx);
+
static int helo_rfc0821domain(char *msg, char **domain);
static int helo_rfc1035domain(char *msg, char **domain);
@@ -59,15 +61,21 @@
int lhlo_seen;
char *lhlo_domain;
};
-static void resetsession(struct session *session);
+static void initsession(struct session *session);
+static void resetsession(struct session *session);
struct message {
- char *rfc822message;
+ char *cpMsg; /* the wholly message to be received by DATA command */
+ char *cpHeaders; /* header part of message above */
+ char *cpBody; /* body part of message above */
char *mail_from;
char *azRcpt;
size_t asRcpt;
+ char *azHeaders;
+ size_t asHeaders;
};
+static void initmessage(struct message *message);
static void resetmessage(struct message *message);
struct ns {
@@ -179,8 +187,8 @@
ctx->asGroups = 0;
ctx->azGroupfilters = NULL;
ctx->asGroupfilters = 0;
- resetsession(&ctx->session);
- resetmessage(&ctx->message);
+ initsession(&ctx->session);
+ initmessage(&ctx->message);
{
char buf[1000];
@@ -293,36 +301,49 @@
static void resetsession(struct session *session)
{
+ //FIXME what about non-graceful aborts?
+ if (session->lhlo_domain != NULL)
+ free(session->lhlo_domain);
+ initsession(session);
+ return;
+}
+static void initsession(struct session *session)
+{
session->lhlo_seen = FALSE;
-
- // fprintf(stderr, "DEBUG: session->lhlo_domain=***%s***\n", session->lhlo_domain);
- if (session->lhlo_domain != NULL)
- free(session->lhlo_domain); //FIXME what about non-graceful aborts?
session->lhlo_domain = NULL;
-
return;
}
static void resetmessage(struct message *message)
{
- // fprintf(stderr, "DEBUG: message->mail_from=***%s***\n", message->mail_from);
+ //FIXME what about non-graceful aborts?
if (message->mail_from != NULL)
- free(message->mail_from); //FIXME what about non-graceful aborts?
- message->mail_from = NULL;
-
- // fprintf(stderr, "DEBUG: message->azRcpt=***%s***\n", message->azRcpt);
+ free(message->mail_from);
if (message->azRcpt != NULL)
- free(message->azRcpt); //FIXME what about non-graceful aborts?
- message->azRcpt = NULL;
+ free(message->azRcpt);
+ if (message->azHeaders != NULL)
+ free(message->azHeaders);
+ if (message->cpMsg != NULL)
+ free(message->cpMsg);
+ if (message->cpHeaders != NULL)
+ free(message->cpHeaders);
+ if (message->cpBody != NULL)
+ free(message->cpBody);
+ initmessage(message);
+ return;
+}
+static void initmessage(struct message *message)
+{
+ message->mail_from = NULL;
+ message->azRcpt = NULL;
message->asRcpt = 0;
-
- // fprintf(stderr, "DEBUG: message->rfc822message=***%s***\n", message->rfc822message);
- if (message->rfc822message != NULL)
- free(message->rfc822message); //FIXME what about non-graceful aborts?
- message->rfc822message = NULL;
-
+ message->azHeaders = NULL;
+ message->asHeaders = 0;
+ message->cpMsg = NULL;
+ message->cpHeaders = NULL;
+ message->cpBody = NULL;
return;
}
@@ -618,8 +639,7 @@
lmtp_response(lmtp, &res);
return LMTP_OK;
}
- cp = group;
- // fprintf(stderr, "DEBUG: after transform cp=***%s***\n", cp);
+ // fprintf(stderr, "DEBUG: after transform group=***%s***\n", group);
//FIXME do additional transform and checking
if (0) {
res.statuscode = "550";
@@ -638,8 +658,9 @@
return LMTP_OK;
}
- // fprintf(stderr, "DEBUG: cp=***%s***\n", cp);
+ fprintf(stderr, "DEBUG: cp=***%s***\n", cp);
argz_add(&ctx->message.azRcpt, &ctx->message.asRcpt, cp);
+ argz_add(&ctx->azGroups, &ctx->asGroups, group);
res.statuscode = "250";
res.dsncode = "2.1.5";
res.statusmsg = "Recipient/ Group accepted";
@@ -652,7 +673,6 @@
lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
- char *buf;
char errorstring[STDSTRLEN];
char *rcpt;
@@ -668,32 +688,146 @@
res.dsncode = NULL; /* DSN not used for data */
res.statusmsg = "Enter mail, end with \".\" on a line by itself";
lmtp_response(lmtp, &res);
- rc = lmtp_readmsg(lmtp, &buf, MESSAGE_MAXLEN);
- rcpt = NULL;
- while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL)
- {
- if(rc == LMTP_OK) {
- res.statuscode = "250";
- res.dsncode = "2.0.0";
- str_format(errorstring, sizeof(errorstring), "Message accepted for delivery to %s", rcpt);
- res.statusmsg = errorstring;
- } else if (rc == LMTP_ERR_OVERFLOW) {
+ rc = lmtp_readmsg(lmtp, &ctx->message.cpMsg, MESSAGE_MAXLEN);
+
+ if (rc == LMTP_ERR_OVERFLOW) {
+ rcpt = NULL;
+ while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
res.statuscode = "500";
res.dsncode = "5.0.0";
- res.statusmsg = "FIXME overflow";
- } else if (rc == LMTP_ERR_SYSTEM) {
+ res.statusmsg = "Overflow reading message"; //FIXME temp or perm error?
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
+ }
+ }
+
+ if (rc == LMTP_ERR_SYSTEM) {
+ rcpt = NULL;
+ while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
res.statuscode = "500";
res.dsncode = "5.0.0";
- str_format(errorstring, sizeof(errorstring), "Message accepted for delivery %s", strerror(errno));
+ str_format(errorstring, sizeof(errorstring), "System error reading message: %s", strerror(errno));
res.statusmsg = errorstring;
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
}
+ }
+
+ if(rc != LMTP_OK) {
+ rcpt = NULL;
+ while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
+ res.statuscode = "500";
+ res.dsncode = "5.0.0";
+ res.statusmsg = "Unknown error reading message"; //FIXME call lmtp_error()?
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
+ }
+ }
+
+ /* manipulate headers
+ * - remove To: and Cc: headers
+ * - (re)create Newsgroups: header
+ */
+ prepareheader(ctx);
+
+ rcpt = NULL;
+ while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
+ res.statuscode = "250";
+ res.dsncode = "2.0.0";
+ str_format(errorstring, sizeof(errorstring), "Message accepted for delivery to %s", rcpt);
+ res.statusmsg = errorstring;
lmtp_response(lmtp, &res);
}
+
resetmessage(&ctx->message);
return rc;
}
+lmtp_rc_t prepareheader(void *_ctx)
+{
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
+ char *cpName;
+ char *cpValue;
+ char *cpRem;
+ char *cp;
+ char *azNewsgroups;
+ int asNewsgroups;
+
+ /****************
+ * PARSE HEADER * FIXME make it nice
+ ****************/
+
+ if (!str_parse(ctx->message.cpMsg, "m/((?:.*?)\\n)\\n(.*)$/s", &ctx->message.cpHeaders, &ctx->message.cpBody))
+ return LMTP_ERR_ARG;
+
+ if (strlen(ctx->message.cpHeaders) < 4 + 1)
+ return LMTP_ERR_ARG;
+ memcpy(ctx->message.cpHeaders, "X-F:", 4); /* replace envelope From w/o colon by X-F: pseudotag */
+
+ // fprintf(stderr, "DEBUG: input ***%s***\n", ctx->message.cpHeaders);
+ while (str_parse(ctx->message.cpHeaders, "s/(.*?)\\n[ \\t]+(.*)/$1 $2/s", &cpRem)) { //FIXME poor man's s///g simulator
+ free(ctx->message.cpHeaders);
+ ctx->message.cpHeaders = cpRem;
+ }
+ /*
+ * FIXME str enhancement requests and bugs to be fixed
+ *
+ * - fix bug "not" [^...] working
+ * - improve str_parse(foo, "...", &foo) should free foo() on it's own
+ * - add "global" in s/search/replace/g
+ */
+ // fprintf(stderr, "DEBUG: unwrapped ***%s***\n", ctx->message.cpHeaders);
+
+ while (str_parse(ctx->message.cpHeaders, "m/^([\\w-]+?:)\\s*([\\S \\t]*?)\\n(.*)/s", &cpName, &cpValue, &cpRem)) {
+ free(ctx->message.cpHeaders);
+ ctx->message.cpHeaders = cpRem;
+ fprintf(stderr, "DEBUG: raw Name(%s) = Value(%s)\n", cpName, cpValue);
+ argz_add(&ctx->message.azHeaders, &ctx->message.asHeaders, cpName);
+ argz_add(&ctx->message.azHeaders, &ctx->message.asHeaders, cpValue);
+ }
+ memcpy(ctx->message.azHeaders, "From", 4); /* replace envelope X-F: pseudotag with From w/o colon */
+ // fprintf(stderr, "DEBUG: remainder ***%s***\n", ctx->message.cpHeaders);
+ // fprintf(stderr, "DEBUG: body ***%s***\n", ctx->message.cpBody);
+
+ /*********************
+ * MANIPULATE HEADER * FIXME make it nice
+ *********************/
+
+ cp = NULL;
+ while ((cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp)) != NULL) {
+ if (strcasecmp("To:", cp) == 0) {
+ argz_delete(&ctx->message.azHeaders, &ctx->message.asHeaders, cp); /* name */
+ argz_delete(&ctx->message.azHeaders, &ctx->message.asHeaders, cp); /* value */
+ } //FIXME what bad things can happen here (odd number of argz, delete fails ...
+ if (strcasecmp("Cc:", cp) == 0) {
+ argz_delete(&ctx->message.azHeaders, &ctx->message.asHeaders, cp); /* name */
+ argz_delete(&ctx->message.azHeaders, &ctx->message.asHeaders, cp); /* value */
+ } //FIXME what bad things can happen here (odd number of argz, delete fails ...
+ }
+
+ cp = NULL;
+ azNewsgroups = NULL;
+ asNewsgroups = 0;
+ while ((cp = argz_next(ctx->azGroups, ctx->asGroups, cp)) != NULL) {
+ // fprintf(stderr, "DEBUG: Group(%s)\n", cp);
+ argz_add(&azNewsgroups, &asNewsgroups, cp);
+ }
+ argz_stringify(azNewsgroups, asNewsgroups, ',');
+ argz_add(&ctx->message.azHeaders, &ctx->message.asHeaders, "Newsgroups:");
+ argz_add(&ctx->message.azHeaders, &ctx->message.asHeaders, azNewsgroups);
+
+ cp = NULL;
+ while ((cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp)) != NULL) {
+ cpName = cp;
+ cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp);
+ cpValue = cp;
+ fprintf(stderr, "DEBUG: cooked Name(%s) = Value(%s)\n", cpName, cpValue);
+ }
+
+ return LMTP_OK;
+}
+
static lmtp_rc_t lmtp_cb_noop(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
{
lmtp_res_t res;
|