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... | ... |
@@ -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) { |