git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1151 77e5149b-7576-45b1-b177-96237e5ba77b
Nigel Horne authored on 2004/12/01 22:16:08... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Wed Dec 1 13:14:33 GMT 2004 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav/mbox.c: Decode text/plain parts marked as being encoded, |
|
4 |
+ reported by Trog |
|
5 |
+ |
|
1 | 6 |
Wed Dec 1 12:14:46 GMT 2004 (njh) |
2 | 7 |
---------------------------------- |
3 | 8 |
* libeclamav/message.c: Part of rule 3 of paragraph 5.1 of RFC1521 was |
... | ... |
@@ -17,6 +17,9 @@ |
17 | 17 |
* |
18 | 18 |
* Change History: |
19 | 19 |
* $Log: mbox.c,v $ |
20 |
+ * Revision 1.196 2004/12/01 13:12:35 nigelhorne |
|
21 |
+ * Decode text/plain parts marked as being encoded |
|
22 |
+ * |
|
20 | 23 |
* Revision 1.195 2004/11/29 13:21:20 nigelhorne |
21 | 24 |
* Remove the old continuation marker method |
22 | 25 |
* |
... | ... |
@@ -573,7 +576,7 @@ |
573 | 573 |
* Compilable under SCO; removed duplicate code with message.c |
574 | 574 |
* |
575 | 575 |
*/ |
576 |
-static char const rcsid[] = "$Id: mbox.c,v 1.195 2004/11/29 13:21:20 nigelhorne Exp $"; |
|
576 |
+static char const rcsid[] = "$Id: mbox.c,v 1.196 2004/12/01 13:12:35 nigelhorne Exp $"; |
|
577 | 577 |
|
578 | 578 |
#if HAVE_CONFIG_H |
579 | 579 |
#include "clamav-config.h" |
... | ... |
@@ -967,8 +970,6 @@ cli_mbox(const char *dir, int desc, unsigned int options) |
967 | 967 |
|
968 | 968 |
cli_dbgmsg("Deal with email number %d\n", messagenumber); |
969 | 969 |
} else { |
970 |
- int inHeader = 1; |
|
971 |
- |
|
972 | 970 |
/* |
973 | 971 |
* It's a single message, parse the headers then the body |
974 | 972 |
* Ignore blank lines at the start of the message |
... | ... |
@@ -1019,8 +1020,6 @@ cli_mbox(const char *dir, int desc, unsigned int options) |
1019 | 1019 |
*/ |
1020 | 1020 |
if(messageAddStr(m, ptr) < 0) |
1021 | 1021 |
break; |
1022 |
- if(*ptr == '\0') |
|
1023 |
- inHeader = 0; |
|
1024 | 1022 |
} while(fgets(buffer, sizeof(buffer) - 1, fd) != NULL); |
1025 | 1023 |
} |
1026 | 1024 |
|
... | ... |
@@ -1378,6 +1377,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t |
1378 | 1378 |
checkURLs(mainMessage, dir); |
1379 | 1379 |
break; |
1380 | 1380 |
case MULTIPART: |
1381 |
+ cli_dbgmsg("Content-type 'multipart' handler\n"); |
|
1381 | 1382 |
boundary = messageFindArgument(mainMessage, "boundary"); |
1382 | 1383 |
|
1383 | 1384 |
if(boundary == NULL) { |
... | ... |
@@ -1568,7 +1568,10 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t |
1568 | 1568 |
inMimeHead = continuationMarker(line); |
1569 | 1569 |
messageAddArgument(aMessage, line); |
1570 | 1570 |
} else if(inhead) { /* handling normal headers */ |
1571 |
- char *ptr; |
|
1571 |
+ int quotes; |
|
1572 |
+ char *fullline, *ptr; |
|
1573 |
+ const char *qptr; |
|
1574 |
+ const text *next; |
|
1572 | 1575 |
|
1573 | 1576 |
if(line == NULL) { |
1574 | 1577 |
/* empty line */ |
... | ... |
@@ -1603,73 +1606,55 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t |
1603 | 1603 |
continue; |
1604 | 1604 |
} |
1605 | 1605 |
|
1606 |
- /* |
|
1607 |
- * Some clients are broken and |
|
1608 |
- * put white space after the ; |
|
1609 |
- */ |
|
1610 |
- inMimeHead = continuationMarker(line); |
|
1611 |
- if(!inMimeHead) { |
|
1612 |
- const text *next = t_line->t_next; |
|
1613 |
- char *fullline; |
|
1614 |
- int quotes = 0; |
|
1615 |
- const char *qptr; |
|
1616 |
- |
|
1617 |
- assert(strlen(line) <= LINE_LENGTH); |
|
1618 |
- |
|
1619 |
- fullline = rfc822comments(line); |
|
1620 |
- if(fullline == NULL) |
|
1621 |
- fullline = strdup(line); |
|
1622 |
- |
|
1623 |
- for(qptr = fullline; *qptr; qptr++) |
|
1624 |
- if(*qptr == '\"') |
|
1625 |
- quotes++; |
|
1626 |
- |
|
1627 |
- /* |
|
1628 |
- * Fold next lines to the end of this |
|
1629 |
- * if they start with a white space |
|
1630 |
- * or if this line has an odd number of quotes: |
|
1631 |
- * Content-Type: application/octet-stream; name="foo |
|
1632 |
- * " |
|
1633 |
- */ |
|
1634 |
- while(next && next->t_line) { |
|
1635 |
- const char *data = lineGetData(next->t_line); |
|
1606 |
+ inMimeHead = FALSE; |
|
1636 | 1607 |
|
1637 |
- if((!isspace(data[0])) && |
|
1638 |
- ((quotes & 1) == 0)) |
|
1639 |
- break; |
|
1608 |
+ assert(strlen(line) <= LINE_LENGTH); |
|
1640 | 1609 |
|
1641 |
- ptr = cli_realloc(fullline, |
|
1642 |
- strlen(fullline) + strlen(data) + 1); |
|
1610 |
+ fullline = rfc822comments(line); |
|
1611 |
+ if(fullline == NULL) |
|
1612 |
+ fullline = strdup(line); |
|
1643 | 1613 |
|
1644 |
- if(ptr == NULL) |
|
1645 |
- break; |
|
1614 |
+ quotes = 0; |
|
1615 |
+ for(qptr = fullline; *qptr; qptr++) |
|
1616 |
+ if(*qptr == '\"') |
|
1617 |
+ quotes++; |
|
1646 | 1618 |
|
1647 |
- fullline = ptr; |
|
1648 |
- strcat(fullline, data); |
|
1619 |
+ /* |
|
1620 |
+ * Fold next lines to the end of this |
|
1621 |
+ * if they start with a white space |
|
1622 |
+ * or if this line has an odd number of quotes: |
|
1623 |
+ * Content-Type: application/octet-stream; name="foo |
|
1624 |
+ * " |
|
1625 |
+ */ |
|
1626 |
+ next = t_line->t_next; |
|
1627 |
+ while(next && next->t_line) { |
|
1628 |
+ const char *data = lineGetData(next->t_line); |
|
1649 | 1629 |
|
1650 |
- for(qptr = data; *qptr; qptr++) |
|
1651 |
- if(*qptr == '\"') |
|
1652 |
- quotes++; |
|
1630 |
+ if((!isspace(data[0])) && |
|
1631 |
+ ((quotes & 1) == 0)) |
|
1632 |
+ break; |
|
1653 | 1633 |
|
1654 |
- t_line = next; |
|
1655 |
- next = next->t_next; |
|
1656 |
- } |
|
1657 |
- cli_dbgmsg("Multipart %d: About to parse folded header '%s'\n", |
|
1658 |
- multiparts, fullline); |
|
1634 |
+ ptr = cli_realloc(fullline, |
|
1635 |
+ strlen(fullline) + strlen(data) + 1); |
|
1659 | 1636 |
|
1660 |
- parseEmailHeader(aMessage, fullline, rfc821Table); |
|
1661 |
- free(fullline); |
|
1662 |
- } else { |
|
1663 |
- cli_dbgmsg("Multipart %d: About to parse header '%s'\n", |
|
1664 |
- multiparts, line); |
|
1637 |
+ if(ptr == NULL) |
|
1638 |
+ break; |
|
1665 | 1639 |
|
1666 |
- ptr = rfc822comments(line); |
|
1640 |
+ fullline = ptr; |
|
1641 |
+ strcat(fullline, data); |
|
1667 | 1642 |
|
1668 |
- parseEmailHeader(aMessage, (ptr) ? ptr : line, rfc821Table); |
|
1643 |
+ for(qptr = data; *qptr; qptr++) |
|
1644 |
+ if(*qptr == '\"') |
|
1645 |
+ quotes++; |
|
1669 | 1646 |
|
1670 |
- if(ptr) |
|
1671 |
- free(ptr); |
|
1647 |
+ t_line = next; |
|
1648 |
+ next = next->t_next; |
|
1672 | 1649 |
} |
1650 |
+ cli_dbgmsg("Multipart %d: About to parse folded header '%s'\n", |
|
1651 |
+ multiparts, fullline); |
|
1652 |
+ |
|
1653 |
+ parseEmailHeader(aMessage, fullline, rfc821Table); |
|
1654 |
+ free(fullline); |
|
1673 | 1655 |
} else if(endOfMessage(line, boundary)) { |
1674 | 1656 |
/* |
1675 | 1657 |
* Some viruses put information |
... | ... |
@@ -1930,7 +1915,8 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t |
1930 | 1930 |
cli_dbgmsg("Found uuencoded message in multipart/mixed text portion\n"); |
1931 | 1931 |
messageSetEncoding(aMessage, "x-uuencode"); |
1932 | 1932 |
addAttachment = TRUE; |
1933 |
- } else if(tableFind(subtypeTable, cptr) == PLAIN) { |
|
1933 |
+ } else if((tableFind(subtypeTable, cptr) == PLAIN) && |
|
1934 |
+ (messageGetEncoding(aMessage) == NOENCODING)) { |
|
1934 | 1935 |
char *filename; |
1935 | 1936 |
/* |
1936 | 1937 |
* Strictly speaking |
... | ... |
@@ -2108,7 +2094,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t |
2108 | 2108 |
|
2109 | 2109 |
if(aText && (textIn == NULL)) { |
2110 | 2110 |
if((fb = fileblobCreate()) != NULL) { |
2111 |
- cli_dbgmsg("Save non mime part\n"); |
|
2111 |
+ cli_dbgmsg("Save non mime and/or text/plain part\n"); |
|
2112 | 2112 |
fileblobSetFilename(fb, dir, "textpart"); |
2113 | 2113 |
/*fileblobAddData(fb, "Received: by clamd (textpart)\n", 30);*/ |
2114 | 2114 |
|
... | ... |
@@ -2600,11 +2586,41 @@ strstrip(char *s) |
2600 | 2600 |
} |
2601 | 2601 |
|
2602 | 2602 |
/* |
2603 |
- * No longer used - TODO: remove it |
|
2603 |
+ * Some broken email headers use ';' at the end of a line to continue |
|
2604 |
+ * to the next line and don't add a leading white space on the next line |
|
2604 | 2605 |
*/ |
2605 | 2606 |
static bool |
2606 | 2607 |
continuationMarker(const char *line) |
2607 | 2608 |
{ |
2609 |
+ const char *ptr; |
|
2610 |
+ |
|
2611 |
+ if(line == NULL) |
|
2612 |
+ return FALSE; |
|
2613 |
+ |
|
2614 |
+#ifdef CL_DEBUG |
|
2615 |
+ cli_dbgmsg("continuationMarker(%s)\n", line); |
|
2616 |
+#endif |
|
2617 |
+ |
|
2618 |
+ if(strlen(line) == 0) |
|
2619 |
+ return FALSE; |
|
2620 |
+ |
|
2621 |
+ ptr = strchr(line, '\0'); |
|
2622 |
+ |
|
2623 |
+ assert(ptr != NULL); |
|
2624 |
+ |
|
2625 |
+ while(ptr > line) |
|
2626 |
+ switch(*--ptr) { |
|
2627 |
+ case '\n': |
|
2628 |
+ case '\r': |
|
2629 |
+ case ' ': |
|
2630 |
+ case '\t': |
|
2631 |
+ continue; |
|
2632 |
+ case ';': |
|
2633 |
+ return TRUE; |
|
2634 |
+ default: |
|
2635 |
+ return FALSE; |
|
2636 |
+ } |
|
2637 |
+ |
|
2608 | 2638 |
return FALSE; |
2609 | 2639 |
} |
2610 | 2640 |
|