Howdie all,

Attached there is a patch against mimedefang.c to enable multiline responses. This was mentioned in the mailing list some time back and was a todo on my private mimedefang list.

Can someone take a look at it, and implement it within mimedefang if you like it. Now my c is kinda rusty so there might be some errors somewhere, hey at least it compiles without errors :)

Guess I found Jan's extra second in 2005, better late than never.

Keep up the good work all,
--
Michiel

--- mimedefang.c.original       2009-06-09 00:20:53.000000000 +0200
+++ mimedefang.c        2009-06-09 21:57:06.000000000 +0200
@@ -216,6 +216,13 @@ static int set_reply(SMFICTX *ctx, char 
 /* Number of file descriptors to close when forking */
 #define CLOSEFDS 256
 
+/* Amount of new lines in a response we want to handle (milters max is 32 do 
not raise above that) 
+   As it HAS to be NULL terminated the list is realy one smaller 
+*/
+#define REPLY_MAX_BUFF_SIZE 32-1
+/* max string length of a reply to milter (max is 970 chars including \0 ) */
+#define REPLY_MAX_STR_LENGTH 970
+
 /* Mutex to protect mkdir() calls */
 static pthread_mutex_t MkdirMutex = PTHREAD_MUTEX_INITIALIZER;
 
@@ -336,6 +343,8 @@ set_reply(SMFICTX *ctx,
          char const *reply)
 {
     char *safe_reply;
+    int retcode;
+    
     if (!reply || !*reply) {
        if (*first == '4') {
            reply = "Please try again later";
@@ -351,10 +360,8 @@ set_reply(SMFICTX *ctx,
        if (*first == '4') dsn  = "4.3.0";
        else               dsn  = "5.7.1";
     }
-
     /* We need to double any "%" chars in reply */
     if (strchr(reply, '%')) {
-       int retcode;
        char const *s;
        char *t;
        /* Worst-case, we'll double our length */
@@ -371,13 +378,73 @@ set_reply(SMFICTX *ctx,
            *t++ = *s++;
        }
        *t = 0;
-       retcode = smfi_setreply(ctx, (char *) code, (char *) dsn, safe_reply);
-       free(safe_reply);
-       return retcode;
     }
-
+    else {
+      /* copy over the rely to safe_reply */
+      safe_reply = malloc(strlen(reply) + 1);
+      strncpy(safe_reply, reply, strlen(reply));
+         safe_reply[strlen(reply)]='\0';
+    }
+#ifdef MILTER_BUILDLIB_HAS_SETMLREPLY
+    // if we encounter a \n enter nasty milter phase
+       char *token = strtok(safe_reply, "\n");
+    if ( token != NULL ) {
+      int size = 0;
+      char *replyBuff[REPLY_MAX_BUFF_SIZE];
+      int i = -1;
+         while( token != NULL && ++i < REPLY_MAX_BUFF_SIZE ) {
+           // each reply cannot be large than MAX_REPLY_SIZE
+               size = (strlen(token) > REPLY_MAX_STR_LENGTH - 1 ? 
REPLY_MAX_STR_LENGTH - 1 : strlen(token) );
+        if ( strlen(token) > size ) {
+          syslog(LOG_ERR, "Trunkating reply element [%d] too long", i);
+        }
+
+        if ( !(replyBuff[i] = malloc(size + 1)) ) {
+          syslog(LOG_ERR, "Out of memory splitting reply [%s]",token);
+          return smfi_setreply(ctx, (char *) code, (char *) dsn,
+                        "Out of memory");
+        }
+        strncpy(replyBuff[i], token, size+1);
+               replyBuff[i][size+1]='\0';
+               token = strtok(NULL, "\n");
+         }
+         // notify someone if there are more enters in the safe_reply
+         // as we will not send them (specs u know).
+      if ( strtok(NULL, "\n") != NULL ) {
+        syslog(LOG_ERR, "Dropping extra reply elements");
+      }
+      // initialize all left over buffers
+      while( ++i < REPLY_MAX_BUFF_SIZE ) {
+        replyBuff[i] = NULL;
+      }
+      // send off the reply code (yes I know nasty, tell the milter ppl)
+      retcode = smfi_setmlreply(ctx, (char *) code, (char *) dsn,
+           replyBuff[0], replyBuff[1], replyBuff[2], replyBuff[3], 
replyBuff[4],
+           replyBuff[5], replyBuff[6], replyBuff[7], replyBuff[8], 
replyBuff[9],
+           
replyBuff[10],replyBuff[11],replyBuff[12],replyBuff[13],replyBuff[14],
+           
replyBuff[15],replyBuff[16],replyBuff[17],replyBuff[18],replyBuff[19],
+           
replyBuff[20],replyBuff[21],replyBuff[22],replyBuff[23],replyBuff[24],
+           
replyBuff[25],replyBuff[26],replyBuff[27],replyBuff[28],replyBuff[29],
+          replyBuff[30], NULL);
+     // prevent leaks and free
+      i = -1;
+      while( i++ > REPLY_MAX_BUFF_SIZE && replyBuff[i] != NULL ) {
+        free(replyBuff[i]);
+      }
+         free(safe_reply);
+      return retcode;
+    }
+#else 
+       // no smfi_setmlreply support replace all \n with space
+       char *token = NULL;
+    while( (token = strchr(safe_reply, '\n')) != NULL) {
+               *token = ' ';
+       }
+#endif
     /* smfi_setreply is not const-correct, hence the (char *) casts */
-    return smfi_setreply(ctx, (char *) code, (char *) dsn, (char *) reply);
+    retcode = smfi_setreply(ctx, (char *) code, (char *) dsn, safe_reply);
+    free(safe_reply);
+    return retcode;
 }
 
 /**********************************************************************
_______________________________________________
NOTE: If there is a disclaimer or other legal boilerplate in the above
message, it is NULL AND VOID.  You may ignore it.

Visit http://www.mimedefang.org and http://www.roaringpenguin.com
MIMEDefang mailing list MIMEDefang@lists.roaringpenguin.com
http://lists.roaringpenguin.com/mailman/listinfo/mimedefang

Reply via email to