1174
1042
cli_dbgmsg("messageExport: numberOfEncTypes == %d\n", m->numberOfEncTypes);
1044
if((t_line = binhexBegin(m)) != NULL) {
1046
unsigned long newlen = 0L, len, dataforklen, resourceforklen, l;
1047
unsigned char *data;
1053
* Table look up by Thomas Lamy <Thomas.Lamy@in-online.net>
1054
* HQX conversion table - illegal chars are 0xff
1056
const unsigned char hqxtbl[] = {
1057
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */
1058
/* 00-0f */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1059
/* 10-1f */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1060
/* 20-2f */ 0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0xff,0xff,
1061
/* 30-3f */ 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0xff,0x14,0x15,0xff,0xff,0xff,0xff,0xff,0xff,
1062
/* 40-4f */ 0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0xff,
1063
/* 50-5f */ 0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0xff,0x2c,0x2d,0x2e,0x2f,0xff,0xff,0xff,0xff,
1064
/* 60-6f */ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0xff,0x37,0x38,0x39,0x3a,0x3b,0x3c,0xff,0xff,
1065
/* 70-7f */ 0x3d,0x3e,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
1068
cli_dbgmsg("messageExport: decode binhex\n");
1070
* Decode BinHex4. First create a temporary blob which contains
1071
* the encoded message. Then decode that blob to the target
1072
* blob, free the temporary blob and return the target one
1074
* FIXME: EICAR isn't detected: should create 3 files in fork
1075
* format: .info, .data and .rsrc. This is needed for
1076
* position dependant detection such as EICAR
1080
while(((t_line = t_line->t_next) != NULL) &&
1081
(t_line->t_line == NULL))
1084
tmp = textToBlob(t_line, NULL,
1085
((m->numberOfEncTypes == 1) && (m->encodingTypes[0] == BINHEX)) ? destroy_text : 0);
1089
* FIXME: We've probably run out of memory during the
1091
* TODO: if m->numberOfEncTypes == 1 we could delete
1092
* the text object as we decode it
1094
cli_warnmsg("Couldn't start binhex parser\n");
1099
data = blobGetData(tmp);
1102
cli_warnmsg("Couldn't locate the binhex message that was claimed to be there\n");
1107
len = blobGetDataSize(tmp);
1109
if(data[0] == ':') {
1110
unsigned char *uptr;
1111
/* 7 bit (ala RFC1741) */
1114
* FIXME: this is dirty code, modification of the
1115
* contents of a member of the blob object should be
1116
* done through blob.c
1118
* Convert 7 bit data into 8 bit
1120
cli_dbgmsg("decode HQX7 message (%lu bytes)\n", len);
1122
uptr = cli_malloc(len);
1128
memcpy(uptr, data, len);
1132
* uptr now contains the encoded (7bit) data - len bytes long
1133
* data will contain the unencoded (8bit) data
1135
for(l = 1; l < len; l++) {
1136
unsigned char c = uptr[l];
1141
if((c == '\n') || (c == '\r'))
1144
if((c < 0x20) || (c > 0x7f) || (hqxtbl[c] == 0xff)) {
1145
cli_warnmsg("Invalid HQX7 character '%c' (0x%02x)\n", c, c);
1152
* These masks probably aren't needed, but
1153
* they're here to verify the code is correct
1155
switch(bytenumber) {
1157
data[newlen] = (c << 2) & 0xFC;
1161
data[newlen++] |= (c >> 4) & 0x3;
1162
data[newlen] = (c << 4) & 0xF0;
1166
data[newlen++] |= (c >> 2) & 0xF;
1167
data[newlen] = (c << 6) & 0xC0;
1171
data[newlen++] |= c & 0x3F;
1177
cli_dbgmsg("decoded HQX7 message (now %lu bytes)\n", newlen);
1180
* Throw away the old encoded (7bit) data
1181
* data now points to the encoded (8bit) data - newlen bytes
1183
* The data array may contain repetitive characters
1187
cli_warnmsg("HQX8 messages not yet supported - if you believe this file contains a virus, submit it to www.clamav.net\n");
1192
* Uncompress repetitive characters
1194
if(memchr(data, 0x90, newlen)) {
1195
blob *u = blobCreate(); /* uncompressed data */
1203
* Includes compression
1205
for(l = 0L; l < newlen; l++) {
1206
unsigned char c = data[l];
1209
* TODO: handle the case where the first byte
1212
blobAddData(u, &c, 1);
1214
if((l < (newlen - 1L)) && (data[l + 1] == 0x90)) {
1222
blobAddData(u, &c, 1);
1225
cli_dbgmsg("uncompress HQX7 at 0x%06lu: %d repetitive bytes\n", l, count);
1229
blobAddData(u, &c, 1);
1235
data = blobGetData(tmp);
1236
len = blobGetDataSize(tmp);
1237
cli_dbgmsg("Uncompressed %lu bytes to %lu\n", newlen, len);
1240
cli_dbgmsg("HQX7 message (%lu bytes) is not compressed\n",
1244
cli_warnmsg("Discarding empty binHex attachment\n");
1251
* The blob tmp now contains the uncompressed data
1252
* of len bytes, i.e. the repetitive bytes have been removed
1258
* TODO: set filename argument in message as well
1266
filename = cli_malloc(byte + 1);
1267
if(filename == NULL) {
1272
memcpy(filename, &data[1], byte);
1273
filename[byte] = '\0';
1274
(*setFilename)(ret, dir, filename);
1275
/*ptr = cli_malloc(strlen(filename) + 6);*/
1276
ptr = cli_malloc(byte + 6);
1278
sprintf(ptr, "name=%s", filename);
1279
messageAddArgument(m, ptr);
1284
* skip over length, filename, version, type, creator and flags
1286
byte = 1 + byte + 1 + 4 + 4 + 2;
1289
* Set len to be the data fork length
1291
dataforklen = ((data[byte] << 24) & 0xFF000000) |
1292
((data[byte + 1] << 16) & 0xFF0000) |
1293
((data[byte + 2] << 8) & 0xFF00) |
1294
(data[byte + 3] & 0xFF);
1296
resourceforklen = ((data[byte + 4] << 24) & 0xFF000000) |
1297
((data[byte + 5] << 16) & 0xFF0000) |
1298
((data[byte + 6] << 8) & 0xFF00) |
1299
(data[byte + 7] & 0xFF);
1301
cli_dbgmsg("Filename = '%s', data fork length = %lu, resource fork length = %lu bytes\n",
1302
filename, dataforklen, resourceforklen);
1304
free((char *)filename);
1307
* Skip over data fork length, resource fork length and CRC
1311
l = blobGetDataSize(tmp) - byte;
1313
if(l < dataforklen) {
1314
cli_warnmsg("Corrupt BinHex file, claims it is %lu bytes long in a message of %lu bytes\n",
1318
if(setCTX && m->ctx)
1319
(*setCTX)(ret, m->ctx);
1321
(*addData)(ret, &data[byte], dataforklen);
1328
if((m->numberOfEncTypes == 0) ||
1329
((m->numberOfEncTypes == 1) && (m->encodingTypes[0] == BINHEX))) {
1330
cli_dbgmsg("Finished exporting binhex file\n");
1176
1335
if(m->numberOfEncTypes == 0) {
1180
1339
cli_dbgmsg("messageExport: Entering fast copy mode\n");
1183
filename = messageGetFilename(m);
1185
if(filename == NULL) {
1186
cli_dbgmsg("Unencoded attachment sent with no filename\n");
1187
messageAddArgument(m, "name=attachment");
1188
} else if((strcmp(filename, "textportion") != 0) && (strcmp(filename, "mixedtextportion") != 0))
1190
* Some virus attachments don't say how they've
1191
* been encoded. We assume base64
1193
messageSetEncoding(m, "base64");
1195
1341
filename = (char *)messageFindArgument(m, "filename");
1196
1342
if(filename == NULL) {
1197
1343
filename = (char *)messageFindArgument(m, "name");