Browse code

Started BinHex work

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
Showing 2 changed files
... ...
@@ -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
  *