… | |
… | |
51 | #include <uudeview.h> |
51 | #include <uudeview.h> |
52 | #include <uuint.h> |
52 | #include <uuint.h> |
53 | #include <fptools.h> |
53 | #include <fptools.h> |
54 | #include <uustring.h> |
54 | #include <uustring.h> |
55 | |
55 | |
56 | char * uucheck_id = "$Id: uucheck.c,v 1.24 2020/12/12 02:03:14 root Exp $"; |
56 | char * uucheck_id = "$Id: uucheck.c,v 1.25 2020/12/12 10:48:39 root Exp $"; |
57 | |
57 | |
58 | /* |
58 | /* |
59 | * Arbitrary number. This is the maximum number of part numbers we |
59 | * Arbitrary number. This is the maximum number of part numbers we |
60 | * store for our have-parts and missing-parts lists |
60 | * store for our have-parts and missing-parts lists |
61 | */ |
61 | */ |
… | |
… | |
983 | *ret = UURET_OK; |
983 | *ret = UURET_OK; |
984 | |
984 | |
985 | return result; |
985 | return result; |
986 | } |
986 | } |
987 | |
987 | |
|
|
988 | /* this helper function makes UUInsertPartToList a tiny bit clearer, hopefully */ |
|
|
989 | static int |
|
|
990 | uu_str_eq (const char *a, const char *b) |
|
|
991 | { |
|
|
992 | return a && b && !strcmp (a, b); |
|
|
993 | } |
|
|
994 | |
988 | /* |
995 | /* |
989 | * Insert one part of a file into the global list |
996 | * Insert one part of a file into the global list |
990 | **/ |
997 | **/ |
991 | |
998 | |
992 | int |
999 | int |
993 | UUInsertPartToList (uufile *data) |
1000 | UUInsertPartToList (uufile *data) |
994 | { |
1001 | { |
995 | uulist *iter = UUGlobalFileList, *unew; |
1002 | uulist *iter = UUGlobalFileList, *unew; |
996 | uufile *fiter, *last; |
1003 | uufile *fiter, *last; |
997 | |
1004 | |
|
|
1005 | uint32_t mimeid_hash = fnv1a (data->mimeid); |
|
|
1006 | uint32_t filename_hash = fnv1a (data->filename); |
|
|
1007 | |
|
|
1008 | /* cache locally so the compiler has it easier to reason */ |
|
|
1009 | fileread *data_data = data->data; |
|
|
1010 | |
998 | /* |
1011 | /* |
999 | * Part belongs together, if |
1012 | * Part belongs together, if |
1000 | * (1) The MIME-IDs match, or |
|
|
1001 | * (2) The file name received from the subject lines match, and |
1013 | * (1) The file name received from the subject lines match, and |
1002 | * (a) Not both parts have a begin line |
1014 | * (a) Not both parts have a begin line |
1003 | * (b) Not both parts have an end line |
1015 | * (b) Not both parts have an end line |
1004 | * (c) Both parts don't have different MIME-IDs |
1016 | * (c) Both parts don't have different MIME-IDs |
1005 | * (d) Both parts don't encode different files |
1017 | * (d) Both parts don't encode different files |
1006 | * (e) The other part wants to stay alone (FL_SINGLE) |
1018 | * (e) The other part wants to stay alone (FL_SINGLE) |
1007 | * (g) The yencode file size matches. |
1019 | * (g) The yencode file size matches. |
|
|
1020 | * (2) The MIME-IDs match, or |
1008 | */ |
1021 | */ |
|
|
1022 | |
|
|
1023 | /* TODO: walk two hash chains looked up by filename_hash and mimeid_hash instead */ |
|
|
1024 | /* may have to be be two separate chains, unfortunately, due to the way mimeids are compared? */ |
1009 | |
1025 | |
1010 | /* |
1026 | /* |
1011 | * check if this part wants to be left alone. If so, don't bother |
1027 | * check if this part wants to be left alone. If so, don't bother |
1012 | * to do all the checks |
1028 | * to do all the checks |
1013 | */ |
1029 | */ |
|
|
1030 | if (data_data->flags & FL_SINGLE) |
|
|
1031 | goto newpart; |
1014 | |
1032 | |
1015 | while (iter) { |
1033 | while (iter) { |
1016 | if (data->data->flags & FL_SINGLE) { |
1034 | if ( |
1017 | /* this space intentionally left blank */ |
1035 | ( |
1018 | } |
|
|
1019 | else if ((data->mimeid && iter->mimeid && strcmp (data->mimeid, iter->mimeid) == 0) |
|
|
1020 | || |
|
|
1021 | ( |
|
|
1022 | 1 |
1036 | 1 |
|
|
1037 | && filename_hash == iter->filename_hash |
|
|
1038 | && (data->filename && iter->filename && strcmp (data->filename, iter->filename) == 0) |
|
|
1039 | && !(iter->begin && data_data->begin) |
|
|
1040 | && !(iter->end && data_data->end) |
|
|
1041 | && !(iter->flags & FL_SINGLE) |
1023 | && !(iter->thisfile && iter->thisfile->yefilesize != data->yefilesize) |
1042 | && !(iter->thisfile && iter->thisfile->yefilesize != data->yefilesize) |
1024 | && !(iter->begin && data->data->begin) |
|
|
1025 | && !(iter->end && data->data->end) |
|
|
1026 | && !(iter->flags & FL_SINGLE) |
|
|
1027 | && !(data->filename && iter->filename && strcmp (data->filename, iter->filename) != 0) |
|
|
1028 | && FP_stricmp (data->subfname, iter->subfname) == 0 |
1043 | && FP_stricmp (data->subfname, iter->subfname) == 0 |
|
|
1044 | && mimeid_hash == iter->mimeid_hash |
1029 | && !(data->mimeid && iter->mimeid && strcmp (data->mimeid, iter->mimeid) != 0) |
1045 | && !(data->mimeid && iter->mimeid && strcmp (data->mimeid, iter->mimeid) != 0) |
1030 | ) |
1046 | ) |
|
|
1047 | || (mimeid_hash == iter->mimeid_hash && data->mimeid && iter->mimeid && strcmp (data->mimeid, iter->mimeid) == 0) |
1031 | ) { |
1048 | ) { |
1032 | |
1049 | |
1033 | /* |
1050 | /* |
1034 | * Don't insert a part that is already there. |
1051 | * Don't insert a part that is already there. |
1035 | * |
1052 | * |
1036 | * Also don't add a part beyond the "end" marker (unless we |
1053 | * Also don't add a part beyond the "end" marker (unless we |
… | |
… | |
1055 | /* |
1072 | /* |
1056 | * special case when we might have tagged a part as Base64 when the |
1073 | * special case when we might have tagged a part as Base64 when the |
1057 | * file was really XX |
1074 | * file was really XX |
1058 | */ |
1075 | */ |
1059 | |
1076 | |
1060 | if (data->data->uudet == B64ENCODED && |
1077 | if (data_data->uudet == B64ENCODED && |
1061 | iter->uudet == XX_ENCODED && iter->begin) { |
1078 | iter->uudet == XX_ENCODED && iter->begin) { |
1062 | data->data->uudet = XX_ENCODED; |
1079 | data_data->uudet = XX_ENCODED; |
1063 | } |
1080 | } |
1064 | else if (data->data->uudet == XX_ENCODED && data->data->begin && |
1081 | else if (data_data->uudet == XX_ENCODED && data_data->begin && |
1065 | iter->uudet == B64ENCODED) { |
1082 | iter->uudet == B64ENCODED) { |
1066 | iter->uudet = XX_ENCODED; |
1083 | iter->uudet = XX_ENCODED; |
1067 | |
1084 | |
1068 | fiter = iter->thisfile; |
1085 | fiter = iter->thisfile; |
1069 | while (fiter) { |
1086 | while (fiter) { |
… | |
… | |
1074 | |
1091 | |
1075 | /* |
1092 | /* |
1076 | * If this is from a Message/Partial, we believe only the |
1093 | * If this is from a Message/Partial, we believe only the |
1077 | * iter->uudet from the first part |
1094 | * iter->uudet from the first part |
1078 | */ |
1095 | */ |
1079 | if (data->data->flags & FL_PARTIAL) { |
1096 | if (data_data->flags & FL_PARTIAL) { |
1080 | if (data->partno == 1) { |
1097 | if (data->partno == 1) { |
1081 | iter->uudet = data->data->uudet; |
1098 | iter->uudet = data_data->uudet; |
1082 | iter->flags = data->data->flags; |
1099 | iter->flags = data_data->flags; |
1083 | } |
1100 | } |
1084 | } |
1101 | } |
1085 | else { |
1102 | else { |
1086 | if (data->data->uudet) iter->uudet = data->data->uudet; |
1103 | if (data_data->uudet) iter->uudet = data_data->uudet; |
1087 | if (data->data->flags) iter->flags = data->data->flags; |
1104 | if (data_data->flags) iter->flags = data_data->flags; |
1088 | } |
1105 | } |
1089 | |
1106 | |
1090 | if (iter->mode == 0 && data->data->mode != 0) |
1107 | if (iter->mode == 0 && data_data->mode != 0) |
1091 | iter->mode = data->data->mode; |
1108 | iter->mode = data_data->mode; |
|
|
1109 | |
1092 | if (data->data->begin) iter->begin = (data->partno)?data->partno:1; |
1110 | if (data_data->begin) iter->begin = data->partno ? data->partno : 1; |
1093 | if (data->data->end) iter->end = (data->partno)?data->partno:1; |
1111 | if (data_data->end) iter->end = data->partno ? data->partno : 1; |
1094 | |
1112 | |
1095 | if (data->mimetype) { |
1113 | if (data->mimetype) { |
1096 | FP_free (iter->mimetype); |
1114 | FP_free (iter->mimetype); |
1097 | iter->mimetype = FP_strdup (data->mimetype); |
1115 | iter->mimetype = FP_strdup (data->mimetype); |
1098 | } |
1116 | } |
… | |
… | |
1122 | */ |
1140 | */ |
1123 | if (data->partno == fiter->partno) { |
1141 | if (data->partno == fiter->partno) { |
1124 | if (fiter->data->subject == NULL) |
1142 | if (fiter->data->subject == NULL) |
1125 | return UURET_NODATA; |
1143 | return UURET_NODATA; |
1126 | else if (FP_stristr (fiter->data->subject, "repost") != NULL && |
1144 | else if (FP_stristr (fiter->data->subject, "repost") != NULL && |
1127 | FP_stristr (data->data->subject, "repost") == NULL) |
1145 | FP_stristr (data_data->subject, "repost") == NULL) |
1128 | return UURET_NODATA; |
1146 | return UURET_NODATA; |
1129 | else if (fiter->data->uudet && !data->data->uudet) |
1147 | else if (fiter->data->uudet && !data_data->uudet) |
1130 | return UURET_NODATA; |
1148 | return UURET_NODATA; |
1131 | else { |
1149 | else { |
1132 | /* |
1150 | /* |
1133 | * replace |
1151 | * replace |
1134 | */ |
1152 | */ |
… | |
… | |
1164 | fiter = fiter->NEXT; |
1182 | fiter = fiter->NEXT; |
1165 | } |
1183 | } |
1166 | |
1184 | |
1167 | return UURET_OK; /* Shouldn't get here */ |
1185 | return UURET_OK; /* Shouldn't get here */ |
1168 | } |
1186 | } |
|
|
1187 | |
1169 | goahead: |
1188 | goahead: |
1170 | /* |
1189 | iter = iter->NEXT; |
1171 | * we need iter below |
1190 | |
1172 | */ |
1191 | if (!iter) |
1173 | if (iter->NEXT == NULL) |
|
|
1174 | break; |
1192 | break; |
1175 | |
|
|
1176 | iter = iter->NEXT; |
|
|
1177 | } |
1193 | } |
|
|
1194 | |
|
|
1195 | newpart: |
1178 | /* |
1196 | /* |
1179 | * handle new entry |
1197 | * handle new entry |
1180 | */ |
1198 | */ |
1181 | |
1199 | |
1182 | if (data->partno == -1) { |
1200 | if (data->partno == -1) { |
… | |
… | |
1184 | * if it's got no part no, and it's MIME mail, then assume this is |
1202 | * if it's got no part no, and it's MIME mail, then assume this is |
1185 | * part no. 1. If it's not MIME, then we can't handle it; if it |
1203 | * part no. 1. If it's not MIME, then we can't handle it; if it |
1186 | * had a 'begin', it'd have got a part number assigned by |
1204 | * had a 'begin', it'd have got a part number assigned by |
1187 | * UUPreProcessPart(). |
1205 | * UUPreProcessPart(). |
1188 | */ |
1206 | */ |
1189 | if (data->data->uudet == B64ENCODED || data->data->uudet == BH_ENCODED) |
1207 | if (data_data->uudet == B64ENCODED || data_data->uudet == BH_ENCODED) |
1190 | data->partno = 1; |
1208 | data->partno = 1; |
1191 | else |
1209 | else |
1192 | return UURET_NODATA; |
1210 | return UURET_NODATA; |
1193 | } |
1211 | } |
1194 | |
1212 | |
1195 | if ((unew = (uulist *) malloc (sizeof (uulist))) == NULL) { |
1213 | if ((unew = (uulist *)malloc (sizeof (uulist))) == NULL) { |
1196 | return UURET_NOMEM; |
1214 | return UURET_NOMEM; |
1197 | } |
1215 | } |
1198 | |
1216 | |
1199 | { |
1217 | { |
1200 | const uulist uulist_new = { 0 }; |
1218 | const uulist uulist_new = { 0 }; |
… | |
… | |
1204 | if ((unew->subfname = FP_strdup (data->subfname)) == NULL) { |
1222 | if ((unew->subfname = FP_strdup (data->subfname)) == NULL) { |
1205 | FP_free (unew); |
1223 | FP_free (unew); |
1206 | return UURET_NOMEM; |
1224 | return UURET_NOMEM; |
1207 | } |
1225 | } |
1208 | |
1226 | |
|
|
1227 | unew->filename_hash = filename_hash; |
1209 | if (data->filename != NULL) { |
1228 | if (data->filename != NULL) { |
1210 | if ((unew->filename = FP_strdup (data->filename)) == NULL) { |
1229 | if ((unew->filename = FP_strdup (data->filename)) == NULL) { |
1211 | FP_free (unew->subfname); |
1230 | FP_free (unew->subfname); |
1212 | FP_free (unew); |
1231 | FP_free (unew); |
1213 | return UURET_NOMEM; |
1232 | return UURET_NOMEM; |
1214 | } |
1233 | } |
1215 | } |
1234 | } |
1216 | else |
1235 | else |
1217 | unew->filename = NULL; |
1236 | unew->filename = NULL; |
1218 | |
1237 | |
|
|
1238 | unew->mimeid_hash = mimeid_hash; |
1219 | if (data->mimeid != NULL) { |
1239 | if (data->mimeid != NULL) { |
1220 | if ((unew->mimeid = FP_strdup (data->mimeid)) == NULL) { |
1240 | if ((unew->mimeid = FP_strdup (data->mimeid)) == NULL) { |
1221 | FP_free (unew->subfname); |
1241 | FP_free (unew->subfname); |
1222 | FP_free (unew->filename); |
1242 | FP_free (unew->filename); |
1223 | FP_free (unew); |
1243 | FP_free (unew); |
… | |
… | |
1239 | else |
1259 | else |
1240 | unew->mimetype = NULL; |
1260 | unew->mimetype = NULL; |
1241 | |
1261 | |
1242 | unew->state = UUFILE_READ; |
1262 | unew->state = UUFILE_READ; |
1243 | unew->thisfile = data; |
1263 | unew->thisfile = data; |
1244 | unew->mode = data->data->mode; |
1264 | unew->mode = data_data->mode; |
1245 | unew->uudet = data->data->uudet; |
1265 | unew->uudet = data_data->uudet; |
1246 | unew->flags = data->data->flags; |
1266 | unew->flags = data_data->flags; |
1247 | unew->begin = data->data->begin ? (data->partno ? data->partno : 1) : 0; |
1267 | unew->begin = data_data->begin ? (data->partno ? data->partno : 1) : 0; |
1248 | unew->end = data->data->end ? (data->partno ? data->partno : 1) : 0; |
1268 | unew->end = data_data->end ? (data->partno ? data->partno : 1) : 0; |
1249 | |
1269 | |
1250 | /* insert at the beginning, as parts often show up in bursts */ |
1270 | /* insert at the beginning, as parts often show up in bursts */ |
1251 | unew->NEXT = UUGlobalFileList; |
1271 | unew->NEXT = UUGlobalFileList; |
1252 | UUGlobalFileList = unew; |
1272 | UUGlobalFileList = unew; |
1253 | |
1273 | |