git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@178 77e5149b-7576-45b1-b177-96237e5ba77b
Nigel Horne authored on 2004/01/10 03:02:32... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Fri Jan 9 18:01:28 GMT 2004 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav: Started handling BinHex code. For now only works with |
|
4 |
+ "inline" messages where the BinHex is in the main body of the plain |
|
5 |
+ text portion. |
|
6 |
+ |
|
1 | 7 |
Fri Jan 9 15:08:01 GMT 2004 (njh) |
2 | 8 |
---------------------------------- |
3 | 9 |
* libclamav: Re-engineered handling of |
... | ... |
@@ -17,6 +17,9 @@ |
17 | 17 |
* |
18 | 18 |
* Change History: |
19 | 19 |
* $Log: message.c,v $ |
20 |
+ * Revision 1.13 2004/01/09 18:01:03 nigelhorne |
|
21 |
+ * Started BinHex work |
|
22 |
+ * |
|
20 | 23 |
* Revision 1.12 2003/12/05 09:34:00 nigelhorne |
21 | 24 |
* Use cli_tok instead of strtok - replaced now by cli_strtok |
22 | 25 |
* |
... | ... |
@@ -33,7 +36,7 @@ |
33 | 33 |
* uuencodebegin() no longer static |
34 | 34 |
* |
35 | 35 |
*/ |
36 |
-static char const rcsid[] = "$Id: message.c,v 1.12 2003/12/05 09:34:00 nigelhorne Exp $"; |
|
36 |
+static char const rcsid[] = "$Id: message.c,v 1.13 2004/01/09 18:01:03 nigelhorne Exp $"; |
|
37 | 37 |
|
38 | 38 |
#ifndef CL_DEBUG |
39 | 39 |
/*#define NDEBUG /* map CLAMAV debug onto standard */ |
... | ... |
@@ -604,6 +607,119 @@ messageToBlob(const message *m) |
604 | 604 |
|
605 | 605 |
blobSetFilename(b, filename); |
606 | 606 |
t_line = t_line->t_next; |
607 |
+ } else if((t_line = binhexBegin(m)) != NULL) { |
|
608 |
+ blob *tmp = blobCreate(); |
|
609 |
+ unsigned char *data; |
|
610 |
+ unsigned char byte; |
|
611 |
+ unsigned long len; |
|
612 |
+ char *filename; |
|
613 |
+ |
|
614 |
+ /* |
|
615 |
+ * Decode BinHex4. First create a temporary blob which contains |
|
616 |
+ * the encoded message. Then decode that blob to the target |
|
617 |
+ * blob, free the temporary blob adn return the target one |
|
618 |
+ */ |
|
619 |
+ |
|
620 |
+ while((t_line = t_line->t_next) != NULL) { |
|
621 |
+ blobAddData(tmp, (unsigned char *)t_line->t_text, strlen(t_line->t_text)); |
|
622 |
+ blobAddData(tmp, (unsigned char *)"\n", 1); |
|
623 |
+ } |
|
624 |
+ |
|
625 |
+ data = blobGetData(tmp); |
|
626 |
+ len = blobGetDataSize(tmp); |
|
627 |
+ |
|
628 |
+ if(data[0] == ':') { |
|
629 |
+ char *ptr; |
|
630 |
+ unsigned long i; |
|
631 |
+ unsigned long newlen = 0L; |
|
632 |
+ int bytenumber = 0; |
|
633 |
+ |
|
634 |
+ /* |
|
635 |
+ * Convert 7 bit data into 8 bit |
|
636 |
+ */ |
|
637 |
+ cli_dbgmsg("decode HQX7 message"); |
|
638 |
+ |
|
639 |
+ ptr = cli_malloc(len); |
|
640 |
+ memcpy(ptr, data, len); |
|
641 |
+ |
|
642 |
+ for(i = 1; i < len; i++) { |
|
643 |
+ unsigned char c = ptr[i]; |
|
644 |
+ char *tptr; |
|
645 |
+ |
|
646 |
+ /* TODO: table look up would be quicker */ |
|
647 |
+ const char table[] = |
|
648 |
+ "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; |
|
649 |
+ |
|
650 |
+ if((c == '\n') || (c == '\r')) |
|
651 |
+ continue; |
|
652 |
+ if(c == ':') |
|
653 |
+ break; |
|
654 |
+ /* |
|
655 |
+ * TODO: at least post a sentinal! |
|
656 |
+ */ |
|
657 |
+ for(tptr = table; (*tptr != c) && (*tptr != '\0'); tptr++) |
|
658 |
+ ; |
|
659 |
+ if(*tptr == '\0') { |
|
660 |
+ cli_warnmsg("Invalid HQX7 character '%c'\n", c); |
|
661 |
+ break; |
|
662 |
+ } |
|
663 |
+ c = (unsigned char)(tptr - table); |
|
664 |
+ assert(c <= 63); |
|
665 |
+ |
|
666 |
+ /* |
|
667 |
+ * These masks probably aren't needed, but |
|
668 |
+ * they're here to verify the code is correct |
|
669 |
+ */ |
|
670 |
+ switch(bytenumber) { |
|
671 |
+ case 0: |
|
672 |
+ data[newlen] = (c << 2) & 0xFC; |
|
673 |
+ bytenumber = 1; |
|
674 |
+ break; |
|
675 |
+ case 1: |
|
676 |
+ data[newlen++] |= (c >> 4) & 0x3; |
|
677 |
+ data[newlen] = (c << 4) & 0xF0; |
|
678 |
+ bytenumber = 2; |
|
679 |
+ break; |
|
680 |
+ case 2: |
|
681 |
+ data[newlen++] |= (c >> 2) & 0xF; |
|
682 |
+ data[newlen] = (c << 6) & 0xC0; |
|
683 |
+ bytenumber = 3; |
|
684 |
+ break; |
|
685 |
+ case 3: |
|
686 |
+ data[newlen++] |= c & 0x3F; |
|
687 |
+ bytenumber = 0; |
|
688 |
+ break; |
|
689 |
+ } |
|
690 |
+ } |
|
691 |
+ free(ptr); |
|
692 |
+ } |
|
693 |
+ |
|
694 |
+ /* |
|
695 |
+ * TODO: set filename argument in message as well |
|
696 |
+ */ |
|
697 |
+ byte = data[0]; |
|
698 |
+ filename = cli_malloc(byte + 1); |
|
699 |
+ memcpy(filename, &data[1], byte + 1); |
|
700 |
+ filename[byte] = '\0'; |
|
701 |
+ blobSetFilename(b, filename); |
|
702 |
+ free((char *)filename); |
|
703 |
+ |
|
704 |
+ /* |
|
705 |
+ * skip over length, filename, version, type, creator and flags |
|
706 |
+ */ |
|
707 |
+ byte = 1 + byte + 1 + 4 + 4 + 2; |
|
708 |
+ len = (data[byte] << 24) + (data[byte + 1] << 16) + (data[byte + 2] << 8) + data[byte + 3]; |
|
709 |
+ |
|
710 |
+ /* |
|
711 |
+ * Skip over data fork length, resource fork length and CRC |
|
712 |
+ */ |
|
713 |
+ byte += 10; |
|
714 |
+ |
|
715 |
+ blobAddData(b, &data[byte], len); |
|
716 |
+ |
|
717 |
+ blobDestroy(tmp); |
|
718 |
+ |
|
719 |
+ return b; |
|
607 | 720 |
} else { |
608 | 721 |
/* |
609 | 722 |
* Discard attachments with no filename |
... | ... |
@@ -719,8 +835,13 @@ messageToText(const message *m) |
719 | 719 |
return NULL; |
720 | 720 |
} |
721 | 721 |
t_line = t_line->t_next; |
722 |
- } else |
|
722 |
+ } else { |
|
723 |
+ t_line = binhexBegin(m); |
|
724 |
+ if(t_line) { |
|
725 |
+ cli_warnmsg("Binhex messages not supported yet (2).\n"); |
|
726 |
+ } |
|
723 | 727 |
t_line = messageGetBody(m); |
728 |
+ } |
|
724 | 729 |
|
725 | 730 |
for(; t_line; t_line = t_line->t_next) { |
726 | 731 |
unsigned char data[1024]; |
... | ... |
@@ -761,14 +882,15 @@ messageToText(const message *m) |
761 | 761 |
return first; |
762 | 762 |
} |
763 | 763 |
|
764 |
+/* |
|
765 |
+ * Scan to find the UUENCODED message (if any) |
|
766 |
+ */ |
|
764 | 767 |
const text * |
765 | 768 |
uuencodeBegin(const message *m) |
766 | 769 |
{ |
767 | 770 |
const text *t_line; |
768 | 771 |
|
769 | 772 |
/* |
770 |
- * Scan to find the UUENCODED message (if any) |
|
771 |
- * |
|
772 | 773 |
* Fix based on an idea by Magnus Jonsson |
773 | 774 |
* <Magnus.Jonsson@umdac.umu.se>, to allow for blank |
774 | 775 |
* lines before the begin. Should not happen, but some |
... | ... |
@@ -788,6 +910,21 @@ uuencodeBegin(const message *m) |
788 | 788 |
} |
789 | 789 |
|
790 | 790 |
/* |
791 |
+ * Scan to find the BINHEX message (if any) |
|
792 |
+ */ |
|
793 |
+const text * |
|
794 |
+binhexBegin(const message *m) |
|
795 |
+{ |
|
796 |
+ const text *t_line; |
|
797 |
+ |
|
798 |
+ for(t_line = messageGetBody(m); t_line; t_line = t_line->t_next) |
|
799 |
+ if(strcasecmp(t_line->t_text, "(This file must be converted with BinHex 4.0)") == 0) |
|
800 |
+ return t_line; |
|
801 |
+ |
|
802 |
+ return NULL; |
|
803 |
+} |
|
804 |
+ |
|
805 |
+/* |
|
791 | 806 |
* Decode a line and add it to a buffer, return the end of the buffer |
792 | 807 |
* to help appending callers. There is no new line at the end of "line" |
793 | 808 |
* |