OSSP CVS Repository

ossp - Check-in [657]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 657
Date: 2001-Aug-13 08:41:41 (local)
2001-Aug-13 06:41:41 (UTC)
User:thl
Branch:
Comment: moved message issues from lmtp2nntp.[ch] and nntp.[ch] into separate new file msg.[ch]
Tickets:
Inspections:
Files:
ossp-pkg/lmtp2nntp/lmtp2nntp.c      1.13 -> 1.14     96 inserted, 245 deleted
ossp-pkg/lmtp2nntp/msg.c      added-> 1.1
ossp-pkg/lmtp2nntp/msg.h      added-> 1.1
ossp-pkg/lmtp2nntp/nntp.c      1.3 -> 1.4     66 inserted, 44 deleted
ossp-pkg/lmtp2nntp/nntp.h      1.2 -> 1.3     4 inserted, 1 deleted

ossp-pkg/lmtp2nntp/lmtp2nntp.c 1.13 -> 1.14

--- lmtp2nntp.c  2001/08/08 10:43:00     1.13
+++ lmtp2nntp.c  2001/08/13 06:41:41     1.14
@@ -24,6 +24,7 @@
 #include "lmtp.h"
 #include "nntp.h"
 #include "sa.h"
+#include "msg.h"
 
 #ifndef FALSE
 #define FALSE (1 != 1)
@@ -52,8 +53,6 @@
 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);
 
@@ -65,19 +64,6 @@
 static void initsession(struct session *session);
 static void resetsession(struct session *session);
 
-struct message {
-    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 {
     char *h;        /* host */
     char *p;        /* port */
@@ -97,7 +83,7 @@
     char   *azGroupfilters;
     size_t  asGroupfilters;
     struct  session session;
-    struct  message message;
+    msg_t  *msg;
 } lmtp2nntp_t;
 
 enum {
@@ -188,7 +174,7 @@
     ctx->azGroupfilters = NULL;
     ctx->asGroupfilters = 0;
     initsession(&ctx->session);
-    initmessage(&ctx->message);
+    ctx->msg = NULL;
 
     {
         char buf[1000];
@@ -315,38 +301,6 @@
     return;
 }
 
-static void resetmessage(struct message *message)
-{
-                                             //FIXME what about non-graceful aborts?
-    if (message->mail_from != NULL)
-        free(message->mail_from);
-    if (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;
-    message->azHeaders = NULL;
-    message->asHeaders = 0;
-    message->cpMsg = NULL;
-    message->cpHeaders = NULL;
-    message->cpBody = NULL;
-    return;
-}
-
 static lmtp_rc_t lmtp_cb_lhlo(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
 {
     /*  
@@ -568,36 +522,46 @@
 
 static lmtp_rc_t lmtp_cb_mail(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
 {
-    lmtp_res_t res;
-    lmtp_rc_t rc = LMTP_OK;
     lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
+    lmtp_res_t res;
 
     if (ctx->session.lhlo_seen != TRUE) {
         res.statuscode = "553";
         res.dsncode    = "5.1.8";
         res.statusmsg  = "friendly people say LHLO to open a transmission channel.";
         lmtp_response(lmtp, &res);
+        return LMTP_OK;
     }
-    else if (ctx->message.mail_from != NULL) {
+
+    if (ctx->msg != NULL) {
         res.statuscode = "503";
         res.dsncode    = "5.5.0";
         res.statusmsg  = "Sender already specified.";
         lmtp_response(lmtp, &res);
+        return LMTP_OK;
+    }
+
+    if ((ctx->msg = msg_create()) == NULL) {
+        res.statuscode = "503"; // FIXME
+        res.dsncode    = "5.5.0";
+        res.statusmsg  = "Internal error - memory.";
+        lmtp_response(lmtp, &res);
+        return LMTP_ERR_MEM;
     }
-    else
-        if (!str_parse(req->msg, "m/^MAIL From: <(.+@.+)>$/i", &ctx->message.mail_from)) {
+
+    if (!str_parse(req->msg, "m/^MAIL From: <(.+@.+)>$/i", &ctx->msg->mail_from)) {
         res.statuscode = "553";
         res.dsncode    = "5.5.4";
         res.statusmsg  = "Domain name required for sender address.";
         lmtp_response(lmtp, &res);
+        return LMTP_OK;
     }
-    else {
-        res.statuscode = "250";
-        res.dsncode    = "2.1.0";
-        res.statusmsg  = "Sender ok.";
-        lmtp_response(lmtp, &res);
-    }
-    return rc;
+    
+    res.statuscode = "250";
+    res.dsncode    = "2.1.0";
+    res.statusmsg  = "Sender ok.";
+    lmtp_response(lmtp, &res);
+    return LMTP_OK;
 }
 
 static lmtp_rc_t lmtp_cb_rcpt(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
@@ -607,7 +571,7 @@
     char *cp;
     char *group;
 
-    if (ctx->message.mail_from == NULL) {
+    if (ctx->msg->mail_from == NULL) {
         res.statuscode = "503";
         res.dsncode    = "5.0.0";
         res.statusmsg  = "specify sender with MAIL first.";
@@ -658,8 +622,8 @@
         return LMTP_OK;
     }
 
-    fprintf(stderr, "DEBUG: cp=***%s***\n", cp);
-    argz_add(&ctx->message.azRcpt, &ctx->message.asRcpt, cp);
+    //fprintf(stderr, "DEBUG: cp=***%s***\n", cp);
+    argz_add(&ctx->msg->azRcpt, &ctx->msg->asRcpt, cp);
     argz_add(&ctx->azGroups, &ctx->asGroups, group);
     res.statuscode = "250";
     res.dsncode    = "2.1.5";
@@ -675,8 +639,9 @@
     lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
     char errorstring[STDSTRLEN];
     char *rcpt;
+    int i;
 
-    if (argz_count(ctx->message.azRcpt, ctx->message.asRcpt) == 0) {
+    if (argz_count(ctx->msg->azRcpt, ctx->msg->asRcpt) == 0) {
         res.statuscode = "503";
         res.dsncode    = "5.0.0";
         res.statusmsg  = "specify recipient with RCPT first.";
@@ -689,11 +654,11 @@
     res.statusmsg  = "Enter mail, end with \".\" on a line by itself";
     lmtp_response(lmtp, &res);
 
-    rc = lmtp_readmsg(lmtp, &ctx->message.cpMsg, MESSAGE_MAXLEN);
+    rc = lmtp_readmsg(lmtp, &ctx->msg->cpMsg, MESSAGE_MAXLEN);
 
     if (rc == LMTP_ERR_OVERFLOW) {
         rcpt = NULL;
-        while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
+        while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
             res.statuscode = "500";
             res.dsncode    = "5.0.0";
             res.statusmsg  = "Overflow reading message"; //FIXME temp or perm error?
@@ -704,7 +669,7 @@
 
     if (rc == LMTP_ERR_SYSTEM) {
         rcpt = NULL;
-        while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
+        while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
             res.statuscode = "500";
             res.dsncode    = "5.0.0";
             str_format(errorstring, sizeof(errorstring), "System error reading message: %s", strerror(errno));
@@ -716,7 +681,7 @@
 
     if(rc != LMTP_OK) {
         rcpt = NULL;
-        while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
+        while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
             res.statuscode = "500";
             res.dsncode    = "5.0.0";
             res.statusmsg  = "Unknown error reading message"; //FIXME call lmtp_error()?
@@ -725,14 +690,61 @@
         }
     }
 
-    /* manipulate headers
-     * - remove To: and Cc: headers
-     * - (re)create Newsgroups: header
-     */
-    prepareheader(ctx);
+#if 0
+    fprintf(stderr, "DEBUG: calling msg_split();\n");
+    fprintf(stderr, "DEBUG: msg_split() returned %s\n", msg_error(ctx->msg, msg_split(ctx->msg)));
+#endif
+    if (msg_split(ctx->msg) != MSG_OK) {
+        while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
+            res.statuscode = "500";
+            res.dsncode    = "5.0.0";
+            res.statusmsg  = "Error splitting message."; //FIXME call msg_error()?
+            lmtp_response(lmtp, &res);
+            return LMTP_OK;
+        }
+    }
+
+#if 0
+    { //FIXME just a debug paragraph
+        char *cp;
+        cp = NULL;
+        while((cp = argz_next(ctx->azGroups, ctx->asGroups, cp)) != NULL)
+            fprintf(stderr, "DEBUG: lmtp Groups: ***%s***\n", cp);
+    }
+#endif
+    ctx->msg->azNewsgroups = ctx->azGroups;
+    ctx->msg->asNewsgroups = ctx->asGroups;
+#if 0
+    { //FIXME just a debug paragraph
+        char *cp;
+        cp = NULL;
+        while((cp = argz_next(ctx->msg->azNewsgroups, ctx->msg->asNewsgroups, cp)) != NULL)
+            fprintf(stderr, "DEBUG: article Newsgroups: ***%s***\n", cp);
+        fprintf(stderr, "DEBUG: article Message-ID: ***%s***\n", ctx->msg->cpMsgid);
+    }
+#endif
+
+#if 0
+    fprintf(stderr, "DEBUG: calling msg_join();\n");
+    fprintf(stderr, "DEBUG: msg_join()  returned %s\n", msg_error(ctx->msg, msg_join(ctx->msg)));
+#endif
+    if (msg_join(ctx->msg) != MSG_OK) {
+        while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
+            res.statuscode = "500";
+            res.dsncode    = "5.0.0";
+            res.statusmsg  = "Error joining message."; //FIXME call msg_error()?
+            lmtp_response(lmtp, &res);
+            return LMTP_OK;
+        }
+    }
+
+    for (i=0; i < ctx->nsc; i++) {
+        fprintf(stderr, "DEBUG: trying service %s\n", ctx->ns[i].h);
+        (void)nntp_post(ctx->ns[i].nntp, ctx->msg);
+    }
 
     rcpt = NULL;
-    while ((rcpt = argz_next(ctx->message.azRcpt, ctx->message.asRcpt, rcpt)) != NULL) {
+    while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
         res.statuscode = "250";
         res.dsncode    = "2.0.0";
         str_format(errorstring, sizeof(errorstring), "Message accepted for delivery to %s", rcpt);
@@ -740,175 +752,10 @@
         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;
-    char **aHeaders;
-    char  *cpMsgid;
-    int    i;
-    char  *cpCut;
-    char  *cpWrap;
-
-                                /****************
-                                 * 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-]+?:)[ \\t]*(.*?)[ \\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
-                                 *********************/
-
-    /* check for headers we care about and verfiy them, throw them away ... */
-    cpMsgid = NULL;
-    cp = ctx->message.azHeaders;
-    while (cp != NULL) {
-        fprintf(stderr, "DEBUG: checking header ***%s***\n", cp);
-        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 */
-            continue;
-        } //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 */
-            continue;
-        } //FIXME what bad things can happen here (odd number of argz, delete fails ...
-        if (strcasecmp("Message-ID:", cp) == 0) {
-            if ((cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp)) == NULL)
-                break;
-            cpMsgid = cp;
-            if ((cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp)) == NULL)
-                break;
-            continue;
-        }
-        if ((cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp)) == NULL)
-            break;
-        if ((cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp)) == NULL)
-            break;
-    }
-    if (cpMsgid == NULL)
-        exit(1); //FIXME
-    else
-        fprintf(stderr, "DEBUG: Message-ID = ***%s***\n", cpMsgid);
-
-    /* create a proper Newsgroups: header */
-    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);
-
-    /* merge name/value pairs into single string */
-    argz_add(&ctx->message.azHeaders, &ctx->message.asHeaders, ""); /* append empty string */
-    if ((aHeaders = (char **)malloc((argz_count(ctx->message.azHeaders,
-        ctx->message.asHeaders) + 1) * sizeof(char *))) == NULL)
-        exit(1); //FIXME
-    argz_extract(ctx->message.azHeaders, ctx->message.asHeaders, aHeaders);
-    i=0;
-    while(1) {
-        if ((cp = aHeaders[++i]) == NULL)
-            break;
-        *(cp-1) = ' ';
-        if ((cp = aHeaders[++i]) == NULL)
-            break;
-        // *(cp-1) = '\n';
-    }
-
-    /* fold headers */
-//FIXME where to place this defines best
-#define WRAPAT 120
-#define WRAPUSING "\n    "
-    cp = NULL;
-    while ((cp = argz_next(ctx->message.azHeaders, ctx->message.asHeaders, cp)) != NULL) {
-        if (strlen(cp) >= WRAPAT) {
-            cpRem = cp;
-            cpWrap = NULL;
-            while (strlen(cpRem) >= WRAPAT) {
-                for (i = WRAPAT; i >= 1 && (cpRem[i] != ' ') && (cpRem[i] != '\t'); i--);
-                if (i == 0)
-                    i = WRAPAT; /* sorry, hard cut at non-whitespace */
-                if (i < WRAPAT)
-                    i++; /* we don't care about the whitespace itself */
-                cpCut = str_dup(cpRem, i);
-                //FIXME 1.) continue searching downwards skipping all whitespaces and 2.) as we know the length replace str_dup/ strcat/ free with strncat only
-                if (cpWrap == NULL) {
-                    if ((cpWrap = (char *)malloc(strlen(cpCut)+strlen(WRAPUSING)+1)) == NULL)
-                        exit(1); //FIXME
-                    *cpWrap = '\0';
-                }
-                else {
-                    if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpCut)+strlen(WRAPUSING)+1)) == NULL)
-                        exit(1); //FIXME
-                    strcat(cpWrap, WRAPUSING);
-                }
-                strcat(cpWrap, cpCut);
-                free(cpCut);
-                cpRem += i;
-            }
-            for (i = 0; i < strlen(cpRem) && ((cpRem[i] == ' ') || (cpRem[i] == '\t')); i++);
-            cpRem += i;
-            if (strlen(cpRem) > 0) {
-                if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpRem)+strlen(WRAPUSING)+1)) == NULL)
-                    exit(1); //FIXME
-                strcat(cpWrap, WRAPUSING);
-                strcat(cpWrap, cpRem);
-            }
-            argz_delete(&ctx->message.azHeaders, &ctx->message.asHeaders, cp);
-            argz_insert(&ctx->message.azHeaders, &ctx->message.asHeaders, cp, cpWrap);
-            free(cpWrap);
-        }
-    }
+    msg_destroy(ctx->msg);
+    ctx->msg = NULL;
 
-    argz_stringify(ctx->message.azHeaders, ctx->message.asHeaders, '\n');
-    fprintf(stderr, "DEBUG: flat headers = ***%s***\n", ctx->message.azHeaders);
-
-    return LMTP_OK;
+    return rc;
 }
 
 static lmtp_rc_t lmtp_cb_noop(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
@@ -929,7 +776,9 @@
     lmtp_res_t res;
     lmtp_rc_t rc = LMTP_OK;
 
-    resetmessage(&ctx->message);
+    msg_destroy(ctx->msg);
+    ctx->msg = NULL;
+
     res.statuscode = "250";
     res.dsncode    = "2.0.0";
     res.statusmsg  = "Reset state.";
@@ -943,7 +792,9 @@
     lmtp_res_t res;
     lmtp_rc_t rc = LMTP_EOF;
 
-    resetmessage(&ctx->message);
+    msg_destroy(ctx->msg);
+    ctx->msg = NULL;
+
     resetsession(&ctx->session);
     res.statuscode = "221";
     res.dsncode    = "2.0.0";


ossp-pkg/lmtp2nntp/msg.c -> 1.1

*** /dev/null    Thu Apr 18 19:45:32 2024
--- -    Thu Apr 18 19:46:13 2024
***************
*** 0 ****
--- 1,321 ----
+ 
+ #include <stdlib.h>
+ #include "msg.h"
+ #include "str.h"
+ #include "argz.h"
+ #include <stdio.h>
+ 
+ msg_t *msg_create(void)
+ {
+     msg_t *msg;
+ 
+     if ((msg = (msg_t *)malloc(sizeof(msg_t))) == NULL)
+         return NULL;
+ 
+     msg->mail_from = NULL;
+     msg->azRcpt = NULL;
+     msg->asRcpt = 0;
+     msg->azNewsgroups = NULL;
+     msg->asNewsgroups = 0;
+     msg->azHeaders = NULL;
+     msg->asHeaders = 0;
+     msg->cpMsg = NULL;
+     msg->cpHeaders = NULL;
+     msg->cpBody = NULL;
+     msg->cpMsgid = NULL;
+ 
+     return msg;
+ }
+ 
+ void msg_destroy(msg_t *msg)
+ {
+     if (msg == NULL)
+         return;
+                                              //FIXME what about non-graceful aborts?
+     if (msg->mail_from != NULL)
+         free(msg->mail_from);
+     if (msg->azRcpt != NULL)
+         free(msg->azRcpt);
+     if (msg->azHeaders != NULL)
+         free(msg->azHeaders);
+     if (msg->azNewsgroups != NULL)
+         free(msg->azNewsgroups);
+     if (msg->cpMsg != NULL)
+         free(msg->cpMsg);
+     if (msg->cpHeaders != NULL)
+         free(msg->cpHeaders);
+     if (msg->cpBody != NULL)
+         free(msg->cpBody);
+     free(msg);
+ }
+ 
+ msg_rc_t msg_split(msg_t *msg)
+ {
+     char        *cpName;
+     char        *cpValue;
+     char        *cpRem;
+     char        *cp;
+ 
+     /* INPUTS
+      *
+      * msg->cpMsg
+      * must contain the wholly RFC822 formatted message with native
+      * (unescaped) dots at the beginning of a line, the 'From ' envelope,
+      * headers, double newline, body, '\0', no trailing dot;
+      *
+      * OUTPUTS
+      *
+      * msg->azHeaders, msg->asHeaders
+      * contains the headers in argz format, one logical '\0'-terminated line
+      * per header which might be wrapped into multiple '\n'-ended physical
+      * lines. The "To:" and "Cc:" headers are silently. The "Newsgroups:" and
+      * "Message-ID" headers are removed and their values are stored in
+      * separate structures (see below).
+      *
+      * msg->cpBody
+      * contains the unmodified body of the message, '\0'-terminated, no
+      * trailing dot.
+      *
+      * msg->cpMsgid
+      * contains the message id including surrounding angle brackets.
+      *
+      * msg->azNewsgroups, asNewsgroups
+      * is a argz-type array of strings containing the Newsgroups based on the
+      * header information.
+      */
+ 
+     /* split message into header and body */
+     if (!str_parse(msg->cpMsg, "m/((?:.*?)\\n)\\n(.*)$/s", &msg->cpHeaders, &msg->cpBody))
+         return MSG_ERR_SPLITSPLITBODY;
+ 
+     /* replace envelope From w/o colon by X-F: pseudotag. This eliminates the
+      * special case of having one header, which is really an embedded
+      * envelope, not ending with a colon while all other do. After splitting
+      * headers into name and value pairs this action is reversed.
+      */
+     if (strlen(msg->cpHeaders) < 4)
+         return MSG_ERR_SPLITLEN;
+     if (strncasecmp(msg->cpHeaders, "From", 4) != 0)
+         return MSG_ERR_SPLITMISSINGFROM;
+     memcpy(msg->cpHeaders, "X-F:", 4);
+ 
+     /* unwrap header lines */
+     //FIXME poor man's s///g simulator as current str library doesn't support //global substitution
+     while (str_parse(msg->cpHeaders, "s/(.*?)\\n[ \\t]+(.*)/$1 $2/s", &cpRem)) {
+         free(msg->cpHeaders);
+         msg->cpHeaders = cpRem;
+     }
+ 
+     /* split header lines into names and values */
+     //FIXME str enhancement requests and bugs to be fixed
+     //FIXME - fix bug "not" [^...] working
+     //FIXME - improve str_parse(foo, "...", &foo) should free foo() on it's own
+     //FIXME - add "global" in s/search/replace/g (see above "unwrap hader lines")
+     while (str_parse(msg->cpHeaders, "m/^([\\w-]+?:)[ \\t]*(.*?)[ \\t]*\\n(.*)/s", &cpName, &cpValue, &cpRem)) {
+         free(msg->cpHeaders);
+         msg->cpHeaders = cpRem;
+         argz_add(&msg->azHeaders, &msg->asHeaders, cpName);
+         argz_add(&msg->azHeaders, &msg->asHeaders, cpValue);
+     }
+ 
+     /* reverse the 'From ' to 'X-F: ' replacement */
+     memcpy(msg->azHeaders, "From", 4); /* replace envelope X-F: pseudotag with From w/o colon */
+ 
+     /* check for headers we care about and do whatever neccessary */
+     msg->cpMsgid = NULL;
+     msg->azNewsgroups = NULL;
+     msg->asNewsgroups = 0;
+     cp = msg->azHeaders;
+     while (cp != NULL) {
+         if (strcasecmp("To:", cp) == 0) {
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  name  */
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  value */
+             continue;
+         }
+         if (strcasecmp("Cc:", cp) == 0) {
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  name  */
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  value */
+             continue;
+         }
+         if (strcasecmp("Message-ID:", cp) == 0) {
+             if (msg->cpMsgid != NULL)
+                 return MSG_ERR_SPLITIDMULTI;
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  name  */
+             //fprintf(stderr, "DEBUG: Message-ID cp = ***%s***\n", cp);
+             if ((cp == NULL) || (strlen(cp) == 0))                         /* get  value */
+                 return MSG_ERR_SPLITIDEMPTY;
+             if ((msg->cpMsgid = strdup(cp)) == NULL)
+                 return MSG_ERR_MEM;
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  value */
+             continue;
+         }
+         if (strcasecmp("Newsgroups:", cp) == 0) {
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  name  */
+             //fprintf(stderr, "DEBUG: Newsgroups cp = ***%s***\n", cp);
+             if (argz_add(&msg->azNewsgroups, &msg->asNewsgroups, cp) != 0) /* get  value */
+                 return MSG_ERR_MEM;
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  value */
+             continue;
+         }
+         if ((cp = argz_next(msg->azHeaders, msg->asHeaders, cp)) == NULL)  /* next value */
+             break;
+         if ((cp = argz_next(msg->azHeaders, msg->asHeaders, cp)) == NULL)  /* next name  */
+             break;
+     }
+     if (msg->cpMsgid == NULL)
+         return MSG_ERR_SPLITIDNONE;
+ 
+     if (msg->azNewsgroups != NULL) {
+         argz_stringify(msg->azNewsgroups, msg->asNewsgroups, ',');
+         if (argz_create_sep(msg->azNewsgroups, ',', &msg->azNewsgroups, &msg->asNewsgroups) != 0)
+             return MSG_ERR_MEM;
+     }
+ 
+     return MSG_OK;
+ }
+ 
+ msg_rc_t msg_join(msg_t *msg)
+ {
+     char        *cp;
+     char        *cpRem;
+     char       **aHeaders;
+     int          i;
+     char        *cpCut;
+     char        *cpWrap;
+     char        *cpNew;
+ 
+     /* verify asNewsgroups */
+     if (msg->azNewsgroups == NULL)
+         return MSG_ERR_JOINGROUPNONE;
+     argz_stringify(msg->azNewsgroups, msg->asNewsgroups, ',');
+     //fprintf(stderr, "DEBUG: join consolidated azNewsgroups = ***%s***\n", msg->azNewsgroups);
+     if (strlen(msg->azNewsgroups) == 0)
+         return MSG_ERR_JOINGROUPEMPTY;
+     argz_add(&msg->azHeaders, &msg->asHeaders, "Newsgroups:");
+     argz_add(&msg->azHeaders, &msg->asHeaders, msg->azNewsgroups);
+ 
+     /* verify Message-ID */
+     if (msg->cpMsgid == NULL)
+         return MSG_ERR_JOINIDNONE;
+     if (strlen(msg->cpMsgid) == 0)
+         return MSG_ERR_JOINIDEMPTY;
+     argz_add(&msg->azHeaders, &msg->asHeaders, "Message-ID:");
+     argz_add(&msg->azHeaders, &msg->asHeaders, msg->cpMsgid);
+ 
+     /* merge name/value pairs into single string */
+     argz_add(&msg->azHeaders, &msg->asHeaders, ""); /* append empty string */
+     if ((aHeaders = (char **)malloc((argz_count(msg->azHeaders,
+         msg->asHeaders) + 1) * sizeof(char *))) == NULL)
+         exit(1); //FIXME
+     argz_extract(msg->azHeaders, msg->asHeaders, aHeaders);
+     i=0;
+     while(1) {
+         if ((cp = aHeaders[++i]) == NULL)
+             break;
+         *(cp-1) = ' ';
+         if ((cp = aHeaders[++i]) == NULL)
+             break;
+         // *(cp-1) = '\n';
+     }
+ 
+     /* fold headers */
+ //FIXME where to place this defines best
+ #define WRAPAT 120
+ #define WRAPUSING "\n    "
+     cp = NULL;
+     while ((cp = argz_next(msg->azHeaders, msg->asHeaders, cp)) != NULL) {
+         if (strlen(cp) >= WRAPAT) {
+             cpRem = cp;
+             cpWrap = NULL;
+             while (strlen(cpRem) >= WRAPAT) {
+                 for (i = WRAPAT; i >= 1 && (cpRem[i] != ' ') && (cpRem[i] != '\t'); i--);
+                 if (i == 0)
+                     i = WRAPAT; /* sorry, hard cut at non-whitespace */
+                 if (i < WRAPAT)
+                     i++; /* we don't care about the whitespace itself */
+                 cpCut = str_dup(cpRem, i);
+                 //FIXME 1.) continue searching downwards skipping all whitespaces and 2.) as we know the length replace str_dup/ strcat/ free with strncat only
+                 if (cpWrap == NULL) {
+                     if ((cpWrap = (char *)malloc(strlen(cpCut)+strlen(WRAPUSING)+1)) == NULL)
+                         exit(1); //FIXME
+                     *cpWrap = '\0';
+                 }
+                 else {
+                     if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpCut)+strlen(WRAPUSING)+1)) == NULL)
+                         exit(1); //FIXME
+                     strcat(cpWrap, WRAPUSING);
+                 }
+                 strcat(cpWrap, cpCut);
+                 free(cpCut);
+                 cpRem += i;
+             }
+             for (i = 0; i < strlen(cpRem) && ((cpRem[i] == ' ') || (cpRem[i] == '\t')); i++);
+             cpRem += i;
+             if (strlen(cpRem) > 0) {
+                 if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpRem)+strlen(WRAPUSING)+1)) == NULL)
+                     exit(1); //FIXME
+                 strcat(cpWrap, WRAPUSING);
+                 strcat(cpWrap, cpRem);
+             }
+             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);
+             argz_insert(&msg->azHeaders, &msg->asHeaders, cp, cpWrap);
+             free(cpWrap);
+         }
+     }
+ 
+     argz_stringify(msg->azHeaders, msg->asHeaders, '\n');
+     msg->cpHeaders = msg->azHeaders;
+ 
+     if (argz_create_sep(msg->cpBody, '\n', &msg->azBody, &msg->asBody) != 0)
+         return MSG_ERR_MEM;
+ 
+     /* escape dots at the beginning of each line */
+     cp = NULL;
+     while ((cp =argz_next(msg->azBody, msg->asBody, cp)) != NULL) {
+         if (*cp == '.') {
+             if ((cpNew = malloc(strlen(cp) + 1)) == NULL)
+                 return MSG_ERR_MEM;
+             *cpNew = '.';
+             cpNew++;
+             *cpNew = '\0';
+             strcat(cpNew, cp);
+             argz_delete(&msg->azBody, &msg->asBody, cp);
+             argz_insert(&msg->azBody, &msg->asBody, cp, cpNew);
+         }
+     }
+ 
+     argz_stringify(msg->azBody, msg->asBody, '\n');
+     msg->cpBody = msg->azBody;
+ 
+     if ((msg->cpMsg = malloc(strlen(msg->cpHeaders) + 1 + strlen(msg->cpBody) + 2 + 1)) == NULL)
+         return MSG_ERR_MEM;
+     *msg->cpMsg = '\0';                  /* + 1 in the end */
+     strcat(msg->cpMsg, msg->cpHeaders); 
+     strcat(msg->cpMsg, "\n");            /* + 1 */
+     strcat(msg->cpMsg, msg->cpBody);
+     strcat(msg->cpMsg, ".\n");           /* + 2 */
+ 
+     //fprintf(stderr, "DEBUG: Message = ***%s***\n", msg->cpMsg);
+ 
+     return MSG_OK;
+ }
+ 
+ char *msg_error(msg_t *msg, msg_rc_t rc)
+ {
+     char *str;
+                                               str = "MSG: no description";
+     if      (rc == MSG_OK                   ) str = "MSG: no error";
+     else if (rc == MSG_ERR_MEM              ) str = "MSG: memory";
+     else if (rc == MSG_ERR_SPLITSPLITBODY   ) str = "MSG: split into header and body failed";
+     else if (rc == MSG_ERR_SPLITLEN         ) str = "MSG: header is too short";
+     else if (rc == MSG_ERR_SPLITMISSINGFROM ) str = "MSG: header is missing 'From ' envelope";
+     else if (rc == MSG_ERR_SPLITIDNONE      ) str = "MSG: header is missing 'Message-ID'";
+     else if (rc == MSG_ERR_SPLITIDEMPTY     ) str = "MSG: header has empty 'Message-ID'";
+     else if (rc == MSG_ERR_SPLITIDMULTI     ) str = "MSG: header has multiple 'Message-ID's";
+     else if (rc == MSG_ERR_JOINGROUPNONE    ) str = "MSG: join with no 'Newsgroup'";
+     else if (rc == MSG_ERR_JOINGROUPEMPTY   ) str = "MSG: join with empty 'Newsgroup'";
+     else if (rc == MSG_ERR_JOINIDNONE       ) str = "MSG: join with no 'Message-ID'";
+     else if (rc == MSG_ERR_JOINIDEMPTY      ) str = "MSG: join with empty 'Message-ID'";
+     return str;
+ }
+ 


ossp-pkg/lmtp2nntp/msg.h -> 1.1

*** /dev/null    Thu Apr 18 19:45:32 2024
--- -    Thu Apr 18 19:46:13 2024
***************
*** 0 ****
--- 1,46 ----
+ 
+ #ifndef __MSG_H__
+ #define __MSG_H__
+ 
+ #include <sys/types.h>
+ 
+ typedef struct {
+     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   *cpMsgid;
+     char   *mail_from;
+     char   *azRcpt;
+     size_t  asRcpt;
+     char   *azHeaders;
+     size_t  asHeaders;
+     char   *azBody;
+     size_t  asBody;
+     char   *azNewsgroups;
+     size_t  asNewsgroups;
+ } msg_t;
+ 
+ typedef enum {
+     MSG_OK,
+     MSG_ERR_MEM,
+     MSG_ERR_SPLITSPLITBODY,
+     MSG_ERR_SPLITLEN,
+     MSG_ERR_SPLITMISSINGFROM,
+     MSG_ERR_SPLITIDNONE,
+     MSG_ERR_SPLITIDEMPTY,
+     MSG_ERR_SPLITIDMULTI,
+     MSG_ERR_JOINGROUPNONE,
+     MSG_ERR_JOINGROUPEMPTY,
+     MSG_ERR_JOINIDNONE,
+     MSG_ERR_JOINIDEMPTY,
+     MSG_ERR_ARG
+ } msg_rc_t;
+ 
+ msg_t    *msg_create(void);
+ msg_rc_t  msg_split(msg_t *);
+ msg_rc_t  msg_join(msg_t *);
+ void      msg_destroy(msg_t *);
+ char     *msg_error(msg_t *, msg_rc_t);
+ 
+ #endif /*  __MSG_H__ */
+ 


ossp-pkg/lmtp2nntp/nntp.c 1.3 -> 1.4

--- nntp.c       2001/08/07 09:05:55     1.3
+++ nntp.c       2001/08/13 06:41:42     1.4
@@ -182,6 +182,7 @@
     buf[n] = '\0';          /* string termination */
     if (n == (buflen-1)) 
         return NNTP_ERR_OVERFLOW;
+    fprintf(stderr, "DEBUG: nntp_readline  >>>%s\n", buf);
     return NNTP_OK;
 }
 
@@ -193,73 +194,94 @@
         return NNTP_ERR_ARG;
     strncpy(tmp, buf, NNTP_LINE_MAXLEN-3);
     strcat(tmp, "\r\n");
+    fprintf(stderr, "DEBUG: nntp_writeline >>>%s", tmp);
     if (nntp->io.write(nntp->wfd, tmp, strlen(tmp)) < 0)
         return NNTP_ERR_SYSTEM;
     return NNTP_OK;
 }
 
-nntp_rc_t nntp_post(nntp_t *nntp, char *msg)
+nntp_rc_t nntp_post(nntp_t *nntp, msg_t *msg)
 {
     nntp_rc_t rc = NNTP_OK;
     char line[NNTP_LINE_MAXLEN];
 
-    if ((rc = nntp_readline(nntp, line, sizeof(line))) != NNTP_OK)
-        return rc;
-    fprintf(stderr, "READ:<%s>\n", line);
-    if ((rc = nntp_writeline(nntp, "mode reader")) != NNTP_OK)
+    /*  check if this server already knows that artice
+     *  > STAT <message-id>
+     *  < 223 yes, article already known
+     *  < 430 no, i don't know the article, yet
+     */
+    *line = '\0';
+    strcat(line, "STAT ");
+    strcat(line, msg->cpMsgid);
+    if ((rc = nntp_writeline(nntp, line)) != NNTP_OK)
         return rc;
-    fprintf(stderr, "WRITE:<mode reader>\n");
     if ((rc = nntp_readline(nntp, line, sizeof(line))) != NNTP_OK)
         return rc;
-    fprintf(stderr, "READ:<%s>\n", line);
-    if ((rc = nntp_writeline(nntp, "quit")) != NNTP_OK)
+    if (strncmp(line, "223", 3) == 0)
+        return NNTP_OK;
+    if (strncmp(line, "430", 3) != 0)
+        return NNTP_ERR_POSTPERM; //FIXME
+
+    /*  post the article
+     *  > POST
+     *  < 340 gimme that thing
+     *  > From: ...
+     *  > Subject: ...
+     *  > Newsgroups: ...
+     *  > Message-ID: <...>
+     *  > [additional headers]
+     *  > 
+     *  > [body with dots escaped]
+     *  > .
+     *  < 240 ok, thank you
+     *  < 441 duplicate (ok for us)
+     */
+    *line = '\0';
+    strcat(line, "POST ");
+    strcat(line, msg->cpMsgid);
+    if ((rc = nntp_writeline(nntp, line)) != NNTP_OK)
         return rc;
-    fprintf(stderr, "WRITE:<quit>\n");
     if ((rc = nntp_readline(nntp, line, sizeof(line))) != NNTP_OK)
         return rc;
-    fprintf(stderr, "READ:<%s>\n", line);
+    if (strncmp(line, "xxx", 3) == 0)
+        return NNTP_OK;
+    if (strncmp(line, "340", 3) != 0)
+        return NNTP_ERR_POSTPERM; //FIXME
+
+fprintf(stderr, "DEBUG: before write ***%s***(%d)\n", msg->cpMsg, strlen(msg->cpMsg));
+    if ((rc = nntp->io.write(nntp->wfd, msg->cpMsg, strlen(msg->cpMsg))) < 0)
+        return NNTP_ERR_SYSTEM;
+fprintf(stderr, "DEBUG: after write, written = %i\n", rc);
+
+    {//DEBUG paragraph
+        int i;
+        char buf[NNTP_LINE_MAXLEN];
+
+        fprintf(stderr, "DEBUG: before writeline\n");
+        if ((rc = nntp_writeline(nntp, "\r\n.\r\nHELP\r\n")) != NNTP_OK);
+        fprintf(stderr, "DEBUG: writeline returned %d\n", rc);
+            
+        fprintf(stderr, "DEBUG: before io.read(%d, ..., %d)\n", nntp->rfd, NNTP_LINE_MAXLEN);
+        i = nntp->io.read(nntp->rfd, &buf, NNTP_LINE_MAXLEN);
+        fprintf(stderr, "DEBUG: io.read = ***%s***, rc = %d\n", buf, i);
+
+
+        for (i=0; i<10; i++) {
+    if ((rc = nntp_readline(nntp, line, sizeof(line))) != NNTP_OK)
+        ; //return rc;
+    fprintf(stderr, "DEBUG: answer to post = ***%s***, rc = %s\n", line, nntp_error(nntp, rc));
+        };
+    }
+    return NNTP_OK;
 
-#if 0 //FIXME
-    allservers = x; /* total number of servers specified */
-    deliveries = 0; /* counts successful deliveries */
-    for (i=0; i < allservers; i++) {
-        if (post() == NNTP_OK) {
+#if 0
             /* check if this server accepts at least one of the newsgroups
             > GROUP
             < 211 yes, group exists
             < 411 no, group doesn't exist
             */
 
-            /* check if this server already knows that artice
-            > STAT <message-id>
-            < 223 yes, article already known
-            < 430 no, i don't know the article, yet
-            */
-
-            /* post the article
-            > POST
-            < 340 gimme that thing
-            > From: ...
-            > Subject: ...
-            > Newsgroups: ...
-            > Message-ID: <...>
-            > [additional headers]
-            > 
-            > [body with dots escaped]
-            > .
-            < 240 ok, thank you
-            < 441 duplicate (ok for us)
-            */
-        }
-    }
-    if (((mode == DELIVERYMODE_MANY) || (mode == DELIVERYMODE_ONCE)) && (deliveries >= 1))
-        rc = NNTP_OK;
-    else if ((mode == DELIVERYMODE_ALL) && (deliveries == allservers))
-        rc = NNTP_OK
-    else
-        rc = NNTP_ERR_POST;
 #endif
-    return rc;
 }
 
 char *nntp_error(nntp_t *nntp, nntp_rc_t rc)


ossp-pkg/lmtp2nntp/nntp.h 1.2 -> 1.3

--- nntp.h       2001/08/07 09:05:56     1.2
+++ nntp.h       2001/08/13 06:41:42     1.3
@@ -34,6 +34,7 @@
 #include <sys/uio.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include "msg.h"
 
 struct nntp_st;
 typedef struct nntp_st nntp_t;
@@ -51,6 +52,8 @@
     NNTP_ERR_SYSTEM,
     NNTP_ERR_ARG,
     NNTP_ERR_OVERFLOW,
+    NNTP_ERR_POSTPERM,
+    NNTP_ERR_POSTDEFER,
     NNTP_ERR_INIT
 } nntp_rc_t;
 
@@ -60,7 +63,7 @@
 void        nntp_destroy  (nntp_t *);
 nntp_rc_t   nntp_readline (nntp_t *, char *, size_t);
 nntp_rc_t   nntp_writeline(nntp_t *, char *);
-nntp_rc_t   nntp_post     (nntp_t *, char *);
+nntp_rc_t   nntp_post     (nntp_t *, msg_t *msg);
 char       *nntp_error    (nntp_t *, nntp_rc_t);
 
 #endif /* __NNTP_H__ */

CVSTrac 2.0.1