aboutsummaryrefslogtreecommitdiff
path: root/security/clamav
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@FreeBSD.org>2005-10-11 23:07:39 +0000
committerVsevolod Stakhov <vsevolod@FreeBSD.org>2005-10-11 23:07:39 +0000
commit81a74240a0b228bc003c588eaa7e93bbf47915b3 (patch)
treeeb55e0f40d6c2d4b30be34baf173ae672b437f4a /security/clamav
parent187ecf1c86fc0f35e266748d6deec488d9ff1fb5 (diff)
downloadports-81a74240a0b228bc003c588eaa7e93bbf47915b3.tar.gz
ports-81a74240a0b228bc003c588eaa7e93bbf47915b3.zip
Allow clamav to use rar 3 archives using archivers/libunrar.
PR: 86510 Submitted by: Alex Samorukov <samm@os2.kiev.ua>, Rob <r.evers@nedstat.com> (maintainer)
Notes
Notes: svn path=/head/; revision=145036
Diffstat (limited to 'security/clamav')
-rw-r--r--security/clamav/Makefile20
-rw-r--r--security/clamav/files/clamav-0.87-libunrar3.patch3236
2 files changed, 3255 insertions, 1 deletions
diff --git a/security/clamav/Makefile b/security/clamav/Makefile
index da8acdc2b4cf..8917221165f8 100644
--- a/security/clamav/Makefile
+++ b/security/clamav/Makefile
@@ -7,6 +7,7 @@
PORTNAME= clamav
PORTVERSION= 0.87
+PORTREVISION= 1
CATEGORIES= security
MASTER_SITES= ${MASTER_SITE_SOURCEFORGE_EXTENDED}
MASTER_SITE_SUBDIR= clamav
@@ -23,7 +24,8 @@ RUN_DEPENDS= lha:${PORTSDIR}/archivers/lha \
unzip:${PORTSDIR}/archivers/unzip
OPTIONS= MILTER "Compile the milter interface" Off \
- CURL "Support URL downloading" Off
+ CURL "Support URL downloading" Off \
+ UNRAR "Support for external Unrar library" Off
USE_REINPLACE= yes
USE_LIBTOOL_VER=15
CONFIGURE_TARGET= --build=${MACHINE_ARCH}-portbld-freebsd${OSREL}
@@ -124,9 +126,25 @@ CONFIGURE_ARGS+= --with-libcurl
CONFIGURE_ARGS+= --without-libcurl
.endif
+.if defined(WITH_LIBUNRAR)
+WANT_AUTOMAKE_VER= 19
+USE_AUTOCONF_VER= 259
+LIB_DEPENDS+= unrar.3:${PORTSDIR}/archivers/libunrar
+
+pre-configure:
+ cd ${WRKSRC} && \
+ ${ACLOCAL} && \
+ ${AUTOHEADER} && \
+ ${AUTOCONF} && \
+ ${AUTOMAKE}
+.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 \
diff --git a/security/clamav/files/clamav-0.87-libunrar3.patch b/security/clamav/files/clamav-0.87-libunrar3.patch
new file mode 100644
index 000000000000..a349b3d0ec96
--- /dev/null
+++ b/security/clamav/files/clamav-0.87-libunrar3.patch
@@ -0,0 +1,3236 @@
+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);