Browse code

NEW_WORLD: faster handling of base64 encoded messages

git-svn: trunk@1894

Nigel Horne authored on 2006/04/08 01:30:53
Showing 3 changed files
... ...
@@ -15,7 +15,7 @@
15 15
  *  along with this program; if not, write to the Free Software
16 16
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 17
  */
18
-static	char	const	rcsid[] = "$Id: mbox.c,v 1.282 2006/04/07 11:24:22 nigelhorne Exp $";
18
+static	char	const	rcsid[] = "$Id: mbox.c,v 1.283 2006/04/07 16:30:53 nigelhorne Exp $";
19 19
 
20 20
 #if HAVE_CONFIG_H
21 21
 #include "clamav-config.h"
... ...
@@ -112,9 +112,9 @@ typedef enum	{ FALSE = 0, TRUE = 1 } bool;
112 112
  * "--without-libcurl". I don't know if it works with Sun's own compiler
113 113
  *
114 114
  * Fails to link on Solaris 10 with this error:
115
- *      Undefined                       first referenced
116
- *  symbol                             in file
117
- *  __floatdidf                         /opt/sfw/lib/libcurl.s
115
+ *      Undefined			first referenced
116
+ *  symbol				in file
117
+ *  __floatdidf				/opt/sfw/lib/libcurl.s
118 118
  */
119 119
 #if	C_SOLARIS && __GNUC__
120 120
 #undef	WITH_CURL
... ...
@@ -620,9 +620,38 @@ cli_mbox(const char *dir, int desc, unsigned int options)
620 620
 				}
621 621
 
622 622
 			if(b64size > 0L) {
623
-				int lastline;
623
+				int lastline, tmpfd;
624
+				char *tmpfilename;
625
+				unsigned char *uptr;
626
+
624 627
 				cli_dbgmsg("cli_mbox: decoding %ld base64 bytes\n", b64size);
625 628
 
629
+				tmpfilename = cli_gentemp(dir);
630
+				if(tmpfilename == 0) {
631
+					if(wasAlloced)
632
+						free(start);
633
+					else
634
+						munmap(start, size);
635
+
636
+					return CL_EMEM;
637
+				}
638
+
639
+#ifdef	O_TEXT
640
+				tmpfd = open(tmpfilename, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_TEXT, 0600);
641
+#else
642
+				tmpfd = open(tmpfilename, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
643
+#endif
644
+				if(tmpfd < 0) {
645
+					cli_errmsg("Can't make %s\n", tmpfilename);
646
+					free(tmpfilename);
647
+					if(wasAlloced)
648
+						free(start);
649
+					else
650
+						munmap(start, size);
651
+
652
+					return CL_ETMPFILE;
653
+				}
654
+
626 655
 				line = NULL;
627 656
 
628 657
 				m = messageCreate();
... ...
@@ -631,16 +660,22 @@ cli_mbox(const char *dir, int desc, unsigned int options)
631 631
 						free(start);
632 632
 					else
633 633
 						munmap(start, size);
634
+					close(tmpfd);
635
+					unlink(tmpfilename);
636
+					free(tmpfilename);
634 637
 
635 638
 					return CL_EMEM;
636 639
 				}
637 640
 				messageSetEncoding(m, "base64");
641
+				free(tmpfilename);
638 642
 
639 643
 				lastline = 0;
640 644
 
641 645
 				do {
642
-					int length = 0;
646
+					int length = 0, datalen;
643 647
 					char *newline, *equal;
648
+					unsigned char *bigbuf, *data;
649
+					unsigned char smallbuf[1024];
644 650
 
645 651
 					/*printf("%ld: ", b64size); fflush(stdout);*/
646 652
 
... ...
@@ -666,8 +701,31 @@ cli_mbox(const char *dir, int desc, unsigned int options)
666 666
 					}
667 667
 					/*puts(line);*/
668 668
 
669
+#if	0
669 670
 					if(messageAddStr(m, line) < 0)
670 671
 						break;
672
+#endif
673
+					if(length >= sizeof(smallbuf)) {
674
+						datalen = length + 2;
675
+						data = bigbuf = cli_malloc(datalen);
676
+						if(data == NULL)
677
+							break;
678
+					} else {
679
+						bigbuf = NULL;
680
+						data = smallbuf;
681
+						datalen = sizeof(data) - 1;
682
+					}
683
+					uptr = decodeLine(m, BASE64, line, data, datalen);
684
+
685
+					if(uptr == NULL) {
686
+						if(bigbuf)
687
+							free(bigbuf);
688
+						break;
689
+					}
690
+					/*cli_dbgmsg("base64: write %u bytes\n", (size_t)(uptr - data));*/
691
+					cli_writen(tmpfd, data, (size_t)(uptr - data));
692
+					if(bigbuf)
693
+						free(bigbuf);
671 694
 
672 695
 					if((b64size > 0) && (*ptr == '\r')) {
673 696
 						b64start = ++ptr;
... ...
@@ -681,6 +739,7 @@ cli_mbox(const char *dir, int desc, unsigned int options)
681 681
 						break;
682 682
 				} while(b64size > 0L);
683 683
 
684
+#if	0
684 685
 				free(line);
685 686
 				fb = messageToFileblob(m, dir);
686 687
 				messageDestroy(m);
... ...
@@ -689,6 +748,21 @@ cli_mbox(const char *dir, int desc, unsigned int options)
689 689
 					fileblobDestroy(fb);
690 690
 				else
691 691
 					ret = -1;
692
+#else
693
+				if(m->base64chars) {
694
+					unsigned char data[4];
695
+
696
+					uptr = base64Flush(m, data);
697
+					if(uptr) {
698
+						/*cli_dbgmsg("base64: flush %u bytes\n", (size_t)(uptr - data));*/
699
+						cli_writen(tmpfd, data, (size_t)(uptr - data));
700
+					}
701
+				}
702
+
703
+				messageDestroy(m);
704
+				free(line);
705
+				close(tmpfd);
706
+#endif
692 707
 			}
693 708
 		} else if(scanelem->decoder == QUOTEDPRINTABLE) {
694 709
 			const char *quotedstart = scanelem->start;
... ...
@@ -804,6 +878,7 @@ cli_mbox(const char *dir, int desc, unsigned int options)
804 804
 	/*
805 805
 	 * FIXME: Need to run cl_scandir() here and return that value
806 806
 	 */
807
+	cli_dbgmsg("cli_mbox: ret = %d\n", ret);
807 808
 	if(ret == 0)
808 809
 		return CL_CLEAN;	/* a lie - but it gets things going */
809 810
 
... ...
@@ -15,7 +15,7 @@
15 15
  *  along with this program; if not, write to the Free Software
16 16
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 17
  */
18
-static	char	const	rcsid[] = "$Id: message.c,v 1.162 2006/04/07 12:03:13 nigelhorne Exp $";
18
+static	char	const	rcsid[] = "$Id: message.c,v 1.163 2006/04/07 16:30:53 nigelhorne Exp $";
19 19
 
20 20
 #if HAVE_CONFIG_H
21 21
 #include "clamav-config.h"
... ...
@@ -1480,18 +1480,30 @@ messageExport(message *m, const char *dir, void *(*create)(void), void (*destroy
1480 1480
 			unsigned char data[4];
1481 1481
 			unsigned char *ptr;
1482 1482
 
1483
-			cli_dbgmsg("%u trailing bytes to export\n", m->base64chars);
1484
-
1485
-			ptr = decode(m, NULL, data, base64, FALSE);
1483
+			ptr = base64Flush(m, data);
1486 1484
 			if(ptr)
1487 1485
 				(*addData)(ret, data, (size_t)(ptr - data));
1488
-			m->base64chars = 0;
1489 1486
 		}
1490 1487
 	}
1491 1488
 
1492 1489
 	return ret;
1493 1490
 }
1494 1491
 
1492
+unsigned char *
1493
+base64Flush(message *m, unsigned char *buf)
1494
+{
1495
+	cli_dbgmsg("%u trailing bytes to export\n", m->base64chars);
1496
+
1497
+	if(m->base64chars) {
1498
+		unsigned char *ret = decode(m, NULL, buf, base64, FALSE);
1499
+
1500
+		m->base64chars = 0;
1501
+
1502
+		return ret;
1503
+	}
1504
+	return NULL;
1505
+}
1506
+
1495 1507
 /*
1496 1508
  * Decode and transfer the contents of the message into a fileblob
1497 1509
  * The caller must free the returned fileblob
... ...
@@ -61,6 +61,7 @@ int	messageAddStr(message *m, const char *data);
61 61
 int	messageAddStrAtTop(message *m, const char *data);
62 62
 const	text	*messageGetBody(const message *m);
63 63
 void	messageClean(message *m);
64
+unsigned	char	*base64Flush(message *m, unsigned char *buf);
64 65
 fileblob	*messageToFileblob(message *m, const char *dir);
65 66
 blob	*messageToBlob(message *m);
66 67
 text	*messageToText(message *m);