Merge branch 'eb/mailinfo' into next
authorJunio C Hamano <junkio@cox.net>
Fri, 26 May 2006 07:51:05 +0000 (00:51 -0700)
committerJunio C Hamano <junkio@cox.net>
Fri, 26 May 2006 07:51:05 +0000 (00:51 -0700)
* eb/mailinfo:
mailinfo: More carefully parse header lines in read_one_header_line()

1  2 
mailinfo.c
diff --combined mailinfo.c
index 78d2a15dd0ea79b5950772c3f35837f7b99a9ac8,88f9fbb198a7343715fb01c64c72044a7abaedab..5b6c2157ede415e019099098f2d0dc522b1e7a27
@@@ -240,18 -240,11 +240,18 @@@ static int eatspace(char *line
  #define SEEN_FROM 01
  #define SEEN_DATE 02
  #define SEEN_SUBJECT 04
 -#define SEEN_PREFIX  0x08
 +#define SEEN_BOGUS_UNIX_FROM 010
 +#define SEEN_PREFIX  020
  
  /* First lines of body can have From:, Date:, and Subject: */
  static void handle_inbody_header(int *seen, char *line)
  {
 +      if (!memcmp(">From", line, 5) && isspace(line[5])) {
 +              if (!(*seen & SEEN_BOGUS_UNIX_FROM)) {
 +                      *seen |= SEEN_BOGUS_UNIX_FROM;
 +                      return;
 +              }
 +      }
        if (!memcmp("From:", line, 5) && isspace(line[5])) {
                if (!(*seen & SEEN_FROM) && handle_from(line+6)) {
                        *seen |= SEEN_FROM;
@@@ -389,19 -382,40 +389,40 @@@ static void check_header_line(char *lin
        check_header(line, header);
  }
  
+ static int is_rfc2822_header(char *line)
+ {
+       /*
+        * The section that defines the loosest possible
+        * field name is "3.6.8 Optional fields".
+        *
+        * optional-field = field-name ":" unstructured CRLF
+        * field-name = 1*ftext
+        * ftext = %d33-57 / %59-126
+        */
+       int ch;
+       char *cp = line;
+       while ((ch = *cp++)) {
+               if (ch == ':')
+                       return cp != line;
+               if ((33 <= ch && ch <= 57) ||
+                   (59 <= ch && ch <= 126))
+                       continue;
+               break;
+       }
+       return 0;
+ }
  static int read_one_header_line(char *line, int sz, FILE *in)
  {
        int ofs = 0;
        while (ofs < sz) {
-               const char *colon;
                int peek, len;
                if (fgets(line + ofs, sz - ofs, in) == NULL)
                        break;
                len = eatspace(line + ofs);
                if (len == 0)
                        break;
-               colon = strchr(line, ':');
-               if (!colon || !isspace(colon[1])) {
+               if (!is_rfc2822_header(line)) {
                        /* Re-add the newline */
                        line[ofs + len] = '\n';
                        line[ofs + len + 1] = '\0';