git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1201 77e5149b-7576-45b1-b177-96237e5ba77b
Nigel Horne authored on 2004/12/19 22:50:08... | ... |
@@ -17,6 +17,9 @@ |
17 | 17 |
* |
18 | 18 |
* Change History: |
19 | 19 |
* $Log: mbox.c,v $ |
20 |
+ * Revision 1.203 2004/12/19 13:50:08 nigelhorne |
|
21 |
+ * Tidy |
|
22 |
+ * |
|
20 | 23 |
* Revision 1.202 2004/12/18 16:32:10 nigelhorne |
21 | 24 |
* Added parseEmailFile |
22 | 25 |
* |
... | ... |
@@ -594,7 +597,7 @@ |
594 | 594 |
* Compilable under SCO; removed duplicate code with message.c |
595 | 595 |
* |
596 | 596 |
*/ |
597 |
-static char const rcsid[] = "$Id: mbox.c,v 1.202 2004/12/18 16:32:10 nigelhorne Exp $"; |
|
597 |
+static char const rcsid[] = "$Id: mbox.c,v 1.203 2004/12/19 13:50:08 nigelhorne Exp $"; |
|
598 | 598 |
|
599 | 599 |
#if HAVE_CONFIG_H |
600 | 600 |
#include "clamav-config.h" |
... | ... |
@@ -752,7 +755,7 @@ static char *rfc822comments(const char *in); |
752 | 752 |
static int rfc1341(message *m, const char *dir); |
753 | 753 |
#endif |
754 | 754 |
static bool usefulHeader(int commandNumber, const char *cmd); |
755 |
-#ifdef notdef |
|
755 |
+#if 0 |
|
756 | 756 |
static const char *cli_pmemstr(const char *haystack, size_t hs, const char *needle, size_t ns); |
757 | 757 |
#endif |
758 | 758 |
|
... | ... |
@@ -875,7 +878,7 @@ static pthread_mutex_t tables_mutex = PTHREAD_MUTEX_INITIALIZER; |
875 | 875 |
#define O_BINARY 0 |
876 | 876 |
#endif |
877 | 877 |
|
878 |
-#ifdef notdef |
|
878 |
+#if 0 |
|
879 | 879 |
|
880 | 880 |
#if HAVE_MMAP |
881 | 881 |
#if HAVE_SYS_MMAN_H |
... | ... |
@@ -888,22 +891,28 @@ static pthread_mutex_t tables_mutex = PTHREAD_MUTEX_INITIALIZER; |
888 | 888 |
/* |
889 | 889 |
* This could be the future. Instead of parsing and decoding it just decodes. |
890 | 890 |
* Currently this code is about 50% *slower* than the full blown parser, but |
891 |
- * that may improve with time. |
|
891 |
+ * that may improve with time. To speed it up we only scan less than 10MB - |
|
892 |
+ * need access to the options structure to check StreamMaxLength |
|
892 | 893 |
* USE IT AT YOUR PERIL, a large number of viruses are not detected with this |
893 | 894 |
* method, possibly because the decoded files must be exact and not have |
894 | 895 |
* extra data at the start or end, which this code will produce. |
896 |
+ * |
|
897 |
+ * One big hole is that if there's two attachements of the same type it only |
|
898 |
+ * extracts the first |
|
895 | 899 |
*/ |
896 | 900 |
int |
897 | 901 |
cli_mbox(const char *dir, int desc, unsigned int options) |
898 | 902 |
{ |
899 |
- char *start, *ptr, *line, *buf, *p; |
|
903 |
+ char *start, *ptr, *line, *p; |
|
904 |
+ char *b64start, *quotedstart; |
|
900 | 905 |
const char *last; |
901 |
- int decoder; |
|
902 |
- long bytesleft; |
|
906 |
+ int decoder, length; |
|
903 | 907 |
size_t size, headersize, bodysize; |
908 |
+ long b64size, quotedsize; |
|
904 | 909 |
struct stat statb; |
905 | 910 |
message *m; |
906 | 911 |
fileblob *fb; |
912 |
+ int ret = 0; |
|
907 | 913 |
|
908 | 914 |
if(fstat(desc, &statb) < 0) |
909 | 915 |
return CL_EOPEN; |
... | ... |
@@ -913,15 +922,12 @@ cli_mbox(const char *dir, int desc, unsigned int options) |
913 | 913 |
if(size == 0) |
914 | 914 |
return CL_CLEAN; |
915 | 915 |
|
916 |
- m = messageCreate(); |
|
917 |
- if(m == NULL) |
|
918 |
- return CL_EMEM; |
|
916 |
+ if(size > 10*1024*1024) |
|
917 |
+ return CL_CLEAN; /* should be StreamMaxLength, I guess */ |
|
919 | 918 |
|
920 | 919 |
start = ptr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0); |
921 |
- if(ptr == MAP_FAILED) { |
|
922 |
- messageDestroy(m); |
|
920 |
+ if(ptr == MAP_FAILED) |
|
923 | 921 |
return CL_EMEM; |
924 |
- } |
|
925 | 922 |
|
926 | 923 |
cli_dbgmsg("mmap'ed mbox\n"); |
927 | 924 |
|
... | ... |
@@ -944,7 +950,6 @@ cli_mbox(const char *dir, int desc, unsigned int options) |
944 | 944 |
} |
945 | 945 |
if(ptr >= last) { |
946 | 946 |
cli_dbgmsg("cli_mbox: can't determine the end of the headers\n"); |
947 |
- messageDestroy(m); |
|
948 | 947 |
munmap(start, size); |
949 | 948 |
return cli_parse_mbox(dir, desc, options); |
950 | 949 |
} |
... | ... |
@@ -954,122 +959,214 @@ cli_mbox(const char *dir, int desc, unsigned int options) |
954 | 954 |
|
955 | 955 |
cli_dbgmsg("cli_mbox: size=%u, headersize=%u, bodysize=%u\n", size, headersize, bodysize); |
956 | 956 |
|
957 |
- bytesleft = bodysize; |
|
958 |
- buf = ptr; |
|
957 |
+ b64start = quotedstart = NULL; |
|
958 |
+ b64size = quotedsize = 0; |
|
959 | 959 |
decoder = 0; |
960 | 960 |
|
961 |
- /* Would be nice to have a case insensitive cli_memstr() */ |
|
962 |
- if(cli_pmemstr(start, headersize, "base64", 6)) { |
|
961 |
+ /* |
|
962 |
+ * Would be nice to have a case insensitive cli_memstr() |
|
963 |
+ * |
|
964 |
+ * This is v. slow especially on large files |
|
965 |
+ */ |
|
966 |
+ if((p = (char *)cli_pmemstr(ptr, bodysize, "base64", 6)) != NULL) { |
|
963 | 967 |
cli_dbgmsg("Header base64\n"); |
964 | 968 |
decoder |= 1; |
969 |
+ b64start = &p[6]; |
|
970 |
+ b64size = (size_t)(last - b64start) + 1; |
|
965 | 971 |
} |
966 |
- if(cli_pmemstr(start, headersize, "quoted-printable", 16)) { |
|
972 |
+ if((p = (char *)cli_pmemstr(ptr, bodysize, "quoted-printable", 16)) != NULL) { |
|
967 | 973 |
cli_dbgmsg("Header quoted-printable\n"); |
968 | 974 |
decoder |= 2; |
975 |
+ quotedstart = p; |
|
976 |
+ quotedsize = (size_t)(last - quotedstart) + 1; |
|
969 | 977 |
} |
970 | 978 |
if(!(decoder&1)) |
971 | 979 |
if((p = (char *)cli_pmemstr(ptr, bodysize, "base64", 6)) != NULL) { |
972 | 980 |
cli_dbgmsg("Body base64\n"); |
973 | 981 |
decoder |= 1; |
974 |
- buf = &p[6]; |
|
975 |
- bytesleft = (unsigned long)(last - buf) + 1; |
|
976 |
- messageSetEncoding(m, "base64"); |
|
982 |
+ b64start = &p[6]; |
|
983 |
+ b64size = (unsigned long)(last - b64start) + 1; |
|
977 | 984 |
} |
978 | 985 |
if(!(decoder&2)) |
979 | 986 |
if((p = (char *)cli_pmemstr(ptr, bodysize, "quoted-printable", 16)) != NULL) { |
980 | 987 |
cli_dbgmsg("Body quoted-printable\n"); |
981 | 988 |
decoder |= 2; |
982 |
- if((p < buf) || (buf == ptr)) { |
|
983 |
- buf = &p[16]; |
|
984 |
- bytesleft = (unsigned long)(last - buf) + 1; |
|
985 |
- } |
|
986 |
- messageSetEncoding(m, "quoted-printable"); |
|
989 |
+ quotedstart = &p[16]; |
|
990 |
+ quotedsize = (unsigned long)(last - quotedstart) + 1; |
|
987 | 991 |
} |
988 | 992 |
|
989 | 993 |
if(decoder == 0) { |
990 |
- messageDestroy(m); |
|
991 | 994 |
munmap(start, size); |
992 | 995 |
cli_dbgmsg("cli_mbox: unknown encoder\n"); |
993 | 996 |
return cli_parse_mbox(dir, desc, options); |
994 | 997 |
} |
995 | 998 |
|
996 |
- line = NULL; |
|
999 |
+ if(b64start) { |
|
1000 |
+ while(*b64start != '\n') { |
|
1001 |
+ b64start++; |
|
1002 |
+ b64size--; |
|
1003 |
+ } |
|
1004 |
+ /* |
|
1005 |
+ * Look for the end of the headers |
|
1006 |
+ */ |
|
1007 |
+ while(b64start < last) { |
|
1008 |
+ if(*b64start == ';') { |
|
1009 |
+ b64start++; |
|
1010 |
+ b64size--; |
|
1011 |
+ } else if(*b64start == '\n') { |
|
1012 |
+ b64start++; |
|
1013 |
+ b64size--; |
|
1014 |
+ if((*b64start == '\n') || (*b64start == '\r')) { |
|
1015 |
+ b64start++; |
|
1016 |
+ b64size--; |
|
1017 |
+ break; |
|
1018 |
+ } |
|
1019 |
+ } |
|
1020 |
+ b64start++; |
|
1021 |
+ b64size--; |
|
1022 |
+ } |
|
997 | 1023 |
|
998 |
- while(*buf != '\n') { |
|
999 |
- buf++; |
|
1000 |
- bytesleft--; |
|
1001 |
- } |
|
1002 |
- /* |
|
1003 |
- * Look for the end of the headers |
|
1004 |
- */ |
|
1005 |
- while(buf < last) { |
|
1006 |
- if(*buf == ';') { |
|
1007 |
- buf++; |
|
1008 |
- bytesleft--; |
|
1009 |
- } else if(*buf == '\n') { |
|
1010 |
- buf++; |
|
1011 |
- bytesleft--; |
|
1012 |
- if((*buf == '\n') || (*buf == '\r')) { |
|
1013 |
- buf++; |
|
1014 |
- bytesleft--; |
|
1015 |
- break; |
|
1024 |
+ while(!isalnum(*b64start)) { |
|
1025 |
+ b64start++; |
|
1026 |
+ b64size--; |
|
1027 |
+ } |
|
1028 |
+ |
|
1029 |
+ if(b64size > 0L) { |
|
1030 |
+ cli_dbgmsg("cli_mbox: decoding %ld base64 bytes\n", b64size); |
|
1031 |
+ |
|
1032 |
+ line = NULL; |
|
1033 |
+ length = 0; |
|
1034 |
+ |
|
1035 |
+ m = messageCreate(); |
|
1036 |
+ if(m == NULL) |
|
1037 |
+ return CL_EMEM; |
|
1038 |
+ messageSetEncoding(m, "base64"); |
|
1039 |
+ |
|
1040 |
+ while(b64size > 0L) { |
|
1041 |
+ length = 0; |
|
1042 |
+ |
|
1043 |
+ /*printf("%ld: ", bytesleft); fflush(stdout);*/ |
|
1044 |
+ |
|
1045 |
+ for(ptr = b64start; b64size && (*ptr != '\n') && (*ptr != '\r'); ptr++) { |
|
1046 |
+ length++; |
|
1047 |
+ --b64size; |
|
1048 |
+ } |
|
1049 |
+ |
|
1050 |
+ /*printf("%d: ", length); fflush(stdout);*/ |
|
1051 |
+ |
|
1052 |
+ line = cli_realloc(line, length + 1); |
|
1053 |
+ |
|
1054 |
+ memcpy(line, b64start, length); |
|
1055 |
+ line[length] = '\0'; |
|
1056 |
+ |
|
1057 |
+ /*puts(line);*/ |
|
1058 |
+ |
|
1059 |
+ if(messageAddStr(m, line) < 0) |
|
1060 |
+ break; |
|
1061 |
+ |
|
1062 |
+ if((b64size > 0) && (*ptr == '\r')) { |
|
1063 |
+ ptr++; |
|
1064 |
+ --b64size; |
|
1065 |
+ } |
|
1066 |
+ b64start = ++ptr; |
|
1067 |
+ --b64size; |
|
1068 |
+ if(strchr(line, '=')) |
|
1069 |
+ break; |
|
1016 | 1070 |
} |
1071 |
+ fb = messageToFileblob(m, dir); |
|
1072 |
+ messageDestroy(m); |
|
1073 |
+ |
|
1074 |
+ if(fb) |
|
1075 |
+ fileblobDestroy(fb); |
|
1076 |
+ else |
|
1077 |
+ ret = -1; |
|
1017 | 1078 |
} |
1018 |
- buf++; |
|
1019 |
- bytesleft--; |
|
1020 | 1079 |
} |
1080 |
+ if(quotedstart) { |
|
1081 |
+ while(*quotedstart != '\n') { |
|
1082 |
+ quotedstart++; |
|
1083 |
+ quotedsize--; |
|
1084 |
+ } |
|
1085 |
+ /* |
|
1086 |
+ * Look for the end of the headers |
|
1087 |
+ */ |
|
1088 |
+ while(quotedstart < last) { |
|
1089 |
+ if(*quotedstart == ';') { |
|
1090 |
+ quotedstart++; |
|
1091 |
+ quotedsize--; |
|
1092 |
+ } else if(*quotedstart == '\n') { |
|
1093 |
+ quotedstart++; |
|
1094 |
+ quotedsize--; |
|
1095 |
+ if((*quotedstart == '\n') || (*quotedstart == '\r')) { |
|
1096 |
+ quotedstart++; |
|
1097 |
+ quotedsize--; |
|
1098 |
+ break; |
|
1099 |
+ } |
|
1100 |
+ } |
|
1101 |
+ quotedstart++; |
|
1102 |
+ quotedsize--; |
|
1103 |
+ } |
|
1021 | 1104 |
|
1022 |
- while(!isalnum(*buf)) { |
|
1023 |
- buf++; |
|
1024 |
- bytesleft--; |
|
1025 |
- } |
|
1105 |
+ while(!isalnum(*quotedstart)) { |
|
1106 |
+ quotedstart++; |
|
1107 |
+ quotedsize--; |
|
1108 |
+ } |
|
1026 | 1109 |
|
1027 |
- if(bytesleft > 1024*1024) |
|
1028 |
- bytesleft = 1024*1024; /* should be MaxStreamSize, I guess */ |
|
1110 |
+ if(quotedsize > 0L) { |
|
1111 |
+ cli_dbgmsg("cli_mbox: decoding %ld quoted-printable bytes\n", quotedsize); |
|
1029 | 1112 |
|
1030 |
- cli_dbgmsg("cli_mbox: decoding %ld bytes\n", bytesleft); |
|
1113 |
+ m = messageCreate(); |
|
1114 |
+ if(m == NULL) |
|
1115 |
+ return CL_EMEM; |
|
1116 |
+ messageSetEncoding(m, "quoted-printable"); |
|
1031 | 1117 |
|
1032 |
- while(bytesleft > 0) { |
|
1033 |
- int length = 0; |
|
1118 |
+ line = NULL; |
|
1119 |
+ length = 0; |
|
1034 | 1120 |
|
1035 |
- /*printf("%ld: ", bytesleft); fflush(stdout);*/ |
|
1121 |
+ while(quotedsize > 0L) { |
|
1122 |
+ length = 0; |
|
1036 | 1123 |
|
1037 |
- for(ptr = buf; bytesleft && (*ptr != '\n') && (*ptr != '\r'); ptr++) { |
|
1038 |
- length++; |
|
1039 |
- --bytesleft; |
|
1040 |
- } |
|
1124 |
+ /*printf("%ld: ", bytesleft); fflush(stdout);*/ |
|
1041 | 1125 |
|
1042 |
- /*printf("%d: ", length); fflush(stdout);*/ |
|
1126 |
+ for(ptr = quotedstart; quotedsize && (*ptr != '\n') && (*ptr != '\r'); ptr++) { |
|
1127 |
+ length++; |
|
1128 |
+ --quotedsize; |
|
1129 |
+ } |
|
1043 | 1130 |
|
1044 |
- line = cli_realloc(line, length + 1); |
|
1131 |
+ /*printf("%d: ", length); fflush(stdout);*/ |
|
1045 | 1132 |
|
1046 |
- memcpy(line, buf, length); |
|
1047 |
- line[length] = '\0'; |
|
1133 |
+ line = cli_realloc(line, length + 1); |
|
1048 | 1134 |
|
1049 |
- /*puts(line);*/ |
|
1135 |
+ memcpy(line, quotedstart, length); |
|
1136 |
+ line[length] = '\0'; |
|
1050 | 1137 |
|
1051 |
- if(messageAddStr(m, line) < 0) |
|
1052 |
- break; |
|
1138 |
+ /*puts(line);*/ |
|
1053 | 1139 |
|
1054 |
- if((bytesleft > 0) && (*ptr == '\r')) { |
|
1055 |
- ptr++; |
|
1056 |
- bytesleft--; |
|
1140 |
+ if(messageAddStr(m, line) < 0) |
|
1141 |
+ break; |
|
1142 |
+ |
|
1143 |
+ if((quotedsize > 0) && (*ptr == '\r')) { |
|
1144 |
+ ptr++; |
|
1145 |
+ --quotedsize; |
|
1146 |
+ } |
|
1147 |
+ quotedstart = ++ptr; |
|
1148 |
+ --quotedsize; |
|
1149 |
+ } |
|
1150 |
+ fb = messageToFileblob(m, dir); |
|
1151 |
+ messageDestroy(m); |
|
1152 |
+ |
|
1153 |
+ if(fb) |
|
1154 |
+ fileblobDestroy(fb); |
|
1155 |
+ else |
|
1156 |
+ ret = -1; |
|
1057 | 1157 |
} |
1058 |
- buf = ++ptr; |
|
1059 |
- bytesleft--; |
|
1060 | 1158 |
} |
1061 |
- if(line) |
|
1062 |
- free(line); |
|
1063 | 1159 |
|
1064 | 1160 |
munmap(start, size); |
1065 | 1161 |
|
1066 |
- fb = messageToFileblob(m, dir); |
|
1067 |
- messageDestroy(m); |
|
1068 |
- |
|
1069 |
- if(fb) { |
|
1070 |
- fileblobDestroy(fb); |
|
1162 |
+ if(ret == 0) |
|
1071 | 1163 |
return CL_CLEAN; /* a lie - but it gets things going */ |
1072 |
- } |
|
1164 |
+ |
|
1073 | 1165 |
return cli_parse_mbox(dir, desc, options); |
1074 | 1166 |
} |
1075 | 1167 |
#else |
... | ... |
@@ -1151,6 +1248,20 @@ cli_parse_mbox(const char *dir, int desc, unsigned int options) |
1151 | 1151 |
/* |
1152 | 1152 |
* Have been asked to check a UNIX style mbox file, which |
1153 | 1153 |
* may contain more than one e-mail message to decode |
1154 |
+ * |
|
1155 |
+ * It would be far better for scanners.c to do this splitting |
|
1156 |
+ * and do this |
|
1157 |
+ * FOR EACH mail in the mailbox |
|
1158 |
+ * DO |
|
1159 |
+ * pass this mail to cli_mbox -- |
|
1160 |
+ * scan this file |
|
1161 |
+ * IF this file has a virus quit |
|
1162 |
+ * THEN |
|
1163 |
+ * return CL_VIRUS |
|
1164 |
+ * FI |
|
1165 |
+ * END |
|
1166 |
+ * This would remove a problem with this code that it can |
|
1167 |
+ * fill up the tmp directory before it starts scanning |
|
1154 | 1168 |
*/ |
1155 | 1169 |
bool lastLineWasEmpty; |
1156 | 1170 |
int messagenumber; |
... | ... |
@@ -3386,6 +3497,10 @@ rfc1341(message *m, const char *dir) |
3386 | 3386 |
const char *tmpdir; |
3387 | 3387 |
char pdir[NAME_MAX + 1]; |
3388 | 3388 |
|
3389 |
+ id = (char *)messageFindArgument(m, "id"); |
|
3390 |
+ if(id == NULL) |
|
3391 |
+ return -1; |
|
3392 |
+ |
|
3389 | 3393 |
#ifdef CYGWIN |
3390 | 3394 |
if((tmpdir = getenv("TEMP")) == (char *)NULL) |
3391 | 3395 |
if((tmpdir = getenv("TMP")) == (char *)NULL) |
... | ... |
@@ -3419,9 +3534,6 @@ rfc1341(message *m, const char *dir) |
3419 | 3419 |
pdir, statb.st_mode & 0777); |
3420 | 3420 |
} |
3421 | 3421 |
|
3422 |
- id = (char *)messageFindArgument(m, "id"); |
|
3423 |
- if(id == NULL) |
|
3424 |
- return -1; |
|
3425 | 3422 |
number = (char *)messageFindArgument(m, "number"); |
3426 | 3423 |
if(number == NULL) { |
3427 | 3424 |
free(id); |
... | ... |
@@ -3457,6 +3569,7 @@ rfc1341(message *m, const char *dir) |
3457 | 3457 |
int t = atoi(total); |
3458 | 3458 |
DIR *dd = NULL; |
3459 | 3459 |
|
3460 |
+ free(total); |
|
3460 | 3461 |
/* |
3461 | 3462 |
* If it's the last one - reassemble it |
3462 | 3463 |
* FIXME: this assumes that we receive the parts in order |
... | ... |
@@ -3473,7 +3586,6 @@ rfc1341(message *m, const char *dir) |
3473 | 3473 |
if(fout == NULL) { |
3474 | 3474 |
cli_errmsg("Can't open '%s' for writing", outname); |
3475 | 3475 |
free(id); |
3476 |
- free(total); |
|
3477 | 3476 |
free(number); |
3478 | 3477 |
closedir(dd); |
3479 | 3478 |
return -1; |
... | ... |
@@ -3498,7 +3610,6 @@ rfc1341(message *m, const char *dir) |
3498 | 3498 |
#else /*!HAVE_READDIR_R*/ |
3499 | 3499 |
while((dent = readdir(dd))) { |
3500 | 3500 |
#endif |
3501 |
- char fullname[NAME_MAX + 1]; |
|
3502 | 3501 |
FILE *fin; |
3503 | 3502 |
char buffer[BUFSIZ]; |
3504 | 3503 |
int nblanks; |
... | ... |
@@ -3510,14 +3621,13 @@ rfc1341(message *m, const char *dir) |
3510 | 3510 |
if(strncmp(filename, dent->d_name, strlen(filename)) != 0) |
3511 | 3511 |
continue; |
3512 | 3512 |
|
3513 |
- sprintf(fullname, "%s/%s", pdir, dent->d_name); |
|
3514 |
- fin = fopen(fullname, "rb"); |
|
3513 |
+ sprintf(filename, "%s/%s", pdir, dent->d_name); |
|
3514 |
+ fin = fopen(filename, "rb"); |
|
3515 | 3515 |
if(fin == NULL) { |
3516 |
- cli_errmsg("Can't open '%s' for reading", fullname); |
|
3516 |
+ cli_errmsg("Can't open '%s' for reading", filename); |
|
3517 | 3517 |
fclose(fout); |
3518 | 3518 |
unlink(outname); |
3519 | 3519 |
free(id); |
3520 |
- free(total); |
|
3521 | 3520 |
free(number); |
3522 | 3521 |
closedir(dd); |
3523 | 3522 |
return -1; |
... | ... |
@@ -3528,9 +3638,9 @@ rfc1341(message *m, const char *dir) |
3528 | 3528 |
* Ensure that trailing newlines |
3529 | 3529 |
* aren't copied |
3530 | 3530 |
*/ |
3531 |
- if(buffer[0] == '\n') { |
|
3531 |
+ if(buffer[0] == '\n') |
|
3532 | 3532 |
nblanks++; |
3533 |
- } else { |
|
3533 |
+ else { |
|
3534 | 3534 |
if(nblanks) |
3535 | 3535 |
do |
3536 | 3536 |
putc('\n', fout); |
... | ... |
@@ -3541,7 +3651,7 @@ rfc1341(message *m, const char *dir) |
3541 | 3541 |
|
3542 | 3542 |
/* don't unlink if leave temps */ |
3543 | 3543 |
if(!cli_leavetemps_flag) |
3544 |
- unlink(fullname); |
|
3544 |
+ unlink(filename); |
|
3545 | 3545 |
break; |
3546 | 3546 |
} |
3547 | 3547 |
rewinddir(dd); |
... | ... |
@@ -3549,10 +3659,9 @@ rfc1341(message *m, const char *dir) |
3549 | 3549 |
closedir(dd); |
3550 | 3550 |
fclose(fout); |
3551 | 3551 |
} |
3552 |
- free(number); |
|
3553 | 3552 |
} |
3553 |
+ free(number); |
|
3554 | 3554 |
free(id); |
3555 |
- free(total); |
|
3556 | 3555 |
|
3557 | 3556 |
return 0; |
3558 | 3557 |
} |
... | ... |
@@ -3899,7 +4008,7 @@ usefulHeader(int commandNumber, const char *cmd) |
3899 | 3899 |
return FALSE; |
3900 | 3900 |
} |
3901 | 3901 |
|
3902 |
-#ifdef notdef |
|
3902 |
+#if 0 |
|
3903 | 3903 |
/* |
3904 | 3904 |
* like cli_memstr - but returns the location of the match |
3905 | 3905 |
*/ |
... | ... |
@@ -17,6 +17,9 @@ |
17 | 17 |
* |
18 | 18 |
* Change History: |
19 | 19 |
* $Log: message.c,v $ |
20 |
+ * Revision 1.133 2004/12/19 13:50:08 nigelhorne |
|
21 |
+ * Tidy |
|
22 |
+ * |
|
20 | 23 |
* Revision 1.132 2004/12/16 15:29:51 nigelhorne |
21 | 24 |
* Tidy |
22 | 25 |
* |
... | ... |
@@ -393,7 +396,7 @@ |
393 | 393 |
* uuencodebegin() no longer static |
394 | 394 |
* |
395 | 395 |
*/ |
396 |
-static char const rcsid[] = "$Id: message.c,v 1.132 2004/12/16 15:29:51 nigelhorne Exp $"; |
|
396 |
+static char const rcsid[] = "$Id: message.c,v 1.133 2004/12/19 13:50:08 nigelhorne Exp $"; |
|
397 | 397 |
|
398 | 398 |
#if HAVE_CONFIG_H |
399 | 399 |
#include "clamav-config.h" |
... | ... |
@@ -441,6 +444,8 @@ static char const rcsid[] = "$Id: message.c,v 1.132 2004/12/16 15:29:51 nigelhor |
441 | 441 |
#undef FALSE |
442 | 442 |
#endif |
443 | 443 |
|
444 |
+#define RFC2045LENGTH 76 /* maximum number of characters on a line */ |
|
445 |
+ |
|
444 | 446 |
typedef enum { FALSE = 0, TRUE = 1 } bool; |
445 | 447 |
|
446 | 448 |
static void messageIsEncoding(message *m); |
... | ... |
@@ -837,9 +842,7 @@ messageAddArguments(message *m, const char *s) |
837 | 837 |
return; |
838 | 838 |
} |
839 | 839 |
|
840 |
- string = data; |
|
841 |
- |
|
842 |
- string++; |
|
840 |
+ string = &data[1]; |
|
843 | 841 |
|
844 | 842 |
/* |
845 | 843 |
* Handle white space to the right of the equals sign |
... | ... |
@@ -875,9 +878,7 @@ messageAddArguments(message *m, const char *s) |
875 | 875 |
ptr = strchr(key, ':'); |
876 | 876 |
*ptr = '\0'; |
877 | 877 |
|
878 |
- cptr++; |
|
879 |
- |
|
880 |
- string = strchr(cptr, '"'); |
|
878 |
+ string = strchr(++cptr, '"'); |
|
881 | 879 |
|
882 | 880 |
if(string == NULL) { |
883 | 881 |
cli_dbgmsg("Unbalanced quote character in \"%s\"\n", s); |
... | ... |
@@ -1002,7 +1003,6 @@ messageFindArgument(const message *m, const char *variable) |
1002 | 1002 |
if(ret == NULL) |
1003 | 1003 |
return NULL; |
1004 | 1004 |
|
1005 |
- ret[strlen(ret) - 1] = '\0'; |
|
1006 | 1005 |
/* |
1007 | 1006 |
* Thomas Lamy <Thomas.Lamy@in-online.net>: |
1008 | 1007 |
* fix un-quoting of boundary strings from |
... | ... |
@@ -1013,8 +1013,10 @@ messageFindArgument(const message *m, const char *variable) |
1013 | 1013 |
* quoted argument |
1014 | 1014 |
* end string at next quote |
1015 | 1015 |
*/ |
1016 |
- if((p = strchr(ret, '"')) != NULL) |
|
1016 |
+ if((p = strchr(ret, '"')) != NULL) { |
|
1017 |
+ ret[strlen(ret) - 1] = '\0'; |
|
1017 | 1018 |
*p = '\0'; |
1019 |
+ } |
|
1018 | 1020 |
return ret; |
1019 | 1021 |
} |
1020 | 1022 |
return strdup(ptr); |
... | ... |
@@ -1052,16 +1054,37 @@ messageSetEncoding(message *m, const char *enctype) |
1052 | 1052 |
int highestSimil = 0; |
1053 | 1053 |
const char *closest = NULL; |
1054 | 1054 |
|
1055 |
- for(e = encoding_map; e->string; e++) |
|
1056 |
- if(strcasecmp(type, e->string) == 0) { |
|
1055 |
+ for(e = encoding_map; e->string; e++) { |
|
1056 |
+ int sim; |
|
1057 |
+ const char lowertype = tolower(type[0]); |
|
1058 |
+ |
|
1059 |
+ if((lowertype != tolower(e->string[0])) && (lowertype != 'x')) |
|
1060 |
+ /* |
|
1061 |
+ * simil is expensive, I'm yet to encounter only |
|
1062 |
+ * one example of a missent encoding when the |
|
1063 |
+ * first character was wrong, so lets assume no |
|
1064 |
+ * match to save the call. |
|
1065 |
+ * |
|
1066 |
+ * That example was quoted-printable sent as |
|
1067 |
+ * X-quoted-printable. |
|
1068 |
+ */ |
|
1069 |
+ continue; |
|
1070 |
+ |
|
1071 |
+ sim = simil(type, e->string); |
|
1072 |
+ |
|
1073 |
+ if(sim == 100) { |
|
1057 | 1074 |
int j; |
1058 | 1075 |
encoding_type *et; |
1059 | 1076 |
|
1060 | 1077 |
for(j = 0; j < m->numberOfEncTypes; j++) |
1061 |
- if(m->encodingTypes[j] == e->type) { |
|
1062 |
- cli_dbgmsg("Ignoring duplicate encoding mechanism\n"); |
|
1078 |
+ if(m->encodingTypes[j] == e->type) |
|
1063 | 1079 |
break; |
1064 |
- } |
|
1080 |
+ |
|
1081 |
+ if(j < m->numberOfEncTypes) { |
|
1082 |
+ cli_dbgmsg("Ignoring duplicate encoding mechanism '%s'\n", |
|
1083 |
+ type); |
|
1084 |
+ break; |
|
1085 |
+ } |
|
1065 | 1086 |
|
1066 | 1087 |
et = (encoding_type *)cli_realloc(m->encodingTypes, (m->numberOfEncTypes + 1) * sizeof(encoding_type)); |
1067 | 1088 |
if(et == NULL) |
... | ... |
@@ -1072,15 +1095,11 @@ messageSetEncoding(message *m, const char *enctype) |
1072 | 1072 |
|
1073 | 1073 |
cli_dbgmsg("Encoding type %d is \"%s\"\n", m->numberOfEncTypes, type); |
1074 | 1074 |
break; |
1075 |
- |
|
1076 |
- } else { |
|
1077 |
- const int sim = simil(type, e->string); |
|
1078 |
- |
|
1079 |
- if(sim > highestSimil) { |
|
1080 |
- closest = e->string; |
|
1081 |
- highestSimil = sim; |
|
1082 |
- } |
|
1075 |
+ } else if(sim > highestSimil) { |
|
1076 |
+ closest = e->string; |
|
1077 |
+ highestSimil = sim; |
|
1083 | 1078 |
} |
1079 |
+ } |
|
1084 | 1080 |
|
1085 | 1081 |
if(e->string == NULL) { |
1086 | 1082 |
/* |
... | ... |
@@ -2196,6 +2215,7 @@ decodeLine(message *m, encoding_type et, const char *line, unsigned char *buf, s |
2196 | 2196 |
bool softbreak; |
2197 | 2197 |
char *p2; |
2198 | 2198 |
char *copy; |
2199 |
+ char base64buf[RFC2045LENGTH + 1]; |
|
2199 | 2200 |
|
2200 | 2201 |
/*printf("decodeLine(et = %d buflen = %u)\n", (int)et, buflen);*/ |
2201 | 2202 |
|
... | ... |
@@ -2222,70 +2242,6 @@ decodeLine(message *m, encoding_type et, const char *line, unsigned char *buf, s |
2222 | 2222 |
break; |
2223 | 2223 |
} |
2224 | 2224 |
|
2225 |
-#if 0 |
|
2226 |
- /* |
|
2227 |
- * Section 5.1 of RFC2045 states that any number of white |
|
2228 |
- * space characters may appear on the end of the line |
|
2229 |
- * before the final '=' which indicates a soft break. |
|
2230 |
- * |
|
2231 |
- * Section 6.7.(3) of RFC2045 is no clearer. |
|
2232 |
- * |
|
2233 |
- * This means that we have to do a look ahead here. |
|
2234 |
- * |
|
2235 |
- * This is a real pain because not everyone is |
|
2236 |
- * aware of the implication of the above sentence, |
|
2237 |
- * namely that you must encode any white space before |
|
2238 |
- * the final '=' to ensure it is correctly transfered |
|
2239 |
- * otherwise it is dropped. |
|
2240 |
- * This code adheres to the RFC, but I don't think most |
|
2241 |
- * other software does so I may have to change it |
|
2242 |
- */ |
|
2243 |
- p2 = strchr(line, '\0'); |
|
2244 |
- if(p2 == line) { /* empty line */ |
|
2245 |
- *buf++ = '\n'; |
|
2246 |
- break; |
|
2247 |
- } |
|
2248 |
- if(*--p2 == '=') { |
|
2249 |
- softbreak = TRUE; |
|
2250 |
- do |
|
2251 |
- --p2; |
|
2252 |
- while(isspace(*p2) && (p2 > line)); |
|
2253 |
- } else |
|
2254 |
- softbreak = FALSE; |
|
2255 |
- |
|
2256 |
- /* |
|
2257 |
- * p2 now points to the last significant character on the line |
|
2258 |
- */ |
|
2259 |
- while(line <= p2) { |
|
2260 |
- if(*line == '=') { |
|
2261 |
- unsigned char byte; |
|
2262 |
- |
|
2263 |
- if((*++line == '\0') || (*line == '\n')) { |
|
2264 |
- /* soft line break detected */ |
|
2265 |
- if(!softbreak) |
|
2266 |
- cli_warnmsg("Unexpected soft line break\n"); |
|
2267 |
- break; |
|
2268 |
- } |
|
2269 |
- |
|
2270 |
- byte = hex(*line); |
|
2271 |
- |
|
2272 |
- if((*++line == '\0') || (*line == '\n')) { |
|
2273 |
- /* |
|
2274 |
- * broken e-mail, not |
|
2275 |
- * adhering to RFC2045 |
|
2276 |
- */ |
|
2277 |
- *buf++ = byte; |
|
2278 |
- break; |
|
2279 |
- } |
|
2280 |
- |
|
2281 |
- byte <<= 4; |
|
2282 |
- byte += hex(*line); |
|
2283 |
- *buf++ = byte; |
|
2284 |
- } else |
|
2285 |
- *buf++ = *line; |
|
2286 |
- line++; |
|
2287 |
- } |
|
2288 |
-#else |
|
2289 | 2225 |
softbreak = FALSE; |
2290 | 2226 |
while((line < (char *)&buf[buflen]) && *line) { |
2291 | 2227 |
if(*line == '=') { |
... | ... |
@@ -2315,7 +2271,6 @@ decodeLine(message *m, encoding_type et, const char *line, unsigned char *buf, s |
2315 | 2315 |
*buf++ = *line; |
2316 | 2316 |
line++; |
2317 | 2317 |
} |
2318 |
-#endif |
|
2319 | 2318 |
if(!softbreak) |
2320 | 2319 |
/* Put the new line back in */ |
2321 | 2320 |
*buf++ = '\n'; |
... | ... |
@@ -2328,9 +2283,14 @@ decodeLine(message *m, encoding_type et, const char *line, unsigned char *buf, s |
2328 | 2328 |
* RFC2045 sets the maximum length to 76 bytes |
2329 | 2329 |
* but many e-mail clients ignore that |
2330 | 2330 |
*/ |
2331 |
- copy = strdup(line); |
|
2332 |
- if(copy == NULL) |
|
2333 |
- break; |
|
2331 |
+ if(strlen(line) < sizeof(base64buf)) { |
|
2332 |
+ strcpy(base64buf, line); |
|
2333 |
+ copy = base64buf; |
|
2334 |
+ } else { |
|
2335 |
+ copy = strdup(line); |
|
2336 |
+ if(copy == NULL) |
|
2337 |
+ break; |
|
2338 |
+ } |
|
2334 | 2339 |
|
2335 | 2340 |
p2 = strchr(copy, '='); |
2336 | 2341 |
if(p2) |
... | ... |
@@ -2343,7 +2303,8 @@ decodeLine(message *m, encoding_type et, const char *line, unsigned char *buf, s |
2343 | 2343 |
*/ |
2344 | 2344 |
buf = decode(m, copy, buf, base64, (p2 == NULL) && ((strlen(copy) & 3) == 0)); |
2345 | 2345 |
|
2346 |
- free(copy); |
|
2346 |
+ if(copy != base64buf) |
|
2347 |
+ free(copy); |
|
2347 | 2348 |
break; |
2348 | 2349 |
|
2349 | 2350 |
case UUENCODE: |