auto-detect changed prefix and/or changed build flags
[gitweb.git] / mailinfo.c
index a2b15e2624702c90bd05d5a457df4c03694020c3..d9b74f30de32194a34e234314a8d28063344f9a1 100644 (file)
@@ -72,11 +72,14 @@ static int bogus_from(char *line)
        return 1;
 }
 
-static int handle_from(char *line)
+static int handle_from(char *in_line)
 {
-       char *at = strchr(line, '@');
+       char line[1000];
+       char *at;
        char *dst;
 
+       strcpy(line, in_line);
+       at = strchr(line, '@');
        if (!at)
                return bogus_from(line);
 
@@ -237,13 +240,29 @@ 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: */
+/* First lines of body can have From:, Date:, and Subject: or empty */
 static void handle_inbody_header(int *seen, char *line)
 {
        if (*seen & SEEN_PREFIX)
                return;
+       if (isspace(*line)) {
+               char *cp;
+               for (cp = line + 1; *cp; cp++) {
+                       if (!isspace(*cp))
+                               break;
+               }
+               if (!*cp)
+                       return;
+       }
+       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;
@@ -306,6 +325,7 @@ static char *cleanup_subject(char *subject)
                        }       
                        break;
                }
+               eatspace(subject);
                return subject;
        }
 }                      
@@ -381,19 +401,38 @@ static void check_header_line(char *line)
        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 ((len == 0) || !is_rfc2822_header(line)) {
                        /* Re-add the newline */
                        line[ofs + len] = '\n';
                        line[ofs + len + 1] = '\0';
@@ -733,10 +772,8 @@ static void handle_body(void)
 {
        int seen = 0;
 
-       if (line[0] || fgets(line, sizeof(line), stdin) != NULL) {
-               handle_commit_msg(&seen);
-               handle_patch();
-       }
+       handle_commit_msg(&seen);
+       handle_patch();
        fclose(patchfile);
        if (!patch_lines) {
                fprintf(stderr, "No patch found\n");