]> Pileus Git - ~andy/fetchmail/commitdiff
Simpler and more effective address parsing.
authorEric S. Raymond <esr@thyrsus.com>
Sat, 11 Jan 1997 17:33:27 +0000 (17:33 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Sat, 11 Jan 1997 17:33:27 +0000 (17:33 -0000)
svn path=/trunk/; revision=741

rfc822.c

index 4cf4333d16a060c4e6aa715373765a6a3ab621d0..8497c54ba3464d9e69f2bb2edf54d7fefc6a5940 100644 (file)
--- a/rfc822.c
+++ b/rfc822.c
@@ -154,7 +154,7 @@ const char *hdr;    /* header to be parsed, NUL to continue previous hdr */
 {
     static char *tp, address[POPBUFSIZE+1];
     static const char *hp;
-    static int state;
+    static int state, oldstate;
     int parendepth;
 
     /*
@@ -163,11 +163,11 @@ const char *hdr;  /* header to be parsed, NUL to continue previous hdr */
      * a marker for RFC822 continuations elsewhere.
      */
 #define START_HDR      0       /* before header colon */
-#define BARE_ADDRESS   1       /* collecting address without delimiters */
-#define INSIDE_DQUOTE  2       /* inside double quotes */
-#define INSIDE_PARENS  3       /* inside parentheses */
-#define INSIDE_BRACKETS        4       /* inside bracketed address */
-#define STR_INSIDE_BR  5       /* copying string within bracketed address */
+#define SKIP_JUNK      1       /* skip whitespace, \n, and junk */
+#define BARE_ADDRESS   2       /* collecting address without delimiters */
+#define INSIDE_DQUOTE  3       /* inside double quotes */
+#define INSIDE_PARENS  4       /* inside parentheses */
+#define INSIDE_BRACKETS        5       /* inside bracketed address */
 #define ENDIT_ALL      6       /* after last address */
 
     if (hdr)
@@ -188,45 +188,58 @@ const char *hdr;  /* header to be parsed, NUL to continue previous hdr */
            }
            else if (*hp == ':')
            {
-               state = BARE_ADDRESS;
+               state = SKIP_JUNK;
                tp = address;
            }
            break;
 
-       case BARE_ADDRESS:   /* collecting address without delimiters */
-           if (*hp == '\n')    /* end of address list */
+       case SKIP_JUNK:         /* looking for address start */
+           if (*hp == '\n')            /* no more addresses */
            {
-               *tp++ = '\0';
                state = ENDIT_ALL;
-               return(tp = address);
-           }
-           else if (*hp == ',')  /* end of address */
-           {
-               if (tp > address)
-               {
-                   *tp++ = '\0';
-                   ++hp;
-                   return(tp = address);
-               }
+               return(NULL);
            }
-           else if (*hp == '"') /* quoted string */
+           else if (*hp == '"')        /* quoted string */
            {
+               oldstate = SKIP_JUNK;
                state = INSIDE_DQUOTE;
                *tp++ = *hp;
            }
-           else if (*hp == '(') /* address comment -- ignore */
+           else if (*hp == '(')        /* address comment -- ignore */
            {
                parendepth = 1;
                state = INSIDE_PARENS;    
            }
-           else if (*hp == '<') /* begin <address> */
+           else if (*hp == '<')        /* begin <address> */
            {
                state = INSIDE_BRACKETS;
                tp = address;
            }
-           else if (isspace(*hp)) /* ignore space */
+           else if (!isspace(*hp))     /* ignore space */
+           {
+               --hp;
                state = BARE_ADDRESS;
-           else   /* just take it */
+           }
+           break;
+
+       case BARE_ADDRESS:   /* collecting address without delimiters */
+           if (*hp == '\n')    /* end of bare address */
+           {
+               *tp++ = '\0';
+               state = ENDIT_ALL;
+               return(tp = address);
+           }
+           else if (*hp == ',' || isspace(*hp))  /* end of address */
+           {
+               if (tp > address)
+               {
+                   *tp++ = '\0';
+                   ++hp;
+                   state = SKIP_JUNK;
+                   return(tp = address);
+               }
+           }
+           else                /* just take it */
            {
                state = BARE_ADDRESS;
                *tp++ = *hp;
@@ -244,7 +257,7 @@ const char *hdr;    /* header to be parsed, NUL to continue previous hdr */
            else
            {
                *tp++ = *hp;
-               state = BARE_ADDRESS;
+               state = oldstate;
            }
            break;
 
@@ -256,14 +269,14 @@ const char *hdr;  /* header to be parsed, NUL to continue previous hdr */
            else if (*hp == ')')
                --parendepth;
            if (parendepth == 0)
-               state = BARE_ADDRESS;
+               state = SKIP_JUNK;
            break;
 
        case INSIDE_BRACKETS:   /* possible <>-enclosed address */
            if (*hp == '>') /* end of address */
            {
                *tp++ = '\0';
-               state = BARE_ADDRESS;
+               state = SKIP_JUNK;
                ++hp;
                return(tp = address);
            }
@@ -272,27 +285,13 @@ const char *hdr;  /* header to be parsed, NUL to continue previous hdr */
            else if (*hp == '"') /* quoted address */
            {
                *tp++ = *hp;
-               state = STR_INSIDE_BR;
+               oldstate = INSIDE_BRACKETS;
+               state = INSIDE_DQUOTE;
            }
            else  /* just copy address */
                *tp++ = *hp;
            break;
 
-       case STR_INSIDE_BR:   /* we're in a quoted address, copy verbatim */
-           if (*hp == '\n')  /* mismatched quotes */
-           {
-               state = ENDIT_ALL;
-               return(NULL);
-           }
-           if (*hp != '"')  /* just copy it if it isn't a quote */
-               *tp++ = *hp;
-           else if (*hp == '"')  /* end of quoted string */
-           {
-               *tp++ = *hp;
-               state = INSIDE_BRACKETS;
-           }
-           break;
-
        case ENDIT_ALL: /* after last address */
            return(NULL);
            break;