Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Sep 2005 17:18:53 +0300
From:      "Alex Samorukov" <samm@os2.kiev.ua>
To:        "FreeBSD gnats submit" <FreeBSD-gnats-submit@FreeBSD.org>
Cc:        samm@os2.kiev.ua
Subject:   ports/86510: [PATCH] security/clamav libunrar support 
Message-ID:  <1127485133.0@samm.loc>
Resent-Message-ID: <200509231420.j8NEK5YD005379@freefall.freebsd.org>

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

>Number:         86510
>Category:       ports
>Synopsis:       [PATCH] security/clamav libunrar support
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 23 14:20:05 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Alex Samorukov
>Release:        FreeBSD 5.4-STABLE i386
>Organization:
Shevchenko Didkovskiy and Partners 
>Environment:


System: FreeBSD 5.4-STABLE #15: Mon Aug  8 10:59:05 EEST 2005
    root@samm.loc:/usr/obj/usr/src/sys/SAMMKRNL



>Description:


This patch allow to use clamav with RAR 3 files. Patch is based on the http://mcmcc.bat.ru/clamav/ patches.


>How-To-Repeat:


1. Install security/clamav
2. Create file with EICAR-virus and pack it with rar3
3. Try to check it with clamscan/clamdscan. You will get an error. 
4. Apply this patch and reinstall clamav with WITH_LIBUNRAR option,
5. Repeat step 3-4. You will get a message about EICAR virus


>Fix:


diff -ur --new-file /usr/ports/security/clamav/Makefile /home/samm/src/clamav/Makefile
--- /usr/ports/security/clamav/Makefile	Tue Sep 20 11:09:03 2005
+++ /home/samm/src/clamav/Makefile	Fri Sep 23 16:14:43 2005
@@ -124,9 +124,25 @@
 CONFIGURE_ARGS+=	--without-libcurl
 .endif
 
+.if defined(WITH_LIBUNRAR)
+WANT_AUTOMAKE_VER=      19
+USE_AUTOCONF_VER=       259
+LIB_DEPENDS+=		unrar.3:${PORTSDIR}/devel/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 -ur --new-file /usr/ports/security/clamav/README.html /home/samm/src/clamav/README.html
--- /usr/ports/security/clamav/README.html	Thu Jan  1 03:00:00 1970
+++ /home/samm/src/clamav/README.html	Mon Feb 23 21:24:05 2004
@@ -0,0 +1,43 @@
+<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
+
+<html>
+  <head>
+    <title>The FreeBSD Ports Collection (security/clamav)</title>
+  </head>
+
+  <body>
+    <h1>The FreeBSD Ports Collection (security/clamav)</h1>
+    <hr>
+
+    <p>You are now in the directory for the port "security/clamav".</p>
+
+    <p>The package name of this port is "clamav-0.65_1".</p>
+
+    <p>This is the one-line description for this port:</p>
+    <hr>
+
+    <p>
+Command line virus scanner written entirely in C
+    </p>
+    <hr>
+
+    <p>Please read the "<a href="pkg-descr">description file</a>" for a
+    longer description and/or visit the <a href="http://clamav.sourceforge.net/">web site</a> for futher informations.</p>
+
+    <p>If needed, you may contact the <a href=
+    "mailto:markun@onohara.to">maintainer</a> of this port or the port <a href=
+    "mailto:ports@FreeBSD.org">mailing-list</a>.</p>
+
+    <p>This port requires package(s) "expat-1.95.6_1 gettext-0.12.1 gmake-3.80_1 libgmp-4.1.2_2 libiconv-1.9.1_3" to build.</p>
+
+    <p>This port requires package(s) "arc-5.21j lha-1.14i_2 libgmp-4.1.2_2 rc_subr-1.16 unarj-2.43_1 unrar-3.20,2 unzip-5.50_2 zoo-2.10.1" to run.</p>
+
+    <p>Go to the <a href="../../README.html">top of the ports tree</a> for
+    a summary on how to use the ports collection.</p>
+    <hr>
+
+    <p><a href="../README.html">Go up one level</a> | <a href=
+    "../../README.html">Go to top of ports tree</a></p>
+  </body>
+</html>
+
diff -ur --new-file /usr/ports/security/clamav/files/clamav-0.87-libunrar3.patch /home/samm/src/clamav/files/clamav-0.87-libunrar3.patch
--- /usr/ports/security/clamav/files/clamav-0.87-libunrar3.patch	Thu Jan  1 03:00:00 1970
+++ /home/samm/src/clamav/files/clamav-0.87-libunrar3.patch	Fri Sep 23 16:07:04 2005
@@ -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);


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



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