OSSP CVS Repository

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

Check-in Number: 658
Date: 2001-Aug-13 17:16:32 (local)
2001-Aug-13 15:16:32 (UTC)
User:thl
Branch:
Comment: first successful posting
Tickets:
Inspections:
Files:
ossp-pkg/lmtp2nntp/lmtp2nntp.c      1.14 -> 1.15     17 inserted, 7 deleted
ossp-pkg/lmtp2nntp/msg.c      1.1 -> 1.2     68 inserted, 6 deleted
ossp-pkg/lmtp2nntp/nntp.c      1.4 -> 1.5     72 inserted, 26 deleted
ossp-pkg/lmtp2nntp/nntp.h      1.3 -> 1.4     1 inserted, 1 deleted
ossp-pkg/lmtp2nntp/test/run.sh      1.1 -> 1.2     10 inserted, 3 deleted

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

--- lmtp2nntp.c  2001/08/13 06:41:41     1.14
+++ lmtp2nntp.c  2001/08/13 15:16:32     1.15
@@ -640,6 +640,7 @@
     char errorstring[STDSTRLEN];
     char *rcpt;
     int i;
+    int bSuccess;
 
     if (argz_count(ctx->msg->azRcpt, ctx->msg->asRcpt) == 0) {
         res.statuscode = "503";
@@ -738,18 +739,27 @@
         }
     }
 
-    for (i=0; i < ctx->nsc; i++) {
+    bSuccess = FALSE;
+    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);
+        if (nntp_post(ctx->ns[i].nntp, ctx->msg) == NNTP_OK)
+            bSuccess = TRUE;
     }
 
     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);
-        res.statusmsg  = errorstring;
-        lmtp_response(lmtp, &res);
+        if (bSuccess == TRUE) {
+            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);
+        } else {
+            res.statuscode = "500";
+            res.dsncode    = "5.0.0";
+            res.statusmsg  = "Error posting message."; //FIXME call nntp_error()?
+            lmtp_response(lmtp, &res);
+        }
     }
 
     msg_destroy(ctx->msg);


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

--- msg.c        2001/08/13 06:41:41     1.1
+++ msg.c        2001/08/13 15:16:32     1.2
@@ -127,6 +127,11 @@
     msg->asNewsgroups = 0;
     cp = msg->azHeaders;
     while (cp != NULL) {
+        if (strcasecmp("From", cp) == 0) {
+            argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  name  */
+            argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  value */
+            continue;
+        }
         if (strcasecmp("To:", cp) == 0) {
             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  name  */
             argz_delete(&msg->azHeaders, &msg->asHeaders, cp);             /* del  value */
@@ -183,6 +188,8 @@
     char        *cpCut;
     char        *cpWrap;
     char        *cpNew;
+    char         c;
+    int          n;
 
     /* verify asNewsgroups */
     if (msg->azNewsgroups == NULL)
@@ -287,13 +294,68 @@
     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)
+    /********************************************************************
+     * header + CRLF + body + '.' + CRLF + '\0', replacing NL with CRLF *
+     ********************************************************************/
+
+    n = 0;
+    /* count size of headers, reserve space for NL to CRLF conversion */
+    for (i = 0; ((c = msg->cpHeaders[i]) != '\0'); i++) {
+        if (c == '\n')
+            n++;
+        n++;
+    }
+    /* if headers don't end with NL, reserve space for CRLF */
+    if (i >= 0 && msg->cpHeaders[i - 1] != '\n')
+        n+=2;
+    /* reserve space for CRLF between headers and body */
+    n+=2;
+    /* count size of body, reserve space for NL to CRLF conversion */
+    for (i = 0; ((c = msg->cpBody[i]) != '\0'); i++) {
+        if (c == '\n')
+            n++;
+        n++;
+    }
+    /* if body doesn't end with NL, reserve space for CRLF */
+    if (i >= 0 && msg->cpBody[i - 1] != '\n')
+        n+=2;
+    /* reserve space for terminating '.'-CRLF-NUL at the end of the message */
+    n+=4;
+
+    if ((msg->cpMsg = (char *)malloc(n)) == 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 */
+
+    n = 0;
+    /* copy headers, do NL to CRLF conversion */
+    for (i = 0; ((c = msg->cpHeaders[i]) != '\0'); i++) {
+        if (c == '\n')
+            msg->cpMsg[n++] = '\r';
+        msg->cpMsg[n++] = c;
+    }
+    /* if headers don't end with NL, append CRLF */
+    if (i >= 0 && msg->cpHeaders[i - 1] != '\n') {
+        msg->cpMsg[n++] = '\r';
+        msg->cpMsg[n++] = '\n';
+    }
+    /* add CRLF between headers and body */
+    msg->cpMsg[n++] = '\r';
+    msg->cpMsg[n++] = '\n';
+    /* copy body, do NL to CRLF conversion */
+    for (i = 0; ((c = msg->cpBody[i]) != '\0'); i++) {
+        if (c == '\n')
+            msg->cpMsg[n++] = '\r';
+        msg->cpMsg[n++] = c;
+    }
+    /* if body doesn't end with NL, append CRLF */
+    if (i >= 0 && msg->cpBody[i - 1] != '\n') {
+        msg->cpMsg[n++] = '\r';
+        msg->cpMsg[n++] = '\n';
+    }
+    /* add terminating '.'-CRLF-NUL at the end of the message */
+    msg->cpMsg[n++] =  '.';
+    msg->cpMsg[n++] = '\r';
+    msg->cpMsg[n++] = '\n';
+    msg->cpMsg[n]   = '\0';
 
     //fprintf(stderr, "DEBUG: Message = ***%s***\n", msg->cpMsg);
 


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

--- nntp.c       2001/08/13 06:41:42     1.4
+++ nntp.c       2001/08/13 15:16:32     1.5
@@ -182,7 +182,7 @@
     buf[n] = '\0';          /* string termination */
     if (n == (buflen-1)) 
         return NNTP_ERR_OVERFLOW;
-    fprintf(stderr, "DEBUG: nntp_readline  >>>%s\n", buf);
+    fprintf(stderr, "DEBUG: nntp_readline  <<<%s\n", buf);
     return NNTP_OK;
 }
 
@@ -205,11 +205,57 @@
     nntp_rc_t rc = NNTP_OK;
     char line[NNTP_LINE_MAXLEN];
 
+    /*  RFC 2980
+     *   
+     *  2.3 MODE READER
+     *  MODE READER is used by the client to indicate to the server that it is
+     *  a news reading client.  Some implementations make use of this
+     *  information to reconfigure themselves for better performance in
+     *  responding to news reader commands.  This command can be contrasted
+     *  with the SLAVE command in RFC 977, which was not widely implemented.
+     *  MODE READER was first available in INN.
+     *  
+     *  2.3.1 Responses
+     *  200 Hello, you can post
+     *  201 Hello, you can't post
+     *  
+     *  Research:
+     *  
+     *  < 200 dev16 InterNetNews server INN 2.3.2 ready
+     *  > POST
+     *  < 500 "post" not implemented; try "help".
+     *  > MODE READER
+     *  < 200 dev16 InterNetNews NNRP server INN 2.3.2 ready (posting ok).
+     *  > POST
+     *  < 340 Ok, recommended ID <...>
+     *  
+     *  In other words, INN *requires* the use of "MODE READER".
+     */
+    *line = '\0';
+    strcat(line, "MODE READER");
+    if ((rc = nntp_writeline(nntp, line)) != NNTP_OK)
+        return rc;
+    if ((rc = nntp_readline(nntp, line, sizeof(line))) != NNTP_OK)
+        return rc;
+
+    /*  A 200 response means posting ok, 201 means posting not allowed. We
+     *  don't care about 5xx errors, they simply mean the server doesn't know
+     *  about the RFC2980 "MODE READER" command. But any other response is not
+     *  expected and we treat this as an error.
+     */
+    if (strncmp(line, "201", 3) == 0)
+        return NNTP_ERR_POST;
+    if (   strncmp(line, "200", 3) != 0
+        && strncmp(line, "5"  , 1) != 0
+          )
+        return NNTP_ERR_POST;
+
     /*  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
      */
+#if 0
     *line = '\0';
     strcat(line, "STAT ");
     strcat(line, msg->cpMsgid);
@@ -220,7 +266,8 @@
     if (strncmp(line, "223", 3) == 0)
         return NNTP_OK;
     if (strncmp(line, "430", 3) != 0)
-        return NNTP_ERR_POSTPERM; //FIXME
+        return NNTP_ERR_POST;
+#endif
 
     /*  post the article
      *  > POST
@@ -235,10 +282,22 @@
      *  > .
      *  < 240 ok, thank you
      *  < 441 duplicate (ok for us)
+     *  
+     *  Research:
+     *  
+     *  < 200 dev16 InterNetNews server INN 2.3.2 ready
+     *  > POST
+     *  [...]
+     *  240 Article posted <...>
+     *  441 435 Duplicate
+     *  441 437 Too old
+     *  441 Duplicate "Newsgroups" header
+     *  441 Required "Subject" header is missing
+     *  
+     *  In other words, INN uses 441 for other status messages as well.
      */
     *line = '\0';
-    strcat(line, "POST ");
-    strcat(line, msg->cpMsgid);
+    strcat(line, "POST");
     if ((rc = nntp_writeline(nntp, line)) != NNTP_OK)
         return rc;
     if ((rc = nntp_readline(nntp, line, sizeof(line))) != NNTP_OK)
@@ -246,33 +305,19 @@
     if (strncmp(line, "xxx", 3) == 0)
         return NNTP_OK;
     if (strncmp(line, "340", 3) != 0)
-        return NNTP_ERR_POSTPERM; //FIXME
+        return NNTP_ERR_POST;
 
-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)
+    if ((rc = nntp->io.write(nntp->wfd, msg->cpMsg, strlen(msg->cpMsg))) < 0) //FIXME while() wrapper around write required
         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;
+        return rc;
     fprintf(stderr, "DEBUG: answer to post = ***%s***, rc = %s\n", line, nntp_error(nntp, rc));
-        };
-    }
-    return NNTP_OK;
+    if (   (strncmp(line, "240", 3) == 0)
+        || (strncmp(line, "441", 3) == 0)
+          )
+        return NNTP_OK;
+    return NNTP_ERR_POST;
 
 #if 0
             /* check if this server accepts at least one of the newsgroups
@@ -294,6 +339,7 @@
     else if (rc == NNTP_ERR_SYSTEM  ) str = "NNTP: see errno";
     else if (rc == NNTP_ERR_ARG     ) str = "NNTP: invalid argument";
     else if (rc == NNTP_ERR_OVERFLOW) str = "NNTP: buffer overflow";
+    else if (rc == NNTP_ERR_POST    ) str = "NNTP: cannot post message";
     return str;
 }
 


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

--- nntp.h       2001/08/13 06:41:42     1.3
+++ nntp.h       2001/08/13 15:16:32     1.4
@@ -52,7 +52,7 @@
     NNTP_ERR_SYSTEM,
     NNTP_ERR_ARG,
     NNTP_ERR_OVERFLOW,
-    NNTP_ERR_POSTPERM,
+    NNTP_ERR_POST,
     NNTP_ERR_POSTDEFER,
     NNTP_ERR_INIT
 } nntp_rc_t;


ossp-pkg/lmtp2nntp/test/run.sh 1.1 -> 1.2

--- run.sh       2001/08/08 10:40:43     1.1
+++ run.sh       2001/08/13 15:16:32     1.2
@@ -6,12 +6,19 @@
 fi
 echo ------------------------------------------------------------
 #./lmtp2nntp -h news-muc1.de.cw.net -h news-ffm2.de.cw.net -h news-dus2.de.cw.net -h news-ecrc.de
-awk <testmessage1 "\
- /Message-ID/ { print \"Message-ID: `date +%Y%m%d%H%M%S`@dev12.dev.de.cw.net\" } \
+#clear ; ./lmtp2nntp <testmessage2 -g envelope -h dev16
+#exit
+
+clear ; awk <testmessage2 "\
+  /Message-ID/ { print \"Message-ID: <`date +%Y%m%d%H%M%S`@dev12.dev.de.cw.net>\" } \
  !/Message-ID/ { print \$0 } \
  " \
- | ./lmtp2nntp -g envelope -h news-ffm2.de.cw.net -h news-dus2.de.cw.net -h news.ecrc.de
+ | tee /tmp/reusetestmessage \
+ | ./lmtp2nntp -g envelope -h dev16
+cat /tmp/reusetestmessage | ./lmtp2nntp -g envelope -h dev16
 echo -----------------------------------------------------------
+exit
+
 if [ -r /tmp/t ]
 then
     cat /tmp/t

CVSTrac 2.0.1