Browse code

Add support for MacOffice98 documents

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@405 77e5149b-7576-45b1-b177-96237e5ba77b

Trog authored on 2004/03/17 18:26:29
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Mar 17 09:32:45 GMT 2004 (trog)
2
+-----------------------------------
3
+  * libclamav/vba_extract.c: Add support for MacOffice98 documents
4
+
1 5
 Tue Mar 16 20:43:20 CET 2004 (tk)
2 6
 ---------------------------------
3 7
   * libclamav: unrarlib: don't use UnstoreFile() because it causes memory
... ...
@@ -47,24 +47,41 @@ typedef struct vba_version_tag {
47 47
 } vba_version_t;
48 48
 
49 49
 
50
+uint16_t vba_endian_convert_16(uint16_t value, int is_mac)
51
+{
52
+        if (is_mac) {
50 53
 #if WORDS_BIGENDIAN == 0
51
-#define vba_endian_convert_16(v)       (v)
54
+                return ((value >> 8) + (value << 8));;
52 55
 #else
53
-static uint16_t vba_endian_convert_16(uint16_t v)
54
-{
55
-        return ((v >> 8) + (v << 8));
56
-}
56
+                return value;
57 57
 #endif
58
- 
58
+        } else {
59 59
 #if WORDS_BIGENDIAN == 0
60
-#define vba_endian_convert_32(v)    (v)
60
+                return value;
61 61
 #else
62
-static uint32_t vba_endian_convert_32(uint32_t v)
63
-{
64
-        return ((v >> 24) | ((v & 0x00FF0000) >> 8) |
65
-                ((v & 0x0000FF00) << 8) | (v << 24));
62
+                return ((value >> 8) + (value << 8));
63
+#endif
64
+        }
66 65
 }
66
+ 
67
+uint32_t vba_endian_convert_32(uint32_t value, int is_mac)
68
+{
69
+        if (is_mac) {
70
+#if WORDS_BIGENDIAN == 0
71
+                return ((value >> 24) | ((value & 0x00FF0000) >> 8) |
72
+                ((value & 0x0000FF00) << 8) | (value << 24));
73
+#else
74
+                return value;
67 75
 #endif
76
+        } else {
77
+#if WORDS_BIGENDIAN == 0
78
+                return value;
79
+#else
80
+                return ((value >> 24) | ((value & 0x00FF0000) >> 8) |
81
+                        ((value & 0x0000FF00) << 8) | (value << 24));
82
+#endif
83
+        }
84
+}
68 85
 
69 86
 typedef struct byte_array_tag {
70 87
 	unsigned int length;
... ...
@@ -144,12 +161,12 @@ int vba_writen(int fd, void *buff, unsigned int count)
144 144
         return count;
145 145
 }
146 146
 
147
-char *get_unicode_name(char *name, int size)
147
+char *get_unicode_name(char *name, int size, int is_mac)
148 148
 {
149 149
         int i, j;
150 150
         char *newname;
151 151
 
152
-	 if (*name == 0 || size == 0) {
152
+	 if (*name == 0 || size <= 0) {
153 153
                 return NULL;
154 154
         }
155 155
 
... ...
@@ -158,7 +175,7 @@ char *get_unicode_name(char *name, int size)
158 158
                 return NULL;
159 159
         }
160 160
         j=0;
161
-        for (i=0 ; i < size; i+=2) {
161
+        for (i=0 ; i < size; i += (is_mac ? 1 : 2) ) {
162 162
                 if (isprint(name[i])) {
163 163
                         newname[j++] = name[i];
164 164
                 } else {
... ...
@@ -208,7 +225,7 @@ static void vba56_test_end(int fd)
208 208
 
209 209
         if (memcmp(test_end, end_str, 20) != 0) {
210 210
                 lseek(fd, -20, SEEK_CUR);
211
-        }
211
+	}
212 212
         return;
213 213
 }
214 214
 
... ...
@@ -219,7 +236,7 @@ vba_project_t *vba56_dir_read(const char *dir)
219 219
 	unsigned char version[4];
220 220
 	unsigned char *buff, *name;
221 221
         unsigned char vba56_signature[] = { 0xcc, 0x61 };
222
-	int16_t record_count, length;
222
+	uint16_t record_count, length;
223 223
 	uint16_t ooff;
224 224
 	uint8_t byte_count;
225 225
 	uint32_t offset;
... ...
@@ -232,7 +249,7 @@ vba_project_t *vba56_dir_read(const char *dir)
232 232
 	uint16_t LenB;
233 233
 	uint16_t LenC;
234 234
 	uint16_t LenD;
235
-	int i, j, fd;
235
+	int i, j, fd, is_mac;
236 236
 	vba_project_t *vba_project;
237 237
 	char *fullname;
238 238
 
... ...
@@ -280,6 +297,12 @@ vba_project_t *vba56_dir_read(const char *dir)
280 280
 	cli_dbgmsg("VBA Project: %s, VBA Version=%d\n", vba_version[i].name,
281 281
 				vba_version[i].vba_version);
282 282
 
283
+	if (i == 9) {
284
+		cli_dbgmsg("MacOffice2001 not currently supported\n");
285
+		close(fd);
286
+		return NULL;
287
+	}
288
+	is_mac = vba_version[i].is_mac;
283 289
 
284 290
 	/*****************************************/
285 291
 
... ...
@@ -330,13 +353,13 @@ vba_project_t *vba56_dir_read(const char *dir)
330 330
 		return NULL;
331 331
 	}
332 332
 
333
-        LidA = vba_endian_convert_32(LidA);
334
-        LidB = vba_endian_convert_32(LidB);
335
-        CharSet = vba_endian_convert_16(CharSet);
336
-        LenA = vba_endian_convert_16(LenA);
337
-        LenB = vba_endian_convert_16(LenB);
338
-        LenC = vba_endian_convert_16(LenC);
339
-        LenD = vba_endian_convert_16(LenD);
333
+        LidA = vba_endian_convert_32(LidA, is_mac);
334
+        LidB = vba_endian_convert_32(LidB, is_mac);
335
+        CharSet = vba_endian_convert_16(CharSet, is_mac);
336
+        LenA = vba_endian_convert_16(LenA, is_mac);
337
+        LenB = vba_endian_convert_16(LenB, is_mac);
338
+        LenC = vba_endian_convert_16(LenC, is_mac);
339
+        LenD = vba_endian_convert_16(LenD, is_mac);
340 340
 
341 341
 	cli_dbgmsg(" LidA: %d\n LidB: %d\n CharSet: %d\n", LidA, LidB, CharSet);
342 342
 	cli_dbgmsg(" LenA: %d\n UnknownB: %d\n UnknownC: %d\n", LenA, UnknownB, UnknownC);
... ...
@@ -370,7 +393,7 @@ vba_project_t *vba56_dir_read(const char *dir)
370 370
 		if (vba_readn(fd, &length, 2) != 2) {
371 371
 			return NULL;
372 372
 		}
373
-		length = vba_endian_convert_16(length);
373
+		length = vba_endian_convert_16(length, is_mac);
374 374
 		if (length < 6) {
375 375
 			lseek(fd, -2, SEEK_CUR);
376 376
 			break;
... ...
@@ -387,7 +410,7 @@ vba_project_t *vba56_dir_read(const char *dir)
387 387
 			close(fd);
388 388
 			return NULL;
389 389
 		}
390
-		name = get_unicode_name(buff, length);
390
+		name = get_unicode_name(buff, length, is_mac);
391 391
 		cli_dbgmsg("name: %s\n", name);
392 392
 		free(buff);
393 393
 
... ...
@@ -395,7 +418,7 @@ vba_project_t *vba56_dir_read(const char *dir)
395 395
 		   Type 'C' entries come in pairs, the second also
396 396
 		   having a 12 byte trailer */
397 397
 		/* TODO: Need to check if types H(same as G) and D(same as C) exist */
398
-                if (!strncmp ("*\\G", name, 3)) {
398
+                if (!strncmp ("*\\G", name, 3) || !strncmp ("*\\H", name, 3)) {
399 399
 			buff = (unsigned char *) cli_malloc(12);
400 400
                         if (vba_readn(fd, buff, 12) != 12) {
401 401
 				cli_errmsg("failed to read blob\n");
... ...
@@ -405,7 +428,7 @@ vba_project_t *vba56_dir_read(const char *dir)
405 405
 				return NULL;
406 406
                         }
407 407
 			free(buff);
408
-                } else if (!strncmp("*\\C", name, 3)) {
408
+                } else if (!strncmp("*\\C", name, 3) || !strncmp("*\\D", name, 3)) {
409 409
 			if (i == 1) {
410 410
 				buff = (unsigned char *) cli_malloc(12);
411 411
                         	if (vba_readn(fd, buff, 12) != 12) {
... ...
@@ -438,7 +461,7 @@ vba_project_t *vba56_dir_read(const char *dir)
438 438
 		close(fd);
439 439
 		return NULL;
440 440
 	}
441
-	record_count = vba_endian_convert_16(record_count);
441
+	record_count = vba_endian_convert_16(record_count, is_mac);
442 442
 	cli_dbgmsg("\nVBA Record count: %d\n", record_count);
443 443
 	/*if (record_count <= 0) {
444 444
 		close(fd);
... ...
@@ -482,7 +505,7 @@ vba_project_t *vba56_dir_read(const char *dir)
482 482
 
483 483
 	/* no idea what this stuff is */
484 484
 	if (ooff != 0xFFFF) {
485
-		ooff = vba_endian_convert_16(ooff);
485
+		ooff = vba_endian_convert_16(ooff, is_mac);
486 486
 		lseek(fd, ooff, SEEK_CUR);
487 487
 	}
488 488
 	if (vba_readn(fd, &ooff, 2) != 2) {
... ...
@@ -490,7 +513,7 @@ vba_project_t *vba56_dir_read(const char *dir)
490 490
 		return NULL;
491 491
 	}
492 492
 	if (ooff != 0xFFFF) {
493
-		ooff = vba_endian_convert_16(ooff);
493
+		ooff = vba_endian_convert_16(ooff, is_mac);
494 494
 		lseek(fd, ooff, SEEK_CUR);
495 495
 	}
496 496
 	lseek(fd, 100, SEEK_CUR);
... ...
@@ -499,7 +522,7 @@ vba_project_t *vba56_dir_read(const char *dir)
499 499
 		close(fd);
500 500
 		return NULL;
501 501
 	}
502
-	record_count = vba_endian_convert_16(record_count);
502
+	record_count = vba_endian_convert_16(record_count, is_mac);
503 503
 	cli_dbgmsg("\nVBA Record count: %d\n", record_count);
504 504
 	
505 505
 	vba_project = (vba_project_t *) cli_malloc(sizeof(struct vba_project_tag));
... ...
@@ -512,7 +535,7 @@ vba_project_t *vba56_dir_read(const char *dir)
512 512
 		if (vba_readn(fd, &length, 2) != 2) {
513 513
 			goto out_error;
514 514
 		}
515
-		length = vba_endian_convert_16(length);
515
+		length = vba_endian_convert_16(length, is_mac);
516 516
 		buff = (unsigned char *) cli_malloc(length);
517 517
 		if (!buff) {
518 518
 			cli_dbgmsg("cli_malloc failed\n");
... ...
@@ -523,7 +546,7 @@ vba_project_t *vba56_dir_read(const char *dir)
523 523
 			free(buff);
524 524
 			goto out_error;
525 525
 		}
526
-		vba_project->name[i] = get_unicode_name(buff, length);
526
+		vba_project->name[i] = get_unicode_name(buff, length, is_mac);
527 527
 		cli_dbgmsg("project name: %s, ", vba_project->name[i]);
528 528
 		free(buff);
529 529
 
... ...
@@ -532,7 +555,7 @@ vba_project_t *vba56_dir_read(const char *dir)
532 532
 			free(vba_project->name[i]);
533 533
 			goto out_error;
534 534
 		}
535
-		length = vba_endian_convert_16(length);
535
+		length = vba_endian_convert_16(length, is_mac);
536 536
 		lseek(fd, length, SEEK_CUR);
537 537
 
538 538
 		/* unknown stuff */
... ...
@@ -540,14 +563,14 @@ vba_project_t *vba56_dir_read(const char *dir)
540 540
 			free(vba_project->name[i]);
541 541
 			goto out_error;
542 542
 		}
543
-		ooff = vba_endian_convert_16(ooff);
543
+		ooff = vba_endian_convert_16(ooff, is_mac);
544 544
 		if (ooff == 0xFFFF) {
545 545
 			lseek(fd, 2, SEEK_CUR);
546 546
 			if (vba_readn(fd, &ooff, 2) != 2) {
547 547
 				free(vba_project->name[i]);
548 548
 				goto out_error;
549 549
 			}
550
-			ooff = vba_endian_convert_16(ooff);
550
+			ooff = vba_endian_convert_16(ooff, is_mac);
551 551
 			lseek(fd, ooff, SEEK_CUR);
552 552
 		} else {
553 553
 			lseek(fd, 2 + ooff, SEEK_CUR);
... ...
@@ -566,7 +589,7 @@ vba_project_t *vba56_dir_read(const char *dir)
566 566
 			free(vba_project->name[i]);
567 567
 			goto out_error;
568 568
 		}
569
-		offset = vba_endian_convert_32(offset);
569
+		offset = vba_endian_convert_32(offset, is_mac);
570 570
 		vba_project->offset[i] = offset;
571 571
 		cli_dbgmsg("offset:%d\n", offset);
572 572
 		lseek(fd, 2, SEEK_CUR);
... ...
@@ -637,7 +660,7 @@ unsigned char *vba_decompress(int fd, uint32_t offset, int *size)
637 637
 					}
638 638
 					return NULL;
639 639
 				}
640
-				token = vba_endian_convert_16(token);
640
+				token = vba_endian_convert_16(token, FALSE);
641 641
 				win_pos = pos % VBA_COMPRESSION_WINDOW;
642 642
 				if (win_pos <= 0x80) {
643 643
 					if (win_pos <= 0x20) {