Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Oct 2005 15:06:48 -0300 (BRT)
From:      Marcus Alves Grando <mnag@FreeBSD.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        rob@debank.tv
Subject:   ports/87338: Update port: security/clamav many fixes
Message-ID:  <20051012180648.03FBF4E@marcus.grupos.com.br>
Resent-Message-ID: <200510121810.j9CIABe7033523@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         87338
>Category:       ports
>Synopsis:       Update port: security/clamav many fixes
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 12 18:10:11 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Marcus Alves Grando
>Release:        FreeBSD 6.0-RC1 i386
>Organization:
>Environment:
System: FreeBSD marcus.grupos.com.br 6.0-RC1 FreeBSD 6.0-RC1 #44: Wed Oct 12 12:48:00 BRT 2005 root@marcus.grupos.com.br:/space/obj/usr/src/sys/MARCUS i386


	
>Description:

Fix package list when use LIBUNRAR
If use LIBUNRAR don't use archivers/unrar
Remake patches to work without autotools

	
>How-To-Repeat:
	
>Fix:

	

--- clamav.patch begins here ---
Index: Makefile
===================================================================
RCS file: /home/pcvs/ports/security/clamav/Makefile,v
retrieving revision 1.66
diff -u -r1.66 Makefile
--- Makefile	12 Oct 2005 10:05:11 -0000	1.66
+++ Makefile	12 Oct 2005 18:00:50 -0000
@@ -7,7 +7,7 @@
 
 PORTNAME=	clamav
 PORTVERSION=	0.87
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	security
 MASTER_SITES=	${MASTER_SITE_SOURCEFORGE_EXTENDED}
 MASTER_SITE_SUBDIR=	clamav
@@ -18,7 +18,6 @@
 LIB_DEPENDS=	gmp.6:${PORTSDIR}/math/libgmp4
 RUN_DEPENDS=	lha:${PORTSDIR}/archivers/lha \
 		unarj:${PORTSDIR}/archivers/unarj \
-		unrar:${PORTSDIR}/archivers/unrar \
 		zoo:${PORTSDIR}/archivers/zoo \
 		arc:${PORTSDIR}/archivers/arc \
 		unzip:${PORTSDIR}/archivers/unzip
@@ -26,6 +25,7 @@
 OPTIONS=	MILTER "Compile the milter interface" Off \
 		CURL "Support URL downloading" Off \
 		LIBUNRAR "Support for external Unrar library" Off
+
 USE_REINPLACE=	yes
 USE_LIBTOOL_VER=15
 CONFIGURE_TARGET=	--build=${MACHINE_ARCH}-portbld-freebsd${OSREL}
@@ -127,24 +127,18 @@
 .endif
 
 .if defined(WITH_LIBUNRAR)
-WANT_AUTOMAKE_VER=      19
-USE_AUTOCONF_VER=       259
+CFLAGS+=		-DUNRAR3
+LDFLAGS+=		-lunrar
 LIB_DEPENDS+=		unrar.3:${PORTSDIR}/archivers/libunrar
-
-pre-configure:
-	cd ${WRKSRC} && \
-	${ACLOCAL} && \
-	${AUTOHEADER} && \
-	${AUTOCONF} && \
-	${AUTOMAKE}
+EXTRA_PATCHES=		${FILESDIR}/extra-patch-libunrar
+.else
+RUN_DEPENDS+=		unrar:${PORTSDIR}/archivers/unrar
+EXTRA_PATCHES=		${FILESDIR}/extra-patch-libclamav__unrarlib.h
 .endif
 
 post-patch:
 	@${REINPLACE_CMD} -e 's|-pthread -lc_r|${PTHREAD_LIBS}|g' \
 		${CONFIGURE_WRKSRC}/${CONFIGURE_SCRIPT}
-.if defined(WITH_LIBUNRAR)
-	${PATCH} -d  ${WRKSRC}/libclamav < ${PORTSDIR}/security/clamav/files/clamav-0.87-libunrar3.patch
-.endif
 
 pre-build:
 	@if ${LDCONFIG} -r | ${GREP} -qw -e -lclamav; then \
@@ -182,7 +176,6 @@
 	@${MKDIR} ${DESTDIR}${DOCSDIR}/html
 	@${INSTALL_DATA} ${INSTALL_WRKSRC}/docs/html/*.* \
 		${DESTDIR}${DOCSDIR}/html
-
 .endif
 	@${SETENV} PKG_PREFIX=${PREFIX} PKG_DESTDIR=${DESTDIR} \
 		${SH} ${PKGINSTALL} ${PREFIX} POST-INSTALL
Index: files/clamav-0.87-libunrar3.patch
===================================================================
RCS file: files/clamav-0.87-libunrar3.patch
diff -N files/clamav-0.87-libunrar3.patch
--- files/clamav-0.87-libunrar3.patch	11 Oct 2005 23:07:39 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,3236 +0,0 @@
-diff -ruN clamav-0.84.orig/libclamav/Makefile.am clamav-0.84/libclamav/Makefile.am
---- clamav-0.84.orig/libclamav/Makefile.am	2005-04-20 03:33:17.000000000 +0400
-+++ clamav-0.84/libclamav/Makefile.am	2005-05-04 02:12:02.540693464 +0400
-@@ -17,6 +17,8 @@
- 
- 
- INCLUDES = -I$(top_srcdir) -I@srcdir@/zziplib -I@srcdir@/mspack
-+CFLAGS = @CFLAGS@ -DUNRAR3
-+LDFLAGS = @LDFLAGS@ -lunrar
- 
- libclamav_la_LIBADD = @LIBCLAMAV_LIBS@
- 
-diff -ruN clamav-0.84.orig/libclamav/scanners.c clamav-0.84/libclamav/scanners.c
---- clamav-0.84.orig/libclamav/scanners.c	2005-04-29 05:31:10.000000000 +0400
-+++ clamav-0.84/libclamav/scanners.c	2005-05-04 02:12:02.543693008 +0400
-@@ -42,12 +42,13 @@
- 
- #include <mspack.h>
- 
-+#ifndef UNRAR3
- #ifdef CL_THREAD_SAFE
- #  include <pthread.h>
- pthread_mutex_t cli_scanrar_mutex = PTHREAD_MUTEX_INITIALIZER;
- #endif
- int cli_scanrar_inuse = 0;
--
-+#endif
- extern short cli_leavetemps_flag;
- 
- extern int cli_mbox(const char *dir, int desc, unsigned int options); /* FIXME */
-@@ -111,6 +112,7 @@
- static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
- 
- 
-+#ifndef UNRAR3
- #ifdef CL_THREAD_SAFE
- static void cli_unlock_mutex(void *mtx)
- {
-@@ -330,6 +332,7 @@
- 
-     return ret;
- }
-+#endif
- 
- #ifdef HAVE_ZLIB_H
- static int cli_scanzip(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
-@@ -1213,6 +1216,43 @@
-     return ret;
- }
- 
-+#ifdef UNRAR3
-+static int cli_scanrar3(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
-+{
-+	const char *tmpdir;
-+	char *dir;
-+	int ret = CL_CLEAN;
-+
-+
-+	cli_dbgmsg("in cli_scanrar3()\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("Rar3: Can't create temporary directory %s\n", dir);
-+    	    return CL_ETMPDIR;
-+        }
-+
-+        if((ret = cli_unrar3(dir, desc)))
-+    	    cli_dbgmsg("Rar3: %s\n", cl_strerror(ret));
-+        else
-+    	    ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
-+
-+        if(!cli_leavetemps_flag)
-+    	    cli_rmdirs(dir);
-+
-+        free(dir);
-+        return ret;
-+}
-+#endif
-+
- static int cli_scanmschm(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
- {
- 	char *tempname;
-@@ -1400,8 +1440,13 @@
- 
-     switch(type) {
- 	case CL_TYPE_RAR:
-+#ifdef UNRAR3
-+	    if(!DISABLE_RAR && SCAN_ARCHIVE)
-+		ret = cli_scanrar3(desc, virname, scanned, root, limits, options, arec, mrec);
-+#else
- 	    if(!DISABLE_RAR && SCAN_ARCHIVE && !cli_scanrar_inuse)
- 		ret = cli_scanrar(desc, virname, scanned, root, limits, options, arec, mrec);
-+#endif
- 	    break;
- 
- 	case CL_TYPE_ZIP:
-@@ -1538,8 +1583,17 @@
- 	 * in raw mode. Now we will try to unpack them
- 	 */
- 	case CL_TYPE_MSEXE:
-+#ifdef UNRAR3
-+	    if(!DISABLE_RAR && SCAN_ARCHIVE)
-+		ret = cli_scanrar3(desc, virname, scanned, root, limits, options, arec, mrec);
-+	    if(SCAN_PE && ret != CL_VIRUS)
-+#else
- 	    if(SCAN_PE)
-+#endif
-+	    {
-+		lseek(desc, 0, SEEK_SET);
- 		ret = cli_scanpe(desc, virname, scanned, root, limits, options, arec, mrec);
-+	    }
- 	    break;
- 
- 	default:
-diff -ruN clamav-0.84.orig/libclamav/unrarlib.c clamav-0.84/libclamav/unrarlib.c
---- clamav-0.84.orig/libclamav/unrarlib.c	2005-04-20 03:33:17.000000000 +0400
-+++ clamav-0.84/libclamav/unrarlib.c	2005-05-04 02:12:27.131955024 +0400
-@@ -1,2774 +1,119 @@
--/* It contains some changes needed for libclamav and isn't compatible with
-- * the original version, --tk
-+/*
-+ *  Copyright (C) 2004 McMCC <mcmcc@mail.ru>
-+ *
-+ *  Support check archives RAR v.3.x
-+ *
-+ *  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.
-+ *
-  */
--/* ***************************************************************************
-- **
-- **  This file is part of the UniquE RAR File Library.
-- **
-- **  Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
-- **  UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
-- **
-- **  The contents of this file are subject to the UniquE RAR File Library
-- **  License (the "unrarlib-license.txt"). You may not use this file except
-- **  in compliance with the License. You may obtain a copy of the License
-- **  at http://www.unrarlib.org/license.html.
-- **  Software distributed under the License is distributed on an "AS IS"
-- **  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
-- **
-- **  Alternatively, the contents of this file may be used under the terms
-- **  of the GNU General Public License Version 2 or later (the "GPL"), in
-- **  which case the provisions of the GPL are applicable instead of those
-- **  above. If you wish to allow use of your version of this file only
-- **  under the terms of the GPL and not to allow others to use your version
-- **  of this file under the terms of the UniquE RAR File Library License,
-- **  indicate your decision by deleting the provisions above and replace
-- **  them with the notice and other provisions required by the GPL. If you
-- **  do not delete the provisions above, a recipient may use your version
-- **  of this file under the terms of the GPL or the UniquE RAR File Library
-- **  License.
-- **
-- ************************************************************************** */
--
--/* ***************************************************************************
-- **
-- **                           UniquE RAR File Library
-- **                     The free file lib for the demoscene
-- **                   multi-OS version (Win32, Linux and SunOS)
-- **
-- *****************************************************************************
-- **
-- **   ==> Please configure the program in "unrarlib.h". <==
-- **
-- **   RAR decompression code:
-- **    (C) Eugene Roshal
-- **   Modifications to a FileLib:
-- **    (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
-- **   Linux port:
-- **    (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
-- **
-- **  The UniquE RAR File Library gives you the ability to access RAR archives
-- **  (any compression method supported in RAR v2.0 including Multimedia
-- **  Compression and encryption) directly from your program with ease an by
-- **  adding only 12kB (6kB UPX-compressed) additional code to your program.
-- **  Both solid and normal (recommended for fast random access to the files!)
-- **  archives are supported. This FileLib is made for the Demo scene, so it's
-- **  designed for easy use within your demos and intros.
-- **  Please read "licence.txt" to learn more about how you may use URARFileLib
-- **  in your productions.
-- **
-- *****************************************************************************
-- **
-- **  ==> see the "CHANGES" file to see what's new
-- **
-- ************************************************************************** */
--
--/* -- include files ------------------------------------------------------- */
--#if HAVE_CONFIG_H
--#include "clamav-config.h"
--#endif
--
--#include "unrarlib.h"                       /* include global configuration */
--#include "others.h"
--/* ------------------------------------------------------------------------ */
--
-+static char const rcsid[] = "$Id: unrarlib.c,v 1.0 2004/10/20 18:18:46 mcmcc Exp $";
- 
--
--/* -- global stuff -------------------------------------------------------- */
--#ifdef _WIN_32
--
--#include <windows.h>                        /* WIN32 definitions            */
- #include <stdio.h>
--#include <string.h>
--
--
--#define ENABLE_ACCESS
--
--#define HOST_OS     WIN_32
--
--#define FM_NORMAL   0x00
--#define FM_RDONLY   0x01
--#define FM_HIDDEN   0x02
--#define FM_SYSTEM   0x04
--#define FM_LABEL    0x08
--#define FM_DIREC    0x10
--#define FM_ARCH     0x20
--
--#define PATHDIVIDER  "\\"
--#define CPATHDIVIDER '\\'
--#define MASKALL      "*.*"
--
--#define READBINARY   "rb"
--#define READTEXT     "rt"
--#define UPDATEBINARY "r+b"
--#define CREATEBINARY "w+b"
--#define CREATETEXT   "w"
--#define APPENDTEXT   "at"
--
--#endif
--
--#ifdef _UNIX
--
--#include <stdio.h>                          /* LINUX/UNIX definitions       */
- #include <stdlib.h>
--#include <unistd.h>
--#include <ctype.h>
--#include <string.h>
- #include <errno.h>
--
--#define ENABLE_ACCESS
--
--#define HOST_OS     UNIX
--
--#define FM_LABEL    0x0000
--#define FM_DIREC    0x4000
--
--#define PATHDIVIDER  "/"
--#define CPATHDIVIDER '/'
--#define MASKALL      "*.*"
--
--#define READBINARY   "r"
--#define READTEXT     "r"
--#define UPDATEBINARY "r+"
--#define CREATEBINARY "w+"
--#define CREATETEXT   "w"
--#define APPENDTEXT   "a"
--
--
--/* emulation of the windows API and data types                              */
--/* 20-08-2000 Johannes Winkelmann, jw@tks6.net                              */
--
--typedef long    DWORD;
--typedef short   BOOL;
--#define TRUE    1
--#define FALSE   0
--
--
--#ifdef _DEBUG_LOG                           /* define macros for debugging  */
-+#include <string.h>
- #include <unistd.h>
--#include <sys/time.h>
--
--DWORD GetTickCount()
--{
--    struct timeval tv;
--    gettimeofday( &tv, 0 );
--    return (tv.tv_usec / 1000);
--}
--#endif
--
--#endif
--
--
--
--
--
--#ifdef _DEBUG_LOG                           /* define macros for debugging  */
--
--BOOL debug_log_first_start = TRUE;
--
--#define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
--#define debug_init(a); debug_init_proc(a);
--
--void debug_log_proc(char *text, char *sourcefile, int sourceline);
--void debug_init_proc(char *file_name);
--
--#else
--#define debug_log(a);	cli_dbgmsg("%s:%d %s\n", __FILE__, __LINE__, a);
--#define debug_init(a);  /* no debug this time */
--#endif
--
--
--
--
--
--#define MAXWINSIZE      0x100000
--#define MAXWINMASK      (MAXWINSIZE-1)
--#define UNP_MEMORY      MAXWINSIZE
--#define Min(x,y) (((x)<(y)) ? (x):(y))
--#define Max(x,y) (((x)>(y)) ? (x):(y))
--#define NM  260
--
--#define SIZEOF_MARKHEAD         7
--#define SIZEOF_OLDMHD           7
--#define SIZEOF_NEWMHD          13
--#define SIZEOF_OLDLHD          21
--#define SIZEOF_NEWLHD          32
--#define SIZEOF_SHORTBLOCKHEAD   7
--#define SIZEOF_LONGBLOCKHEAD   11
--#define SIZEOF_COMMHEAD        13
--#define SIZEOF_PROTECTHEAD     26
--
--
--#define PACK_VER       20                   /* version of decompression code*/
--#define UNP_VER        20
--#define PROTECT_VER    20
--
--
--enum { M_DENYREAD,M_DENYWRITE,M_DENYNONE,M_DENYALL };
--enum { FILE_EMPTY,FILE_ADD,FILE_UPDATE,FILE_COPYOLD,FILE_COPYBLOCK };
--enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
--       OPEN_ERROR,USER_ERROR,MEMORY_ERROR,USER_BREAK=255,IMM_ABORT=0x8000 };
--enum { EN_LOCK=1,EN_VOL=2 };
--enum { SD_MEMORY=1,SD_FILES=2 };
--enum { NAMES_DONTCHANGE };
--enum { LOG_ARC=1,LOG_FILE=2 };
--enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
--enum { OLD_UNPACK,NEW_UNPACK };
--
--
--#define MHD_COMMENT        2
--#define MHD_LOCK           4
--#define MHD_PACK_COMMENT   16
--#define MHD_AV             32
--#define MHD_PROTECT        64
--
--#define LHD_SPLIT_BEFORE   1
--#define LHD_SPLIT_AFTER    2
--#define LHD_PASSWORD       4
--#define LHD_COMMENT        8
--#define LHD_SOLID          16
--
--#define LHD_WINDOWMASK     0x00e0
--#define LHD_WINDOW64       0
--#define LHD_WINDOW128      32
--#define LHD_WINDOW256      64
--#define LHD_WINDOW512      96
--#define LHD_WINDOW1024     128
--#define LHD_DIRECTORY      0x00e0
--
--#define LONG_BLOCK         0x8000
--#define READSUBBLOCK       0x8000
--
--enum { ALL_HEAD=0,MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,
--       COMM_HEAD=0x75,AV_HEAD=0x76,SUB_HEAD=0x77,PROTECT_HEAD=0x78};
--enum { EA_HEAD=0x100 };
--enum { MS_DOS=0,OS2=1,WIN_32=2,UNIX=3 };
--
--
--struct MarkHeader
--{
--  UBYTE Mark[7];
--};
--
--
--struct NewMainArchiveHeader
--{
--  UWORD HeadCRC;
--  UBYTE HeadType;
--  UWORD Flags;
--  UWORD HeadSize;
--  UWORD Reserved;
--  UDWORD Reserved1;
--};
--
--
--struct NewFileHeader
--{
--  UWORD HeadCRC;
--  UBYTE HeadType;
--  UWORD Flags;
--  UWORD HeadSize;
--  UDWORD PackSize;
--  UDWORD UnpSize;
--  UBYTE HostOS;
--  UDWORD FileCRC;
--  UDWORD FileTime;
--  UBYTE UnpVer;
--  UBYTE Method;
--  UWORD NameSize;
--  UDWORD FileAttr;
--};
--
--
--struct BlockHeader
--{
--  UWORD HeadCRC;
--  UBYTE HeadType;
--  UWORD Flags;
--  UWORD HeadSize;
--  UDWORD DataSize;
--};
--
--
--struct Decode
--{
--  unsigned int MaxNum;
--  unsigned int DecodeLen[16];
--  unsigned int DecodePos[16];
--  unsigned int DecodeNum[2];
--};
--
--
--static struct MarkHeader MarkHead;
--static struct NewMainArchiveHeader NewMhd;
--static struct NewFileHeader NewLhd;
--static struct BlockHeader BlockHead;
--
--static UBYTE *TempMemory = NULL;                          /* temporary unpack-buffer      */
--static char *CommMemory = NULL;
--
--
--static UBYTE *UnpMemory = NULL;
--static char ArgName[NM];                           /* current file in rar archive  */
--static char ArcFileName[NM];                       /* file to decompress           */
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION  /* mem-to-mem decompression     */
--static  MemoryFile *MemRARFile;                   /* pointer to RAR file in memory*/
--#else
--static  FILE *ArcPtr;                             /* input RAR file handler       */
--#endif
--static char Password[255];                         /* password to decrypt files    */
--
--static unsigned char *temp_output_buffer;          /* extract files to this pointer*/
--static unsigned long *temp_output_buffer_offset;   /* size of temp. extract buffer */
--
--static int MainHeadSize;
--
--static long CurBlockPos,NextBlockPos;
--
--static unsigned long CurUnpRead;
--static long UnpPackedSize;
--static long DestUnpSize;
--
--static UDWORD HeaderCRC;
--static int Encryption;
--
--static unsigned int UnpPtr,WrPtr;
--
--static unsigned char PN1,PN2,PN3;
--static unsigned short OldKey[4];
--
--
--
--/* function header definitions                                              */
--static int ReadHeader(int BlockType);
--static BOOL ExtrFile(int desc);
--static int tread(void *stream,void *buf,unsigned len);
--static int tseek(void *stream,long offset,int fromwhere);
--/* static BOOL UnstoreFile(void); */
--static int IsArchive(void);
--static int ReadBlock(int BlockType);
--static unsigned int UnpRead(unsigned char *Addr,unsigned int Count);
--static void UnpInitData(void);
--static void Unpack(unsigned char *UnpAddr, BOOL FileFound);
--static UBYTE DecodeAudio(int Delta);
--static void DecodeNumber(struct Decode *Dec);
--static void UpdKeys(UBYTE *Buf);
--static void SetCryptKeys(char* NewPassword);
--static void SetOldKeys(char *NewPassword);
--static void DecryptBlock(unsigned char *Buf);
--static void InitCRC(void);
--static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);
--static void UnpReadBuf(int FirstBuf);
--static void ReadTables(void);
--static void ReadLastTables(void);
--static void MakeDecodeTables(unsigned char *LenTab,
--                             struct Decode *Dec,
--                             int Size);
--static int stricomp(char *Str1,char *Str2);
--/* ------------------------------------------------------------------------ */
--
--
--/* -- global functions ---------------------------------------------------- */
--
--int urarlib_get(void *output,
--                unsigned long *size,
--                char *filename,
--                int desc,
--                char *libpassword)
--/* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
-- * does everything from allocating memory, decrypting and unpacking the file
-- * from the archive. TRUE is returned if the file could be successfully
-- * extracted, else a FALSE indicates a failure.
-- */
--{
--  BOOL  retcode = FALSE;
--
--#ifdef _DEBUG_LOG
--  int  str_offs;                            /* used for debug-strings       */
--  char DebugMsg[500];                       /* used to compose debug msg    */
--
--  if(debug_log_first_start)
--  {
--    debug_log_first_start=FALSE;            /* only create a new log file   */
--    debug_init(_DEBUG_LOG_FILE);            /* on startup                   */
--  }
--
--#endif
--
--  InitCRC();                                /* init some vars               */
--
--  strcpy(ArgName, filename);                /* set file(s) to extract       */
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  MemRARFile = rarfile;                     /* set pointer to mem-RAR file  */
--#endif
--  if(libpassword != NULL)
--    strcpy(Password, libpassword);          /* init password                */
--
--  temp_output_buffer = NULL;
--  temp_output_buffer_offset=size;           /* set size of the temp buffer  */
--
--  retcode = ExtrFile(desc);                     /* unpack file now! */
--
--
--  memset(Password,0,sizeof(Password));      /* clear password               */
--
--#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  if (ArcPtr!=NULL){
--      /* FIXME: possible FILE* leak */
--      cli_dbgmsg("%s:%d NOT Close ArcPtr from fd %d\n", __FILE__, __LINE__, desc);
--      /*
--      fclose(ArcPtr);
--      lseek(desc, 0, SEEK_SET);
--      ArcPtr = NULL;
--      */
--  }
--#endif
--
--  if(UnpMemory)
--    free(UnpMemory);
--
--  if(TempMemory)
--    free(TempMemory);
--
--  if(CommMemory)
--    free(CommMemory);
--
--  UnpMemory=NULL;
--  TempMemory=NULL;
--  CommMemory=NULL;
--
--
--  if(retcode == FALSE)
--  {
--    if(temp_output_buffer)
--	free(temp_output_buffer);               /* free memory and return NULL  */
--    temp_output_buffer=NULL;
--    *(DWORD*)output=0;                      /* pointer on errors            */
--    *size=0;
--#ifdef _DEBUG_LOG
--
--
--   /* sorry for this ugly code, but older SunOS gcc compilers don't support */
--   /* white spaces within strings                                           */
--   str_offs  = sprintf(DebugMsg, "Error - couldn't extract ");
--   str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename);
--   str_offs += sprintf(DebugMsg + str_offs, " and allocated ");
--   str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size);
--   str_offs += sprintf(DebugMsg + str_offs, " of unused memory!");
--
--  } else
--  {
--    sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
--  }
--  debug_log(DebugMsg);
--#else
--  }
--#endif
--  *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
--                                            /* data                       */
--
--  return retcode;
--}
--
--
--int urarlib_list(int desc, ArchiveList_struct *list)
--{
--  ArchiveList_struct *tmp_List = NULL;
--  int NoOfFilesInArchive       = 0;         /* number of files in archive   */
--  int newdesc;
--
--#ifdef _DEBUG_LOG
--  if(debug_log_first_start)
--  {
--    debug_log_first_start=FALSE;            /* only create a new log file   */
--    debug_init(_DEBUG_LOG_FILE);            /* on startup                   */
--  }
--#endif
--
--  InitCRC();                                /* init some vars               */
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  MemRARFile         = rarfile;             /* assign pointer to RAR file   */
--  MemRARFile->offset = 0;
--  if (!IsArchive())
--  {
--    debug_log("Not a RAR file");
--    return NoOfFilesInArchive;              /* error => exit!               */
--  }
--#else
--  /* open and identify archive                                              */
--  newdesc = dup(desc);
--  cli_dbgmsg("ExtrFile(): dup(%d) = %d\n", desc, newdesc);
--  if ((ArcPtr=fdopen(newdesc,READBINARY))!=NULL)
--  {
--    if (!IsArchive())
--    {
--      cli_dbgmsg("urarlib_list(): Not a valid archive.");
--      debug_log("Not a RAR file");
--      fclose(ArcPtr);
--      lseek(desc, 0, SEEK_SET);
--      ArcPtr = NULL;
--      return NoOfFilesInArchive;            /* error => exit!               */
--    }
--  }
--  else {
--    cli_dbgmsg("urarlib_list(): Error opening file: %s", strerror(errno));
--    debug_log("Error opening file.");
--    cli_dbgmsg("%s:%d Close fd %d\n", __FILE__, __LINE__, newdesc);
--    close(newdesc);
--    return NoOfFilesInArchive;
--  }
--#endif
--
--  if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
--  {
--    cli_dbgmsg("urarlib_list(): out of memory.");
--    debug_log("Can't allocate memory for decompression!");
--    fclose(ArcPtr);
--    return NoOfFilesInArchive;
--  }
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
--#else
--  tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
--#endif
--  (*(DWORD*)list) = (DWORD)NULL;            /* init file list               */
--  /* do while file is not extracted and there's no error                    */
--  for(;;)
--  {
--    int ReadBlockResult;
--    if ((ReadBlockResult = ReadBlock(FILE_HEAD | READSUBBLOCK)) <= 0) /* read name of the next  */
--    {                                       /* file within the RAR archive  */
--      cli_dbgmsg("Couldn't read next filename from archive (I/O error): %d\n", ReadBlockResult);
--      break;                                /* error, file not found in     */
--    }                                       /* archive or I/O error         */
--    if (BlockHead.HeadType==SUB_HEAD)
--    {
--      debug_log("Sorry, sub-headers not supported.");
--      NoOfFilesInArchive = 0;
--      break;                                /* error => exit                */
--    }
--
--    if((void*)(*(DWORD*)list) == NULL)      /* first entry                  */
--    {
--      tmp_List = malloc(sizeof(ArchiveList_struct));
--      tmp_List->next = NULL;
--
--      (*(DWORD*)list) = (DWORD)tmp_List;
--
--    } else                                  /* add entry                    */
--    {
--      tmp_List->next = malloc(sizeof(ArchiveList_struct));
--      tmp_List = (ArchiveList_struct*) tmp_List->next;
--      tmp_List->next = NULL;
--    }
--
--    tmp_List->item.Name = malloc(NewLhd.NameSize + 1);
--    strcpy(tmp_List->item.Name, ArcFileName);
--    tmp_List->item.NameSize = NewLhd.NameSize;
--    tmp_List->item.PackSize = NewLhd.PackSize;
--    tmp_List->item.UnpSize = NewLhd.UnpSize;
--    tmp_List->item.HostOS = NewLhd.HostOS;
--    tmp_List->item.FileCRC = NewLhd.FileCRC;
--    tmp_List->item.FileTime = NewLhd.FileTime;
--    tmp_List->item.UnpVer = NewLhd.UnpVer;
--    tmp_List->item.Method = NewLhd.Method;
--    tmp_List->item.FileAttr = NewLhd.FileAttr;
--    tmp_List->item.Flags = NewLhd.Flags;
--
--    NoOfFilesInArchive++;                   /* count files                  */
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--    MemRARFile->offset = NextBlockPos;
--#else
--    if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
--#endif
--
--  };
--
--  /* free memory, clear password and close archive                          */
--  memset(Password,0,sizeof(Password));      /* clear password               */
--#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  if (ArcPtr!=NULL){
--      fclose(ArcPtr);
--      ArcPtr = NULL;
--      lseek(desc, 0, SEEK_SET);
--  }
--#endif
--
--  if(UnpMemory)
--    free(UnpMemory);
--
--  if(TempMemory)
--    free(TempMemory);
--
--  if(CommMemory)
--    free(CommMemory);
--
--  UnpMemory=NULL;
--  TempMemory=NULL;
--  CommMemory=NULL;
--
--  return NoOfFilesInArchive;
--}
--
--
--
--/* urarlib_freelist:
-- * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
-- * and Johannes Winkelmann who independently wrote a patch)
-- * free the memory of a ArchiveList_struct created by urarlib_list.
-- *
-- *    input: *list          pointer to an ArchiveList_struct
-- *    output: -
-- */
--
--void urarlib_freelist(ArchiveList_struct *list)
--{
--    ArchiveList_struct* tmp = list;
--
--    while ( list ) {
--        tmp = list->next;
--        free( list->item.Name );
--        free( list );
--        list = tmp;
--    }
--}
--
--
--/* ------------------------------------------------------------------------ */
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--/****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                    B L O C K   I / O                         *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************/
--
--
--
--#define GetHeaderByte(N) Header[N]
--
--#define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
--
--#define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
--                          ((UDWORD)Header[N+2]<<16)+\
--                          ((UDWORD)Header[N+3]<<24))
--
--
--int ReadBlock(int BlockType)
--{
--  struct NewFileHeader SaveFileHead;
--  int Size=0,ReadSubBlock=0;
--  static int LastBlock;
--  memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
--  if (BlockType & READSUBBLOCK) {
--    ReadSubBlock=1;
--    BlockType &= 0xff;
--  }
--  {
--    while (1)
--    {
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--      CurBlockPos=MemRARFile->offset;       /* get offset of mem-file       */
--#else
--      CurBlockPos=ftell(ArcPtr);
--#endif
--      Size=ReadHeader(FILE_HEAD);
--      if (Size!=0)
--      {
--        if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
--          return(0);
--        NextBlockPos=CurBlockPos+NewLhd.HeadSize;
--        if (NewLhd.Flags & LONG_BLOCK)
--          NextBlockPos+=NewLhd.PackSize;
--        if (NextBlockPos<=CurBlockPos)
--          return(0);
--      }
--
--      if (Size > 0 && BlockType!=SUB_HEAD)
--        LastBlock=BlockType;
--      if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
--          (NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
--        break;
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--      MemRARFile->offset = NextBlockPos;
--#else
--      tseek(ArcPtr, NextBlockPos, SEEK_SET);
--#endif
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+#include <sys/param.h>
-+#include <libunrar3/dll.hpp>
-+#include "clamav.h"
-+#include "others.h"
-+#include "unrarlib.h"
-+#include "mbox.h"
-+#include "blob.h"
-+
-+int cli_unrar3(const char *dir, int desc)
-+{
-+
-+    struct RAROpenArchiveDataEx OpenArchiveData;
-+    struct RARHeaderData HeaderData;
-+    int iReadHeaderCode, iProcessFileCode, fd, s_buff;
-+    char buff[4096], uname[48];
-+    const char *tmpdir;
-+    HANDLE hArcData;
-+    FILE *out;
-+
-+    if((tmpdir = getenv("TMPDIR")) == NULL)
-+#ifdef P_tmpdir
-+        tmpdir = P_tmpdir;
-+#else
-+        tmpdir = "/tmp";
-+#endif
-+
-+    sprintf(uname, "%s/rarXXXXXX", tmpdir);
-+
-+    if((fd = mkstemp(uname)) < 0 || (out = fdopen(fd, "w+")) == NULL)
-+    {
-+	
-+	cli_dbgmsg("cli_unrar3: 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_unrar3: can't write to file %s.\n", uname); 
-+	    fclose(out);
-+	    close(fd);
-+	    unlink(uname);
-+	    return CL_EOPEN;
-+	}
-     }
--  }
--
--  BlockHead.HeadCRC=NewLhd.HeadCRC;
--  BlockHead.HeadType=NewLhd.HeadType;
--  BlockHead.Flags=NewLhd.Flags;
--  BlockHead.HeadSize=NewLhd.HeadSize;
--  BlockHead.DataSize=NewLhd.PackSize;
--
--  if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
--
--  if((FILE_HEAD == BlockType) && (Size>0))
--  {
--    NewLhd.NameSize=Min(NewLhd.NameSize,sizeof(ArcFileName)-1);
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--    tread(MemRARFile, ArcFileName, NewLhd.NameSize);
--#else
--    tread(ArcPtr,ArcFileName,NewLhd.NameSize);
--#endif
--    ArcFileName[NewLhd.NameSize]=0;
--#ifdef _DEBUG_LOG
--    if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
--                                          NewLhd.NameSize))
--    {
--      debug_log("file header broken");
-+    fclose(out);
-+    close(fd);
-+    
-+    memset(&OpenArchiveData, 0, sizeof(OpenArchiveData));
-+	
-+    OpenArchiveData.ArcName         = uname; /* name arch */
-+    OpenArchiveData.CmtBuf          = NULL;
-+    OpenArchiveData.OpenMode        = RAR_OM_EXTRACT;
-+		    
-+    hArcData = RAROpenArchiveEx(&OpenArchiveData);
-+			
-+    if (OpenArchiveData.OpenResult != 0)
-+    {
-+        cli_dbgmsg("cli_unrar3: error archive open (%d)\n", OpenArchiveData.OpenResult);
-+	unlink(uname);
-+        return CL_EOPEN;
-+    }
-+						    
-+    HeaderData.CmtBuf = NULL;
-+									
-+    while ((iReadHeaderCode = RARReadHeader(hArcData, &HeaderData)) == 0)
-+    {
-+        iProcessFileCode = RARProcessFile(hArcData, RAR_EXTRACT, (char *)dir, NULL);
-+        if (iProcessFileCode != 0)
-+	{
-+            cli_dbgmsg("cli_unrar3: error archive extract (%d)\n", iProcessFileCode);
-+            break;
-+	}
-+		    
-     }
--#endif
--    Size+=NewLhd.NameSize;
--  } else
--  {
--    memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--    MemRARFile->offset = CurBlockPos;
--#else
--    tseek(ArcPtr,CurBlockPos,SEEK_SET);
--#endif
--  }
--
--
--  return(Size);
--}
--
--
--int ReadHeader(int BlockType)
--{
--  int Size = 0;
--  unsigned char Header[64];
--  memset(Header, 0, sizeof(Header));
--  switch(BlockType)
--  {
--    case MAIN_HEAD:
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--        Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
--#else
--        Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
--#endif
--        NewMhd.HeadCRC=(unsigned short)GetHeaderWord(0);
--        NewMhd.HeadType=GetHeaderByte(2);
--        NewMhd.Flags=(unsigned short)GetHeaderWord(3);
--        NewMhd.HeadSize=(unsigned short)GetHeaderWord(5);
--        NewMhd.Reserved=(unsigned short)GetHeaderWord(7);
--        NewMhd.Reserved1=GetHeaderDword(9);
--        HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWMHD-2);
--      break;
--    case FILE_HEAD:
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--        Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
--#else
--        Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
--#endif
--        NewLhd.HeadCRC=(unsigned short)GetHeaderWord(0);
--        NewLhd.HeadType=GetHeaderByte(2);
--        NewLhd.Flags=(unsigned short)GetHeaderWord(3);
--        NewLhd.HeadSize=(unsigned short)GetHeaderWord(5);
--        NewLhd.PackSize=GetHeaderDword(7);
--        NewLhd.UnpSize=GetHeaderDword(11);
--        NewLhd.HostOS=GetHeaderByte(15);
--        NewLhd.FileCRC=GetHeaderDword(16);
--        NewLhd.FileTime=GetHeaderDword(20);
--        NewLhd.UnpVer=GetHeaderByte(24);
--        NewLhd.Method=GetHeaderByte(25);
--        NewLhd.NameSize=(unsigned short)GetHeaderWord(26);
--        NewLhd.FileAttr=GetHeaderDword(28);
--        HeaderCRC=CalcCRC32(0xFFFFFFFFL,Header+2,SIZEOF_NEWLHD-2);
--      break;
--
--#ifdef _DEBUG_LOG
--  case COMM_HEAD:                           /* log errors in case of debug  */
--        debug_log("Comment headers not supported! "\
--                  "Please create archives without comments.");
--      break;
--  case PROTECT_HEAD:
--        debug_log("Protected headers not supported!");
--      break;
--  case ALL_HEAD:
--        debug_log("ShortBlockHeader not supported!");
--      break;
--  default:
--        debug_log("Unknown//unsupported !");
--#else
--  default:                                  /* else do nothing              */
--        break;
--#endif
--  }
--  return(Size);
-+					    
-+    RARCloseArchive(hArcData);
-+    unlink(uname);
-+    
-+    /*
-+    if (iProcessFileCode == ERAR_BAD_DATA)
-+	return CL_ERAR;
-+    */
-+    return CL_CLEAN;
- }
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                  E X T R A C T   L O O P                     *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--int IsArchive(void)
--{
--#ifdef _DEBUG_LOG
--  int  str_offs;                            /* used for debug-strings       */
--  char DebugMsg[500];                       /* used to compose debug msg    */
--#endif
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD) {
--    debug_log("IsArchive(): short read: FALSE");
--    return(FALSE);
--  }
--#else
--  if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) {
--    debug_log("IsArchive(): short read: FALSE");
--    return(FALSE);
--  }
--#endif
--  /* Old archive => error                                                   */
--  if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
--      MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
--  {
--    debug_log("Attention: format as OLD detected! Can't handle archive!");
--  }
--  else
--      /* original RAR v2.0                                                  */
--      if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original  */
--           MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
--           MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
--           MarkHead.Mark[6]==0x00) ||
--     /* "UniquE!" - header                                                  */
--          (MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' &&   /* "UniquE!" */
--           MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' &&   /* header    */
--           MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
--           MarkHead.Mark[6]=='!'))
--
--    {
--      if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD) {
--        debug_log("IsArchive(): ReadHeader() failed");
--        return(FALSE);
--      }
--    } else
--    {
--
--#ifdef _DEBUG_LOG
--     /* sorry for this ugly code, but older SunOS gcc compilers don't       */
--     /* support white spaces within strings                                 */
--     str_offs  = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
--     str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
--     str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
--     str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
--
--     debug_log(DebugMsg);
--#endif
--
--    }
--
--
--  MainHeadSize=SIZEOF_NEWMHD;
--
--  return(TRUE);
--}
--
--
--BOOL ExtrFile(int desc)
--{
--  BOOL ReturnCode=TRUE;
--  BOOL FileFound=FALSE;                     /* TRUE=use current extracted   */
--                                            /* data FALSE=throw data away,  */
--                                            /* wrong file                   */
--  int newdesc;
--
--#ifdef  _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  MemRARFile->offset = 0;                   /* start reading from offset 0  */
--  if (!IsArchive())
--  {
--    debug_log("Not a RAR file");
--    return FALSE;                           /* error => exit!               */
--  }
--
--#else
--  /* open and identify archive                                              */
--  newdesc = dup(desc);
--  cli_dbgmsg("ExtrFile(): dup(%d) = %d\n", desc, newdesc);
--  if ((ArcPtr=fdopen(newdesc,READBINARY))!=NULL)
--  {
--    if (!IsArchive())
--    {
--      debug_log("Not a RAR file");
--      fclose(ArcPtr);
--      ArcPtr = NULL;
--      return FALSE;                         /* error => exit!               */
--    }
--  } else
--  {
--    debug_log("Error opening file.");
--    return FALSE;
--  }
--#endif
--
--
--  if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
--  {
--    cli_dbgmsg("unrarlib: Can't allocate memory for decompression!");
--    return FALSE;
--  } else cli_dbgmsg("unrarlib: Allocated %d bytes.\n", UNP_MEMORY);
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
--#else
--  tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
--#endif
--
--  /* do while file is not extracted and there's no error                    */
--  do
--  {
--
--    if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next  */
--    {                                       /* file within the RAR archive  */
--/*
-- *
-- * 21.11.2000  UnQ  There's a problem with some linux distros when a file
-- *                  can not be found in an archive.
-- * 07.09.2004  ThL  Seems more like a logical bug in this lib, since it
-- *		    appears to occur once for every archive.
-- */
--
--      /*
--      debug_log("Couldn't read next filename from archive (I/O error).");
--      */
--      ReturnCode=FALSE;
--      break;                                /* error, file not found in     */
--    }                                       /* archive or I/O error         */
--    if (BlockHead.HeadType==SUB_HEAD)
--    {
--      debug_log("Sorry, sub-headers not supported.");
--      ReturnCode=FALSE;
--      break;                                /* error => exit                */
--    }
--
--
--    if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
--    /* *** file found! ***                                                  */
--    {
--      {
--	cli_dbgmsg("unrarlib: Allocating %d bytes\n", NewLhd.UnpSize);
--        if((temp_output_buffer=malloc(NewLhd.UnpSize)) == NULL) { ;/* allocate memory for the*/
--	    cli_errmsg("unrarlib: Can't malloc %d bytes\n", NewLhd.UnpSize);
--	    ReturnCode = FALSE;
--	    break;
--	}
--      }
--      *temp_output_buffer_offset=0;         /* file. The default offset     */
--                                            /* within the buffer is 0       */
--    }
--
--    /* in case of a solid archive, we need to decompress any single file till
--     * we have found the one we are looking for. In case of normal archives
--     * (recommended!!), we skip the files until we are sure that it is the
--     * one we want.
--     */
--    if((NewMhd.Flags & 0x08) || FileFound)
--    {
--      if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
--      {
--        cli_dbgmsg("unknown compression method: %d  (min=13 max=%d)\n", NewLhd.UnpVer, UNP_VER);
--        ReturnCode=FALSE;
--        break;                              /* error, can't extract file!   */
--      }
--
--      CurUnpRead=0;
--      if ((*Password!=0) && (NewLhd.Flags & LHD_PASSWORD))
--        Encryption=NewLhd.UnpVer;
--      else
--        Encryption=0;
--      if (Encryption) SetCryptKeys(Password);
--
--      UnpPackedSize=NewLhd.PackSize;
--      DestUnpSize=NewLhd.UnpSize;
--
--      if (NewLhd.Method==0x30)
--      {
--	cli_dbgmsg("unrarlib: Unstore method temporarily not supported\n");
--        /* UnstoreFile(); */
--        ReturnCode=FALSE;
--        break;                              /* error, can't extract file! */
--      } else
--      {
--	cli_dbgmsg("unrarlib: Unpack()\n");
--        Unpack(UnpMemory, FileFound);
--      }
--
--
--#ifdef _DO_CRC32_CHECK                      /* calculate CRC32              */
--      if((UBYTE*)temp_output_buffer != NULL)
--      {
--        if(NewLhd.FileCRC!=~CalcCRC32(0xFFFFFFFFL,
--                                      (UBYTE*)temp_output_buffer,
--                                      NewLhd.UnpSize))
--        {
--          debug_log("CRC32 error - file couldn't be decompressed correctly!");
--          ReturnCode=FALSE;
--          break;                              /* error, can't extract file! */
--        }
--      }
--#endif
--
--    }
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--    MemRARFile->offset = NextBlockPos;
--#else
--    if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
--#endif
--  } while(stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */
--
--  /* free memory, clear password and close archive                          */
--  if(UnpMemory)
--    free(UnpMemory);
--
--  UnpMemory=NULL;
--#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--  if (ArcPtr!=NULL){
--      fclose(ArcPtr);
--      lseek(desc, 0, SEEK_SET);
--      ArcPtr = NULL;
--  }
--#endif
--
--  return ReturnCode;
--}
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- *******             G L O B A L   F U N C T I O N S                  *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--int tread(void *stream,void *buf,unsigned len)
--{
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--
--  if(((MemRARFile->offset + len) > MemRARFile->size) || (len == 0))
--     return 0;
--
--  memcpy(buf,
--         (BYTE*)(((MemoryFile*)stream)->data)+((MemoryFile*)stream)->offset,
--         len % ((((MemoryFile*)stream)->size) - 1));
--
--  MemRARFile->offset+=len;                  /* update read pointer          */
--  return len % ((((MemoryFile*)stream)->size) - 1);
--#else
--  return(fread(buf,1,len,(FILE*)stream));
--#endif
--}
--
--
--#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--int tseek(void *stream,long offset,int fromwhere)
--{
--  return(fseek((FILE*)stream,offset,fromwhere));
--}
--#endif
--
--
--static char* strupper(char *Str)
--{
--  char *ChPtr;
--  for (ChPtr=Str;*ChPtr;ChPtr++)
--    *ChPtr=(char)toupper(*ChPtr);
--  return(Str);
--}
--
--
--int stricomp(char *Str1,char *Str2)
--/* compare strings without regard of '\' and '/'                            */
--{
--  char S1[512],S2[512];
--  char *chptr;
--
--  strncpy(S1,Str1,sizeof(S1));
--  strncpy(S2,Str2,sizeof(S2));
--
--  while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash             */
--  {
--    *chptr = '_';
--  }
--
--  while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash             */
--  {
--    *chptr = '_';
--  }
--
--  while((chptr = strchr(S1, '/')) != NULL)  /* ignore slash                 */
--  {
--    *chptr = '_';
--  }
--
--  while((chptr = strchr(S2, '/')) != NULL)  /* ignore slash                 */
--  {
--    *chptr = '_';
--  }
--
--  return(strcmp(strupper(S1),strupper(S2)));
--}
--
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                   U N P A C K   C O D E                      *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--/* *****************************
-- * ** unpack stored RAR files **
-- * *****************************/
--
--/*
--BOOL UnstoreFile(void)
--{
--  if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
--                                                NewLhd.UnpSize))==-1)
--  {
--    cli_dbgmsg("unrarlib: Read error of stored file!");
--    return FALSE;
--  }
--  return TRUE;
--}
--*/
--
--
--/* ****************************************
-- * ** RAR decompression code starts here **
-- * ****************************************/
--
--#define NC 298                              /* alphabet = {0,1,2, .,NC - 1} */
--#define DC 48
--#define RC 28
--#define BC 19
--#define MC 257
--
--enum {CODE_HUFFMAN=0,CODE_LZ=1,CODE_LZ2=2,CODE_REPEATLZ=3,CODE_CACHELZ=4,
--      CODE_STARTFILE=5,CODE_ENDFILE=6,CODE_STARTMM=8,CODE_ENDMM=7,
--      CODE_MMDELTA=9};
--
--struct AudioVariables
--{
--  int K1,K2,K3,K4,K5;
--  int D1,D2,D3,D4;
--  int LastDelta;
--  unsigned int Dif[11];
--  unsigned int ByteCount;
--  int LastChar;
--};
--
--
--#define NC 298  /* alphabet = {0, 1, 2, ..., NC - 1} */
--#define DC 48
--#define RC 28
--#define BC 19
--#define MC 257
--
--
--static struct AudioVariables AudV[4];
--
--#define GetBits()                                                 \
--        BitField = ( ( ( (UDWORD)InBuf[InAddr]   << 16 ) |        \
--                       ( (UWORD) InBuf[InAddr+1] <<  8 ) |        \
--                       (         InBuf[InAddr+2]       ) )        \
--                       >> (8-InBit) ) & 0xffff;
--
--
--#define AddBits(Bits)                          \
--        InAddr += ( InBit + (Bits) ) >> 3;     \
--        InBit  =  ( InBit + (Bits) ) &  7;
--
--static unsigned char *UnpBuf;
--static unsigned int BitField;
--static unsigned int Number;
--
--static unsigned char InBuf[8192];                  /* input read buffer            */
--
--static unsigned char UnpOldTable[MC*4];
--
--static unsigned int InAddr,InBit,ReadTop;
--
--static unsigned int LastDist,LastLength;
--static unsigned int Length,Distance;
--
--static unsigned int OldDist[4],OldDistPtr;
--
--
--static struct LitDecode
--{
--  unsigned int MaxNum;
--  unsigned int DecodeLen[16];
--  unsigned int DecodePos[16];
--  unsigned int DecodeNum[NC];
--} LD;
--
--static struct DistDecode
--{
--  unsigned int MaxNum;
--  unsigned int DecodeLen[16];
--  unsigned int DecodePos[16];
--  unsigned int DecodeNum[DC];
--} DD;
--
--static struct RepDecode
--{
--  unsigned int MaxNum;
--  unsigned int DecodeLen[16];
--  unsigned int DecodePos[16];
--  unsigned int DecodeNum[RC];
--} RD;
--
--static struct MultDecode
--{
--  unsigned int MaxNum;
--  unsigned int DecodeLen[16];
--  unsigned int DecodePos[16];
--  unsigned int DecodeNum[MC];
--} MD[4];
--
--static struct BitDecode
--{
--  unsigned int MaxNum;
--  unsigned int DecodeLen[16];
--  unsigned int DecodePos[16];
--  unsigned int DecodeNum[BC];
--} BD;
--
--static struct MultDecode *MDPtr[4]={&MD[0],&MD[1],&MD[2],&MD[3]};
--
--static int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
--
--
--void Unpack(unsigned char *UnpAddr, BOOL FileFound)
--/* *** 38.3% of all CPU time is spent within this function!!!               */
--{
--  static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
--                                  40,48,56,64,80,96,112,128,160,192,224};
--  static unsigned char LBits[]=  {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
--                                  3,3,3,4,4,4,4,5,5,5,5};
--  static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
--                        512,768,1024,1536,2048,3072,4096,6144,8192,12288,
--                        16384,24576,32768U,49152U,65536,98304,131072,196608,
--                        262144,327680,393216,458752,524288,589824,655360,
--                        720896,786432,851968,917504,983040};
--  static unsigned char DBits[]=  {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,
--                                  9,10,10,11,11,12,12,13,13,14,14,15,15,16,
--                                  16,16,16,16,16,16,16,16,16,16,16,16,16};
--  static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
--  static unsigned char SDBits[]={2,2,3, 4, 5, 6,  6,  6};
--  unsigned int Bits;
--
--
--  UnpBuf=UnpAddr;                           /* UnpAddr is a pointer to the  */
--  UnpInitData();                            /* unpack buffer                */
--  UnpReadBuf(1);
--  if (!(NewLhd.Flags & LHD_SOLID))
--     ReadTables();
--   DestUnpSize--;
--
--  while (DestUnpSize>=0)
--  {
--    UnpPtr&=MAXWINMASK;
--
--    if (InAddr>sizeof(InBuf)-30)
--      UnpReadBuf(0);
--    if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
--    {
--
--
--      if (FileFound)
--      {
--
--        if (UnpPtr<WrPtr)
--        {
--                        if((*temp_output_buffer_offset + ((0-WrPtr) & MAXWINMASK) + UnpPtr) > NewLhd.UnpSize)
--                        {
--                           debug_log("Fatal! Buffer overrun during decompression!");
--                          DestUnpSize=-1;
--
--                    } else
--                        {
--              /* copy extracted data to output buffer                         */
--              memcpy(temp_output_buffer + *temp_output_buffer_offset,
--                     &UnpBuf[WrPtr], (0-WrPtr) & MAXWINMASK);
--              /* update offset within buffer                                  */
--              *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
--              /* copy extracted data to output buffer                         */
--              memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
--                     UnpPtr);
--              /* update offset within buffer                                  */
--              *temp_output_buffer_offset+=UnpPtr;
--                        }
--        } else
--        {
--                        if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
--                        {
--                           debug_log("Fatal! Buffer overrun during decompression!");
--                          DestUnpSize=-1;
--                    } else
--                        {
--                  /* copy extracted data to output buffer                       */
--              memcpy(temp_output_buffer + *temp_output_buffer_offset,
--                     &UnpBuf[WrPtr], UnpPtr-WrPtr);
--              *temp_output_buffer_offset+=UnpPtr-WrPtr;                                                /* update offset within buffer */
--                    }
--
--            }
--      }
--
--      WrPtr=UnpPtr;
--    }
--
--    if (UnpAudioBlock)
--    {
--      DecodeNumber((struct Decode *)MDPtr[CurChannel]);
--      if (Number==256)
--      {
--        ReadTables();
--        continue;
--      }
--      UnpBuf[UnpPtr++]=DecodeAudio(Number);
--      if (++CurChannel==UnpChannels)
--        CurChannel=0;
--      DestUnpSize--;
--      continue;
--    }
--
--    DecodeNumber((struct Decode *)&LD);
--    if (Number<256)
--    {
--      UnpBuf[UnpPtr++]=(UBYTE)Number;
--      DestUnpSize--;
--      continue;
--    }
--    if (Number>269)
--    {
--      Length=LDecode[Number-=270]+3;
--      if ((Bits=LBits[Number])>0)
--      {
--        GetBits();
--        Length+=BitField>>(16-Bits);
--        AddBits(Bits);
--      }
--
--      DecodeNumber((struct Decode *)&DD);
--      Distance=DDecode[Number]+1;
--      if ((Bits=DBits[Number])>0)
--      {
--        GetBits();
--        Distance+=BitField>>(16-Bits);
--        AddBits(Bits);
--      }
--
--      if (Distance>=0x40000L)
--        Length++;
--
--      if (Distance>=0x2000)
--        Length++;
--
--       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
--       DestUnpSize-=(LastLength=Length);
--       while (Length--)
--       {
--         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
--         UnpPtr=(UnpPtr+1) & MAXWINMASK;
--       }
--
--      continue;
--    }
--    if (Number==269)
--    {
--      ReadTables();
--      continue;
--    }
--    if (Number==256)
--    {
--      Length=LastLength;
--      Distance=LastDist;
--       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
--       DestUnpSize-=(LastLength=Length);
--       while (Length--)
--       {
--         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
--         UnpPtr=(UnpPtr+1) & MAXWINMASK;
--       }
--      continue;
--    }
--    if (Number<261)
--    {
--      Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
--      DecodeNumber((struct Decode *)&RD);
--      Length=LDecode[Number]+2;
--      if ((Bits=LBits[Number])>0)
--      {
--        GetBits();
--        Length+=BitField>>(16-Bits);
--        AddBits(Bits);
--      }
--      if (Distance>=0x40000)
--        Length++;
--      if (Distance>=0x2000)
--        Length++;
--      if (Distance>=0x101)
--        Length++;
--       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
--       DestUnpSize-=(LastLength=Length);
--       while (Length--)
--       {
--         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
--         UnpPtr=(UnpPtr+1) & MAXWINMASK;
--       }
--      continue;
--    }
--    if (Number<270)
--    {
--      Distance=SDDecode[Number-=261]+1;
--      if ((Bits=SDBits[Number])>0)
--      {
--        GetBits();
--        Distance+=BitField>>(16-Bits);
--        AddBits(Bits);
--      }
--      Length=2;
--       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
--       DestUnpSize-=(LastLength=Length);
--       while (Length--)
--       {
--         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
--         UnpPtr=(UnpPtr+1) & MAXWINMASK;
--       }
--      continue;
--   }
--  }
--  ReadLastTables();
--
--  if (FileFound)                            /* flush buffer                 */
--  {
--
--    if (UnpPtr<WrPtr)
--    {
--          if((*temp_output_buffer_offset + ((0-WrPtr) & MAXWINMASK) + UnpPtr) > NewLhd.UnpSize)
--          {
--            debug_log("Fatal! Buffer overrun during decompression!");
--                DestUnpSize=-1;
--          } else
--          {
--        /* copy extracted data to output buffer                             */
--        memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
--               (0-WrPtr) & MAXWINMASK);
--        /* update offset within buffer                                      */
--        *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
--        /* copy extracted data to output buffer                             */
--        memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf, UnpPtr);
--        /* update offset within buffer                                      */
--        *temp_output_buffer_offset+=UnpPtr;
--          }
--    } else
--    {
--          if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
--          {
--                 debug_log("Fatal! Buffer overrun during decompression!");
--                DestUnpSize=-1;
--          } else
--          {
--        /* copy extracted data to output buffer                             */
--        memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
--               UnpPtr-WrPtr);
--        /* update offset within buffer                                      */
--        *temp_output_buffer_offset+=UnpPtr-WrPtr;
--          }
--    }
--  }
--
--  WrPtr=UnpPtr;
--}
--
--
--unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
--{
--  int RetCode=0;
--  unsigned int I,ReadSize,TotalRead=0;
--  unsigned char *ReadAddr;
--  ReadAddr=Addr;
--  while (Count > 0)
--  {
--    ReadSize=(unsigned int)((Count>(unsigned long)UnpPackedSize) ?
--                                                  UnpPackedSize : Count);
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--    cli_dbgmsg("unrarlib: UnpREAD: Using memory->memory decompression\n");
--    if(MemRARFile->data == NULL)
--      return(0);
--    RetCode=tread(MemRARFile, ReadAddr, ReadSize);
--#else
--    if (ArcPtr==NULL)
--      return(0);
--    RetCode=tread(ArcPtr,ReadAddr,ReadSize);
--#endif
--    CurUnpRead+=RetCode;
--    ReadAddr+=RetCode;
--    TotalRead+=RetCode;
--    Count-=RetCode;
--    UnpPackedSize-=RetCode;
--      break;
--  }
--
--  cli_dbgmsg("CurUnpRead == %d, TotalRead == %d, Count == %d, UnpPackedSize == %d\n", CurUnpRead, TotalRead, Count, UnpPackedSize);
--
--  if (RetCode!= -1)
--  {
--    RetCode=TotalRead;
--    if (Encryption)
--    {
--      if (Encryption<20)
--          {
--            cli_dbgmsg("unrarlib: Old Crypt() not supported!");
--          }
--      else
--      {
--        for (I=0;I<(unsigned int)RetCode;I+=16)
--          DecryptBlock(&Addr[I]);
--      }
--    }
--  }
--  return(RetCode);
--}
--
--
--void UnpReadBuf(int FirstBuf)
--{
--  int RetCode;
--  if (FirstBuf)
--  {
--    ReadTop=UnpRead(InBuf,sizeof(InBuf));
--    InAddr=0;
--  }
--  else
--  {
--    memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
--    InAddr&=0x1f;
--    RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
--    if (RetCode>0)
--      ReadTop=RetCode+32;
--    else
--      ReadTop=InAddr;
--  }
--}
--
--
--void ReadTables(void)
--{
--  UBYTE BitLength[BC];
--  unsigned char Table[MC*4];
--  int TableSize,N,I;
--  if (InAddr>sizeof(InBuf)-25)
--    UnpReadBuf(0);
--  GetBits();
--  UnpAudioBlock=(BitField & 0x8000);
--
--  if (!(BitField & 0x4000))
--    memset(UnpOldTable,0,sizeof(UnpOldTable));
--  AddBits(2);
--
--
--  if (UnpAudioBlock)
--  {
--    UnpChannels=((BitField>>12) & 3)+1;
--    if (CurChannel>=UnpChannels)
--      CurChannel=0;
--    AddBits(2);
--    TableSize=MC*UnpChannels;
--  }
--  else
--    TableSize=NC+DC+RC;
--
--
--  for (I=0;I<BC;I++)
--  {
--    GetBits();
--    BitLength[I]=(UBYTE)(BitField >> 12);
--    AddBits(4);
--  }
--  MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
--  I=0;
--  while (I<TableSize)
--  {
--    if (InAddr>sizeof(InBuf)-5)
--      UnpReadBuf(0);
--    DecodeNumber((struct Decode *)&BD);
--    if (Number<16) {
--      Table[I]=(Number+UnpOldTable[I]) & 0xf;
--      I++;
--    }
--    else
--      if (Number==16)
--      {
--        GetBits();
--        N=(BitField >> 14)+3;
--        AddBits(2);
--        while (N-- > 0 && I<TableSize)
--        {
--          Table[I]=Table[I-1];
--          I++;
--        }
--      }
--      else
--      {
--        if (Number==17)
--        {
--          GetBits();
--          N=(BitField >> 13)+3;
--          AddBits(3);
--        }
--        else
--        {
--          GetBits();
--          N=(BitField >> 9)+11;
--          AddBits(7);
--        }
--        while (N-- > 0 && I<TableSize)
--          Table[I++]=0;
--      }
--  }
--  if (UnpAudioBlock)
--    for (I=0;I<UnpChannels;I++)
--      MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
--  else
--  {
--    MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
--    MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
--    MakeDecodeTables(&Table[NC+DC],(struct Decode *)&RD,RC);
--  }
--  memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
--}
--
--
--static void ReadLastTables(void)
--{
--  if (ReadTop>=InAddr+5)
--  {
--    if (UnpAudioBlock)
--    {
--      DecodeNumber((struct Decode *)MDPtr[CurChannel]);
--      if (Number==256)
--        ReadTables();
--    }
--    else
--    {
--      DecodeNumber((struct Decode *)&LD);
--      if (Number==269)
--        ReadTables();
--    }
--  }
--}
--
--
--static void MakeDecodeTables(unsigned char *LenTab,
--                             struct Decode *Dec,
--                             int Size)
--{
--  int LenCount[16],TmpPos[16],I;
--  long M,N;
--  memset(LenCount,0,sizeof(LenCount));
--  for (I=0;I<Size;I++)
--    LenCount[LenTab[I] & 0xF]++;
--
--  LenCount[0]=0;
--  for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
--  {
--    N=2*(N+LenCount[I]);
--    M=N<<(15-I);
--    if (M>0xFFFF)
--      M=0xFFFF;
--    Dec->DecodeLen[I]=(unsigned int)M;
--    TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
--  }
--
--  for (I=0;I<Size;I++)
--    if (LenTab[I]!=0)
--      Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
--  Dec->MaxNum=Size;
--}
--
--
--static void DecodeNumber(struct Decode *Deco)
--/* *** 52.6% of all CPU time is spent within this function!!!               */
--{
--  unsigned int I;
--  register unsigned int N;
--  GetBits();
--
--#ifdef _USE_ASM
--
--#ifdef _WIN_32
-- __asm {
--
--    xor eax, eax
--    mov eax, BitField                       /* N=BitField & 0xFFFE; */
--    and eax, 0xFFFFFFFE
--    mov [N], eax
--    mov edx, [Deco]                         /* EAX=N, EDX=Deco */
--
--          cmp  eax, dword ptr[edx + 8*4 + 4] /* if (N<Dec->DecodeLen[8]) */
--          jae  else_G
--
--             cmp  eax, dword ptr[edx + 4*4 + 4] /* if (N<Dec->DecodeLen[4]) */
--             jae  else_F
--
--
--                cmp  eax, dword ptr[edx + 2*4 + 4] /* if (N<Dec->DecodeLen[2]) */
--                jae  else_C
--
--                   cmp  eax, dword ptr[edx + 1*4 + 4] /* if (N<Dec->DecodeLen[1]) */
--                   jae  else_1
--                   mov  I, 1                         /*  I=1; */
--                   jmp  next_1
--                 else_1:                             /* else */
--                   mov  I, 2                         /*  I=2; */
--                 next_1:
--
--                jmp  next_C
--              else_C:                             /* else */
--
--                   cmp  eax, dword ptr[edx + 3*4 + 4] /* if (N<Dec->DecodeLen[3]) */
--                   jae  else_2
--                   mov  I, 3                         /*  I=3; */
--                   jmp  next_2
--                 else_2:                             /* else */
--                   mov  I, 4                         /*  I=4; */
--                 next_2:
--
--              next_C:                             /* else */
--
--             jmp  next_F
--           else_F:
--
--
--             cmp  eax, dword ptr[edx + 6*4 + 4] /* if (N<Dec->DecodeLen[6]) */
--             jae  else_E
--
--                cmp  eax, dword ptr[edx + 5*4 + 4] /* if (N<Dec->DecodeLen[5]) */
--                jae  else_3
--                mov  I, 5                         /*  I=5; */
--                jmp  next_3
--              else_3:                             /* else */
--                mov  I, 6                         /*  I=6; */
--              next_3:
--
--             jmp  next_E
--           else_E:                             /* else */
--
--                cmp  eax, dword ptr[edx + 7*4 + 4] /* if (N<Dec->DecodeLen[7]) */
--                jae  else_4
--                mov  I, 7                         /*  I=7; */
--                jmp  next_4
--              else_4:                             /* else */
--                mov  I, 8                         /*  I=8; */
--              next_4:
--
--           next_E:
--
--           next_F:
--
--          jmp  next_G
--        else_G:
--
--          cmp  eax, dword ptr[edx + 12*4 + 4] /* if (N<Dec->DecodeLen[12]) */
--          jae  else_D
--
--             cmp  eax, dword ptr[edx + 10*4 + 4] /* if (N<Dec->DecodeLen[10]) */
--             jae  else_B
--
--                cmp  eax, dword ptr[edx + 9*4 + 4] /* if (N<Dec->DecodeLen[9]) */
--                jae  else_5
--                mov  I, 9                         /*  I=9; */
--                jmp  next_5
--              else_5:                             /* else */
--                mov  I, 10                         /*  I=10; */
--              next_5:
--
--             jmp  next_B
--           else_B:                             /* else */
--
--                cmp  eax, dword ptr[edx + 11*4 + 4] /* if (N<Dec->DecodeLen[11]) */
--                jae  else_6
--                mov  I, 11                         /*  I=11; */
--                jmp  next_6
--              else_6:                              /* else */
--                mov  I, 12                         /*  I=12; */
--              next_6:
--
--           next_B:
--
--
--          jmp  next_D
--        else_D:                             /* else */
--
--               cmp  eax, dword ptr[edx + 14*4 + 4] /* if (N<Dec->DecodeLen[14]) */
--               jae  else_A
--
--                  cmp  eax, dword ptr[edx + 13*4 + 4] /* if (N<Dec->DecodeLen[13]) */
--                  jae  else_7
--                  mov  I, 13                         /*  I=13; */
--                  jmp  next_7
--                 else_7:                             /* else */
--                  mov  I, 14                         /*  I=14; */
--                 next_7:
--
--               jmp  next_A
--              else_A:                             /* else */
--               mov  I, 15                         /*  I=15; */
--              next_A:
--
--        next_D:
--    next_G:
--}
--#else
-- __asm__ __volatile__ (
--     "andl $0xFFFFFFFE, %%eax"
--"      movl %%eax, %1"
--"          cmpl 8*4(%%edx), %%eax /* 5379 */"
--"          jae  else_G"
--""
--"             cmpl 4*4(%%edx), %%eax"
--"             jae  else_F"
--""
--"                cmpl 2*4(%%edx), %%eax"
--"                jae  else_C"
--""
--"                   cmpl 1*4(%%edx), %%eax"
--""
--"                   jae  else_1"
--"                   movl $1, %0"
--"                   jmp  next_1"
--"                 else_1:       "
--"                   movl  $2, %0"
--"                 next_1:"
--"                "
--"                jmp  next_C"
--"              else_C:          "
--""
--"                   cmpl 3*4(%%edx), %%eax "
--"                   jae  else_2"
--"                   movl  $3, %0"
--"                   jmp  next_2"
--"                 else_2:       "
--"                   movl  $4, %0"
--"                 next_2:"
--""
--"              next_C:          "
--""
--"             jmp  next_F"
--"           else_F:"
--""
--"             cmpl 6*4(%%edx), %%eax"
--"             jae  else_E"
--""
--"                cmpl 5*4(%%edx), %%eax"
--"                jae  else_3"
--"                movl  $5, %0   "
--"                jmp  next_3"
--"              else_3:          "
--"                movl  $6, %0   "
--"              next_3:"
--""
--"             jmp  next_E"
--"           else_E:             "
--""
--"                cmpl 7*4(%%edx), %%eax"
--"                jae  else_4"
--"                movl  $7, %0   "
--"                jmp  next_4"
--"              else_4:          "
--"                movl  $8, %0   "
--"              next_4:"
--""
--"           next_E:"
--""
--"           next_F:"
--""
--"          jmp  next_G"
--"        else_G:"
--""
--"          cmpl 12*4(%%edx), %%eax"
--"          jae  else_D"
--""
--"             cmpl 10*4(%%edx), %%eax"
--"             jae  else_B"
--""
--"                cmpl 9*4(%%edx), %%eax"
--"                jae  else_5"
--"                movl  $9, %0   "
--"                jmp  next_5"
--"              else_5:          "
--"                movl  $10, %0  "
--"              next_5:"
--""
--"             jmp  next_B"
--"           else_B:             "
--""
--"                cmpl 11*4(%%edx), %%eax"
--" "
--"                jae  else_6"
--"                movl  $11, %0  "
--"                jmp  next_6"
--"              else_6:          "
--"                movl  $12, %0  "
--"              next_6:"
--""
--"           next_B:"
--"      "
--"        "
--"          jmp  next_D"
--"        else_D:                "
--""
--"               cmpl 14*4(%%edx), %%eax"
--"               jae  else_A"
--""
--"                  cmpl 13*4(%%edx), %%eax"
--"                  jae  else_7"
--"                  movl  $13, %0"
--"                  jmp  next_7"
--"                 else_7:       "
--"                  movl  $14, %0"
--"                 next_7:"
--""
--"               jmp  next_A"
--"              else_A:          "
--"               movl  $15, %0   "
--"              next_A:"
--"          "
--"        next_D:                             "
--"    next_G:"
--     : "=g" (I), "=r"(N)
--     : "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
--      : "memory"
--     );
--#endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
--
--#else
--  N=BitField & 0xFFFE;
--  if (N<Deco->DecodeLen[8])  {
--    if (N<Deco->DecodeLen[4]) {
--      if (N<Deco->DecodeLen[2]) {
--        if (N<Deco->DecodeLen[1])
--          I=1;
--        else
--          I=2;
--      } else {
--        if (N<Deco->DecodeLen[3])
--          I=3;
--        else
--          I=4;
--      }
--    } else {
--      if (N<Deco->DecodeLen[6])  {
--        if (N<Deco->DecodeLen[5])
--          I=5;
--        else
--          I=6;
--      } else {
--        if (N<Deco->DecodeLen[7])
--          I=7;
--        else
--          I=8;
--      }
--   }
--  } else {
--    if (N<Deco->DecodeLen[12]) {
--      if (N<Deco->DecodeLen[10]) {
--        if (N<Deco->DecodeLen[9])
--          I=9;
--        else
--          I=10;
--      } else {
--        if (N<Deco->DecodeLen[11])
--          I=11;
--        else
--          I=12;
--      }
--    } else {
--      if (N<Deco->DecodeLen[14]) {
--        if (N<Deco->DecodeLen[13])
--          I=13;
--        else
--          I=14;
--
--      } else {
--          I=15;
--      }
--    }
--
--  }
--#endif
--
--  AddBits(I);
--  if ((N=Deco->DecodePos[I]+((N-Deco->DecodeLen[I-1])>>(16-I)))>=Deco->MaxNum)
--      N=0;
--  Number=Deco->DecodeNum[N];
--}
--
--
--void UnpInitData()
--{
--  InAddr=InBit=0;
--  if (!(NewLhd.Flags & LHD_SOLID))
--  {
--    ChannelDelta=CurChannel=0;
--
--#ifdef _USE_ASM
--
--#ifdef _WIN_32                              /* Win32 with VisualC           */
--
--    __asm {
--        push edi
--        push eax
--        push ecx
--
--        cld                                 /* increment EDI and ESI        */
--        mov  al, 0x00
--        mov  ecx, SIZE AudV
--        mov  edi, Offset AudV
--        rep  stosb                          /* clear memory                 */
--
--        mov  ecx, SIZE OldDist
--        mov  edi, Offset OldDist
--        rep  stosb                          /* clear memory                 */
--
--        mov  ecx, SIZE UnpOldTable
--        mov  edi, Offset UnpOldTable
--        rep  stosb                          /* clear memory                 */
--
--        pop  ecx
--        pop  eax
--        pop  edi
--
--
--        mov  [OldDistPtr], 0
--        mov  [LastDist], 0
--        mov  [LastLength], 0
--        mov  [UnpPtr], 0
--        mov  [WrPtr], 0
--        mov  [OldDistPtr], 0
--        mov  [LastLength], 0
--        mov  [LastDist], 0
--        mov  [UnpPtr], 0
--        mov  [WrPtr], 0
--
--    }
--    memset(UnpBuf,0,MAXWINSIZE);
--
--
--#else                    /* unix/linux on i386 cpus */
--    __asm__ __volatile (
--"        cld                                 /* increment EDI and ESI        */"
--"        movb $0x00, %%al"
--"        movl %0, %%ecx"
--"        movl %1, %%edi"
--"        rep  "
--"        stosb                              /* clear memory                 */"
--""
--"        movl %2, %%ecx"
--"        mov  %3, %%edi"
--"        rep  "
--"        stosb                              /* clear memory                 */"
--""
--"        movl %4, %%ecx"
--"        movl %5, %%edi"
--"        rep  "
--"        stosb                              /* clear memory                 */"
--""
--"        movl $0, (OldDistPtr)"
--"        movl $0, (LastDist)"
--"        movl $0, (LastLength)"
--"        movl $0, (UnpPtr)"
--"        movl $0, (WrPtr)"
--"        movl $0, (OldDistPtr)"
--"        movl $0, (LastLength)"
--"        movl $0, (LastDist)"
--"        movl $0, (UnpPtr)"
--"        movl $0, (WrPtr)"
--        :
--        : "m" ((long)sizeof(AudV)),
--          "m" ((long)AudV),
--          "m" ((long)sizeof(OldDist)),
--          "m" ((long)OldDist),
--          "m" ((long)sizeof(UnpOldTable)),
--          "m" ((long)UnpOldTable)
--        : "memory", "edi", "eax", "ecx"
--    );
--    memset(UnpBuf,0,MAXWINSIZE);
--#endif
--
--#else                                       /* unix/linux on non-i386 cpu  */
--    memset(AudV,0,sizeof(AudV));
--    memset(OldDist,0,sizeof(OldDist));
--    OldDistPtr=0;
--    LastDist=LastLength=0;
--    memset(UnpBuf,0,MAXWINSIZE);
--    memset(UnpOldTable,0,sizeof(UnpOldTable));
--    UnpPtr=WrPtr=0;
--#endif
--
--  }
--}
--
--
--UBYTE DecodeAudio(int Delta)
--{
--  struct AudioVariables *V;
--  unsigned int Ch;
--  unsigned int NumMinDif,MinDif;
--  int PCh,I;
--
--  V=&AudV[CurChannel];
--  V->ByteCount++;
--  V->D4=V->D3;
--  V->D3=V->D2;
--  V->D2=V->LastDelta-V->D1;
--  V->D1=V->LastDelta;
--  PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+
--           V->K3*V->D3+V->K4*V->D4+V->K5*ChannelDelta;
--  PCh=(PCh>>3) & 0xFF;
--
--  Ch=PCh-Delta;
--
--  I=((signed char)Delta)<<3;
--
--  V->Dif[0]+=abs(I);
--  V->Dif[1]+=abs(I-V->D1);
--  V->Dif[2]+=abs(I+V->D1);
--  V->Dif[3]+=abs(I-V->D2);
--  V->Dif[4]+=abs(I+V->D2);
--  V->Dif[5]+=abs(I-V->D3);
--  V->Dif[6]+=abs(I+V->D3);
--  V->Dif[7]+=abs(I-V->D4);
--  V->Dif[8]+=abs(I+V->D4);
--  V->Dif[9]+=abs(I-ChannelDelta);
--  V->Dif[10]+=abs(I+ChannelDelta);
--
--  ChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
--  V->LastChar=Ch;
--
--  if ((V->ByteCount & 0x1F)==0)
--  {
--    MinDif=V->Dif[0];
--    NumMinDif=0;
--    V->Dif[0]=0;
--    for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
--    {
--      if (V->Dif[I]<MinDif)
--      {
--        MinDif=V->Dif[I];
--        NumMinDif=I;
--      }
--      V->Dif[I]=0;
--    }
--    switch(NumMinDif)
--    {
--      case 1:
--        if (V->K1>=-16)
--          V->K1--;
--        break;
--      case 2:
--        if (V->K1<16)
--          V->K1++;
--        break;
--      case 3:
--        if (V->K2>=-16)
--          V->K2--;
--        break;
--      case 4:
--        if (V->K2<16)
--          V->K2++;
--        break;
--      case 5:
--        if (V->K3>=-16)
--          V->K3--;
--        break;
--      case 6:
--        if (V->K3<16)
--          V->K3++;
--        break;
--      case 7:
--        if (V->K4>=-16)
--          V->K4--;
--        break;
--      case 8:
--        if (V->K4<16)
--          V->K4++;
--        break;
--      case 9:
--        if (V->K5>=-16)
--          V->K5--;
--        break;
--      case 10:
--        if (V->K5<16)
--          V->K5++;
--        break;
--    }
--  }
--  return((UBYTE)Ch);
--}
--
--
--
--
--
--
--
--/* ***************************************************
-- * ** CRCCrypt Code - decryption engine starts here **
-- * ***************************************************/
--
--
--#define NROUNDS 32
--
--#define rol(x,n)  (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
--#define ror(x,n)  (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
--
--#define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
--           ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
--           ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
--           ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
--
--
--static UDWORD CRCTab[256];
--
--static UBYTE SubstTable[256];
--static const UBYTE InitSubstTable[256]={
--  215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221,  2, 42,
--  232,  1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
--  255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86,  6,
--   71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
--  107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
--  158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
--   97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
--  164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
--  207,120,189,210,  8,226, 41, 72,183,203,135,165,166, 60, 98,  7,
--  122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
--  131,  3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
--  224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
--  118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45,  4,148,108,
--  161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
--    0, 46,169,186, 68, 95,237, 65, 53,208,253,168,  9, 18,100, 52,
--  116,184,160, 96,109, 37, 30,106,140,104,150,  5,204,117,112, 84
--};
--
--static UDWORD Key[4];
--
--
--static void EncryptBlock(UBYTE *Buf)
--{
--  int I;
--
--  UDWORD A,B,C,D,T,TA,TB;
--#ifdef NON_INTEL_BYTE_ORDER
--  A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
--      ((UDWORD)Buf[3]<<24))^Key[0];
--  B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
--      ((UDWORD)Buf[7]<<24))^Key[1];
--  C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
--      ((UDWORD)Buf[11]<<24))^Key[2];
--  D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
--      ((UDWORD)Buf[15]<<24))^Key[3];
--#else
--  UDWORD *BufPtr;
--  BufPtr=(UDWORD *)Buf;
--  A=BufPtr[0]^Key[0];
--  B=BufPtr[1]^Key[1];
--  C=BufPtr[2]^Key[2];
--  D=BufPtr[3]^Key[3];
--#endif
--  for(I=0;I<NROUNDS;I++)
--  {
--    T=((C+rol(D,11))^Key[I&3]);
--    TA=A^substLong(T);
--    T=((D^rol(C,17))+Key[I&3]);
--    TB=B^substLong(T);
--    A=C;
--    B=D;
--    C=TA;
--    D=TB;
--  }
--#ifdef NON_INTEL_BYTE_ORDER
--  C^=Key[0];
--  Buf[0]=(UBYTE)C;
--  Buf[1]=(UBYTE)(C>>8);
--  Buf[2]=(UBYTE)(C>>16);
--  Buf[3]=(UBYTE)(C>>24);
--  D^=Key[1];
--  Buf[4]=(UBYTE)D;
--  Buf[5]=(UBYTE)(D>>8);
--  Buf[6]=(UBYTE)(D>>16);
--  Buf[7]=(UBYTE)(D>>24);
--  A^=Key[2];
--  Buf[8]=(UBYTE)A;
--  Buf[9]=(UBYTE)(A>>8);
--  Buf[10]=(UBYTE)(A>>16);
--  Buf[11]=(UBYTE)(A>>24);
--  B^=Key[3];
--  Buf[12]=(UBYTE)B;
--  Buf[13]=(UBYTE)(B>>8);
--  Buf[14]=(UBYTE)(B>>16);
--  Buf[15]=(UBYTE)(B>>24);
--#else
--  BufPtr[0]=C^Key[0];
--  BufPtr[1]=D^Key[1];
--  BufPtr[2]=A^Key[2];
--  BufPtr[3]=B^Key[3];
--#endif
--  UpdKeys(Buf);
--}
--
--
--void DecryptBlock(UBYTE *Buf)
--{
--  int I;
--  UBYTE InBuf[16];
--  UDWORD A,B,C,D,T,TA,TB;
--#ifdef NON_INTEL_BYTE_ORDER
--  A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
--      ((UDWORD)Buf[3]<<24))^Key[0];
--  B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
--      ((UDWORD)Buf[7]<<24))^Key[1];
--  C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
--      ((UDWORD)Buf[11]<<24))^Key[2];
--  D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
--      ((UDWORD)Buf[15]<<24))^Key[3];
--#else
--  UDWORD *BufPtr;
--  BufPtr=(UDWORD *)Buf;
--  A=BufPtr[0]^Key[0];                       /* xxx may be this can be       */
--  B=BufPtr[1]^Key[1];                       /* optimized in assembler       */
--  C=BufPtr[2]^Key[2];
--  D=BufPtr[3]^Key[3];
--#endif
--  memcpy(InBuf,Buf,sizeof(InBuf));
--  for(I=NROUNDS-1;I>=0;I--)
--  {
--    T=((C+rol(D,11))^Key[I&3]);
--    TA=A^substLong(T);
--    T=((D^rol(C,17))+Key[I&3]);
--    TB=B^substLong(T);
--    A=C;
--    B=D;
--    C=TA;
--    D=TB;
--  }
--#ifdef NON_INTEL_BYTE_ORDER
--  C^=Key[0];
--  Buf[0]=(UBYTE)C;
--  Buf[1]=(UBYTE)(C>>8);
--  Buf[2]=(UBYTE)(C>>16);
--  Buf[3]=(UBYTE)(C>>24);
--  D^=Key[1];
--  Buf[4]=(UBYTE)D;
--  Buf[5]=(UBYTE)(D>>8);
--  Buf[6]=(UBYTE)(D>>16);
--  Buf[7]=(UBYTE)(D>>24);
--  A^=Key[2];
--  Buf[8]=(UBYTE)A;
--  Buf[9]=(UBYTE)(A>>8);
--  Buf[10]=(UBYTE)(A>>16);
--  Buf[11]=(UBYTE)(A>>24);
--  B^=Key[3];
--  Buf[12]=(UBYTE)B;
--  Buf[13]=(UBYTE)(B>>8);
--  Buf[14]=(UBYTE)(B>>16);
--  Buf[15]=(UBYTE)(B>>24);
--#else
--  BufPtr[0]=C^Key[0];
--  BufPtr[1]=D^Key[1];
--  BufPtr[2]=A^Key[2];
--  BufPtr[3]=B^Key[3];
--#endif
--  UpdKeys(InBuf);
--}
--
--
--void UpdKeys(UBYTE *Buf)
--{
--  int I;
--  for (I=0;I<16;I+=4)
--  {
--    Key[0]^=CRCTab[Buf[I]];                 /* xxx may be I'll rewrite this */
--    Key[1]^=CRCTab[Buf[I+1]];               /* in asm for speedup           */
--    Key[2]^=CRCTab[Buf[I+2]];
--    Key[3]^=CRCTab[Buf[I+3]];
--  }
--}
--
--static void SetCryptKeys(char *NewPassword)
--{
--  unsigned int I,J,K,PswLength;
--  unsigned char N1,N2;
--  unsigned char Psw[256];
--
--#if !defined _USE_ASM
--  UBYTE Ch;
--#endif
--
--  SetOldKeys(NewPassword);
--
--  Key[0]=0xD3A3B879L;
--  Key[1]=0x3F6D12F7L;
--  Key[2]=0x7515A235L;
--  Key[3]=0xA4E7F123L;
--  memset(Psw,0,sizeof(Psw));
--  strcpy((char *)Psw,NewPassword);
--  PswLength=strlen(NewPassword);
--  memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
--
--  for (J=0;J<256;J++)
--    for (I=0;I<PswLength;I+=2)
--    {
--      N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xFF];
--      for (K=1, N1=(unsigned char)CRCTab[(Psw[I]-J)&0xFF];
--           (N1!=N2);
--           N1++, K++)
--          {
--#ifdef _USE_ASM
--
--#ifdef _WIN_32
--          __asm {
--
--                    mov ebx, Offset SubstTable
--                    mov edx, ebx
--
--                    xor ecx, ecx            /* read SubstTable[N1]... */
--                    mov cl, N1
--                    add ebx, ecx
--                    mov al, byte ptr[ebx]
--
--                    mov cl, N1              /* read SubstTable[(N1+I+K)&0xFF]... */
--                    add ecx, I
--                    add ecx, K
--                    and ecx, 0xFF
--                    add edx, ecx
--                    mov ah, byte ptr[edx]
--
--                    mov  byte ptr[ebx], ah  /* and write back */
--                    mov  byte ptr[edx], al
--
--               }
--#else
--                     __asm__ __volatile__ (
--"                    xorl %%ecx, %%ecx"
--"                    movl %2, %%ecx                     /* ecx = N1 */"
--"                    mov %%ebx, %%edx"
--"                    addl %%ecx, %%ebx"
--""
--"                    addl %0, %%ecx"
--"                    addl %1, %%ecx"
--"                    andl $0x000000FF, %%ecx"
--"                    addl %%ecx, %%edx"
--"                    "
--"                    movb (%%ebx), %%al"
--"                    movb (%%edx), %%ah"
--""
--"                    movb  %%ah, (%%ebx)     /* and write back */"
--"                    movb  %%al, (%%edx)"
--                    : : "g" ((long)I),
--                        "g" ((long)K),
--                        "g" ((long)N1),
--                        "ebx"((long)SubstTable)
--                    : "ecx", "edx"
--
--              );
--#endif
--
--#else
--            /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]);            */
--             Ch=SubstTable[N1];
--             SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
--             SubstTable[(N1+I+K)&0xFF]=Ch;
--#endif
--          }
--    }
--  for (I=0;I<PswLength;I+=16)
--    EncryptBlock(&Psw[I]);
--}
--
--
--void SetOldKeys(char *NewPassword)
--{
--  UDWORD PswCRC;
--  UBYTE Ch;
--  PswCRC=CalcCRC32(0xFFFFFFFFL,(UBYTE*)NewPassword,strlen(NewPassword));
--  OldKey[0]=(UWORD)PswCRC;
--  OldKey[1]=(UWORD)(PswCRC>>16);
--  OldKey[2]=OldKey[3]=0;
--  PN1=PN2=PN3=0;
--  while ((Ch=*NewPassword)!=0)
--  {
--    PN1+=Ch;
--    PN2^=Ch;
--    PN3+=Ch;
--    PN3=(UBYTE)rol(PN3,1);
--    OldKey[2]^=((UWORD)(Ch^CRCTab[Ch]));
--    OldKey[3]+=((UWORD)(Ch+(CRCTab[Ch]>>16)));
--    NewPassword++;
--  }
--}
--
--static short crcInitialized = 0;
--void InitCRC(void)
--{
--  int I, J;
--  UDWORD C;
--  if (crcInitialized) return;
--
--  cli_dbgmsg("%s:%d:%s Initialize CRC table\n", __FILE__, __LINE__, "InitCRC");
--  for (I=0;I<256;I++)
--  {
--    for (C=I,J=0;J<8;J++)
--      C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
--    CRCTab[I]=C;
--  }
--  crcInitialized = 1;
--}
--
--
--static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
--{
--  unsigned int I;
--  for (I=0; I<Size; I++)
--    StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
--  return(StartCRC);
--}
--
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- *******              D E B U G    F U N C T I O N S                  *******
-- *******                                                              *******
-- *******                                                              *******
-- *******                                                              *******
-- ****************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--#ifdef _DEBUG_LOG
--
--
--/* -- global stuff -------------------------------------------------------- */
--char  log_file_name[256];                   /* file name for the log file   */
--DWORD debug_start_time;                     /* starttime of debug           */
--BOOL  debug_started = FALSE;                /* debug_log writes only if     */
--                                            /* this is TRUE                 */
--/* ------------------------------------------------------------------------ */
--
--
--/* -- global functions ---------------------------------------------------- */
--void debug_init_proc(char *file_name)
--/* Create/Rewrite a log file                                                */
--{
--  FILE *fp;
--  char date[] = __DATE__;
--  char time[] = __TIME__;
--
--  debug_start_time = GetTickCount();        /* get start time               */
--  strcpy(log_file_name, file_name);         /* save file name               */
--
--  if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
--  {
--    debug_started = TRUE;                   /* enable debug                 */
--    fprintf(fp, "Debug log of UniquE's RARFileLib\n"\
--                "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
--    fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time);
--    fclose(fp);
--  }
--}
--
--
--void debug_log_proc(char *text, char *sourcefile, int sourceline)
--/* add a line to the log file                                               */
--{
--  FILE *fp;
--
--  if(debug_started == FALSE) return;        /* exit if not initialized      */
--
--  if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile  */
--
--  {
--    fprintf(fp, " %8u ms (line %u in %s):\n              - %s\n",
--            (unsigned int)(GetTickCount() - debug_start_time),
--            sourceline, sourcefile, text);
--    fclose(fp);
--  }
--}
--
--/* ------------------------------------------------------------------------ */
--#endif
--/* **************************************************************************
-- ****************************************************************************
-- ****************************************************************************
-- ************************************************************************** */
--
--
--/* end of file urarlib.c */
-diff -ruN clamav-0.84.orig/libclamav/unrarlib.h clamav-0.84/libclamav/unrarlib.h
---- clamav-0.84.orig/libclamav/unrarlib.h	2005-04-20 03:33:17.000000000 +0400
-+++ clamav-0.84/libclamav/unrarlib.h	2005-05-04 02:12:02.551691792 +0400
-@@ -1,205 +1,22 @@
--/* ***************************************************************************
-- **
-- **  This file is part of the UniquE RAR File Library.
-- **
-- **  Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
-- **  UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
-- **
-- **  The contents of this file are subject to the UniquE RAR File Library
-- **  License (the "unrarlib-license.txt"). You may not use this file except
-- **  in compliance with the License. You may obtain a copy of the License
-- **  at http://www.unrarlib.org/license.html.
-- **  Software distributed under the License is distributed on an "AS IS"
-- **  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
-- **
-- **  Alternatively, the contents of this file may be used under the terms
-- **  of the GNU General Public License Version 2 or later (the "GPL"), in
-- **  which case the provisions of the GPL are applicable instead of those
-- **  above. If you wish to allow use of your version of this file only
-- **  under the terms of the GPL and not to allow others to use your version
-- **  of this file under the terms of the UniquE RAR File Library License,
-- **  indicate your decision by deleting the provisions above and replace
-- **  them with the notice and other provisions required by the GPL. If you
-- **  do not delete the provisions above, a recipient may use your version
-- **  of this file under the terms of the GPL or the UniquE RAR File Library
-- **  License.
-- **
-- ************************************************************************** */
--
--/* include file for the "UniquE RAR File Library"  */
--/* (C) 2000-2002 by Christian Scheurer aka. UniquE */
--/* multi-OS version (Win32, Linux and SUN)         */
--
--#ifndef __URARLIB_H
--#define __URARLIB_H
--
--#ifdef __cplusplus
--extern "C"
--{
--#endif
--
--
--/* ************************************************************************ */
--/* ************************************************************************ */
--/* **                                                                    ** */
--/* **   CONFIGURATION of the UniquE RAR FileLib                          ** */
--/* **   ==> you may change the setting for the lib HERE!                 ** */
--/* **                                                                    ** */
--/* ************************************************************************ */
--/* ************************************************************************ */
--
--
--/* #define _DEBUG_LOG */                          /* generate debug messages      */
--
--#define _DO_CRC32_CHECK                     /* perform cyclical redundancy  */
--                                            /* check (CRC32) - disable this */
--                                            /* for a little speed-up        */
--/*#define _USE_ASM*/                            /*
--                                             * enable assembly extensions
--                                             * x86 cpus.
--                                             */
--
--/*#define _USE_MEMORY_TO_MEMORY_DECOMPRESSION*/ /* read file from memory or a   */
--                                            /* resource instead of reading  */
--                                            /* from a file. NOTE: you wont't*/
--                                            /*  be able to decompress from  */
--                                            /*  file if you enable this     */
--                                            /*  option!                     */
--
--
--#ifdef WIN32                                /* autodetect Win32 and Linux   */
--#define _WIN_32                             /* Win32 with VisualC           */
--#define _DEBUG_LOG_FILE "C:\\temp\\debug_unrar.txt" /* log file path        */
--#else
--#define _UNIX                               /* Linux or Unix with GCC       */
--#define _DEBUG_LOG_FILE "/tmp/debug_unrar.txt" /* log file path             */
--/*#define NON_INTEL_BYTE_ORDER*/               /* GCC on motorola systems    */
--
--#endif
--
--/* ------------------------------------------------------------------------ */
--
--/* detected by clamav/configure */
--#if 1 - WORDS_BIGENDIAN
--#define NON_INTEL_BYTE_ORDER
--#endif
--
--/* -- global type definitions --------------------------------------------- */
--
--#ifdef NON_INTEL_BYTE_ORDER
--#ifdef _USE_ASM
--#warning Disabling assembly because NON_INTEL_BYTE_ORDER is set
--#undef _USE_ASM
--#endif
--#endif
--
--#ifdef _WIN_32
--typedef unsigned char    UBYTE;             /* WIN32 definitions            */
--typedef unsigned short   UWORD;
--typedef unsigned long    UDWORD;
--#endif
--
--#ifdef _UNIX                                /* LINUX/UNIX definitions       */
--typedef unsigned char    UBYTE;
--typedef unsigned short   UWORD;
--typedef unsigned long    UDWORD;
--#endif
--
--#define RAR_FENTRY_ATTR_DIRECTORY ( 0x10 | 0x4000 )
--
--/* This structure is used for listing archive content                       */
--struct RAR20_archive_entry                  /* These infos about files are  */
--{                                           /* stored in RAR v2.0 archives  */
--  char   *Name;
--  UWORD  NameSize;
--  UDWORD PackSize;
--  UDWORD UnpSize;
--  UBYTE  HostOS;                            /* MSDOS=0,OS2=1,WIN32=2,UNIX=3 */
--  UDWORD FileCRC;
--  UDWORD FileTime;
--  UBYTE  UnpVer;
--  UBYTE  Method;
--  UDWORD FileAttr;
--  UWORD  Flags;
--};
--
--typedef struct  archivelist                 /* used to list archives        */
--{
--  struct RAR20_archive_entry item;
--  struct archivelist         *next;
--} ArchiveList_struct;
--
--
--#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
--typedef struct  memory_file                 /* used to decompress files in  */
--{                                           /* memory                       */
--  void                       *data;         /* pointer to the file data     */
--  unsigned long              size;          /* total size of the file data  */
--  unsigned long              offset;        /* offset within "memory-file"  */
--} MemoryFile;
--#endif
--
--/* -- global functions ---------------------------------------------------- */
--
--/* urarlib_get:
-- * decompresses and decrypt data from a RAR file to a buffer in system memory.
-+/*
-+ *  Copyright (C) 2004 McMCC <mcmcc@mail.ru>
-  *
-- *   input: *output         pointer to an empty char*. This pointer will show
-- *                          to the extracted data
-- *          *size           shows where to write the size of the decompressed
-- *                          file
-- *                          (**NOTE: URARLib _does_ memory allocation etc.!**)
-- *          *filename       pointer to string containing the file to decompress
-- *          *rarfile        pointer to a string with the full name and path of
-- *                          the RAR file or pointer to a RAR file in memory if
-- *                          memory-to-memory decompression is active.
-- *          *libpassword    pointer to a string with the password used to
-- *                          en-/decrypt the RAR
-- *   output: int            returns TRUE on success or FALSE on error
-- *                          (FALSE=0, TRUE=1)
-- */
--
--extern int urarlib_get(void  *output,
--                       unsigned long *size,
--                       char *filename,
--                       int desc,
--                       char *libpassword);
--
--
--
--/* urarlib_list:
-- * list the content of a RAR archive.
-+ *  Support check archives RAR v.3.x
-  *
-- *   input: *rarfile        pointer to a string with the full name and path of
-- *                          the RAR file or pointer to a RAR file in memory if
-- *                          memory-to-memory decompression is active.
-- *          *list           pointer to an ArchiveList_struct that can be
-- *                          filled with details about the archive
-- *                          to the extracted data
-- *   output: int            number of files/directories within archive
-- */
--
--extern int urarlib_list(int desc, ArchiveList_struct *list);
--
--
--/* urarlib_freelist:
-- * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
-- * and Johannes Winkelmann who independently wrote a patch)
-- * free the memory of a ArchiveList_struct created by urarlib_list.
-+ *  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.
-  *
-- *    input: *list          pointer to an ArchiveList_struct
-- *    output: -
-  */
- 
--extern void urarlib_freelist(ArchiveList_struct *list);
--
--/* ------------------------------------------------------------------------ */
--
--
--
--#ifdef __cplusplus
--}
--#endif
--
--#endif
--
-+int cli_unrar3(const char *dir, int desc);
Index: files/extra-patch-libclamav__unrarlib.h
===================================================================
RCS file: files/extra-patch-libclamav__unrarlib.h
diff -N files/extra-patch-libclamav__unrarlib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/extra-patch-libclamav__unrarlib.h	12 Oct 2005 18:00:50 -0000
@@ -0,0 +1,11 @@
+--- libclamav/unrarlib.h.orig	Fri May 13 09:07:21 2005
++++ libclamav/unrarlib.h	Fri May 13 09:07:26 2005
+@@ -198,7 +198,7 @@
+ 
+ 
+ #ifdef __cplusplus
+-};
++}
+ #endif
+ 
+ #endif
Index: files/extra-patch-libunrar
===================================================================
RCS file: files/extra-patch-libunrar
diff -N files/extra-patch-libunrar
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/extra-patch-libunrar	12 Oct 2005 18:00:51 -0000
@@ -0,0 +1,3221 @@
+--- ./libclamav/scanners.c.orig	Thu Sep 15 18:45:30 2005
++++ ./libclamav/scanners.c	Wed Oct 12 14:40:13 2005
+@@ -42,12 +42,13 @@
+ 
+ #include <mspack.h>
+ 
++#ifndef UNRAR3
+ #ifdef CL_THREAD_SAFE
+ #  include <pthread.h>
+ pthread_mutex_t cli_scanrar_mutex = PTHREAD_MUTEX_INITIALIZER;
+ #endif
+ int cli_scanrar_inuse = 0;
+-
++#endif
+ extern short cli_leavetemps_flag;
+ 
+ extern int cli_mbox(const char *dir, int desc, unsigned int options); /* FIXME */
+@@ -111,6 +112,7 @@
+ static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
+ 
+ 
++#ifndef UNRAR3
+ #ifdef CL_THREAD_SAFE
+ static void cli_unlock_mutex(void *mtx)
+ {
+@@ -330,6 +332,7 @@
+ 
+     return ret;
+ }
++#endif
+ 
+ #ifdef HAVE_ZLIB_H
+ static int cli_scanzip(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
+@@ -1216,6 +1219,43 @@
+     return ret;
+ }
+ 
++#ifdef UNRAR3
++static int cli_scanrar3(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
++{
++	const char *tmpdir;
++	char *dir;
++	int ret = CL_CLEAN;
++
++
++	cli_dbgmsg("in cli_scanrar3()\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("Rar3: Can't create temporary directory %s\n", dir);
++    	    return CL_ETMPDIR;
++        }
++
++        if((ret = cli_unrar3(dir, desc)))
++    	    cli_dbgmsg("Rar3: %s\n", cl_strerror(ret));
++        else
++    	    ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
++
++        if(!cli_leavetemps_flag)
++    	    cli_rmdirs(dir);
++
++        free(dir);
++        return ret;
++}
++#endif
++
+ static int cli_scanmschm(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
+ {
+ 	char *tempname;
+@@ -1403,8 +1443,13 @@
+ 
+     switch(type) {
+ 	case CL_TYPE_RAR:
++#ifdef UNRAR3
++	    if(!DISABLE_RAR && SCAN_ARCHIVE)
++		ret = cli_scanrar3(desc, virname, scanned, root, limits, options, arec, mrec);
++#else
+ 	    if(!DISABLE_RAR && SCAN_ARCHIVE && !cli_scanrar_inuse)
+ 		ret = cli_scanrar(desc, virname, scanned, root, limits, options, arec, mrec);
++#endif
+ 	    break;
+ 
+ 	case CL_TYPE_ZIP:
+@@ -1541,8 +1586,17 @@
+ 	 * in raw mode. Now we will try to unpack them
+ 	 */
+ 	case CL_TYPE_MSEXE:
++#ifdef UNRAR3
++	    if(!DISABLE_RAR && SCAN_ARCHIVE)
++		ret = cli_scanrar3(desc, virname, scanned, root, limits, options, arec, mrec);
++	    if(SCAN_PE && ret != CL_VIRUS)
++#else
+ 	    if(SCAN_PE)
++#endif
++	    {
++		lseek(desc, 0, SEEK_SET);
+ 		ret = cli_scanpe(desc, virname, scanned, root, limits, options, arec, mrec);
++	    }
+ 	    break;
+ 
+ 	default:
+--- ./libclamav/unrarlib.c.orig	Thu Jun 23 17:03:12 2005
++++ ./libclamav/unrarlib.c	Wed Oct 12 14:40:13 2005
+@@ -1,2774 +1,119 @@
+-/* It contains some changes needed for libclamav and isn't compatible with
+- * the original version, --tk
++/*
++ *  Copyright (C) 2004 McMCC <mcmcc@mail.ru>
++ *
++ *  Support check archives RAR v.3.x
++ *
++ *  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.
++ *
+  */
+-/* ***************************************************************************
+- **
+- **  This file is part of the UniquE RAR File Library.
+- **
+- **  Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
+- **  UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
+- **
+- **  The contents of this file are subject to the UniquE RAR File Library
+- **  License (the "unrarlib-license.txt"). You may not use this file except
+- **  in compliance with the License. You may obtain a copy of the License
+- **  at http://www.unrarlib.org/license.html.
+- **  Software distributed under the License is distributed on an "AS IS"
+- **  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
+- **
+- **  Alternatively, the contents of this file may be used under the terms
+- **  of the GNU General Public License Version 2 or later (the "GPL"), in
+- **  which case the provisions of the GPL are applicable instead of those
+- **  above. If you wish to allow use of your version of this file only
+- **  under the terms of the GPL and not to allow others to use your version
+- **  of this file under the terms of the UniquE RAR File Library License,
+- **  indicate your decision by deleting the provisions above and replace
+- **  them with the notice and other provisions required by the GPL. If you
+- **  do not delete the provisions above, a recipient may use your version
+- **  of this file under the terms of the GPL or the UniquE RAR File Library
+- **  License.
+- **
+- ************************************************************************** */
+-
+-/* ***************************************************************************
+- **
+- **                           UniquE RAR File Library
+- **                     The free file lib for the demoscene
+- **                   multi-OS version (Win32, Linux and SunOS)
+- **
+- *****************************************************************************
+- **
+- **   ==> Please configure the program in "unrarlib.h". <==
+- **
+- **   RAR decompression code:
+- **    (C) Eugene Roshal
+- **   Modifications to a FileLib:
+- **    (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
+- **   Linux port:
+- **    (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
+- **
+- **  The UniquE RAR File Library gives you the ability to access RAR archives
+- **  (any compression method supported in RAR v2.0 including Multimedia
+- **  Compression and encryption) directly from your program with ease an by
+- **  adding only 12kB (6kB UPX-compressed) additional code to your program.
+- **  Both solid and normal (recommended for fast random access to the files!)
+- **  archives are supported. This FileLib is made for the Demo scene, so it's
+- **  designed for easy use within your demos and intros.
+- **  Please read "licence.txt" to learn more about how you may use URARFileLib
+- **  in your productions.
+- **
+- *****************************************************************************
+- **
+- **  ==> see the "CHANGES" file to see what's new
+- **
+- ************************************************************************** */
+-
+-/* -- include files ------------------------------------------------------- */
+-#if HAVE_CONFIG_H
+-#include "clamav-config.h"
+-#endif
+-
+-#include "unrarlib.h"                       /* include global configuration */
+-#include "others.h"
+-/* ------------------------------------------------------------------------ */
+-
++static char const rcsid[] = "$Id: unrarlib.c,v 1.0 2004/10/20 18:18:46 mcmcc Exp $";
+ 
+-
+-/* -- global stuff -------------------------------------------------------- */
+-#ifdef _WIN_32
+-
+-#include <windows.h>                        /* WIN32 definitions            */
+ #include <stdio.h>
+-#include <string.h>
+-
+-
+-#define ENABLE_ACCESS
+-
+-#define HOST_OS     WIN_32
+-
+-#define FM_NORMAL   0x00
+-#define FM_RDONLY   0x01
+-#define FM_HIDDEN   0x02
+-#define FM_SYSTEM   0x04
+-#define FM_LABEL    0x08
+-#define FM_DIREC    0x10
+-#define FM_ARCH     0x20
+-
+-#define PATHDIVIDER  "\\"
+-#define CPATHDIVIDER '\\'
+-#define MASKALL      "*.*"
+-
+-#define READBINARY   "rb"
+-#define READTEXT     "rt"
+-#define UPDATEBINARY "r+b"
+-#define CREATEBINARY "w+b"
+-#define CREATETEXT   "w"
+-#define APPENDTEXT   "at"
+-
+-#endif
+-
+-#ifdef _UNIX
+-
+-#include <stdio.h>                          /* LINUX/UNIX definitions       */
+ #include <stdlib.h>
+-#include <unistd.h>
+-#include <ctype.h>
+-#include <string.h>
+ #include <errno.h>
+-
+-#define ENABLE_ACCESS
+-
+-#define HOST_OS     UNIX
+-
+-#define FM_LABEL    0x0000
+-#define FM_DIREC    0x4000
+-
+-#define PATHDIVIDER  "/"
+-#define CPATHDIVIDER '/'
+-#define MASKALL      "*.*"
+-
+-#define READBINARY   "r"
+-#define READTEXT     "r"
+-#define UPDATEBINARY "r+"
+-#define CREATEBINARY "w+"
+-#define CREATETEXT   "w"
+-#define APPENDTEXT   "a"
+-
+-
+-/* emulation of the windows API and data types                              */
+-/* 20-08-2000 Johannes Winkelmann, jw@tks6.net                              */
+-
+-typedef long    DWORD;
+-typedef short   BOOL;
+-#define TRUE    1
+-#define FALSE   0
+-
+-
+-#ifdef _DEBUG_LOG                           /* define macros for debugging  */
++#include <string.h>
+ #include <unistd.h>
+-#include <sys/time.h>
+-
+-DWORD GetTickCount()
+-{
+-    struct timeval tv;
+-    gettimeofday( &tv, 0 );
+-    return (tv.tv_usec / 1000);
+-}
+-#endif
+-
+-#endif
+-
+-
+-
+-
+-
+-#ifdef _DEBUG_LOG                           /* define macros for debugging  */
+-
+-BOOL debug_log_first_start = TRUE;
+-
+-#define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
+-#define debug_init(a); debug_init_proc(a);
+-
+-void debug_log_proc(char *text, char *sourcefile, int sourceline);
+-void debug_init_proc(char *file_name);
+-
+-#else
+-#define debug_log(a);	cli_dbgmsg("%s:%d %s\n", __FILE__, __LINE__, a);
+-#define debug_init(a);  /* no debug this time */
+-#endif
+-
+-
+-
+-
+-
+-#define MAXWINSIZE      0x100000
+-#define MAXWINMASK      (MAXWINSIZE-1)
+-#define UNP_MEMORY      MAXWINSIZE
+-#define Min(x,y) (((x)<(y)) ? (x):(y))
+-#define Max(x,y) (((x)>(y)) ? (x):(y))
+-#define NM  260
+-
+-#define SIZEOF_MARKHEAD         7
+-#define SIZEOF_OLDMHD           7
+-#define SIZEOF_NEWMHD          13
+-#define SIZEOF_OLDLHD          21
+-#define SIZEOF_NEWLHD          32
+-#define SIZEOF_SHORTBLOCKHEAD   7
+-#define SIZEOF_LONGBLOCKHEAD   11
+-#define SIZEOF_COMMHEAD        13
+-#define SIZEOF_PROTECTHEAD     26
+-
+-
+-#define PACK_VER       20                   /* version of decompression code*/
+-#define UNP_VER        20
+-#define PROTECT_VER    20
+-
+-
+-enum { M_DENYREAD,M_DENYWRITE,M_DENYNONE,M_DENYALL };
+-enum { FILE_EMPTY,FILE_ADD,FILE_UPDATE,FILE_COPYOLD,FILE_COPYBLOCK };
+-enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
+-       OPEN_ERROR,USER_ERROR,MEMORY_ERROR,USER_BREAK=255,IMM_ABORT=0x8000 };
+-enum { EN_LOCK=1,EN_VOL=2 };
+-enum { SD_MEMORY=1,SD_FILES=2 };
+-enum { NAMES_DONTCHANGE };
+-enum { LOG_ARC=1,LOG_FILE=2 };
+-enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
+-enum { OLD_UNPACK,NEW_UNPACK };
+-
+-
+-#define MHD_COMMENT        2
+-#define MHD_LOCK           4
+-#define MHD_PACK_COMMENT   16
+-#define MHD_AV             32
+-#define MHD_PROTECT        64
+-
+-#define LHD_SPLIT_BEFORE   1
+-#define LHD_SPLIT_AFTER    2
+-#define LHD_PASSWORD       4
+-#define LHD_COMMENT        8
+-#define LHD_SOLID          16
+-
+-#define LHD_WINDOWMASK     0x00e0
+-#define LHD_WINDOW64       0
+-#define LHD_WINDOW128      32
+-#define LHD_WINDOW256      64
+-#define LHD_WINDOW512      96
+-#define LHD_WINDOW1024     128
+-#define LHD_DIRECTORY      0x00e0
+-
+-#define LONG_BLOCK         0x8000
+-#define READSUBBLOCK       0x8000
+-
+-enum { ALL_HEAD=0,MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,
+-       COMM_HEAD=0x75,AV_HEAD=0x76,SUB_HEAD=0x77,PROTECT_HEAD=0x78};
+-enum { EA_HEAD=0x100 };
+-enum { MS_DOS=0,OS2=1,WIN_32=2,UNIX=3 };
+-
+-
+-struct MarkHeader
+-{
+-  UBYTE Mark[7];
+-};
+-
+-
+-struct NewMainArchiveHeader
+-{
+-  UWORD HeadCRC;
+-  UBYTE HeadType;
+-  UWORD Flags;
+-  UWORD HeadSize;
+-  UWORD Reserved;
+-  UDWORD Reserved1;
+-};
+-
+-
+-struct NewFileHeader
+-{
+-  UWORD HeadCRC;
+-  UBYTE HeadType;
+-  UWORD Flags;
+-  UWORD HeadSize;
+-  UDWORD PackSize;
+-  UDWORD UnpSize;
+-  UBYTE HostOS;
+-  UDWORD FileCRC;
+-  UDWORD FileTime;
+-  UBYTE UnpVer;
+-  UBYTE Method;
+-  UWORD NameSize;
+-  UDWORD FileAttr;
+-};
+-
+-
+-struct BlockHeader
+-{
+-  UWORD HeadCRC;
+-  UBYTE HeadType;
+-  UWORD Flags;
+-  UWORD HeadSize;
+-  UDWORD DataSize;
+-};
+-
+-
+-struct Decode
+-{
+-  unsigned int MaxNum;
+-  unsigned int DecodeLen[16];
+-  unsigned int DecodePos[16];
+-  unsigned int DecodeNum[2];
+-};
+-
+-
+-static struct MarkHeader MarkHead;
+-static struct NewMainArchiveHeader NewMhd;
+-static struct NewFileHeader NewLhd;
+-static struct BlockHeader BlockHead;
+-
+-static UBYTE *TempMemory = NULL;                          /* temporary unpack-buffer      */
+-static char *CommMemory = NULL;
+-
+-
+-static UBYTE *UnpMemory = NULL;
+-static char ArgName[NM];                           /* current file in rar archive  */
+-static char ArcFileName[NM];                       /* file to decompress           */
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION  /* mem-to-mem decompression     */
+-static  MemoryFile *MemRARFile;                   /* pointer to RAR file in memory*/
+-#else
+-static  FILE *ArcPtr;                             /* input RAR file handler       */
+-#endif
+-static char Password[255];                         /* password to decrypt files    */
+-
+-static unsigned char *temp_output_buffer;          /* extract files to this pointer*/
+-static unsigned long *temp_output_buffer_offset;   /* size of temp. extract buffer */
+-
+-static int MainHeadSize;
+-
+-static long CurBlockPos,NextBlockPos;
+-
+-static unsigned long CurUnpRead;
+-static long UnpPackedSize;
+-static long DestUnpSize;
+-
+-static UDWORD HeaderCRC;
+-static int Encryption;
+-
+-static unsigned int UnpPtr,WrPtr;
+-
+-static unsigned char PN1,PN2,PN3;
+-static unsigned short OldKey[4];
+-
+-
+-
+-/* function header definitions                                              */
+-static int ReadHeader(int BlockType);
+-static BOOL ExtrFile(int desc);
+-static int tread(void *stream,void *buf,unsigned len);
+-static int tseek(void *stream,long offset,int fromwhere);
+-/* static BOOL UnstoreFile(void); */
+-static int IsArchive(void);
+-static int ReadBlock(int BlockType);
+-static unsigned int UnpRead(unsigned char *Addr,unsigned int Count);
+-static void UnpInitData(void);
+-static void Unpack(unsigned char *UnpAddr, BOOL FileFound);
+-static UBYTE DecodeAudio(int Delta);
+-static void DecodeNumber(struct Decode *Dec);
+-static void UpdKeys(UBYTE *Buf);
+-static void SetCryptKeys(char* NewPassword);
+-static void SetOldKeys(char *NewPassword);
+-static void DecryptBlock(unsigned char *Buf);
+-static void InitCRC(void);
+-static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);
+-static void UnpReadBuf(int FirstBuf);
+-static void ReadTables(void);
+-static void ReadLastTables(void);
+-static void MakeDecodeTables(unsigned char *LenTab,
+-                             struct Decode *Dec,
+-                             int Size);
+-static int stricomp(char *Str1,char *Str2);
+-/* ------------------------------------------------------------------------ */
+-
+-
+-/* -- global functions ---------------------------------------------------- */
+-
+-int urarlib_get(void *output,
+-                unsigned long *size,
+-                char *filename,
+-                int desc,
+-                char *libpassword)
+-/* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
+- * does everything from allocating memory, decrypting and unpacking the file
+- * from the archive. TRUE is returned if the file could be successfully
+- * extracted, else a FALSE indicates a failure.
+- */
+-{
+-  BOOL  retcode = FALSE;
+-
+-#ifdef _DEBUG_LOG
+-  int  str_offs;                            /* used for debug-strings       */
+-  char DebugMsg[500];                       /* used to compose debug msg    */
+-
+-  if(debug_log_first_start)
+-  {
+-    debug_log_first_start=FALSE;            /* only create a new log file   */
+-    debug_init(_DEBUG_LOG_FILE);            /* on startup                   */
+-  }
+-
+-#endif
+-
+-  InitCRC();                                /* init some vars               */
+-
+-  strcpy(ArgName, filename);                /* set file(s) to extract       */
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  MemRARFile = rarfile;                     /* set pointer to mem-RAR file  */
+-#endif
+-  if(libpassword != NULL)
+-    strcpy(Password, libpassword);          /* init password                */
+-
+-  temp_output_buffer = NULL;
+-  temp_output_buffer_offset=size;           /* set size of the temp buffer  */
+-
+-  retcode = ExtrFile(desc);                     /* unpack file now! */
+-
+-
+-  memset(Password,0,sizeof(Password));      /* clear password               */
+-
+-#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  if (ArcPtr!=NULL){
+-      /* FIXME: possible FILE* leak */
+-      cli_dbgmsg("%s:%d NOT Close ArcPtr from fd %d\n", __FILE__, __LINE__, desc);
+-      /*
+-      fclose(ArcPtr);
+-      lseek(desc, 0, SEEK_SET);
+-      ArcPtr = NULL;
+-      */
+-  }
+-#endif
+-
+-  if(UnpMemory)
+-    free(UnpMemory);
+-
+-  if(TempMemory)
+-    free(TempMemory);
+-
+-  if(CommMemory)
+-    free(CommMemory);
+-
+-  UnpMemory=NULL;
+-  TempMemory=NULL;
+-  CommMemory=NULL;
+-
+-
+-  if(retcode == FALSE)
+-  {
+-    if(temp_output_buffer)
+-	free(temp_output_buffer);               /* free memory and return NULL  */
+-    temp_output_buffer=NULL;
+-    *(DWORD*)output=0;                      /* pointer on errors            */
+-    *size=0;
+-#ifdef _DEBUG_LOG
+-
+-
+-   /* sorry for this ugly code, but older SunOS gcc compilers don't support */
+-   /* white spaces within strings                                           */
+-   str_offs  = sprintf(DebugMsg, "Error - couldn't extract ");
+-   str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename);
+-   str_offs += sprintf(DebugMsg + str_offs, " and allocated ");
+-   str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size);
+-   str_offs += sprintf(DebugMsg + str_offs, " of unused memory!");
+-
+-  } else
+-  {
+-    sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
+-  }
+-  debug_log(DebugMsg);
+-#else
+-  }
+-#endif
+-  *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
+-                                            /* data                       */
+-
+-  return retcode;
+-}
+-
+-
+-int urarlib_list(int desc, ArchiveList_struct *list)
+-{
+-  ArchiveList_struct *tmp_List = NULL;
+-  int NoOfFilesInArchive       = 0;         /* number of files in archive   */
+-  int newdesc;
+-
+-#ifdef _DEBUG_LOG
+-  if(debug_log_first_start)
+-  {
+-    debug_log_first_start=FALSE;            /* only create a new log file   */
+-    debug_init(_DEBUG_LOG_FILE);            /* on startup                   */
+-  }
+-#endif
+-
+-  InitCRC();                                /* init some vars               */
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  MemRARFile         = rarfile;             /* assign pointer to RAR file   */
+-  MemRARFile->offset = 0;
+-  if (!IsArchive())
+-  {
+-    debug_log("Not a RAR file");
+-    return NoOfFilesInArchive;              /* error => exit!               */
+-  }
+-#else
+-  /* open and identify archive                                              */
+-  newdesc = dup(desc);
+-  cli_dbgmsg("ExtrFile(): dup(%d) = %d\n", desc, newdesc);
+-  if ((ArcPtr=fdopen(newdesc,READBINARY))!=NULL)
+-  {
+-    if (!IsArchive())
+-    {
+-      cli_dbgmsg("urarlib_list(): Not a valid archive.");
+-      debug_log("Not a RAR file");
+-      fclose(ArcPtr);
+-      lseek(desc, 0, SEEK_SET);
+-      ArcPtr = NULL;
+-      return NoOfFilesInArchive;            /* error => exit!               */
+-    }
+-  }
+-  else {
+-    cli_dbgmsg("urarlib_list(): Error opening file: %s", strerror(errno));
+-    debug_log("Error opening file.");
+-    cli_dbgmsg("%s:%d Close fd %d\n", __FILE__, __LINE__, newdesc);
+-    close(newdesc);
+-    return NoOfFilesInArchive;
+-  }
+-#endif
+-
+-  if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
+-  {
+-    cli_dbgmsg("urarlib_list(): out of memory.");
+-    debug_log("Can't allocate memory for decompression!");
+-    fclose(ArcPtr);
+-    return NoOfFilesInArchive;
+-  }
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
+-#else
+-  tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
+-#endif
+-  (*(DWORD*)list) = (DWORD)NULL;            /* init file list               */
+-  /* do while file is not extracted and there's no error                    */
+-  for(;;)
+-  {
+-    int ReadBlockResult;
+-    if ((ReadBlockResult = ReadBlock(FILE_HEAD | READSUBBLOCK)) <= 0) /* read name of the next  */
+-    {                                       /* file within the RAR archive  */
+-      cli_dbgmsg("Couldn't read next filename from archive (I/O error): %d\n", ReadBlockResult);
+-      break;                                /* error, file not found in     */
+-    }                                       /* archive or I/O error         */
+-    if (BlockHead.HeadType==SUB_HEAD)
+-    {
+-      debug_log("Sorry, sub-headers not supported.");
+-      NoOfFilesInArchive = 0;
+-      break;                                /* error => exit                */
+-    }
+-
+-    if((void*)(*(DWORD*)list) == NULL)      /* first entry                  */
+-    {
+-      tmp_List = malloc(sizeof(ArchiveList_struct));
+-      tmp_List->next = NULL;
+-
+-      (*(DWORD*)list) = (DWORD)tmp_List;
+-
+-    } else                                  /* add entry                    */
+-    {
+-      tmp_List->next = malloc(sizeof(ArchiveList_struct));
+-      tmp_List = (ArchiveList_struct*) tmp_List->next;
+-      tmp_List->next = NULL;
+-    }
+-
+-    tmp_List->item.Name = malloc(NewLhd.NameSize + 1);
+-    strcpy(tmp_List->item.Name, ArcFileName);
+-    tmp_List->item.NameSize = NewLhd.NameSize;
+-    tmp_List->item.PackSize = NewLhd.PackSize;
+-    tmp_List->item.UnpSize = NewLhd.UnpSize;
+-    tmp_List->item.HostOS = NewLhd.HostOS;
+-    tmp_List->item.FileCRC = NewLhd.FileCRC;
+-    tmp_List->item.FileTime = NewLhd.FileTime;
+-    tmp_List->item.UnpVer = NewLhd.UnpVer;
+-    tmp_List->item.Method = NewLhd.Method;
+-    tmp_List->item.FileAttr = NewLhd.FileAttr;
+-    tmp_List->item.Flags = NewLhd.Flags;
+-
+-    NoOfFilesInArchive++;                   /* count files                  */
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-    MemRARFile->offset = NextBlockPos;
+-#else
+-    if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
+-#endif
+-
+-  };
+-
+-  /* free memory, clear password and close archive                          */
+-  memset(Password,0,sizeof(Password));      /* clear password               */
+-#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  if (ArcPtr!=NULL){
+-      fclose(ArcPtr);
+-      ArcPtr = NULL;
+-      lseek(desc, 0, SEEK_SET);
+-  }
+-#endif
+-
+-  if(UnpMemory)
+-    free(UnpMemory);
+-
+-  if(TempMemory)
+-    free(TempMemory);
+-
+-  if(CommMemory)
+-    free(CommMemory);
+-
+-  UnpMemory=NULL;
+-  TempMemory=NULL;
+-  CommMemory=NULL;
+-
+-  return NoOfFilesInArchive;
+-}
+-
+-
+-
+-/* urarlib_freelist:
+- * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
+- * and Johannes Winkelmann who independently wrote a patch)
+- * free the memory of a ArchiveList_struct created by urarlib_list.
+- *
+- *    input: *list          pointer to an ArchiveList_struct
+- *    output: -
+- */
+-
+-void urarlib_freelist(ArchiveList_struct *list)
+-{
+-    ArchiveList_struct* tmp = list;
+-
+-    while ( list ) {
+-        tmp = list->next;
+-        free( list->item.Name );
+-        free( list );
+-        list = tmp;
+-    }
+-}
+-
+-
+-/* ------------------------------------------------------------------------ */
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-/****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                    B L O C K   I / O                         *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************/
+-
+-
+-
+-#define GetHeaderByte(N) Header[N]
+-
+-#define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
+-
+-#define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
+-                          ((UDWORD)Header[N+2]<<16)+\
+-                          ((UDWORD)Header[N+3]<<24))
+-
+-
+-int ReadBlock(int BlockType)
+-{
+-  struct NewFileHeader SaveFileHead;
+-  int Size=0,ReadSubBlock=0;
+-  static int LastBlock;
+-  memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
+-  if (BlockType & READSUBBLOCK) {
+-    ReadSubBlock=1;
+-    BlockType &= 0xff;
+-  }
+-  {
+-    while (1)
+-    {
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-      CurBlockPos=MemRARFile->offset;       /* get offset of mem-file       */
+-#else
+-      CurBlockPos=ftell(ArcPtr);
+-#endif
+-      Size=ReadHeader(FILE_HEAD);
+-      if (Size!=0)
+-      {
+-        if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
+-          return(0);
+-        NextBlockPos=CurBlockPos+NewLhd.HeadSize;
+-        if (NewLhd.Flags & LONG_BLOCK)
+-          NextBlockPos+=NewLhd.PackSize;
+-        if (NextBlockPos<=CurBlockPos)
+-          return(0);
+-      }
+-
+-      if (Size > 0 && BlockType!=SUB_HEAD)
+-        LastBlock=BlockType;
+-      if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
+-          (NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
+-        break;
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-      MemRARFile->offset = NextBlockPos;
+-#else
+-      tseek(ArcPtr, NextBlockPos, SEEK_SET);
+-#endif
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <sys/param.h>
++#include <libunrar3/dll.hpp>
++#include "clamav.h"
++#include "others.h"
++#include "unrarlib.h"
++#include "mbox.h"
++#include "blob.h"
++
++int cli_unrar3(const char *dir, int desc)
++{
++
++    struct RAROpenArchiveDataEx OpenArchiveData;
++    struct RARHeaderData HeaderData;
++    int iReadHeaderCode, iProcessFileCode, fd, s_buff;
++    char buff[4096], uname[48];
++    const char *tmpdir;
++    HANDLE hArcData;
++    FILE *out;
++
++    if((tmpdir = getenv("TMPDIR")) == NULL)
++#ifdef P_tmpdir
++        tmpdir = P_tmpdir;
++#else
++        tmpdir = "/tmp";
++#endif
++
++    sprintf(uname, "%s/rarXXXXXX", tmpdir);
++
++    if((fd = mkstemp(uname)) < 0 || (out = fdopen(fd, "w+")) == NULL)
++    {
++	
++	cli_dbgmsg("cli_unrar3: 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_unrar3: can't write to file %s.\n", uname); 
++	    fclose(out);
++	    close(fd);
++	    unlink(uname);
++	    return CL_EOPEN;
++	}
+     }
+-  }
+-
+-  BlockHead.HeadCRC=NewLhd.HeadCRC;
+-  BlockHead.HeadType=NewLhd.HeadType;
+-  BlockHead.Flags=NewLhd.Flags;
+-  BlockHead.HeadSize=NewLhd.HeadSize;
+-  BlockHead.DataSize=NewLhd.PackSize;
+-
+-  if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
+-
+-  if((FILE_HEAD == BlockType) && (Size>0))
+-  {
+-    NewLhd.NameSize=Min(NewLhd.NameSize,sizeof(ArcFileName)-1);
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-    tread(MemRARFile, ArcFileName, NewLhd.NameSize);
+-#else
+-    tread(ArcPtr,ArcFileName,NewLhd.NameSize);
+-#endif
+-    ArcFileName[NewLhd.NameSize]=0;
+-#ifdef _DEBUG_LOG
+-    if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
+-                                          NewLhd.NameSize))
+-    {
+-      debug_log("file header broken");
++    fclose(out);
++    close(fd);
++    
++    memset(&OpenArchiveData, 0, sizeof(OpenArchiveData));
++	
++    OpenArchiveData.ArcName         = uname; /* name arch */
++    OpenArchiveData.CmtBuf          = NULL;
++    OpenArchiveData.OpenMode        = RAR_OM_EXTRACT;
++		    
++    hArcData = RAROpenArchiveEx(&OpenArchiveData);
++			
++    if (OpenArchiveData.OpenResult != 0)
++    {
++        cli_dbgmsg("cli_unrar3: error archive open (%d)\n", OpenArchiveData.OpenResult);
++	unlink(uname);
++        return CL_EOPEN;
++    }
++						    
++    HeaderData.CmtBuf = NULL;
++									
++    while ((iReadHeaderCode = RARReadHeader(hArcData, &HeaderData)) == 0)
++    {
++        iProcessFileCode = RARProcessFile(hArcData, RAR_EXTRACT, (char *)dir, NULL);
++        if (iProcessFileCode != 0)
++	{
++            cli_dbgmsg("cli_unrar3: error archive extract (%d)\n", iProcessFileCode);
++            break;
++	}
++		    
+     }
+-#endif
+-    Size+=NewLhd.NameSize;
+-  } else
+-  {
+-    memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-    MemRARFile->offset = CurBlockPos;
+-#else
+-    tseek(ArcPtr,CurBlockPos,SEEK_SET);
+-#endif
+-  }
+-
+-
+-  return(Size);
+-}
+-
+-
+-int ReadHeader(int BlockType)
+-{
+-  int Size = 0;
+-  unsigned char Header[64];
+-  memset(Header, 0, sizeof(Header));
+-  switch(BlockType)
+-  {
+-    case MAIN_HEAD:
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-        Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
+-#else
+-        Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
+-#endif
+-        NewMhd.HeadCRC=(unsigned short)GetHeaderWord(0);
+-        NewMhd.HeadType=GetHeaderByte(2);
+-        NewMhd.Flags=(unsigned short)GetHeaderWord(3);
+-        NewMhd.HeadSize=(unsigned short)GetHeaderWord(5);
+-        NewMhd.Reserved=(unsigned short)GetHeaderWord(7);
+-        NewMhd.Reserved1=GetHeaderDword(9);
+-        HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWMHD-2);
+-      break;
+-    case FILE_HEAD:
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-        Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
+-#else
+-        Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
+-#endif
+-        NewLhd.HeadCRC=(unsigned short)GetHeaderWord(0);
+-        NewLhd.HeadType=GetHeaderByte(2);
+-        NewLhd.Flags=(unsigned short)GetHeaderWord(3);
+-        NewLhd.HeadSize=(unsigned short)GetHeaderWord(5);
+-        NewLhd.PackSize=GetHeaderDword(7);
+-        NewLhd.UnpSize=GetHeaderDword(11);
+-        NewLhd.HostOS=GetHeaderByte(15);
+-        NewLhd.FileCRC=GetHeaderDword(16);
+-        NewLhd.FileTime=GetHeaderDword(20);
+-        NewLhd.UnpVer=GetHeaderByte(24);
+-        NewLhd.Method=GetHeaderByte(25);
+-        NewLhd.NameSize=(unsigned short)GetHeaderWord(26);
+-        NewLhd.FileAttr=GetHeaderDword(28);
+-        HeaderCRC=CalcCRC32(0xFFFFFFFFL,Header+2,SIZEOF_NEWLHD-2);
+-      break;
+-
+-#ifdef _DEBUG_LOG
+-  case COMM_HEAD:                           /* log errors in case of debug  */
+-        debug_log("Comment headers not supported! "\
+-                  "Please create archives without comments.");
+-      break;
+-  case PROTECT_HEAD:
+-        debug_log("Protected headers not supported!");
+-      break;
+-  case ALL_HEAD:
+-        debug_log("ShortBlockHeader not supported!");
+-      break;
+-  default:
+-        debug_log("Unknown//unsupported !");
+-#else
+-  default:                                  /* else do nothing              */
+-        break;
+-#endif
+-  }
+-  return(Size);
++					    
++    RARCloseArchive(hArcData);
++    unlink(uname);
++    
++    /*
++    if (iProcessFileCode == ERAR_BAD_DATA)
++	return CL_ERAR;
++    */
++    return CL_CLEAN;
+ }
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                  E X T R A C T   L O O P                     *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-int IsArchive(void)
+-{
+-#ifdef _DEBUG_LOG
+-  int  str_offs;                            /* used for debug-strings       */
+-  char DebugMsg[500];                       /* used to compose debug msg    */
+-#endif
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD) {
+-    debug_log("IsArchive(): short read: FALSE");
+-    return(FALSE);
+-  }
+-#else
+-  if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) {
+-    debug_log("IsArchive(): short read: FALSE");
+-    return(FALSE);
+-  }
+-#endif
+-  /* Old archive => error                                                   */
+-  if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
+-      MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
+-  {
+-    debug_log("Attention: format as OLD detected! Can't handle archive!");
+-  }
+-  else
+-      /* original RAR v2.0                                                  */
+-      if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original  */
+-           MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
+-           MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
+-           MarkHead.Mark[6]==0x00) ||
+-     /* "UniquE!" - header                                                  */
+-          (MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' &&   /* "UniquE!" */
+-           MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' &&   /* header    */
+-           MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
+-           MarkHead.Mark[6]=='!'))
+-
+-    {
+-      if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD) {
+-        debug_log("IsArchive(): ReadHeader() failed");
+-        return(FALSE);
+-      }
+-    } else
+-    {
+-
+-#ifdef _DEBUG_LOG
+-     /* sorry for this ugly code, but older SunOS gcc compilers don't       */
+-     /* support white spaces within strings                                 */
+-     str_offs  = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
+-     str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
+-     str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
+-     str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
+-
+-     debug_log(DebugMsg);
+-#endif
+-
+-    }
+-
+-
+-  MainHeadSize=SIZEOF_NEWMHD;
+-
+-  return(TRUE);
+-}
+-
+-
+-BOOL ExtrFile(int desc)
+-{
+-  BOOL ReturnCode=TRUE;
+-  BOOL FileFound=FALSE;                     /* TRUE=use current extracted   */
+-                                            /* data FALSE=throw data away,  */
+-                                            /* wrong file                   */
+-  int newdesc;
+-
+-#ifdef  _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  MemRARFile->offset = 0;                   /* start reading from offset 0  */
+-  if (!IsArchive())
+-  {
+-    debug_log("Not a RAR file");
+-    return FALSE;                           /* error => exit!               */
+-  }
+-
+-#else
+-  /* open and identify archive                                              */
+-  newdesc = dup(desc);
+-  cli_dbgmsg("ExtrFile(): dup(%d) = %d\n", desc, newdesc);
+-  if ((ArcPtr=fdopen(newdesc,READBINARY))!=NULL)
+-  {
+-    if (!IsArchive())
+-    {
+-      debug_log("Not a RAR file");
+-      fclose(ArcPtr);
+-      ArcPtr = NULL;
+-      return FALSE;                         /* error => exit!               */
+-    }
+-  } else
+-  {
+-    debug_log("Error opening file.");
+-    return FALSE;
+-  }
+-#endif
+-
+-
+-  if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
+-  {
+-    cli_dbgmsg("unrarlib: Can't allocate memory for decompression!");
+-    return FALSE;
+-  } else cli_dbgmsg("unrarlib: Allocated %d bytes.\n", UNP_MEMORY);
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
+-#else
+-  tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
+-#endif
+-
+-  /* do while file is not extracted and there's no error                    */
+-  do
+-  {
+-
+-    if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next  */
+-    {                                       /* file within the RAR archive  */
+-/*
+- *
+- * 21.11.2000  UnQ  There's a problem with some linux distros when a file
+- *                  can not be found in an archive.
+- * 07.09.2004  ThL  Seems more like a logical bug in this lib, since it
+- *		    appears to occur once for every archive.
+- */
+-
+-      /*
+-      debug_log("Couldn't read next filename from archive (I/O error).");
+-      */
+-      ReturnCode=FALSE;
+-      break;                                /* error, file not found in     */
+-    }                                       /* archive or I/O error         */
+-    if (BlockHead.HeadType==SUB_HEAD)
+-    {
+-      debug_log("Sorry, sub-headers not supported.");
+-      ReturnCode=FALSE;
+-      break;                                /* error => exit                */
+-    }
+-
+-
+-    if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
+-    /* *** file found! ***                                                  */
+-    {
+-      {
+-	cli_dbgmsg("unrarlib: Allocating %d bytes\n", NewLhd.UnpSize);
+-        if((temp_output_buffer=malloc(NewLhd.UnpSize)) == NULL) { ;/* allocate memory for the*/
+-	    cli_errmsg("unrarlib: Can't malloc %d bytes\n", NewLhd.UnpSize);
+-	    ReturnCode = FALSE;
+-	    break;
+-	}
+-      }
+-      *temp_output_buffer_offset=0;         /* file. The default offset     */
+-                                            /* within the buffer is 0       */
+-    }
+-
+-    /* in case of a solid archive, we need to decompress any single file till
+-     * we have found the one we are looking for. In case of normal archives
+-     * (recommended!!), we skip the files until we are sure that it is the
+-     * one we want.
+-     */
+-    if((NewMhd.Flags & 0x08) || FileFound)
+-    {
+-      if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
+-      {
+-        cli_dbgmsg("unknown compression method: %d  (min=13 max=%d)\n", NewLhd.UnpVer, UNP_VER);
+-        ReturnCode=FALSE;
+-        break;                              /* error, can't extract file!   */
+-      }
+-
+-      CurUnpRead=0;
+-      if ((*Password!=0) && (NewLhd.Flags & LHD_PASSWORD))
+-        Encryption=NewLhd.UnpVer;
+-      else
+-        Encryption=0;
+-      if (Encryption) SetCryptKeys(Password);
+-
+-      UnpPackedSize=NewLhd.PackSize;
+-      DestUnpSize=NewLhd.UnpSize;
+-
+-      if (NewLhd.Method==0x30)
+-      {
+-	cli_dbgmsg("unrarlib: Unstore method temporarily not supported\n");
+-        /* UnstoreFile(); */
+-        ReturnCode=FALSE;
+-        break;                              /* error, can't extract file! */
+-      } else
+-      {
+-	cli_dbgmsg("unrarlib: Unpack()\n");
+-        Unpack(UnpMemory, FileFound);
+-      }
+-
+-
+-#ifdef _DO_CRC32_CHECK                      /* calculate CRC32              */
+-      if((UBYTE*)temp_output_buffer != NULL)
+-      {
+-        if(NewLhd.FileCRC!=~CalcCRC32(0xFFFFFFFFL,
+-                                      (UBYTE*)temp_output_buffer,
+-                                      NewLhd.UnpSize))
+-        {
+-          debug_log("CRC32 error - file couldn't be decompressed correctly!");
+-          ReturnCode=FALSE;
+-          break;                              /* error, can't extract file! */
+-        }
+-      }
+-#endif
+-
+-    }
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-    MemRARFile->offset = NextBlockPos;
+-#else
+-    if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
+-#endif
+-  } while(stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */
+-
+-  /* free memory, clear password and close archive                          */
+-  if(UnpMemory)
+-    free(UnpMemory);
+-
+-  UnpMemory=NULL;
+-#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-  if (ArcPtr!=NULL){
+-      fclose(ArcPtr);
+-      lseek(desc, 0, SEEK_SET);
+-      ArcPtr = NULL;
+-  }
+-#endif
+-
+-  return ReturnCode;
+-}
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- *******             G L O B A L   F U N C T I O N S                  *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-int tread(void *stream,void *buf,unsigned len)
+-{
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-
+-  if(((MemRARFile->offset + len) > MemRARFile->size) || (len == 0))
+-     return 0;
+-
+-  memcpy(buf,
+-         (BYTE*)(((MemoryFile*)stream)->data)+((MemoryFile*)stream)->offset,
+-         len % ((((MemoryFile*)stream)->size) - 1));
+-
+-  MemRARFile->offset+=len;                  /* update read pointer          */
+-  return len % ((((MemoryFile*)stream)->size) - 1);
+-#else
+-  return(fread(buf,1,len,(FILE*)stream));
+-#endif
+-}
+-
+-
+-#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-int tseek(void *stream,long offset,int fromwhere)
+-{
+-  return(fseek((FILE*)stream,offset,fromwhere));
+-}
+-#endif
+-
+-
+-static char* strupper(char *Str)
+-{
+-  char *ChPtr;
+-  for (ChPtr=Str;*ChPtr;ChPtr++)
+-    *ChPtr=(char)toupper(*ChPtr);
+-  return(Str);
+-}
+-
+-
+-int stricomp(char *Str1,char *Str2)
+-/* compare strings without regard of '\' and '/'                            */
+-{
+-  char S1[512],S2[512];
+-  char *chptr;
+-
+-  strncpy(S1,Str1,sizeof(S1));
+-  strncpy(S2,Str2,sizeof(S2));
+-
+-  while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash             */
+-  {
+-    *chptr = '_';
+-  }
+-
+-  while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash             */
+-  {
+-    *chptr = '_';
+-  }
+-
+-  while((chptr = strchr(S1, '/')) != NULL)  /* ignore slash                 */
+-  {
+-    *chptr = '_';
+-  }
+-
+-  while((chptr = strchr(S2, '/')) != NULL)  /* ignore slash                 */
+-  {
+-    *chptr = '_';
+-  }
+-
+-  return(strcmp(strupper(S1),strupper(S2)));
+-}
+-
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                   U N P A C K   C O D E                      *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-/* *****************************
+- * ** unpack stored RAR files **
+- * *****************************/
+-
+-/*
+-BOOL UnstoreFile(void)
+-{
+-  if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
+-                                                NewLhd.UnpSize))==-1)
+-  {
+-    cli_dbgmsg("unrarlib: Read error of stored file!");
+-    return FALSE;
+-  }
+-  return TRUE;
+-}
+-*/
+-
+-
+-/* ****************************************
+- * ** RAR decompression code starts here **
+- * ****************************************/
+-
+-#define NC 298                              /* alphabet = {0,1,2, .,NC - 1} */
+-#define DC 48
+-#define RC 28
+-#define BC 19
+-#define MC 257
+-
+-enum {CODE_HUFFMAN=0,CODE_LZ=1,CODE_LZ2=2,CODE_REPEATLZ=3,CODE_CACHELZ=4,
+-      CODE_STARTFILE=5,CODE_ENDFILE=6,CODE_STARTMM=8,CODE_ENDMM=7,
+-      CODE_MMDELTA=9};
+-
+-struct AudioVariables
+-{
+-  int K1,K2,K3,K4,K5;
+-  int D1,D2,D3,D4;
+-  int LastDelta;
+-  unsigned int Dif[11];
+-  unsigned int ByteCount;
+-  int LastChar;
+-};
+-
+-
+-#define NC 298  /* alphabet = {0, 1, 2, ..., NC - 1} */
+-#define DC 48
+-#define RC 28
+-#define BC 19
+-#define MC 257
+-
+-
+-static struct AudioVariables AudV[4];
+-
+-#define GetBits()                                                 \
+-        BitField = ( ( ( (UDWORD)InBuf[InAddr]   << 16 ) |        \
+-                       ( (UWORD) InBuf[InAddr+1] <<  8 ) |        \
+-                       (         InBuf[InAddr+2]       ) )        \
+-                       >> (8-InBit) ) & 0xffff;
+-
+-
+-#define AddBits(Bits)                          \
+-        InAddr += ( InBit + (Bits) ) >> 3;     \
+-        InBit  =  ( InBit + (Bits) ) &  7;
+-
+-static unsigned char *UnpBuf;
+-static unsigned int BitField;
+-static unsigned int Number;
+-
+-static unsigned char InBuf[8192];                  /* input read buffer            */
+-
+-static unsigned char UnpOldTable[MC*4];
+-
+-static unsigned int InAddr,InBit,ReadTop;
+-
+-static unsigned int LastDist,LastLength;
+-static unsigned int Length,Distance;
+-
+-static unsigned int OldDist[4],OldDistPtr;
+-
+-
+-static struct LitDecode
+-{
+-  unsigned int MaxNum;
+-  unsigned int DecodeLen[16];
+-  unsigned int DecodePos[16];
+-  unsigned int DecodeNum[NC];
+-} LD;
+-
+-static struct DistDecode
+-{
+-  unsigned int MaxNum;
+-  unsigned int DecodeLen[16];
+-  unsigned int DecodePos[16];
+-  unsigned int DecodeNum[DC];
+-} DD;
+-
+-static struct RepDecode
+-{
+-  unsigned int MaxNum;
+-  unsigned int DecodeLen[16];
+-  unsigned int DecodePos[16];
+-  unsigned int DecodeNum[RC];
+-} RD;
+-
+-static struct MultDecode
+-{
+-  unsigned int MaxNum;
+-  unsigned int DecodeLen[16];
+-  unsigned int DecodePos[16];
+-  unsigned int DecodeNum[MC];
+-} MD[4];
+-
+-static struct BitDecode
+-{
+-  unsigned int MaxNum;
+-  unsigned int DecodeLen[16];
+-  unsigned int DecodePos[16];
+-  unsigned int DecodeNum[BC];
+-} BD;
+-
+-static struct MultDecode *MDPtr[4]={&MD[0],&MD[1],&MD[2],&MD[3]};
+-
+-static int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
+-
+-
+-void Unpack(unsigned char *UnpAddr, BOOL FileFound)
+-/* *** 38.3% of all CPU time is spent within this function!!!               */
+-{
+-  static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
+-                                  40,48,56,64,80,96,112,128,160,192,224};
+-  static unsigned char LBits[]=  {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
+-                                  3,3,3,4,4,4,4,5,5,5,5};
+-  static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
+-                        512,768,1024,1536,2048,3072,4096,6144,8192,12288,
+-                        16384,24576,32768U,49152U,65536,98304,131072,196608,
+-                        262144,327680,393216,458752,524288,589824,655360,
+-                        720896,786432,851968,917504,983040};
+-  static unsigned char DBits[]=  {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,
+-                                  9,10,10,11,11,12,12,13,13,14,14,15,15,16,
+-                                  16,16,16,16,16,16,16,16,16,16,16,16,16};
+-  static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
+-  static unsigned char SDBits[]={2,2,3, 4, 5, 6,  6,  6};
+-  unsigned int Bits;
+-
+-
+-  UnpBuf=UnpAddr;                           /* UnpAddr is a pointer to the  */
+-  UnpInitData();                            /* unpack buffer                */
+-  UnpReadBuf(1);
+-  if (!(NewLhd.Flags & LHD_SOLID))
+-     ReadTables();
+-   DestUnpSize--;
+-
+-  while (DestUnpSize>=0)
+-  {
+-    UnpPtr&=MAXWINMASK;
+-
+-    if (InAddr>sizeof(InBuf)-30)
+-      UnpReadBuf(0);
+-    if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
+-    {
+-
+-
+-      if (FileFound)
+-      {
+-
+-        if (UnpPtr<WrPtr)
+-        {
+-                        if((*temp_output_buffer_offset + ((0-WrPtr) & MAXWINMASK) + UnpPtr) > NewLhd.UnpSize)
+-                        {
+-                           debug_log("Fatal! Buffer overrun during decompression!");
+-                          DestUnpSize=-1;
+-
+-                    } else
+-                        {
+-              /* copy extracted data to output buffer                         */
+-              memcpy(temp_output_buffer + *temp_output_buffer_offset,
+-                     &UnpBuf[WrPtr], (0-WrPtr) & MAXWINMASK);
+-              /* update offset within buffer                                  */
+-              *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
+-              /* copy extracted data to output buffer                         */
+-              memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
+-                     UnpPtr);
+-              /* update offset within buffer                                  */
+-              *temp_output_buffer_offset+=UnpPtr;
+-                        }
+-        } else
+-        {
+-                        if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
+-                        {
+-                           debug_log("Fatal! Buffer overrun during decompression!");
+-                          DestUnpSize=-1;
+-                    } else
+-                        {
+-                  /* copy extracted data to output buffer                       */
+-              memcpy(temp_output_buffer + *temp_output_buffer_offset,
+-                     &UnpBuf[WrPtr], UnpPtr-WrPtr);
+-              *temp_output_buffer_offset+=UnpPtr-WrPtr;                                                /* update offset within buffer */
+-                    }
+-
+-            }
+-      }
+-
+-      WrPtr=UnpPtr;
+-    }
+-
+-    if (UnpAudioBlock)
+-    {
+-      DecodeNumber((struct Decode *)MDPtr[CurChannel]);
+-      if (Number==256)
+-      {
+-        ReadTables();
+-        continue;
+-      }
+-      UnpBuf[UnpPtr++]=DecodeAudio(Number);
+-      if (++CurChannel==UnpChannels)
+-        CurChannel=0;
+-      DestUnpSize--;
+-      continue;
+-    }
+-
+-    DecodeNumber((struct Decode *)&LD);
+-    if (Number<256)
+-    {
+-      UnpBuf[UnpPtr++]=(UBYTE)Number;
+-      DestUnpSize--;
+-      continue;
+-    }
+-    if (Number>269)
+-    {
+-      Length=LDecode[Number-=270]+3;
+-      if ((Bits=LBits[Number])>0)
+-      {
+-        GetBits();
+-        Length+=BitField>>(16-Bits);
+-        AddBits(Bits);
+-      }
+-
+-      DecodeNumber((struct Decode *)&DD);
+-      Distance=DDecode[Number]+1;
+-      if ((Bits=DBits[Number])>0)
+-      {
+-        GetBits();
+-        Distance+=BitField>>(16-Bits);
+-        AddBits(Bits);
+-      }
+-
+-      if (Distance>=0x40000L)
+-        Length++;
+-
+-      if (Distance>=0x2000)
+-        Length++;
+-
+-       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
+-       DestUnpSize-=(LastLength=Length);
+-       while (Length--)
+-       {
+-         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
+-         UnpPtr=(UnpPtr+1) & MAXWINMASK;
+-       }
+-
+-      continue;
+-    }
+-    if (Number==269)
+-    {
+-      ReadTables();
+-      continue;
+-    }
+-    if (Number==256)
+-    {
+-      Length=LastLength;
+-      Distance=LastDist;
+-       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
+-       DestUnpSize-=(LastLength=Length);
+-       while (Length--)
+-       {
+-         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
+-         UnpPtr=(UnpPtr+1) & MAXWINMASK;
+-       }
+-      continue;
+-    }
+-    if (Number<261)
+-    {
+-      Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
+-      DecodeNumber((struct Decode *)&RD);
+-      Length=LDecode[Number]+2;
+-      if ((Bits=LBits[Number])>0)
+-      {
+-        GetBits();
+-        Length+=BitField>>(16-Bits);
+-        AddBits(Bits);
+-      }
+-      if (Distance>=0x40000)
+-        Length++;
+-      if (Distance>=0x2000)
+-        Length++;
+-      if (Distance>=0x101)
+-        Length++;
+-       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
+-       DestUnpSize-=(LastLength=Length);
+-       while (Length--)
+-       {
+-         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
+-         UnpPtr=(UnpPtr+1) & MAXWINMASK;
+-       }
+-      continue;
+-    }
+-    if (Number<270)
+-    {
+-      Distance=SDDecode[Number-=261]+1;
+-      if ((Bits=SDBits[Number])>0)
+-      {
+-        GetBits();
+-        Distance+=BitField>>(16-Bits);
+-        AddBits(Bits);
+-      }
+-      Length=2;
+-       LastDist=OldDist[OldDistPtr++ & 3]=Distance;
+-       DestUnpSize-=(LastLength=Length);
+-       while (Length--)
+-       {
+-         UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
+-         UnpPtr=(UnpPtr+1) & MAXWINMASK;
+-       }
+-      continue;
+-   }
+-  }
+-  ReadLastTables();
+-
+-  if (FileFound)                            /* flush buffer                 */
+-  {
+-
+-    if (UnpPtr<WrPtr)
+-    {
+-          if((*temp_output_buffer_offset + ((0-WrPtr) & MAXWINMASK) + UnpPtr) > NewLhd.UnpSize)
+-          {
+-            debug_log("Fatal! Buffer overrun during decompression!");
+-                DestUnpSize=-1;
+-          } else
+-          {
+-        /* copy extracted data to output buffer                             */
+-        memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
+-               (0-WrPtr) & MAXWINMASK);
+-        /* update offset within buffer                                      */
+-        *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
+-        /* copy extracted data to output buffer                             */
+-        memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf, UnpPtr);
+-        /* update offset within buffer                                      */
+-        *temp_output_buffer_offset+=UnpPtr;
+-          }
+-    } else
+-    {
+-          if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
+-          {
+-                 debug_log("Fatal! Buffer overrun during decompression!");
+-                DestUnpSize=-1;
+-          } else
+-          {
+-        /* copy extracted data to output buffer                             */
+-        memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
+-               UnpPtr-WrPtr);
+-        /* update offset within buffer                                      */
+-        *temp_output_buffer_offset+=UnpPtr-WrPtr;
+-          }
+-    }
+-  }
+-
+-  WrPtr=UnpPtr;
+-}
+-
+-
+-unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
+-{
+-  int RetCode=0;
+-  unsigned int I,ReadSize,TotalRead=0;
+-  unsigned char *ReadAddr;
+-  ReadAddr=Addr;
+-  while (Count > 0)
+-  {
+-    ReadSize=(unsigned int)((Count>(unsigned long)UnpPackedSize) ?
+-                                                  UnpPackedSize : Count);
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-    cli_dbgmsg("unrarlib: UnpREAD: Using memory->memory decompression\n");
+-    if(MemRARFile->data == NULL)
+-      return(0);
+-    RetCode=tread(MemRARFile, ReadAddr, ReadSize);
+-#else
+-    if (ArcPtr==NULL)
+-      return(0);
+-    RetCode=tread(ArcPtr,ReadAddr,ReadSize);
+-#endif
+-    CurUnpRead+=RetCode;
+-    ReadAddr+=RetCode;
+-    TotalRead+=RetCode;
+-    Count-=RetCode;
+-    UnpPackedSize-=RetCode;
+-      break;
+-  }
+-
+-  cli_dbgmsg("CurUnpRead == %d, TotalRead == %d, Count == %d, UnpPackedSize == %d\n", CurUnpRead, TotalRead, Count, UnpPackedSize);
+-
+-  if (RetCode!= -1)
+-  {
+-    RetCode=TotalRead;
+-    if (Encryption)
+-    {
+-      if (Encryption<20)
+-          {
+-            cli_dbgmsg("unrarlib: Old Crypt() not supported!");
+-          }
+-      else
+-      {
+-        for (I=0;I<(unsigned int)RetCode;I+=16)
+-          DecryptBlock(&Addr[I]);
+-      }
+-    }
+-  }
+-  return(RetCode);
+-}
+-
+-
+-void UnpReadBuf(int FirstBuf)
+-{
+-  int RetCode;
+-  if (FirstBuf)
+-  {
+-    ReadTop=UnpRead(InBuf,sizeof(InBuf));
+-    InAddr=0;
+-  }
+-  else
+-  {
+-    memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
+-    InAddr&=0x1f;
+-    RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
+-    if (RetCode>0)
+-      ReadTop=RetCode+32;
+-    else
+-      ReadTop=InAddr;
+-  }
+-}
+-
+-
+-void ReadTables(void)
+-{
+-  UBYTE BitLength[BC];
+-  unsigned char Table[MC*4];
+-  int TableSize,N,I;
+-  if (InAddr>sizeof(InBuf)-25)
+-    UnpReadBuf(0);
+-  GetBits();
+-  UnpAudioBlock=(BitField & 0x8000);
+-
+-  if (!(BitField & 0x4000))
+-    memset(UnpOldTable,0,sizeof(UnpOldTable));
+-  AddBits(2);
+-
+-
+-  if (UnpAudioBlock)
+-  {
+-    UnpChannels=((BitField>>12) & 3)+1;
+-    if (CurChannel>=UnpChannels)
+-      CurChannel=0;
+-    AddBits(2);
+-    TableSize=MC*UnpChannels;
+-  }
+-  else
+-    TableSize=NC+DC+RC;
+-
+-
+-  for (I=0;I<BC;I++)
+-  {
+-    GetBits();
+-    BitLength[I]=(UBYTE)(BitField >> 12);
+-    AddBits(4);
+-  }
+-  MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
+-  I=0;
+-  while (I<TableSize)
+-  {
+-    if (InAddr>sizeof(InBuf)-5)
+-      UnpReadBuf(0);
+-    DecodeNumber((struct Decode *)&BD);
+-    if (Number<16) {
+-      Table[I]=(Number+UnpOldTable[I]) & 0xf;
+-      I++;
+-    }
+-    else
+-      if (Number==16)
+-      {
+-        GetBits();
+-        N=(BitField >> 14)+3;
+-        AddBits(2);
+-        while (N-- > 0 && I<TableSize)
+-        {
+-          Table[I]=Table[I-1];
+-          I++;
+-        }
+-      }
+-      else
+-      {
+-        if (Number==17)
+-        {
+-          GetBits();
+-          N=(BitField >> 13)+3;
+-          AddBits(3);
+-        }
+-        else
+-        {
+-          GetBits();
+-          N=(BitField >> 9)+11;
+-          AddBits(7);
+-        }
+-        while (N-- > 0 && I<TableSize)
+-          Table[I++]=0;
+-      }
+-  }
+-  if (UnpAudioBlock)
+-    for (I=0;I<UnpChannels;I++)
+-      MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
+-  else
+-  {
+-    MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
+-    MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
+-    MakeDecodeTables(&Table[NC+DC],(struct Decode *)&RD,RC);
+-  }
+-  memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
+-}
+-
+-
+-static void ReadLastTables(void)
+-{
+-  if (ReadTop>=InAddr+5)
+-  {
+-    if (UnpAudioBlock)
+-    {
+-      DecodeNumber((struct Decode *)MDPtr[CurChannel]);
+-      if (Number==256)
+-        ReadTables();
+-    }
+-    else
+-    {
+-      DecodeNumber((struct Decode *)&LD);
+-      if (Number==269)
+-        ReadTables();
+-    }
+-  }
+-}
+-
+-
+-static void MakeDecodeTables(unsigned char *LenTab,
+-                             struct Decode *Dec,
+-                             int Size)
+-{
+-  int LenCount[16],TmpPos[16],I;
+-  long M,N;
+-  memset(LenCount,0,sizeof(LenCount));
+-  for (I=0;I<Size;I++)
+-    LenCount[LenTab[I] & 0xF]++;
+-
+-  LenCount[0]=0;
+-  for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
+-  {
+-    N=2*(N+LenCount[I]);
+-    M=N<<(15-I);
+-    if (M>0xFFFF)
+-      M=0xFFFF;
+-    Dec->DecodeLen[I]=(unsigned int)M;
+-    TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
+-  }
+-
+-  for (I=0;I<Size;I++)
+-    if (LenTab[I]!=0)
+-      Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
+-  Dec->MaxNum=Size;
+-}
+-
+-
+-static void DecodeNumber(struct Decode *Deco)
+-/* *** 52.6% of all CPU time is spent within this function!!!               */
+-{
+-  unsigned int I;
+-  register unsigned int N;
+-  GetBits();
+-
+-#ifdef _USE_ASM
+-
+-#ifdef _WIN_32
+- __asm {
+-
+-    xor eax, eax
+-    mov eax, BitField                       /* N=BitField & 0xFFFE; */
+-    and eax, 0xFFFFFFFE
+-    mov [N], eax
+-    mov edx, [Deco]                         /* EAX=N, EDX=Deco */
+-
+-          cmp  eax, dword ptr[edx + 8*4 + 4] /* if (N<Dec->DecodeLen[8]) */
+-          jae  else_G
+-
+-             cmp  eax, dword ptr[edx + 4*4 + 4] /* if (N<Dec->DecodeLen[4]) */
+-             jae  else_F
+-
+-
+-                cmp  eax, dword ptr[edx + 2*4 + 4] /* if (N<Dec->DecodeLen[2]) */
+-                jae  else_C
+-
+-                   cmp  eax, dword ptr[edx + 1*4 + 4] /* if (N<Dec->DecodeLen[1]) */
+-                   jae  else_1
+-                   mov  I, 1                         /*  I=1; */
+-                   jmp  next_1
+-                 else_1:                             /* else */
+-                   mov  I, 2                         /*  I=2; */
+-                 next_1:
+-
+-                jmp  next_C
+-              else_C:                             /* else */
+-
+-                   cmp  eax, dword ptr[edx + 3*4 + 4] /* if (N<Dec->DecodeLen[3]) */
+-                   jae  else_2
+-                   mov  I, 3                         /*  I=3; */
+-                   jmp  next_2
+-                 else_2:                             /* else */
+-                   mov  I, 4                         /*  I=4; */
+-                 next_2:
+-
+-              next_C:                             /* else */
+-
+-             jmp  next_F
+-           else_F:
+-
+-
+-             cmp  eax, dword ptr[edx + 6*4 + 4] /* if (N<Dec->DecodeLen[6]) */
+-             jae  else_E
+-
+-                cmp  eax, dword ptr[edx + 5*4 + 4] /* if (N<Dec->DecodeLen[5]) */
+-                jae  else_3
+-                mov  I, 5                         /*  I=5; */
+-                jmp  next_3
+-              else_3:                             /* else */
+-                mov  I, 6                         /*  I=6; */
+-              next_3:
+-
+-             jmp  next_E
+-           else_E:                             /* else */
+-
+-                cmp  eax, dword ptr[edx + 7*4 + 4] /* if (N<Dec->DecodeLen[7]) */
+-                jae  else_4
+-                mov  I, 7                         /*  I=7; */
+-                jmp  next_4
+-              else_4:                             /* else */
+-                mov  I, 8                         /*  I=8; */
+-              next_4:
+-
+-           next_E:
+-
+-           next_F:
+-
+-          jmp  next_G
+-        else_G:
+-
+-          cmp  eax, dword ptr[edx + 12*4 + 4] /* if (N<Dec->DecodeLen[12]) */
+-          jae  else_D
+-
+-             cmp  eax, dword ptr[edx + 10*4 + 4] /* if (N<Dec->DecodeLen[10]) */
+-             jae  else_B
+-
+-                cmp  eax, dword ptr[edx + 9*4 + 4] /* if (N<Dec->DecodeLen[9]) */
+-                jae  else_5
+-                mov  I, 9                         /*  I=9; */
+-                jmp  next_5
+-              else_5:                             /* else */
+-                mov  I, 10                         /*  I=10; */
+-              next_5:
+-
+-             jmp  next_B
+-           else_B:                             /* else */
+-
+-                cmp  eax, dword ptr[edx + 11*4 + 4] /* if (N<Dec->DecodeLen[11]) */
+-                jae  else_6
+-                mov  I, 11                         /*  I=11; */
+-                jmp  next_6
+-              else_6:                              /* else */
+-                mov  I, 12                         /*  I=12; */
+-              next_6:
+-
+-           next_B:
+-
+-
+-          jmp  next_D
+-        else_D:                             /* else */
+-
+-               cmp  eax, dword ptr[edx + 14*4 + 4] /* if (N<Dec->DecodeLen[14]) */
+-               jae  else_A
+-
+-                  cmp  eax, dword ptr[edx + 13*4 + 4] /* if (N<Dec->DecodeLen[13]) */
+-                  jae  else_7
+-                  mov  I, 13                         /*  I=13; */
+-                  jmp  next_7
+-                 else_7:                             /* else */
+-                  mov  I, 14                         /*  I=14; */
+-                 next_7:
+-
+-               jmp  next_A
+-              else_A:                             /* else */
+-               mov  I, 15                         /*  I=15; */
+-              next_A:
+-
+-        next_D:
+-    next_G:
+-}
+-#else
+- __asm__ __volatile__ (
+-     "andl $0xFFFFFFFE, %%eax"
+-"      movl %%eax, %1"
+-"          cmpl 8*4(%%edx), %%eax /* 5379 */"
+-"          jae  else_G"
+-""
+-"             cmpl 4*4(%%edx), %%eax"
+-"             jae  else_F"
+-""
+-"                cmpl 2*4(%%edx), %%eax"
+-"                jae  else_C"
+-""
+-"                   cmpl 1*4(%%edx), %%eax"
+-""
+-"                   jae  else_1"
+-"                   movl $1, %0"
+-"                   jmp  next_1"
+-"                 else_1:       "
+-"                   movl  $2, %0"
+-"                 next_1:"
+-"                "
+-"                jmp  next_C"
+-"              else_C:          "
+-""
+-"                   cmpl 3*4(%%edx), %%eax "
+-"                   jae  else_2"
+-"                   movl  $3, %0"
+-"                   jmp  next_2"
+-"                 else_2:       "
+-"                   movl  $4, %0"
+-"                 next_2:"
+-""
+-"              next_C:          "
+-""
+-"             jmp  next_F"
+-"           else_F:"
+-""
+-"             cmpl 6*4(%%edx), %%eax"
+-"             jae  else_E"
+-""
+-"                cmpl 5*4(%%edx), %%eax"
+-"                jae  else_3"
+-"                movl  $5, %0   "
+-"                jmp  next_3"
+-"              else_3:          "
+-"                movl  $6, %0   "
+-"              next_3:"
+-""
+-"             jmp  next_E"
+-"           else_E:             "
+-""
+-"                cmpl 7*4(%%edx), %%eax"
+-"                jae  else_4"
+-"                movl  $7, %0   "
+-"                jmp  next_4"
+-"              else_4:          "
+-"                movl  $8, %0   "
+-"              next_4:"
+-""
+-"           next_E:"
+-""
+-"           next_F:"
+-""
+-"          jmp  next_G"
+-"        else_G:"
+-""
+-"          cmpl 12*4(%%edx), %%eax"
+-"          jae  else_D"
+-""
+-"             cmpl 10*4(%%edx), %%eax"
+-"             jae  else_B"
+-""
+-"                cmpl 9*4(%%edx), %%eax"
+-"                jae  else_5"
+-"                movl  $9, %0   "
+-"                jmp  next_5"
+-"              else_5:          "
+-"                movl  $10, %0  "
+-"              next_5:"
+-""
+-"             jmp  next_B"
+-"           else_B:             "
+-""
+-"                cmpl 11*4(%%edx), %%eax"
+-" "
+-"                jae  else_6"
+-"                movl  $11, %0  "
+-"                jmp  next_6"
+-"              else_6:          "
+-"                movl  $12, %0  "
+-"              next_6:"
+-""
+-"           next_B:"
+-"      "
+-"        "
+-"          jmp  next_D"
+-"        else_D:                "
+-""
+-"               cmpl 14*4(%%edx), %%eax"
+-"               jae  else_A"
+-""
+-"                  cmpl 13*4(%%edx), %%eax"
+-"                  jae  else_7"
+-"                  movl  $13, %0"
+-"                  jmp  next_7"
+-"                 else_7:       "
+-"                  movl  $14, %0"
+-"                 next_7:"
+-""
+-"               jmp  next_A"
+-"              else_A:          "
+-"               movl  $15, %0   "
+-"              next_A:"
+-"          "
+-"        next_D:                             "
+-"    next_G:"
+-     : "=g" (I), "=r"(N)
+-     : "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
+-      : "memory"
+-     );
+-#endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
+-
+-#else
+-  N=BitField & 0xFFFE;
+-  if (N<Deco->DecodeLen[8])  {
+-    if (N<Deco->DecodeLen[4]) {
+-      if (N<Deco->DecodeLen[2]) {
+-        if (N<Deco->DecodeLen[1])
+-          I=1;
+-        else
+-          I=2;
+-      } else {
+-        if (N<Deco->DecodeLen[3])
+-          I=3;
+-        else
+-          I=4;
+-      }
+-    } else {
+-      if (N<Deco->DecodeLen[6])  {
+-        if (N<Deco->DecodeLen[5])
+-          I=5;
+-        else
+-          I=6;
+-      } else {
+-        if (N<Deco->DecodeLen[7])
+-          I=7;
+-        else
+-          I=8;
+-      }
+-   }
+-  } else {
+-    if (N<Deco->DecodeLen[12]) {
+-      if (N<Deco->DecodeLen[10]) {
+-        if (N<Deco->DecodeLen[9])
+-          I=9;
+-        else
+-          I=10;
+-      } else {
+-        if (N<Deco->DecodeLen[11])
+-          I=11;
+-        else
+-          I=12;
+-      }
+-    } else {
+-      if (N<Deco->DecodeLen[14]) {
+-        if (N<Deco->DecodeLen[13])
+-          I=13;
+-        else
+-          I=14;
+-
+-      } else {
+-          I=15;
+-      }
+-    }
+-
+-  }
+-#endif
+-
+-  AddBits(I);
+-  if ((N=Deco->DecodePos[I]+((N-Deco->DecodeLen[I-1])>>(16-I)))>=Deco->MaxNum)
+-      N=0;
+-  Number=Deco->DecodeNum[N];
+-}
+-
+-
+-void UnpInitData()
+-{
+-  InAddr=InBit=0;
+-  if (!(NewLhd.Flags & LHD_SOLID))
+-  {
+-    ChannelDelta=CurChannel=0;
+-
+-#ifdef _USE_ASM
+-
+-#ifdef _WIN_32                              /* Win32 with VisualC           */
+-
+-    __asm {
+-        push edi
+-        push eax
+-        push ecx
+-
+-        cld                                 /* increment EDI and ESI        */
+-        mov  al, 0x00
+-        mov  ecx, SIZE AudV
+-        mov  edi, Offset AudV
+-        rep  stosb                          /* clear memory                 */
+-
+-        mov  ecx, SIZE OldDist
+-        mov  edi, Offset OldDist
+-        rep  stosb                          /* clear memory                 */
+-
+-        mov  ecx, SIZE UnpOldTable
+-        mov  edi, Offset UnpOldTable
+-        rep  stosb                          /* clear memory                 */
+-
+-        pop  ecx
+-        pop  eax
+-        pop  edi
+-
+-
+-        mov  [OldDistPtr], 0
+-        mov  [LastDist], 0
+-        mov  [LastLength], 0
+-        mov  [UnpPtr], 0
+-        mov  [WrPtr], 0
+-        mov  [OldDistPtr], 0
+-        mov  [LastLength], 0
+-        mov  [LastDist], 0
+-        mov  [UnpPtr], 0
+-        mov  [WrPtr], 0
+-
+-    }
+-    memset(UnpBuf,0,MAXWINSIZE);
+-
+-
+-#else                    /* unix/linux on i386 cpus */
+-    __asm__ __volatile (
+-"        cld                                 /* increment EDI and ESI        */"
+-"        movb $0x00, %%al"
+-"        movl %0, %%ecx"
+-"        movl %1, %%edi"
+-"        rep  "
+-"        stosb                              /* clear memory                 */"
+-""
+-"        movl %2, %%ecx"
+-"        mov  %3, %%edi"
+-"        rep  "
+-"        stosb                              /* clear memory                 */"
+-""
+-"        movl %4, %%ecx"
+-"        movl %5, %%edi"
+-"        rep  "
+-"        stosb                              /* clear memory                 */"
+-""
+-"        movl $0, (OldDistPtr)"
+-"        movl $0, (LastDist)"
+-"        movl $0, (LastLength)"
+-"        movl $0, (UnpPtr)"
+-"        movl $0, (WrPtr)"
+-"        movl $0, (OldDistPtr)"
+-"        movl $0, (LastLength)"
+-"        movl $0, (LastDist)"
+-"        movl $0, (UnpPtr)"
+-"        movl $0, (WrPtr)"
+-        :
+-        : "m" ((long)sizeof(AudV)),
+-          "m" ((long)AudV),
+-          "m" ((long)sizeof(OldDist)),
+-          "m" ((long)OldDist),
+-          "m" ((long)sizeof(UnpOldTable)),
+-          "m" ((long)UnpOldTable)
+-        : "memory", "edi", "eax", "ecx"
+-    );
+-    memset(UnpBuf,0,MAXWINSIZE);
+-#endif
+-
+-#else                                       /* unix/linux on non-i386 cpu  */
+-    memset(AudV,0,sizeof(AudV));
+-    memset(OldDist,0,sizeof(OldDist));
+-    OldDistPtr=0;
+-    LastDist=LastLength=0;
+-    memset(UnpBuf,0,MAXWINSIZE);
+-    memset(UnpOldTable,0,sizeof(UnpOldTable));
+-    UnpPtr=WrPtr=0;
+-#endif
+-
+-  }
+-}
+-
+-
+-UBYTE DecodeAudio(int Delta)
+-{
+-  struct AudioVariables *V;
+-  unsigned int Ch;
+-  unsigned int NumMinDif,MinDif;
+-  int PCh,I;
+-
+-  V=&AudV[CurChannel];
+-  V->ByteCount++;
+-  V->D4=V->D3;
+-  V->D3=V->D2;
+-  V->D2=V->LastDelta-V->D1;
+-  V->D1=V->LastDelta;
+-  PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+
+-           V->K3*V->D3+V->K4*V->D4+V->K5*ChannelDelta;
+-  PCh=(PCh>>3) & 0xFF;
+-
+-  Ch=PCh-Delta;
+-
+-  I=((signed char)Delta)<<3;
+-
+-  V->Dif[0]+=abs(I);
+-  V->Dif[1]+=abs(I-V->D1);
+-  V->Dif[2]+=abs(I+V->D1);
+-  V->Dif[3]+=abs(I-V->D2);
+-  V->Dif[4]+=abs(I+V->D2);
+-  V->Dif[5]+=abs(I-V->D3);
+-  V->Dif[6]+=abs(I+V->D3);
+-  V->Dif[7]+=abs(I-V->D4);
+-  V->Dif[8]+=abs(I+V->D4);
+-  V->Dif[9]+=abs(I-ChannelDelta);
+-  V->Dif[10]+=abs(I+ChannelDelta);
+-
+-  ChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
+-  V->LastChar=Ch;
+-
+-  if ((V->ByteCount & 0x1F)==0)
+-  {
+-    MinDif=V->Dif[0];
+-    NumMinDif=0;
+-    V->Dif[0]=0;
+-    for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
+-    {
+-      if (V->Dif[I]<MinDif)
+-      {
+-        MinDif=V->Dif[I];
+-        NumMinDif=I;
+-      }
+-      V->Dif[I]=0;
+-    }
+-    switch(NumMinDif)
+-    {
+-      case 1:
+-        if (V->K1>=-16)
+-          V->K1--;
+-        break;
+-      case 2:
+-        if (V->K1<16)
+-          V->K1++;
+-        break;
+-      case 3:
+-        if (V->K2>=-16)
+-          V->K2--;
+-        break;
+-      case 4:
+-        if (V->K2<16)
+-          V->K2++;
+-        break;
+-      case 5:
+-        if (V->K3>=-16)
+-          V->K3--;
+-        break;
+-      case 6:
+-        if (V->K3<16)
+-          V->K3++;
+-        break;
+-      case 7:
+-        if (V->K4>=-16)
+-          V->K4--;
+-        break;
+-      case 8:
+-        if (V->K4<16)
+-          V->K4++;
+-        break;
+-      case 9:
+-        if (V->K5>=-16)
+-          V->K5--;
+-        break;
+-      case 10:
+-        if (V->K5<16)
+-          V->K5++;
+-        break;
+-    }
+-  }
+-  return((UBYTE)Ch);
+-}
+-
+-
+-
+-
+-
+-
+-
+-/* ***************************************************
+- * ** CRCCrypt Code - decryption engine starts here **
+- * ***************************************************/
+-
+-
+-#define NROUNDS 32
+-
+-#define rol(x,n)  (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
+-#define ror(x,n)  (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
+-
+-#define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
+-           ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
+-           ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
+-           ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
+-
+-
+-static UDWORD CRCTab[256];
+-
+-static UBYTE SubstTable[256];
+-static const UBYTE InitSubstTable[256]={
+-  215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221,  2, 42,
+-  232,  1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
+-  255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86,  6,
+-   71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
+-  107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
+-  158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
+-   97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
+-  164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
+-  207,120,189,210,  8,226, 41, 72,183,203,135,165,166, 60, 98,  7,
+-  122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
+-  131,  3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
+-  224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
+-  118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45,  4,148,108,
+-  161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
+-    0, 46,169,186, 68, 95,237, 65, 53,208,253,168,  9, 18,100, 52,
+-  116,184,160, 96,109, 37, 30,106,140,104,150,  5,204,117,112, 84
+-};
+-
+-static UDWORD Key[4];
+-
+-
+-static void EncryptBlock(UBYTE *Buf)
+-{
+-  int I;
+-
+-  UDWORD A,B,C,D,T,TA,TB;
+-#ifdef NON_INTEL_BYTE_ORDER
+-  A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
+-      ((UDWORD)Buf[3]<<24))^Key[0];
+-  B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
+-      ((UDWORD)Buf[7]<<24))^Key[1];
+-  C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
+-      ((UDWORD)Buf[11]<<24))^Key[2];
+-  D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
+-      ((UDWORD)Buf[15]<<24))^Key[3];
+-#else
+-  UDWORD *BufPtr;
+-  BufPtr=(UDWORD *)Buf;
+-  A=BufPtr[0]^Key[0];
+-  B=BufPtr[1]^Key[1];
+-  C=BufPtr[2]^Key[2];
+-  D=BufPtr[3]^Key[3];
+-#endif
+-  for(I=0;I<NROUNDS;I++)
+-  {
+-    T=((C+rol(D,11))^Key[I&3]);
+-    TA=A^substLong(T);
+-    T=((D^rol(C,17))+Key[I&3]);
+-    TB=B^substLong(T);
+-    A=C;
+-    B=D;
+-    C=TA;
+-    D=TB;
+-  }
+-#ifdef NON_INTEL_BYTE_ORDER
+-  C^=Key[0];
+-  Buf[0]=(UBYTE)C;
+-  Buf[1]=(UBYTE)(C>>8);
+-  Buf[2]=(UBYTE)(C>>16);
+-  Buf[3]=(UBYTE)(C>>24);
+-  D^=Key[1];
+-  Buf[4]=(UBYTE)D;
+-  Buf[5]=(UBYTE)(D>>8);
+-  Buf[6]=(UBYTE)(D>>16);
+-  Buf[7]=(UBYTE)(D>>24);
+-  A^=Key[2];
+-  Buf[8]=(UBYTE)A;
+-  Buf[9]=(UBYTE)(A>>8);
+-  Buf[10]=(UBYTE)(A>>16);
+-  Buf[11]=(UBYTE)(A>>24);
+-  B^=Key[3];
+-  Buf[12]=(UBYTE)B;
+-  Buf[13]=(UBYTE)(B>>8);
+-  Buf[14]=(UBYTE)(B>>16);
+-  Buf[15]=(UBYTE)(B>>24);
+-#else
+-  BufPtr[0]=C^Key[0];
+-  BufPtr[1]=D^Key[1];
+-  BufPtr[2]=A^Key[2];
+-  BufPtr[3]=B^Key[3];
+-#endif
+-  UpdKeys(Buf);
+-}
+-
+-
+-void DecryptBlock(UBYTE *Buf)
+-{
+-  int I;
+-  UBYTE InBuf[16];
+-  UDWORD A,B,C,D,T,TA,TB;
+-#ifdef NON_INTEL_BYTE_ORDER
+-  A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
+-      ((UDWORD)Buf[3]<<24))^Key[0];
+-  B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
+-      ((UDWORD)Buf[7]<<24))^Key[1];
+-  C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
+-      ((UDWORD)Buf[11]<<24))^Key[2];
+-  D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
+-      ((UDWORD)Buf[15]<<24))^Key[3];
+-#else
+-  UDWORD *BufPtr;
+-  BufPtr=(UDWORD *)Buf;
+-  A=BufPtr[0]^Key[0];                       /* xxx may be this can be       */
+-  B=BufPtr[1]^Key[1];                       /* optimized in assembler       */
+-  C=BufPtr[2]^Key[2];
+-  D=BufPtr[3]^Key[3];
+-#endif
+-  memcpy(InBuf,Buf,sizeof(InBuf));
+-  for(I=NROUNDS-1;I>=0;I--)
+-  {
+-    T=((C+rol(D,11))^Key[I&3]);
+-    TA=A^substLong(T);
+-    T=((D^rol(C,17))+Key[I&3]);
+-    TB=B^substLong(T);
+-    A=C;
+-    B=D;
+-    C=TA;
+-    D=TB;
+-  }
+-#ifdef NON_INTEL_BYTE_ORDER
+-  C^=Key[0];
+-  Buf[0]=(UBYTE)C;
+-  Buf[1]=(UBYTE)(C>>8);
+-  Buf[2]=(UBYTE)(C>>16);
+-  Buf[3]=(UBYTE)(C>>24);
+-  D^=Key[1];
+-  Buf[4]=(UBYTE)D;
+-  Buf[5]=(UBYTE)(D>>8);
+-  Buf[6]=(UBYTE)(D>>16);
+-  Buf[7]=(UBYTE)(D>>24);
+-  A^=Key[2];
+-  Buf[8]=(UBYTE)A;
+-  Buf[9]=(UBYTE)(A>>8);
+-  Buf[10]=(UBYTE)(A>>16);
+-  Buf[11]=(UBYTE)(A>>24);
+-  B^=Key[3];
+-  Buf[12]=(UBYTE)B;
+-  Buf[13]=(UBYTE)(B>>8);
+-  Buf[14]=(UBYTE)(B>>16);
+-  Buf[15]=(UBYTE)(B>>24);
+-#else
+-  BufPtr[0]=C^Key[0];
+-  BufPtr[1]=D^Key[1];
+-  BufPtr[2]=A^Key[2];
+-  BufPtr[3]=B^Key[3];
+-#endif
+-  UpdKeys(InBuf);
+-}
+-
+-
+-void UpdKeys(UBYTE *Buf)
+-{
+-  int I;
+-  for (I=0;I<16;I+=4)
+-  {
+-    Key[0]^=CRCTab[Buf[I]];                 /* xxx may be I'll rewrite this */
+-    Key[1]^=CRCTab[Buf[I+1]];               /* in asm for speedup           */
+-    Key[2]^=CRCTab[Buf[I+2]];
+-    Key[3]^=CRCTab[Buf[I+3]];
+-  }
+-}
+-
+-static void SetCryptKeys(char *NewPassword)
+-{
+-  unsigned int I,J,K,PswLength;
+-  unsigned char N1,N2;
+-  unsigned char Psw[256];
+-
+-#if !defined _USE_ASM
+-  UBYTE Ch;
+-#endif
+-
+-  SetOldKeys(NewPassword);
+-
+-  Key[0]=0xD3A3B879L;
+-  Key[1]=0x3F6D12F7L;
+-  Key[2]=0x7515A235L;
+-  Key[3]=0xA4E7F123L;
+-  memset(Psw,0,sizeof(Psw));
+-  strcpy((char *)Psw,NewPassword);
+-  PswLength=strlen(NewPassword);
+-  memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
+-
+-  for (J=0;J<256;J++)
+-    for (I=0;I<PswLength;I+=2)
+-    {
+-      N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xFF];
+-      for (K=1, N1=(unsigned char)CRCTab[(Psw[I]-J)&0xFF];
+-           (N1!=N2);
+-           N1++, K++)
+-          {
+-#ifdef _USE_ASM
+-
+-#ifdef _WIN_32
+-          __asm {
+-
+-                    mov ebx, Offset SubstTable
+-                    mov edx, ebx
+-
+-                    xor ecx, ecx            /* read SubstTable[N1]... */
+-                    mov cl, N1
+-                    add ebx, ecx
+-                    mov al, byte ptr[ebx]
+-
+-                    mov cl, N1              /* read SubstTable[(N1+I+K)&0xFF]... */
+-                    add ecx, I
+-                    add ecx, K
+-                    and ecx, 0xFF
+-                    add edx, ecx
+-                    mov ah, byte ptr[edx]
+-
+-                    mov  byte ptr[ebx], ah  /* and write back */
+-                    mov  byte ptr[edx], al
+-
+-               }
+-#else
+-                     __asm__ __volatile__ (
+-"                    xorl %%ecx, %%ecx"
+-"                    movl %2, %%ecx                     /* ecx = N1 */"
+-"                    mov %%ebx, %%edx"
+-"                    addl %%ecx, %%ebx"
+-""
+-"                    addl %0, %%ecx"
+-"                    addl %1, %%ecx"
+-"                    andl $0x000000FF, %%ecx"
+-"                    addl %%ecx, %%edx"
+-"                    "
+-"                    movb (%%ebx), %%al"
+-"                    movb (%%edx), %%ah"
+-""
+-"                    movb  %%ah, (%%ebx)     /* and write back */"
+-"                    movb  %%al, (%%edx)"
+-                    : : "g" ((long)I),
+-                        "g" ((long)K),
+-                        "g" ((long)N1),
+-                        "ebx"((long)SubstTable)
+-                    : "ecx", "edx"
+-
+-              );
+-#endif
+-
+-#else
+-            /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]);            */
+-             Ch=SubstTable[N1];
+-             SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
+-             SubstTable[(N1+I+K)&0xFF]=Ch;
+-#endif
+-          }
+-    }
+-  for (I=0;I<PswLength;I+=16)
+-    EncryptBlock(&Psw[I]);
+-}
+-
+-
+-void SetOldKeys(char *NewPassword)
+-{
+-  UDWORD PswCRC;
+-  UBYTE Ch;
+-  PswCRC=CalcCRC32(0xFFFFFFFFL,(UBYTE*)NewPassword,strlen(NewPassword));
+-  OldKey[0]=(UWORD)PswCRC;
+-  OldKey[1]=(UWORD)(PswCRC>>16);
+-  OldKey[2]=OldKey[3]=0;
+-  PN1=PN2=PN3=0;
+-  while ((Ch=*NewPassword)!=0)
+-  {
+-    PN1+=Ch;
+-    PN2^=Ch;
+-    PN3+=Ch;
+-    PN3=(UBYTE)rol(PN3,1);
+-    OldKey[2]^=((UWORD)(Ch^CRCTab[Ch]));
+-    OldKey[3]+=((UWORD)(Ch+(CRCTab[Ch]>>16)));
+-    NewPassword++;
+-  }
+-}
+-
+-static short crcInitialized = 0;
+-void InitCRC(void)
+-{
+-  int I, J;
+-  UDWORD C;
+-  if (crcInitialized) return;
+-
+-  cli_dbgmsg("%s:%d:%s Initialize CRC table\n", __FILE__, __LINE__, "InitCRC");
+-  for (I=0;I<256;I++)
+-  {
+-    for (C=I,J=0;J<8;J++)
+-      C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
+-    CRCTab[I]=C;
+-  }
+-  crcInitialized = 1;
+-}
+-
+-
+-static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
+-{
+-  unsigned int I;
+-  for (I=0; I<Size; I++)
+-    StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
+-  return(StartCRC);
+-}
+-
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- *******              D E B U G    F U N C T I O N S                  *******
+- *******                                                              *******
+- *******                                                              *******
+- *******                                                              *******
+- ****************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-#ifdef _DEBUG_LOG
+-
+-
+-/* -- global stuff -------------------------------------------------------- */
+-char  log_file_name[256];                   /* file name for the log file   */
+-DWORD debug_start_time;                     /* starttime of debug           */
+-BOOL  debug_started = FALSE;                /* debug_log writes only if     */
+-                                            /* this is TRUE                 */
+-/* ------------------------------------------------------------------------ */
+-
+-
+-/* -- global functions ---------------------------------------------------- */
+-void debug_init_proc(char *file_name)
+-/* Create/Rewrite a log file                                                */
+-{
+-  FILE *fp;
+-  char date[] = __DATE__;
+-  char time[] = __TIME__;
+-
+-  debug_start_time = GetTickCount();        /* get start time               */
+-  strcpy(log_file_name, file_name);         /* save file name               */
+-
+-  if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
+-  {
+-    debug_started = TRUE;                   /* enable debug                 */
+-    fprintf(fp, "Debug log of UniquE's RARFileLib\n"\
+-                "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
+-    fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time);
+-    fclose(fp);
+-  }
+-}
+-
+-
+-void debug_log_proc(char *text, char *sourcefile, int sourceline)
+-/* add a line to the log file                                               */
+-{
+-  FILE *fp;
+-
+-  if(debug_started == FALSE) return;        /* exit if not initialized      */
+-
+-  if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile  */
+-
+-  {
+-    fprintf(fp, " %8u ms (line %u in %s):\n              - %s\n",
+-            (unsigned int)(GetTickCount() - debug_start_time),
+-            sourceline, sourcefile, text);
+-    fclose(fp);
+-  }
+-}
+-
+-/* ------------------------------------------------------------------------ */
+-#endif
+-/* **************************************************************************
+- ****************************************************************************
+- ****************************************************************************
+- ************************************************************************** */
+-
+-
+-/* end of file urarlib.c */
+--- ./libclamav/unrarlib.h.orig	Thu Jun 23 17:03:12 2005
++++ ./libclamav/unrarlib.h	Wed Oct 12 14:40:13 2005
+@@ -1,205 +1,22 @@
+-/* ***************************************************************************
+- **
+- **  This file is part of the UniquE RAR File Library.
+- **
+- **  Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
+- **  UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
+- **
+- **  The contents of this file are subject to the UniquE RAR File Library
+- **  License (the "unrarlib-license.txt"). You may not use this file except
+- **  in compliance with the License. You may obtain a copy of the License
+- **  at http://www.unrarlib.org/license.html.
+- **  Software distributed under the License is distributed on an "AS IS"
+- **  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
+- **
+- **  Alternatively, the contents of this file may be used under the terms
+- **  of the GNU General Public License Version 2 or later (the "GPL"), in
+- **  which case the provisions of the GPL are applicable instead of those
+- **  above. If you wish to allow use of your version of this file only
+- **  under the terms of the GPL and not to allow others to use your version
+- **  of this file under the terms of the UniquE RAR File Library License,
+- **  indicate your decision by deleting the provisions above and replace
+- **  them with the notice and other provisions required by the GPL. If you
+- **  do not delete the provisions above, a recipient may use your version
+- **  of this file under the terms of the GPL or the UniquE RAR File Library
+- **  License.
+- **
+- ************************************************************************** */
+-
+-/* include file for the "UniquE RAR File Library"  */
+-/* (C) 2000-2002 by Christian Scheurer aka. UniquE */
+-/* multi-OS version (Win32, Linux and SUN)         */
+-
+-#ifndef __URARLIB_H
+-#define __URARLIB_H
+-
+-#ifdef __cplusplus
+-extern "C"
+-{
+-#endif
+-
+-
+-/* ************************************************************************ */
+-/* ************************************************************************ */
+-/* **                                                                    ** */
+-/* **   CONFIGURATION of the UniquE RAR FileLib                          ** */
+-/* **   ==> you may change the setting for the lib HERE!                 ** */
+-/* **                                                                    ** */
+-/* ************************************************************************ */
+-/* ************************************************************************ */
+-
+-
+-/* #define _DEBUG_LOG */                          /* generate debug messages      */
+-
+-#define _DO_CRC32_CHECK                     /* perform cyclical redundancy  */
+-                                            /* check (CRC32) - disable this */
+-                                            /* for a little speed-up        */
+-/*#define _USE_ASM*/                            /*
+-                                             * enable assembly extensions
+-                                             * x86 cpus.
+-                                             */
+-
+-/*#define _USE_MEMORY_TO_MEMORY_DECOMPRESSION*/ /* read file from memory or a   */
+-                                            /* resource instead of reading  */
+-                                            /* from a file. NOTE: you wont't*/
+-                                            /*  be able to decompress from  */
+-                                            /*  file if you enable this     */
+-                                            /*  option!                     */
+-
+-
+-#ifdef WIN32                                /* autodetect Win32 and Linux   */
+-#define _WIN_32                             /* Win32 with VisualC           */
+-#define _DEBUG_LOG_FILE "C:\\temp\\debug_unrar.txt" /* log file path        */
+-#else
+-#define _UNIX                               /* Linux or Unix with GCC       */
+-#define _DEBUG_LOG_FILE "/tmp/debug_unrar.txt" /* log file path             */
+-/*#define NON_INTEL_BYTE_ORDER*/               /* GCC on motorola systems    */
+-
+-#endif
+-
+-/* ------------------------------------------------------------------------ */
+-
+-/* detected by clamav/configure */
+-#if 1 - WORDS_BIGENDIAN
+-#define NON_INTEL_BYTE_ORDER
+-#endif
+-
+-/* -- global type definitions --------------------------------------------- */
+-
+-#ifdef NON_INTEL_BYTE_ORDER
+-#ifdef _USE_ASM
+-#warning Disabling assembly because NON_INTEL_BYTE_ORDER is set
+-#undef _USE_ASM
+-#endif
+-#endif
+-
+-#ifdef _WIN_32
+-typedef unsigned char    UBYTE;             /* WIN32 definitions            */
+-typedef unsigned short   UWORD;
+-typedef unsigned long    UDWORD;
+-#endif
+-
+-#ifdef _UNIX                                /* LINUX/UNIX definitions       */
+-typedef unsigned char    UBYTE;
+-typedef unsigned short   UWORD;
+-typedef unsigned long    UDWORD;
+-#endif
+-
+-#define RAR_FENTRY_ATTR_DIRECTORY ( 0x10 | 0x4000 )
+-
+-/* This structure is used for listing archive content                       */
+-struct RAR20_archive_entry                  /* These infos about files are  */
+-{                                           /* stored in RAR v2.0 archives  */
+-  char   *Name;
+-  UWORD  NameSize;
+-  UDWORD PackSize;
+-  UDWORD UnpSize;
+-  UBYTE  HostOS;                            /* MSDOS=0,OS2=1,WIN32=2,UNIX=3 */
+-  UDWORD FileCRC;
+-  UDWORD FileTime;
+-  UBYTE  UnpVer;
+-  UBYTE  Method;
+-  UDWORD FileAttr;
+-  UWORD  Flags;
+-};
+-
+-typedef struct  archivelist                 /* used to list archives        */
+-{
+-  struct RAR20_archive_entry item;
+-  struct archivelist         *next;
+-} ArchiveList_struct;
+-
+-
+-#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+-typedef struct  memory_file                 /* used to decompress files in  */
+-{                                           /* memory                       */
+-  void                       *data;         /* pointer to the file data     */
+-  unsigned long              size;          /* total size of the file data  */
+-  unsigned long              offset;        /* offset within "memory-file"  */
+-} MemoryFile;
+-#endif
+-
+-/* -- global functions ---------------------------------------------------- */
+-
+-/* urarlib_get:
+- * decompresses and decrypt data from a RAR file to a buffer in system memory.
++/*
++ *  Copyright (C) 2004 McMCC <mcmcc@mail.ru>
+  *
+- *   input: *output         pointer to an empty char*. This pointer will show
+- *                          to the extracted data
+- *          *size           shows where to write the size of the decompressed
+- *                          file
+- *                          (**NOTE: URARLib _does_ memory allocation etc.!**)
+- *          *filename       pointer to string containing the file to decompress
+- *          *rarfile        pointer to a string with the full name and path of
+- *                          the RAR file or pointer to a RAR file in memory if
+- *                          memory-to-memory decompression is active.
+- *          *libpassword    pointer to a string with the password used to
+- *                          en-/decrypt the RAR
+- *   output: int            returns TRUE on success or FALSE on error
+- *                          (FALSE=0, TRUE=1)
+- */
+-
+-extern int urarlib_get(void  *output,
+-                       unsigned long *size,
+-                       char *filename,
+-                       int desc,
+-                       char *libpassword);
+-
+-
+-
+-/* urarlib_list:
+- * list the content of a RAR archive.
++ *  Support check archives RAR v.3.x
+  *
+- *   input: *rarfile        pointer to a string with the full name and path of
+- *                          the RAR file or pointer to a RAR file in memory if
+- *                          memory-to-memory decompression is active.
+- *          *list           pointer to an ArchiveList_struct that can be
+- *                          filled with details about the archive
+- *                          to the extracted data
+- *   output: int            number of files/directories within archive
+- */
+-
+-extern int urarlib_list(int desc, ArchiveList_struct *list);
+-
+-
+-/* urarlib_freelist:
+- * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
+- * and Johannes Winkelmann who independently wrote a patch)
+- * free the memory of a ArchiveList_struct created by urarlib_list.
++ *  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.
+  *
+- *    input: *list          pointer to an ArchiveList_struct
+- *    output: -
+  */
+ 
+-extern void urarlib_freelist(ArchiveList_struct *list);
+-
+-/* ------------------------------------------------------------------------ */
+-
+-
+-
+-#ifdef __cplusplus
+-};
+-#endif
+-
+-#endif
+-
++int cli_unrar3(const char *dir, int desc);
Index: files/patch-libclamav_unrarlib.h
===================================================================
RCS file: files/patch-libclamav_unrarlib.h
diff -N files/patch-libclamav_unrarlib.h
--- files/patch-libclamav_unrarlib.h	13 May 2005 08:16:40 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,11 +0,0 @@
---- libclamav/unrarlib.h.orig	Fri May 13 09:07:21 2005
-+++ libclamav/unrarlib.h	Fri May 13 09:07:26 2005
-@@ -198,7 +198,7 @@
- 
- 
- #ifdef __cplusplus
--};
-+}
- #endif
- 
- #endif
--- clamav.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20051012180648.03FBF4E>