diff -dPNur clamav-0.90.1/libclamav/clamav.h clamav-0.90.1-new/libclamav/clamav.h
--- clamav-0.90.1/libclamav/clamav.h	2007-02-22 16:09:00.000000000 +0100
+++ clamav-0.90.1-new/libclamav/clamav.h	2007-03-29 14:15:14.000000000 +0200
@@ -63,6 +63,7 @@
 #define CL_EFORMAT	-124 /* bad format or broken file */
 #define CL_ESUPPORT	-125 /* not supported data format */
 #define CL_ELOCKDB	-126 /* can't lock DB directory */
+#define CL_E7ZIP	-127 /* 7zip  module error */
 
 /* NodalCore */
 #define CL_ENCINIT	-200 /* NodalCore initialization failed */
diff -dPNur clamav-0.90.1/libclamav/filetypes.c clamav-0.90.1-new/libclamav/filetypes.c
--- clamav-0.90.1/libclamav/filetypes.c	2007-03-02 00:44:29.000000000 +0100
+++ clamav-0.90.1-new/libclamav/filetypes.c	2007-03-29 14:11:58.000000000 +0200
@@ -67,6 +67,7 @@
     /* Archives */
 
     {0,	    "Rar!",			4,  "RAR",		CL_TYPE_RAR},
+    {0,	    "7z\274\257\047\034",	6,  "7ZIP",		CL_TYPE_7ZIP},
     {0,	    "PK\003\004",		4,  "ZIP",		CL_TYPE_ZIP},
     {0,	    "PK00PK\003\004",		8,  "ZIP",		CL_TYPE_ZIP},
     {0,	    "\037\213",			2,  "GZip",		CL_TYPE_GZ},
diff -dPNur clamav-0.90.1/libclamav/filetypes.c.orig clamav-0.90.1-new/libclamav/filetypes.c.orig
--- clamav-0.90.1/libclamav/filetypes.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ clamav-0.90.1-new/libclamav/filetypes.c.orig	2007-03-02 00:44:29.000000000 +0100
@@ -0,0 +1,409 @@
+/*
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
+ *  With enhancements from Thomas Lamy <Thomas.Lamy@in-online.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+#include "clamav-config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#ifdef	HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "clamav.h"
+#include "filetypes.h"
+#include "others.h"
+#include "readdb.h"
+#include "matcher-ac.h"
+#include "str.h"
+
+#ifdef CL_EXPERIMENTAL
+#include "htmlnorm.h"
+#include "entconv.h"
+#endif
+
+struct cli_magic_s {
+    size_t offset;
+    const char *magic;
+    size_t length;
+    const char *descr;
+    cli_file_t type;
+};
+
+struct cli_smagic_s {
+    const char *sig;
+    const char *descr;
+    cli_file_t type;
+};
+
+static const struct cli_magic_s cli_magic[] = {
+
+    /* Executables */
+
+    {0,  "MZ",				2,  "DOS/W32 executable/library/driver", CL_TYPE_MSEXE},
+    {0,	 "\177ELF",			4,  "ELF",		CL_TYPE_ELF},
+
+    /* Archives */
+
+    {0,	    "Rar!",			4,  "RAR",		CL_TYPE_RAR},
+    {0,	    "PK\003\004",		4,  "ZIP",		CL_TYPE_ZIP},
+    {0,	    "PK00PK\003\004",		8,  "ZIP",		CL_TYPE_ZIP},
+    {0,	    "\037\213",			2,  "GZip",		CL_TYPE_GZ},
+    {0,	    "BZh",			3,  "BZip",		CL_TYPE_BZ},
+    {0,	    "SZDD",			4,  "compress.exe'd",	CL_TYPE_MSSZDD},
+    {0,	    "MSCF",			4,  "MS CAB",		CL_TYPE_MSCAB},
+    {0,	    "ITSF",			4,  "MS CHM",           CL_TYPE_MSCHM},
+    {8,	    "\x19\x04\x00\x10",		4,  "SIS",		CL_TYPE_SIS},
+    {0,     "#@~^",			4,  "SCRENC",		CL_TYPE_SCRENC},
+    {0,     "(This file must be converted with BinHex 4.0)",
+				       45, "BinHex",		CL_TYPE_BINHEX},
+
+    /* Mail */
+
+    {0,  "From ",			 5, "MBox",		  CL_TYPE_MAIL},
+    {0,  "Received: ",			10, "Raw mail",		  CL_TYPE_MAIL},
+    {0,  "Return-Path: ",		13, "Maildir",		  CL_TYPE_MAIL},
+    {0,  "Return-path: ",		13, "Maildir",		  CL_TYPE_MAIL},
+    {0,  "Delivered-To: ",		14, "Mail",		  CL_TYPE_MAIL},
+    {0,  "X-UIDL: ",			 8, "Mail",		  CL_TYPE_MAIL},
+    {0,  "X-Apparently-To: ",		17, "Mail",		  CL_TYPE_MAIL},
+    {0,  "X-Envelope-From: ",		17, "Mail",		  CL_TYPE_MAIL},
+    {0,  "X-Original-To: ",		15, "Mail",		  CL_TYPE_MAIL},
+    {0,  "X-Symantec-",			11, "Symantec",		  CL_TYPE_MAIL},
+    {0,  "X-EVS",			 5, "EVS mail",		  CL_TYPE_MAIL},
+    {0,  "X-Real-To: ",                 11, "Mail",               CL_TYPE_MAIL},
+    {0,  "X-Sieve: ",			 9, "Mail",		  CL_TYPE_MAIL},
+    {0,  ">From ",			 6, "Mail",		  CL_TYPE_MAIL},
+    {0,  "Date: ",			 6, "Mail",		  CL_TYPE_MAIL},
+    {0,  "Message-Id: ",		12, "Mail",		  CL_TYPE_MAIL},
+    {0,  "Message-ID: ",		12, "Mail",		  CL_TYPE_MAIL},
+    {0,  "Envelope-to: ",		13, "Mail",		  CL_TYPE_MAIL},
+    {0,  "Delivery-date: ",		15, "Mail",		  CL_TYPE_MAIL},
+    {0,  "To: ",			 4, "Mail",		  CL_TYPE_MAIL},
+    {0,  "Subject: ",			 9, "Mail",		  CL_TYPE_MAIL},
+    {0,  "For: ",			 5, "Eserv mail",	  CL_TYPE_MAIL},
+    {0,  "From: ",			 6, "Exim mail",	  CL_TYPE_MAIL},
+    {0,  "v:\015\012Received: ",	14, "VPOP3 Mail (DOS)",	  CL_TYPE_MAIL},
+    {0,  "v:\012Received: ",		13, "VPOP3 Mail (UNIX)",  CL_TYPE_MAIL},
+    {0,  "Hi. This is the qmail-send",  26, "Qmail bounce",	  CL_TYPE_MAIL},
+    {0,  "\170\237\076\042",		 4, "TNEF",               CL_TYPE_TNEF},
+
+    {0,  "begin ",			6,  "UUencoded",	  CL_TYPE_UUENCODED},
+
+    /* Graphics (may contain exploits against MS systems) */
+
+    {0,  "GIF",				 3, "GIF",	    CL_TYPE_GRAPHICS},
+    {0,  "BM",				 2, "BMP",          CL_TYPE_GRAPHICS},
+    {0,  "\377\330\377",		 3, "JPEG",         CL_TYPE_GRAPHICS},
+    {6,  "JFIF",			 4, "JPEG",         CL_TYPE_GRAPHICS},
+    {6,  "Exif",			 4, "JPEG",         CL_TYPE_GRAPHICS},
+    {0,  "\x89PNG",			 4, "PNG",          CL_TYPE_GRAPHICS},
+    {0,  "RIFF",                         4, "RIFF",         CL_TYPE_RIFF},
+    {0,  "RIFX",                         4, "RIFX",         CL_TYPE_RIFF},
+
+    /* Others */
+
+    {0,  "\320\317\021\340\241\261\032\341", 8, "OLE2 container", CL_TYPE_MSOLE2},
+    {0,  "%PDF-",			 5, "PDF document", CL_TYPE_PDF},
+    {0,  "\266\271\254\256\376\377\377\377", 8, "CryptFF", CL_TYPE_CRYPTFF},
+    {0,  "{\\rtf",                           5, "RTF", CL_TYPE_RTF}, 
+
+    /* Ignored types */
+
+    {0,  "\000\000\001\263",             4, "MPEG video stream",  CL_TYPE_DATA},
+    {0,  "\000\000\001\272",             4, "MPEG sys stream",    CL_TYPE_DATA},
+    {0,  "OggS",                         4, "Ogg Stream",         CL_TYPE_DATA},
+    {0,  "ID3",				 3, "MP3",		  CL_TYPE_DATA},
+    {0,  "\377\373\220",		 3, "MP3",		  CL_TYPE_DATA},
+    {0,  "%!PS-Adobe-",			11, "PostScript",	  CL_TYPE_DATA},
+    {0,  "\060\046\262\165\216\146\317", 7, "WMA/WMV/ASF",	  CL_TYPE_DATA},
+    {0,  ".RMF" ,			 4, "Real Media File",	  CL_TYPE_DATA},
+
+    {0, NULL,				 0, NULL,		  CL_TYPE_UNKNOWN_DATA}
+};
+
+static const struct cli_smagic_s cli_smagic[] = {
+
+    /* "\nFrom: " * "\nContent-Type: " */
+    {"0a46726f6d3a20{-2048}0a436f6e74656e742d547970653a20", "Mail file", CL_TYPE_MAIL},
+
+    /* "\nReceived: " * "\nContent-Type: " */
+    {"0a52656365697665643a20{-2048}0a436f6e74656e742d547970653a20", "Mail file", CL_TYPE_MAIL},
+
+    /* "\nReceived: " * "\nContent-type: " */
+    {"0a52656365697665643a20{-2048}0a436f6e74656e742d747970653a20", "Mail file", CL_TYPE_MAIL},
+
+    /* "MIME-Version: " * "\nContent-Type: " */
+    {"4d494d452d56657273696f6e3a20{-2048}0a436f6e74656e742d547970653a20", "Mail file", CL_TYPE_MAIL},
+
+    /* remember the matcher is case sensitive */
+    {"3c62723e",       "HTML data", CL_TYPE_HTML},	/* <br> */
+    {"3c42723e",       "HTML data", CL_TYPE_HTML},	/* <Br> */
+    {"3c42523e",       "HTML data", CL_TYPE_HTML},	/* <BR> */
+    {"3c703e",	       "HTML data", CL_TYPE_HTML},	/* <p> */
+    {"3c503e",	       "HTML data", CL_TYPE_HTML},	/* <P> */
+    {"68726566",       "HTML data", CL_TYPE_HTML},	/* href */
+    {"48726566",       "HTML data", CL_TYPE_HTML},	/* Href */
+    {"48524546",       "HTML data", CL_TYPE_HTML},	/* HREF */
+    {"3c68746d6c3e",   "HTML data", CL_TYPE_HTML},      /* <html> */
+    {"3c48544d4c3e",   "HTML data", CL_TYPE_HTML},      /* <HTML> */
+    {"3c48746d6c3e",   "HTML data", CL_TYPE_HTML},      /* <Html> */
+    {"3c686561643e",   "HTML data", CL_TYPE_HTML},      /* <head> */
+    {"3c484541443e",   "HTML data", CL_TYPE_HTML},      /* <HEAD> */
+    {"3c486561643e",   "HTML data", CL_TYPE_HTML},      /* <Head> */
+    {"3c666f6e74",     "HTML data", CL_TYPE_HTML},	/* <font */
+    {"3c466f6e74",     "HTML data", CL_TYPE_HTML},	/* <Font */
+    {"3c464f4e54",     "HTML data", CL_TYPE_HTML},	/* <FONT */
+    {"3c696d67",       "HTML data", CL_TYPE_HTML},      /* <img */
+    {"3c494d47",       "HTML data", CL_TYPE_HTML},      /* <IMG */
+    {"3c496d67",       "HTML data", CL_TYPE_HTML},      /* <Img */
+    {"3c736372697074", "HTML data", CL_TYPE_HTML},	/* <script */
+    {"3c536372697074", "HTML data", CL_TYPE_HTML},	/* <Script */
+    {"3c534352495054", "HTML data", CL_TYPE_HTML},	/* <SCRIPT */
+    {"3c6f626a656374", "HTML data", CL_TYPE_HTML},      /* <object */
+    {"3c4f626a656374", "HTML data", CL_TYPE_HTML},      /* <Object */
+    {"3c4f424a454354", "HTML data", CL_TYPE_HTML},      /* <OBJECT */
+    {"3c696672616d65", "HTML data", CL_TYPE_HTML},      /* <iframe */
+    {"3c494652414d45", "HTML data", CL_TYPE_HTML},      /* <IFRAME */
+    {"3c7461626c65",   "HTML data", CL_TYPE_HTML},	/* <table */
+    {"3c5441424c45",   "HTML data", CL_TYPE_HTML},	/* <TABLE */
+
+    {"526172211a0700", "RAR-SFX", CL_TYPE_RARSFX},
+    {"504b0304", "ZIP-SFX", CL_TYPE_ZIPSFX},
+    {"4d534346", "CAB-SFX", CL_TYPE_CABSFX},
+
+    {NULL,  NULL,   CL_TYPE_UNKNOWN_DATA}
+};
+
+static char internat[256] = {
+    /* TODO: Remember to buy a beer to Joerg Wunsch <joerg@FreeBSD.ORG> */
+    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,  /* 0x0X */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,  /* 0x1X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x2X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x3X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x4X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x5X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x6X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,  /* 0x7X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x8X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x9X */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0xaX */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0xbX */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0xcX */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0xdX */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0xeX */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1   /* 0xfX */
+};
+
+cli_file_t cli_filetype(const unsigned char *buf, size_t buflen)
+{
+	int i, text = 1, len;
+
+
+    for(i = 0; cli_magic[i].magic; i++) {
+	if(buflen >= cli_magic[i].offset+cli_magic[i].length) {
+	    if(memcmp(buf+cli_magic[i].offset, cli_magic[i].magic, cli_magic[i].length) == 0) {
+		cli_dbgmsg("Recognized %s file\n", cli_magic[i].descr);
+		return cli_magic[i].type;
+	    }
+	}
+    }
+
+/* improve or drop this code
+ * https://wwws.clamav.net/bugzilla/show_bug.cgi?id=373
+ *
+    buflen < 25 ? (len = buflen) : (len = 25);
+    for(i = 0; i < len; i++)
+	if(!iscntrl(buf[i]) && !isprint(buf[i]) && !internat[buf[i] & 0xff]) {
+	    text = 0;
+	    break;
+	}
+*/
+    return text ? CL_TYPE_UNKNOWN_TEXT : CL_TYPE_UNKNOWN_DATA;
+}
+
+int is_tar(unsigned char *buf, unsigned int nbytes);
+
+cli_file_t cli_filetype2(int desc, const struct cl_engine *engine)
+{
+	unsigned char smallbuff[MAGIC_BUFFER_SIZE + 1], *decoded, *bigbuff;
+	int bread, sret;
+	cli_file_t ret = CL_TYPE_UNKNOWN_DATA;
+	struct cli_matcher *root;
+	struct cli_ac_data mdata;
+
+
+    memset(smallbuff, 0, sizeof(smallbuff));
+    if((bread = read(desc, smallbuff, MAGIC_BUFFER_SIZE)) > 0)
+	ret = cli_filetype(smallbuff, bread);
+
+    if(engine && ret == CL_TYPE_UNKNOWN_TEXT) {
+	root = engine->root[0];
+	if(!root)
+	    return ret;
+
+	if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN))
+	    return ret;
+
+	sret = cli_ac_scanbuff(smallbuff, bread, NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL);
+
+	cli_ac_freedata(&mdata);
+
+	if(sret >= CL_TYPENO) {
+	    ret = sret;
+	} else {
+	    if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN))
+		return ret;
+
+	    decoded = (unsigned char *) cli_utf16toascii((char *) smallbuff, bread);
+	    if(decoded) {
+		sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL);
+		free(decoded);
+		if(sret == CL_TYPE_HTML)
+		    ret = CL_TYPE_HTML_UTF16;
+	    }
+	    cli_ac_freedata(&mdata);
+
+#ifdef CL_EXPERIMENTAL
+	    if(ret != CL_TYPE_HTML_UTF16) {
+		    struct entity_conv conv;
+		    const size_t conv_size = 2*bread < 256 ? 256 : 2*bread;
+
+		if(init_entity_converter(&conv,UNKNOWN,conv_size) == 0) {
+			int end = 0;
+			m_area_t area;
+			area.buffer = (unsigned char *) smallbuff;
+			area.length = bread;
+			area.offset = 0;
+
+		    while(!end) {
+			if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN))
+			    return ret;
+
+			decoded =  encoding_norm_readline(&conv, NULL, &area, bread);
+
+			if(decoded) {
+			    sret = cli_ac_scanbuff(decoded, strlen((const char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL);
+			    free(decoded);
+			    if(sret == CL_TYPE_HTML) {
+				ret = CL_TYPE_HTML;
+				end = 1;
+			    }
+			} else
+			    end = 1;
+
+			cli_ac_freedata(&mdata);
+		    }
+
+		    entity_norm_done(&conv);
+
+		} else {
+		    cli_warnmsg("cli_filetype2: Error initializing entity converter\n");
+		}
+	    }
+#endif /* CL_EXPERIMENTAL */
+	}
+    }
+
+    if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) {
+
+	if(!(bigbuff = (unsigned char *) cli_calloc(37638 + 1, sizeof(unsigned char))))
+	    return ret;
+
+	lseek(desc, 0, SEEK_SET);
+	if((bread = read(desc, bigbuff, 37638)) > 0) {
+
+	    bigbuff[bread] = 0;
+
+	    switch(is_tar(bigbuff, bread)) {
+		case 1:
+		    ret = CL_TYPE_OLD_TAR;
+		    cli_dbgmsg("Recognized old fashioned tar file\n");
+		    break;
+		case 2:
+		    ret = CL_TYPE_POSIX_TAR;
+		    cli_dbgmsg("Recognized POSIX tar file\n");
+		    break;
+	    }
+	}
+
+	if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) {
+
+	    if(!memcmp(bigbuff + 32769, "CD001" , 5) || !memcmp(bigbuff + 37633, "CD001" , 5)) {
+		cli_dbgmsg("Recognized ISO 9660 CD-ROM data\n");
+		ret = CL_TYPE_DATA;
+	    } else if(!memcmp(bigbuff + 32776, "CDROM" , 5)) {
+		cli_dbgmsg("Recognized High Sierra CD-ROM data\n");
+		ret = CL_TYPE_DATA;
+	    }
+	}
+
+	free(bigbuff);
+    }
+
+    return ret;
+}
+
+int cli_addtypesigs(struct cl_engine *engine)
+{
+	int i, ret;
+	struct cli_matcher *root;
+
+
+    if(!engine->root[0]) {
+	cli_dbgmsg("cli_addtypesigs: Need to allocate AC trie in engine->root[0]\n");
+	root = engine->root[0] = (struct cli_matcher *) cli_calloc(1, sizeof(struct cli_matcher));
+	if(!root) {
+	    cli_errmsg("cli_addtypesigs: Can't initialise AC pattern matcher\n");
+	    return CL_EMEM;
+	}
+
+	if(engine->ncore) {
+	    /*
+	    cli_dbgmsg("cli_addtypesigs: AC depth 10 (ncore mode)\n");
+	    cli_ac_setdepth(10);
+	    */
+	}
+
+	root->ac_root =  (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
+	if(!root->ac_root) {
+	    cli_errmsg("cli_addtypesigs: Can't initialise AC pattern matcher\n");
+	    /* No need to free previously allocated memory here - all engine
+	     * elements will be properly freed by cl_free()
+	     */
+	    return CL_EMEM;
+	}
+    } else {
+	root = engine->root[0];
+    }
+
+    for(i = 0; cli_smagic[i].sig; i++) {
+	if((ret = cli_parse_add(root, cli_smagic[i].descr, cli_smagic[i].sig, cli_smagic[i].type, NULL, 0))) {
+	    cli_errmsg("cli_addtypesigs: Problem adding signature for %s\n", cli_smagic[i].descr);
+	    return ret;
+	}
+    }
+
+    return 0;
+}
diff -dPNur clamav-0.90.1/libclamav/filetypes.h clamav-0.90.1-new/libclamav/filetypes.h
--- clamav-0.90.1/libclamav/filetypes.h	2007-03-02 00:45:36.000000000 +0100
+++ clamav-0.90.1-new/libclamav/filetypes.h	2007-03-29 14:11:58.000000000 +0200
@@ -39,6 +39,7 @@
     CL_TYPE_ZIP,
     CL_TYPE_BZ,
     CL_TYPE_RAR,
+    CL_TYPE_7ZIP,
     CL_TYPE_MSSZDD,
     CL_TYPE_MSOLE2,
     CL_TYPE_MSCAB,
diff -dPNur clamav-0.90.1/libclamav/filetypes.h.orig clamav-0.90.1-new/libclamav/filetypes.h.orig
--- clamav-0.90.1/libclamav/filetypes.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ clamav-0.90.1-new/libclamav/filetypes.h.orig	2007-03-02 00:45:36.000000000 +0100
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
+ *  With enhancements from Thomas Lamy <Thomas.Lamy@in-online.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301, USA.
+ */
+
+#ifndef __FILETYPES_H
+#define __FILETYPES_H
+
+#include <sys/types.h>
+
+#define MAGIC_BUFFER_SIZE 256
+#define CL_TYPENO 500
+#define SFX_MAX_TESTS 10
+
+typedef enum {
+    CL_TYPE_UNKNOWN_TEXT = CL_TYPENO,
+    CL_TYPE_UNKNOWN_DATA,
+    CL_TYPE_MSEXE,
+    CL_TYPE_ELF,
+    CL_TYPE_DATA,
+    CL_TYPE_POSIX_TAR,
+    CL_TYPE_OLD_TAR,
+    CL_TYPE_GZ,
+    CL_TYPE_ZIP,
+    CL_TYPE_BZ,
+    CL_TYPE_RAR,
+    CL_TYPE_MSSZDD,
+    CL_TYPE_MSOLE2,
+    CL_TYPE_MSCAB,
+    CL_TYPE_MSCHM,
+    CL_TYPE_SIS,
+    CL_TYPE_SCRENC,
+    CL_TYPE_GRAPHICS,
+    CL_TYPE_RIFF,
+    CL_TYPE_BINHEX,
+    CL_TYPE_TNEF,
+    CL_TYPE_CRYPTFF,
+    CL_TYPE_PDF,
+    CL_TYPE_UUENCODED,
+    CL_TYPE_HTML_UTF16,
+    CL_TYPE_RTF,
+
+    /* bigger numbers have higher priority (in o-t-f detection) */
+    CL_TYPE_HTML, /* on the fly */
+    CL_TYPE_MAIL,  /* magic + on the fly */
+    CL_TYPE_SFX, /* foo SFX marker */
+    CL_TYPE_ZIPSFX, /* on the fly */
+    CL_TYPE_RARSFX, /* on the fly */
+    CL_TYPE_CABSFX
+
+} cli_file_t;
+
+struct cli_matched_type {
+    cli_file_t type;
+    off_t offset;
+    unsigned short cnt;
+    struct cli_matched_type *next;
+};
+
+cli_file_t cli_filetype(const unsigned char *buf, size_t buflen);
+cli_file_t cli_filetype2(int desc, const struct cl_engine *engine);
+int cli_addtypesigs(struct cl_engine *engine);
+
+#endif
diff -dPNur clamav-0.90.1/libclamav/Makefile.am clamav-0.90.1-new/libclamav/Makefile.am
--- clamav-0.90.1/libclamav/Makefile.am	2007-03-02 00:44:21.000000000 +0100
+++ clamav-0.90.1-new/libclamav/Makefile.am	2007-03-29 15:20:51.000000000 +0200
@@ -19,7 +19,7 @@
 
 INCLUDES = -I$(top_srcdir) -I@srcdir@/unrar
 
-libclamav_la_LIBADD = @LIBCLAMAV_LIBS@ @THREAD_LIBS@
+libclamav_la_LIBADD = @LIBCLAMAV_LIBS@ @THREAD_LIBS@ -lun7zip
 
 libclamav_la_LDFLAGS = @TH_SAFE@ -version-info @LIBCLAMAV_VERSION@ -no-undefined
 
@@ -52,6 +52,8 @@
 	scanners.h \
 	filetypes.c \
 	filetypes.h \
+	un7zip.c \
+	un7zip.h \
 	rtf.c \
 	rtf.h \
 	blob.c \
diff -dPNur clamav-0.90.1/libclamav/others.c clamav-0.90.1-new/libclamav/others.c
--- clamav-0.90.1/libclamav/others.c	2007-02-28 22:59:01.000000000 +0100
+++ clamav-0.90.1-new/libclamav/others.c	2007-03-29 14:11:58.000000000 +0200
@@ -162,6 +162,8 @@
 	    return "File size limit exceeded";
 	case CL_EMAXFILES:
 	    return "Files number limit exceeded";
+	case CL_E7ZIP:
+	    return "7zip module failure";
 	case CL_ERAR:
 	    return "RAR module failure";
 	case CL_EZIP:
diff -dPNur clamav-0.90.1/libclamav/others.c.orig clamav-0.90.1-new/libclamav/others.c.orig
--- clamav-0.90.1/libclamav/others.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ clamav-0.90.1-new/libclamav/others.c.orig	2007-02-28 22:59:01.000000000 +0100
@@ -0,0 +1,940 @@
+/*
+ *  Copyright (C) 1999 - 2005 Tomasz Kojm <tkojm@clamav.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301, USA.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "clamav-config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef	HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef	C_WINDOWS
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <dirent.h>
+#endif
+#include <time.h>
+#include <fcntl.h>
+#ifndef	C_WINDOWS
+#include <pwd.h>
+#endif
+#include <errno.h>
+#include "target.h"
+#ifndef	C_WINDOWS
+#include <sys/time.h>
+#endif
+#ifdef	HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef	HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#if	defined(_MSC_VER) && defined(_DEBUG)
+#include <crtdbg.h>
+#endif
+
+#ifdef CL_THREAD_SAFE
+#  include <pthread.h>
+static pthread_mutex_t cli_gentempname_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
+#include <limits.h>
+#include <stddef.h>
+#endif
+
+#include "clamav.h"
+#include "others.h"
+#include "md5.h"
+#include "cltypes.h"
+
+#ifndef	O_BINARY
+#define	O_BINARY	0
+#endif
+
+#ifdef        C_WINDOWS
+#undef        P_tmpdir
+#define       P_tmpdir        "C:\\WINDOWS\\TEMP"
+#endif
+
+#define CL_FLEVEL 14 /* don't touch it */
+
+short cli_debug_flag = 0, cli_leavetemps_flag = 0;
+
+static unsigned char name_salt[16] = { 16, 38, 97, 12, 8, 4, 72, 196, 217, 144, 33, 124, 18, 11, 17, 253 };
+
+
+void cli_warnmsg(const char *str, ...)
+{
+	va_list args;
+	int sz = sizeof("LibClamAV Warning: ") - 1;
+	char buff[256];
+
+    strncpy(buff, "LibClamAV Warning: ", sz);
+    va_start(args, str);
+    vsnprintf(buff + sz, sizeof(buff) - sz, str, args);
+    buff[sizeof(buff) - 1] = '\0';
+    fputs(buff, stderr);
+    va_end(args);
+}
+
+void cli_errmsg(const char *str, ...)
+{
+	va_list args;
+	int sz = sizeof("LibClamAV Error: ") - 1;
+	char buff[256];
+
+    strncpy(buff, "LibClamAV Error: ", sz);
+    va_start(args, str);
+    vsnprintf(buff + sz, sizeof(buff) - sz, str, args);
+    buff[sizeof(buff) - 1] = '\0';
+    fputs(buff, stderr);
+    va_end(args);
+}
+
+void cli_dbgmsg(const char *str, ...)
+{
+
+    if(cli_debug_flag) {
+	    va_list args;
+	    int sz = sizeof("LibClamAV debug: ") - 1;
+	    char buff[BUFSIZ];
+
+	memcpy(buff, "LibClamAV debug: ", sz);
+	va_start(args, str);
+	vsnprintf(buff + sz, sizeof(buff) - sz, str, args);
+	buff[sizeof(buff) - 1] = '\0';
+	fputs(buff, stderr);
+	va_end(args);
+    } else
+	return;
+}
+
+void cl_debug(void)
+{
+    cli_debug_flag = 1;
+}
+
+unsigned int cl_retflevel(void)
+{
+    return CL_FLEVEL;
+}
+
+const char *cl_retver(void)
+{
+    return VERSION;
+}
+
+const char *cl_strerror(int clerror)
+{
+    switch(clerror) {
+	case CL_CLEAN:
+	    return "No viruses detected";
+	case CL_VIRUS:
+	    return "Virus(es) detected";
+	case CL_EMAXREC:
+	    return "Recursion limit exceeded";
+	case CL_EMAXSIZE:
+	    return "File size limit exceeded";
+	case CL_EMAXFILES:
+	    return "Files number limit exceeded";
+	case CL_ERAR:
+	    return "RAR module failure";
+	case CL_EZIP:
+	    return "Zip module failure";
+	case CL_EGZIP:
+	    return "GZip module failure";
+	case CL_EMSCOMP:
+	    return "MS Expand module failure";
+	case CL_EMSCAB:
+	    return "MS CAB module failure";
+	case CL_EOLE2:
+	    return "OLE2 module failure";
+	case CL_ETMPFILE:
+	    return "Unable to create temporary file";
+	case CL_ETMPDIR:
+	    return "Unable to create temporary directory";
+	case CL_EFSYNC:
+	    return "Unable to synchronize file <-> disk";
+	case CL_EMEM:
+	    return "Unable to allocate memory";
+	case CL_EOPEN:
+	    return "Unable to open file or directory";
+	case CL_EMALFDB:
+	    return "Malformed database";
+	case CL_EPATSHORT:
+	    return "Too short pattern detected";
+	case CL_ECVD:
+	    return "Broken or not a CVD file";
+	case CL_ECVDEXTR:
+	    return "CVD extraction failure";
+	case CL_EMD5:
+	    return "MD5 verification error";
+	case CL_EDSIG:
+	    return "Digital signature verification error";
+	case CL_ENULLARG:
+	    return "Null argument passed while initialized is required";
+	case CL_EIO:
+	    return "Input/Output error";
+	case CL_EFORMAT:
+	    return "Bad format or broken data";
+	case CL_ESUPPORT:
+	    return "Not supported data format";
+	case CL_ENCINIT:
+	    return "NodalCore initialization failure";
+	case CL_ENCLOAD:
+	    return "Error loading NodalCore database";
+	case CL_ENCIO:
+	    return "NodalCore accelerator Input/Output error";
+	case CL_ELOCKDB:
+	    return "Unable to lock database directory";
+	default:
+	    return "Unknown error code";
+    }
+}
+
+unsigned char *cli_md5digest(int desc)
+{
+	unsigned char *digest;
+	char buff[FILEBUFF];
+	cli_md5_ctx ctx;
+	int bytes;
+
+
+    if(!(digest = cli_malloc(16)))
+	return NULL;
+
+    cli_md5_init(&ctx);
+
+    while((bytes = cli_readn(desc, buff, FILEBUFF)))
+	cli_md5_update(&ctx, buff, bytes);
+
+    cli_md5_final(digest, &ctx);
+
+    return digest;
+}
+
+char *cli_md5stream(FILE *fs, unsigned char *digcpy)
+{
+	unsigned char digest[16];
+	char buff[FILEBUFF];
+	cli_md5_ctx ctx;
+	char *md5str, *pt;
+	int i, bytes;
+
+
+    cli_md5_init(&ctx);
+
+    while((bytes = fread(buff, 1, FILEBUFF, fs)))
+	cli_md5_update(&ctx, buff, bytes);
+
+    cli_md5_final(digest, &ctx);
+
+    if(!(md5str = (char *) cli_calloc(32 + 1, sizeof(char))))
+	return NULL;
+
+    pt = md5str;
+    for(i = 0; i < 16; i++) {
+	sprintf(pt, "%02x", digest[i]);
+	pt += 2;
+    }
+
+    if(digcpy)
+	memcpy(digcpy, digest, 16);
+
+    return md5str;
+}
+
+char *cli_md5file(const char *filename)
+{
+	FILE *fs;
+	char *md5str;
+
+
+    if((fs = fopen(filename, "rb")) == NULL) {
+	cli_errmsg("cli_md5file(): Can't read file %s\n", filename);
+	return NULL;
+    }
+
+    md5str = cli_md5stream(fs, NULL);
+    fclose(fs);
+
+    return md5str;
+}
+
+static char *cli_md5buff(const char *buffer, unsigned int len, unsigned char *dig)
+{
+	unsigned char digest[16];
+	char *md5str, *pt;
+	cli_md5_ctx ctx;
+	int i;
+
+
+    cli_md5_init(&ctx);
+    cli_md5_update(&ctx, (const unsigned char *) buffer, len);
+    cli_md5_final(digest, &ctx);
+
+    if(dig)
+	memcpy(dig, digest, 16);
+
+    if(!(md5str = (char *) cli_calloc(32 + 1, sizeof(char))))
+	return NULL;
+
+    pt = md5str;
+    for(i = 0; i < 16; i++) {
+	sprintf(pt, "%02x", digest[i]);
+	pt += 2;
+    }
+
+    return md5str;
+}
+
+void *cli_malloc(size_t size)
+{
+	void *alloc;
+
+
+    if(!size || size > CLI_MAX_ALLOCATION) {
+	cli_errmsg("cli_malloc(): Attempt to allocate %u bytes. Please report to http://bugs.clamav.net\n", size);
+	return NULL;
+    }
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+    alloc = _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__);
+#else
+    alloc = malloc(size);
+#endif
+
+    if(!alloc) {
+	cli_errmsg("cli_malloc(): Can't allocate memory (%u bytes).\n", size);
+	perror("malloc_problem");
+	/* _exit(1); */
+	return NULL;
+    } else return alloc;
+}
+
+void *cli_calloc(size_t nmemb, size_t size)
+{
+	void *alloc;
+
+
+    if(!size || size > CLI_MAX_ALLOCATION) {
+	cli_errmsg("cli_calloc(): Attempt to allocate %u bytes. Please report to http://bugs.clamav.net\n", size);
+	return NULL;
+    }
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+    alloc = _calloc_dbg(nmemb, size, _NORMAL_BLOCK, __FILE__, __LINE__);
+#else
+    alloc = calloc(nmemb, size);
+#endif
+
+    if(!alloc) {
+	cli_errmsg("cli_calloc(): Can't allocate memory (%u bytes).\n", nmemb * size);
+	perror("calloc_problem");
+	/* _exit(1); */
+	return NULL;
+    } else return alloc;
+}
+
+void *cli_realloc(void *ptr, size_t size)
+{
+	void *alloc;
+
+
+    if(!size || size > CLI_MAX_ALLOCATION) {
+	cli_errmsg("cli_realloc(): Attempt to allocate %u bytes. Please report to http://bugs.clamav.net\n", size);
+	return NULL;
+    }
+
+    alloc = realloc(ptr, size);
+
+    if(!alloc) {
+	cli_errmsg("cli_realloc(): Can't re-allocate memory to %u bytes.\n", size);
+	perror("realloc_problem");
+	return NULL;
+    } else return alloc;
+}
+
+char *cli_strdup(const char *s)
+{
+        char *alloc;
+
+
+    if(s == NULL) {
+        cli_errmsg("cli_strdup(): s == NULL. Please report to http://bugs.clamav.net\n");
+        return NULL;
+    }
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+    alloc = _strdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__);
+#else
+    alloc = strdup(s);
+#endif
+
+    if(!alloc) {
+        cli_errmsg("cli_strdup(): Can't allocate memory (%u bytes).\n", strlen(s));
+        perror("strdup_problem");
+        return NULL;
+    }
+
+    return alloc;
+}
+
+unsigned int cli_rndnum(unsigned int max)
+{
+    struct timeval tv;
+
+  gettimeofday(&tv, (struct timezone *) 0);
+  srand(tv.tv_usec+clock());
+
+  return rand() % max;
+}
+
+void cl_settempdir(const char *dir, short leavetemps)
+{
+	char *var;
+
+    if(dir) {
+	var = (char *) cli_malloc(8 + strlen(dir));
+	sprintf(var, "TMPDIR=%s", dir);
+	if(!putenv(var))
+	    cli_dbgmsg("Setting %s as global temporary directory\n", dir);
+	else
+	    cli_warnmsg("Can't set TMPDIR variable - insufficient space in the environment.\n");
+
+	/* WARNING: var must not be released - see putenv(3) */
+    }
+
+    cli_leavetemps_flag = leavetemps;
+}
+
+static char *cli_gentempname(const char *dir)
+{
+	char *name, *tmp;
+        const char *mdir;
+	unsigned char salt[16 + 32];
+	int i;
+
+    if(!dir) {
+	if((mdir = getenv("TMPDIR")) == NULL)
+#ifdef P_tmpdir
+	    mdir = P_tmpdir;
+#else
+	    mdir = "/tmp";
+#endif
+    } else
+	mdir = dir;
+
+    name = (char *) cli_calloc(strlen(mdir) + 1 + 32 + 1 + 7, sizeof(char));
+    if(!name) {
+	cli_dbgmsg("cli_gentempname('%s'): out of memory\n", mdir);
+	return NULL;
+    }
+
+#ifdef CL_THREAD_SAFE
+    pthread_mutex_lock(&cli_gentempname_mutex);
+#endif
+
+    memcpy(salt, name_salt, 16);
+
+    for(i = 16; i < 48; i++)
+	salt[i] = cli_rndnum(256);
+
+    tmp = cli_md5buff((char *) salt, 48, name_salt);
+
+#ifdef CL_THREAD_SAFE
+    pthread_mutex_unlock(&cli_gentempname_mutex);
+#endif
+
+    if(!tmp) {
+	free(name);
+	cli_dbgmsg("cli_gentempname('%s'): out of memory\n", mdir);
+	return NULL;
+    }
+
+#ifdef	C_WINDOWS
+	sprintf(name, "%s\\clamav-", mdir);
+#else
+	sprintf(name, "%s/clamav-", mdir);
+#endif
+    strncat(name, tmp, 32);
+    free(tmp);
+
+    return(name);
+}
+
+char *cli_gentemp(const char *dir)
+{
+	char *name;
+
+    name = cli_gentempname(dir);
+
+    return(name);
+}
+
+
+char *cli_gentempdir(const char *dir)
+{
+	char *name;
+
+    name = cli_gentempname(dir);
+
+    if(name && mkdir(name, 0700)) {
+	cli_dbgmsg("cli_gentempdir(): can't create temp directory: %s\n", name);
+        free(name);
+        name = NULL;
+    }
+
+    return(name);
+}
+
+char *cli_gentempdesc(const char *dir, int *fd)
+{
+	char *name;
+
+    name = cli_gentempname(dir);
+
+    if(name && ((*fd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0)) {
+	cli_dbgmsg("cli_gentempdesc(): can't create temp file: %s\n", name);
+        free(name);
+        name = NULL;
+    }
+
+    return(name);
+}
+
+char *cli_gentempstream(const char *dir, FILE **fs)
+{
+	char *name;
+
+    name = cli_gentempname(dir);
+
+    if(name && ((*fs = fopen(name, "wb+")) == NULL)) {
+	cli_dbgmsg("cli_gentempstream(): can't create temp file: %s\n", name);
+        free(name);
+        name = NULL;
+    }
+
+    return(name);
+}
+
+#ifdef	C_WINDOWS
+/*
+ * Windows doesn't allow you to delete a directory while it is still open
+ */
+int
+cli_rmdirs(const char *name)
+{
+	int rc;
+	struct stat statb;	
+	DIR *dd;
+	struct dirent *dent;
+#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
+	union {
+	    struct dirent d;
+	    char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
+	} result;
+#endif
+
+
+    if(stat(name, &statb) < 0) {
+	cli_warnmsg("Can't locate %s: %s\n", name, strerror(errno));
+	return -1;
+    }
+
+    if(!S_ISDIR(statb.st_mode)) {
+	if(unlink(name) < 0) {
+	    cli_warnmsg("Can't remove %s: %s\n", name, strerror(errno));
+	    return -1;
+	}
+	return 0;
+    }
+
+    if((dd = opendir(name)) == NULL)
+	return -1;
+
+    rc = 0;
+
+#ifdef HAVE_READDIR_R_3
+    while((readdir_r(dd, &result.d, &dent) == 0) && dent) {
+#elif defined(HAVE_READDIR_R_2)
+    while((dent = (struct dirent *)readdir_r(dd, &result.d)) != NULL) {
+#else
+    while((dent = readdir(dd)) != NULL) {
+#endif
+	    char *fname;
+
+	if(strcmp(dent->d_name, ".") == 0)
+	    continue;
+	if(strcmp(dent->d_name, "..") == 0)
+	    continue;
+
+	fname = cli_malloc(strlen(name) + strlen(dent->d_name) + 2, sizeof(char));
+	if(fname == NULL) {
+	    closedir(dd);
+	    return -1;
+	}
+
+	sprintf(fname, "%s\\%s", name, dent->d_name);
+	rc = cli_rmdirs(fname);
+	free(fname);
+	if(rc != 0)
+	    break;
+    }
+
+    closedir(dd);
+
+    if(rmdir(name) < 0) {
+	cli_errmsg("Can't remove temporary directory %s: %s\n", name, strerror(errno));
+	return -1;
+    }
+
+    return rc;	
+}
+#else
+int cli_rmdirs(const char *dirname)
+{
+	DIR *dd;
+	struct dirent *dent;
+#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
+	union {
+	    struct dirent d;
+	    char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
+	} result;
+#endif
+	struct stat maind, statbuf;
+	char *fname;
+	int ret;
+
+
+    chmod(dirname, 0700);
+    if((dd = opendir(dirname)) != NULL) {
+	while(stat(dirname, &maind) != -1) {
+	    if(!rmdir(dirname)) break;
+	    if(errno != ENOTEMPTY && errno != EEXIST && errno != EBADF) {
+		cli_errmsg("Can't remove temporary directory %s: %s\n", dirname, strerror(errno));
+		closedir(dd);
+		return -1;
+	    }
+
+#ifdef HAVE_READDIR_R_3
+	    while(!readdir_r(dd, &result.d, &dent) && dent) {
+#elif defined(HAVE_READDIR_R_2)
+	    while((dent = (struct dirent *) readdir_r(dd, &result.d))) {
+#else
+	    while((dent = readdir(dd))) {
+#endif
+#if	(!defined(C_CYGWIN)) && (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
+		if(dent->d_ino)
+#endif
+		{
+		    if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
+			fname = cli_malloc(strlen(dirname) + strlen(dent->d_name) + 2);
+			if(!fname) {
+			    closedir(dd);
+			    return -1;
+			}
+
+#ifdef	C_WINDOWS
+			sprintf(fname, "%s\\%s", dirname, dent->d_name);
+#else
+			sprintf(fname, "%s/%s", dirname, dent->d_name);
+#endif
+
+			/* stat the file */
+			if(lstat(fname, &statbuf) != -1) {
+			    if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) {
+				if(rmdir(fname) == -1) { /* can't be deleted */
+				    if(errno == EACCES) {
+					cli_errmsg("Can't remove some temporary directories due to access problem.\n");
+					closedir(dd);
+					free(fname);
+					return -1;
+				    }
+				    ret = cli_rmdirs(fname);
+				    if(ret) {
+					cli_warnmsg("Can't remove directory %s\n", fname);
+					free(fname);
+					closedir(dd);
+					return -1;
+				    }
+				}
+			    } else
+				if(unlink(fname) < 0) {
+				    cli_warnmsg("Couldn't remove %s: %s\n", fname, strerror(errno));
+				    free(fname);
+				    closedir(dd);
+				    return -1;
+				}
+			}
+
+			free(fname);
+		    }
+		}
+	    }
+
+	    rewinddir(dd);
+	}
+
+    } else { 
+	return -1;
+    }
+
+    closedir(dd);
+    return 0;
+}
+#endif
+
+/* Function: readn
+        Try hard to read the requested number of bytes
+*/
+int cli_readn(int fd, void *buff, unsigned int count)
+{
+        int retval;
+        unsigned int todo;
+        unsigned char *current;
+
+
+        todo = count;
+        current = (unsigned char *) buff;
+
+        do {
+                retval = read(fd, current, todo);
+                if (retval == 0) {
+                        return (count - todo);
+                }
+                if (retval < 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			cli_errmsg("cli_readn: read error: %s\n", strerror(errno));
+                        return -1;
+                }
+                todo -= retval;
+                current += retval;
+        } while (todo > 0);
+
+
+        return count;
+}
+
+/* Function: writen
+        Try hard to write the specified number of bytes
+*/
+int cli_writen(int fd, const void *buff, unsigned int count)
+{
+        int retval;
+        unsigned int todo;
+        const unsigned char *current;
+
+
+        todo = count;
+        current = (const unsigned char *) buff;
+
+        do {
+                retval = write(fd, current, todo);
+                if (retval < 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			cli_errmsg("cli_writen: write error: %s\n", strerror(errno));
+                        return -1;
+                }
+                todo -= retval;
+                current += retval;
+        } while (todo > 0);
+
+
+        return count;
+}
+
+int32_t cli_readint32(const char *buff)
+{
+	int32_t ret;
+
+#if WORDS_BIGENDIAN == 0
+    ret = *(const int32_t *) buff;
+#else
+    ret = buff[0] & 0xff;
+    ret |= (buff[1] & 0xff) << 8;
+    ret |= (buff[2] & 0xff) << 16;
+    ret |= (buff[3] & 0xff) << 24;
+#endif
+
+    return ret;
+}
+
+void cli_writeint32(char *offset, uint32_t value)
+{
+    offset[0] = value & 0xff;
+    offset[1] = (value & 0xff00) >> 8;
+    offset[2] = (value & 0xff0000) >> 16;
+    offset[3] = (value & 0xff000000) >> 24;
+}
+
+int cli_filecopy(const char *src, const char *dest)
+{
+	char *buffer;
+	int s, d, bytes;
+
+
+    if((s = open(src, O_RDONLY|O_BINARY)) == -1)
+	return -1;
+
+    if((d = open(dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, S_IRWXU)) == -1) {
+	close(s);
+	return -1;
+    }
+
+    if(!(buffer = cli_malloc(FILEBUFF)))
+	return -1;
+
+    while((bytes = cli_readn(s, buffer, FILEBUFF)) > 0)
+	cli_writen(d, buffer, bytes);
+
+    free(buffer);
+    close(s);
+
+    return close(d);
+}
+
+/* Implement a generic bitset, trog@clamav.net */
+
+#define BITS_PER_CHAR (8)
+#define BITSET_DEFAULT_SIZE (1024)
+#define FALSE (0)
+#define TRUE (1)
+
+static unsigned long nearest_power(unsigned long num)
+{
+	unsigned long n = BITSET_DEFAULT_SIZE;
+
+	while (n < num) {
+		n <<= 1;
+		if (n == 0) {
+			return num;
+		}
+	}
+	return n;
+}
+
+bitset_t *cli_bitset_init(void)
+{
+	bitset_t *bs;
+	
+	bs = cli_malloc(sizeof(bitset_t));
+	if (!bs) {
+		return NULL;
+	}
+	bs->length = BITSET_DEFAULT_SIZE;
+	bs->bitset = cli_calloc(BITSET_DEFAULT_SIZE, 1);
+	return bs;
+}
+
+void cli_bitset_free(bitset_t *bs)
+{
+	if (!bs) {
+		return;
+	}
+	if (bs->bitset) {
+		free(bs->bitset);
+	}
+	free(bs);
+}
+
+static bitset_t *bitset_realloc(bitset_t *bs, unsigned long min_size)
+{
+	unsigned long new_length;
+	
+	new_length = nearest_power(min_size);
+	bs->bitset = (unsigned char *) cli_realloc(bs->bitset, new_length);
+	if (!bs->bitset) {
+		return NULL;
+	}
+	memset(bs->bitset+bs->length, 0, new_length-bs->length);
+	bs->length = new_length;
+	return bs;
+}
+
+int cli_bitset_set(bitset_t *bs, unsigned long bit_offset)
+{
+	unsigned long char_offset;
+	
+	char_offset = bit_offset / BITS_PER_CHAR;
+	bit_offset = bit_offset % BITS_PER_CHAR;
+
+	if (char_offset >= bs->length) {
+		bs = bitset_realloc(bs, char_offset+1);
+		if (!bs) {
+			return FALSE;
+		}
+	}
+	bs->bitset[char_offset] |= ((unsigned char)1 << bit_offset);
+	return TRUE;
+}
+
+int cli_bitset_test(bitset_t *bs, unsigned long bit_offset)
+{
+	unsigned long char_offset;
+	
+	char_offset = bit_offset / BITS_PER_CHAR;
+	bit_offset = bit_offset % BITS_PER_CHAR;
+
+	if (char_offset >= bs->length) {	
+		return FALSE;
+	}
+	return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset));
+}
+
+
+/*
+ * Code from NJH
+ * Different operating systems allow different characters in their filenames
+ * FIXME: What does QNX want? There is no #ifdef C_QNX, but if there were
+ *      it may be best to treat it like MSDOS
+ */
+void
+cli_sanitise_filename(char *name)
+{
+	if(name == NULL)
+		return;
+
+	while(*name) {
+#ifdef  C_DARWIN
+		*name &= '\177';
+#endif
+		/* Also check for tab - "Heinz Martin" <Martin@hemag.ch> */
+#if     defined(MSDOS) || defined(C_CYGWIN) || defined(C_WINDOWS) || defined(C_OS2)
+		if(strchr("%/*?<>|\\\"+=,;:\t ~", *name))
+#else
+		if(*name == '/')
+#endif
+			*name = '_';
+		name++;
+	}
+}
diff -dPNur clamav-0.90.1/libclamav/scanners.c clamav-0.90.1-new/libclamav/scanners.c
--- clamav-0.90.1/libclamav/scanners.c	2007-03-02 00:44:49.000000000 +0100
+++ clamav-0.90.1-new/libclamav/scanners.c	2007-03-29 14:57:28.000000000 +0200
@@ -65,6 +65,7 @@
 #include "matcher-bm.h"
 #include "matcher.h"
 #include "unrar.h"
+#include "un7zip.h"
 #include "ole2_extract.h"
 #include "vba_extract.h"
 #include "msexpand.h"
@@ -984,6 +985,40 @@
     return 0;
 }
 
+static int cli_scan7zip(int desc, cli_ctx *ctx) {
+    const char *tmpdir;
+    char *dir;
+    int ret = CL_CLEAN;
+
+
+    cli_dbgmsg("in cli_scan7zip()\n");
+
+    if((tmpdir = getenv("TMPDIR")) == NULL)
+#ifdef P_tmpdir
+        tmpdir = P_tmpdir;
+#else
+        tmpdir = "/tmp";
+#endif
+
+   /* generate temporary directory */
+      dir = cli_gentemp(tmpdir);
+      if(mkdir(dir, 0700)) {
+        cli_errmsg("7zip: Can't create temporary directory %s\n", dir);
+        return CL_ETMPDIR;
+      }
+
+      if((ret = cli_un7zip(dir, desc)))
+        cli_dbgmsg("7zip: %s\n", cl_strerror(ret));
+      else
+        ret = cli_scandir(dir, ctx);
+
+      if(!cli_leavetemps_flag)
+        cli_rmdirs(dir);
+
+      free(dir);
+      return ret;
+}
+
 static int cli_vba_scandir(const char *dirname, cli_ctx *ctx)
 {
 	int ret = CL_CLEAN, i, fd, ofd, data_len;
@@ -1808,7 +1843,12 @@
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
 		ret = cli_scanrar(desc, ctx, 0, NULL);
 	    break;
-
+	    
+	case CL_TYPE_7ZIP:
+	    if(SCAN_ARCHIVE)
+		ret = cli_scan7zip(desc, ctx);
+	    break;
+	    
 	case CL_TYPE_ZIP:
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
 		ret = cli_scanzip(desc, ctx, 0, NULL);
diff -dPNur clamav-0.90.1/libclamav/un7zip.c clamav-0.90.1-new/libclamav/un7zip.c
--- clamav-0.90.1/libclamav/un7zip.c	1970-01-01 01:00:00.000000000 +0100
+++ clamav-0.90.1-new/libclamav/un7zip.c	2007-03-29 14:11:58.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ *  Copyright (C) 2005 McMCC <mcmcc@mail.ru>
+ *
+ *  Support check archives 7zip
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+static char const rcsid[] = "$Id: un7zip.c,v 1.0 2005/09/05 01:40:44 mcmcc Exp $";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/param.h>
+#include <u7zip.h>
+#include "clamav.h"
+#include "others.h"
+#include "un7zip.h"
+#include "mbox.h"
+#include "blob.h"
+
+int cli_un7zip(const char *dir, int desc)
+{
+    int fd, s_buff, res;
+    char buff[4096], uname[48];
+    const char *tmpdir;
+    FILE *out;
+
+    if((tmpdir = getenv("TMPDIR")) == NULL)
+#ifdef P_tmpdir
+        tmpdir = P_tmpdir;
+#else
+        tmpdir = "/tmp";
+#endif
+
+    sprintf(uname, "%s/szpXXXXXX", tmpdir);
+
+    if((fd = mkstemp(uname)) < 0 || (out = fdopen(fd, "w+")) == NULL)
+    {
+
+        cli_dbgmsg("cli_un7zip: can't generate temporary file %s or open descriptor %d.\n",
+                    uname, fd);
+        if(fd >= 0)
+            close(fd);
+        unlink(uname);
+        return CL_ETMPFILE;
+    }
+
+    while((s_buff=read(desc, buff, sizeof(buff))) > 0)
+    {
+        if(fwrite(buff, 1, s_buff, out) != s_buff)
+        {
+            cli_dbgmsg("cli_un7zip: can't write to file %s.\n", uname);
+            fclose(out);
+            close(fd);
+            unlink(uname);
+            return CL_EOPEN;
+        }
+    }
+    fclose(out);
+    close(fd);
+
+    res = un7zip(uname, dir, EXTRACT_7Z);
+    unlink(uname);
+    if(res) return CL_E7ZIP;
+    return CL_CLEAN;
+}
diff -dPNur clamav-0.90.1/libclamav/un7zip.h clamav-0.90.1-new/libclamav/un7zip.h
--- clamav-0.90.1/libclamav/un7zip.h	1970-01-01 01:00:00.000000000 +0100
+++ clamav-0.90.1-new/libclamav/un7zip.h	2007-03-29 14:11:58.000000000 +0200
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (C) 2005 McMCC <mcmcc@mail.ru>
+ *
+ *  Support check archives 7zip
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+int cli_un7zip(const char *dir, int desc);
