]> Pileus Git - ~andy/fetchmail/blobdiff - rfc822.c
Much simpler rewrite logic.
[~andy/fetchmail] / rfc822.c
index 8820b1b502aa5107b8962b2600a4bdea73e93b61..3e7a96b11b7007e4a4cc96043253e41c6b4e9069 100644 (file)
--- a/rfc822.c
+++ b/rfc822.c
@@ -21,8 +21,8 @@ char *buf;            /* header to be hacked */
 const char *host;      /* server hostname */
 {
     const char *from;
-    int parendepth, state = 0, tokencount = 0;
-    char mycopy[POPBUFSIZE+1];
+    int parendepth, oldstate, state = 0, has_host_part = FALSE;
+    char mycopy[MSGBUFSIZE+1];
 
     if (strncmp("From: ", buf, 6)
        && strncmp("To: ", buf, 4)
@@ -35,121 +35,52 @@ const char *host;  /* server hostname */
     strcpy(mycopy, buf);
     for (from = mycopy; *from; from++)
     {
-#ifdef FOO
-       printf("state %d: %s", state, mycopy);
-       printf("%*s^\n", from - mycopy + 10, " ");
-#endif /* TESTMAIN */
-       switch (state)
-       {
-       case 0:   /* before header colon */
-           if (*from == ':')
-               state = 1;
-           break;
-
-       case 1:   /* we've seen the colon, we're looking for addresses */
-           if (*from == '"')
-               state = 3;
-           else if (*from == '(')
-           {
-               parendepth = 1;
-               state = 4;    
-           }
-           else if (*from == '<' || isalnum(*from))
-               state = 5;
-           else if (isspace(*from))
-               state = 2;
-           break;
-
-       case 2:     /* found a token boundary -- reset without copying */
-           if (*from != ' ' && *from != '\t')
+#define INSERT_HOSTNAME        \
+               strcpy(buf, "@"); \
+               strcat(buf, host); \
+               buf += strlen(buf); \
+               has_host_part = TRUE;
+
+       if (*from == '(')
+           ++parendepth;
+       else if (*from == ')')
+           --parendepth;
+
+       if (!parendepth)
+           switch (state)
            {
-               tokencount++;
-               state = 1;
-               --from;
-               continue;
-           }
-
-       case 3:   /* we're in a quoted human name, copy and ignore */
-           if (*from == '"')
-               state = 1;
-           break;
-
-       case 4:   /* we're in a parenthesized human name, copy and ignore */
-           if (*from == '(')
-               ++parendepth;
-           else if (*from == ')')
-               --parendepth;
-           if (parendepth == 0)
-               state = 1;
-           break;
-
-       case 5:   /* the real work gets done here */
-           /*
-            * We're in something that might be an address part,
-            * either a bare unquoted/unparenthesized text or text
-            * enclosed in <> as per RFC822.
-            */
-           /* if the address part contains an @, don't mess with it */
-           if (*from == '@')
-               state = 6;
-
-           /* If the address token is not properly terminated, ignore it. */
-           else if (*from == ' ' || *from == '\t')
-           {
-               const char *cp;
-
-               /*
-                * The only lookahead case.  If we're looking at space or tab,
-                * we might be looking at a local name immediately followed
-                * by a human name.
-                */
-               for (cp = from; isspace(*cp); cp++)
-                   continue;
-               if (*cp == '(')
-               {
-                   strcpy(buf, "@");
-                   strcat(buf, host);
-                   buf += strlen(buf);
+           case 0:   /* before header colon */
+               if (*from == ':')
                    state = 1;
+               break;
+
+           case 1:   /* we've seen the colon, we're looking for addresses */
+               if (*from == '<')
+                   state = 2;
+               else if (*from == '@')
+                   has_host_part = TRUE;
+               else if ((*from == ',' || *from == '\n') && !has_host_part)
+               {
+                   INSERT_HOSTNAME
                }
-           }
-
-           /*
-            * On proper termination with no @, insert hostname.
-            * Case '>' catches <>-enclosed mail IDs.  Case ',' catches
-            * comma-separated bare IDs.
-            */
-           else if (strchr(">,", *from))
-           {
-               strcpy(buf, "@");
-               strcat(buf, host);
-               buf += strlen(buf);
-               tokencount = 0;
-               state = 1;
-           }
+               break;
 
-           /* a single local name alone on the line */
-           else if (*from == '\n' && tokencount == 1)
-           {
-               strcpy(buf, "@");
-               strcat(buf, host);
-               buf += strlen(buf);
-               state = 2;
+           case 2:   /* we're in a <>-enclosed address */
+               if (*from == '@')
+                   has_host_part = TRUE;
+               else if (*from == '>' && !has_host_part)
+               {
+                   INSERT_HOSTNAME
+               }
+               break;
            }
 
-           /* everything else, including alphanumerics, just passes through */
-           break;
-
-       case 6:   /* we're in a remote mail ID, no need to append hostname */
-           if (*from == '>' || *from == ',' || isspace(*from))
-               state = 1;
-           break;
-       }
-
        /* all characters from the old buffer get copied to the new one */
        *buf++ = *from;
+#undef INSERT_HOSTNAME
     }
-    *buf++ = '\0';
+
+    *buf = '\0';
 }
 
 char *nxtaddr(hdr)