1
/* It contains some changes needed for libclamav and isn't compatible with
2
* the original version, --tk
4
/* ***************************************************************************
6
** This file is part of the UniquE RAR File Library.
8
** Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
9
** UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
11
** The contents of this file are subject to the UniquE RAR File Library
12
** License (the "unrarlib-license.txt"). You may not use this file except
13
** in compliance with the License. You may obtain a copy of the License
14
** at http://www.unrarlib.org/license.html.
15
** Software distributed under the License is distributed on an "AS IS"
16
** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
18
** Alternatively, the contents of this file may be used under the terms
19
** of the GNU General Public License Version 2 or later (the "GPL"), in
20
** which case the provisions of the GPL are applicable instead of those
21
** above. If you wish to allow use of your version of this file only
22
** under the terms of the GPL and not to allow others to use your version
23
** of this file under the terms of the UniquE RAR File Library License,
24
** indicate your decision by deleting the provisions above and replace
25
** them with the notice and other provisions required by the GPL. If you
26
** do not delete the provisions above, a recipient may use your version
27
** of this file under the terms of the GPL or the UniquE RAR File Library
30
************************************************************************** */
32
/* ***************************************************************************
34
** UniquE RAR File Library
35
** The free file lib for the demoscene
36
** multi-OS version (Win32, Linux and SunOS)
38
*****************************************************************************
40
** ==> Please configure the program in "unrarlib.h". <==
42
** RAR decompression code:
44
** Modifications to a FileLib:
45
** (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
47
** (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
49
** The UniquE RAR File Library gives you the ability to access RAR archives
50
** (any compression method supported in RAR v2.0 including Multimedia
51
** Compression and encryption) directly from your program with ease an by
52
** adding only 12kB (6kB UPX-compressed) additional code to your program.
53
** Both solid and normal (recommended for fast random access to the files!)
54
** archives are supported. This FileLib is made for the Demo scene, so it's
55
** designed for easy use within your demos and intros.
56
** Please read "licence.txt" to learn more about how you may use URARFileLib
57
** in your productions.
59
*****************************************************************************
61
** ==> see the "CHANGES" file to see what's new
63
************************************************************************** */
65
/* -- include files ------------------------------------------------------- */
67
#include "clamav-config.h"
70
#include "unrarlib.h" /* include global configuration */
72
/* ------------------------------------------------------------------------ */
76
/* -- global stuff -------------------------------------------------------- */
79
#include <windows.h> /* WIN32 definitions */
86
#define HOST_OS WIN_32
88
#define FM_NORMAL 0x00
89
#define FM_RDONLY 0x01
90
#define FM_HIDDEN 0x02
91
#define FM_SYSTEM 0x04
96
#define PATHDIVIDER "\\"
97
#define CPATHDIVIDER '\\'
100
#define READBINARY "rb"
101
#define READTEXT "rt"
102
#define UPDATEBINARY "r+b"
103
#define CREATEBINARY "w+b"
104
#define CREATETEXT "w"
105
#define APPENDTEXT "at"
111
#include <stdio.h> /* LINUX/UNIX definitions */
118
#define ENABLE_ACCESS
122
#define FM_LABEL 0x0000
123
#define FM_DIREC 0x4000
125
#define PATHDIVIDER "/"
126
#define CPATHDIVIDER '/'
127
#define MASKALL "*.*"
129
#define READBINARY "r"
131
#define UPDATEBINARY "r+"
132
#define CREATEBINARY "w+"
133
#define CREATETEXT "w"
134
#define APPENDTEXT "a"
137
/* emulation of the windows API and data types */
138
/* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
146
#ifdef _DEBUG_LOG /* define macros for debugging */
148
#include <sys/time.h>
153
gettimeofday( &tv, 0 );
154
return (tv.tv_usec / 1000);
164
#ifdef _DEBUG_LOG /* define macros for debugging */
166
BOOL debug_log_first_start = TRUE;
168
#define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
169
#define debug_init(a); debug_init_proc(a);
171
void debug_log_proc(char *text, char *sourcefile, int sourceline);
172
void debug_init_proc(char *file_name);
175
#define debug_log(a); cli_dbgmsg("%s:%d %s\n", __FILE__, __LINE__, a);
176
#define debug_init(a); /* no debug this time */
183
#define MAXWINSIZE 0x100000
184
#define MAXWINMASK (MAXWINSIZE-1)
185
#define UNP_MEMORY MAXWINSIZE
186
#define Min(x,y) (((x)<(y)) ? (x):(y))
187
#define Max(x,y) (((x)>(y)) ? (x):(y))
190
#define SIZEOF_MARKHEAD 7
191
#define SIZEOF_OLDMHD 7
192
#define SIZEOF_NEWMHD 13
193
#define SIZEOF_OLDLHD 21
194
#define SIZEOF_NEWLHD 32
195
#define SIZEOF_SHORTBLOCKHEAD 7
196
#define SIZEOF_LONGBLOCKHEAD 11
197
#define SIZEOF_COMMHEAD 13
198
#define SIZEOF_PROTECTHEAD 26
201
#define PACK_VER 20 /* version of decompression code*/
203
#define PROTECT_VER 20
206
enum { M_DENYREAD,M_DENYWRITE,M_DENYNONE,M_DENYALL };
207
enum { FILE_EMPTY,FILE_ADD,FILE_UPDATE,FILE_COPYOLD,FILE_COPYBLOCK };
208
enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
209
OPEN_ERROR,USER_ERROR,MEMORY_ERROR,USER_BREAK=255,IMM_ABORT=0x8000 };
210
enum { EN_LOCK=1,EN_VOL=2 };
211
enum { SD_MEMORY=1,SD_FILES=2 };
212
enum { NAMES_DONTCHANGE };
213
enum { LOG_ARC=1,LOG_FILE=2 };
214
enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
215
enum { OLD_UNPACK,NEW_UNPACK };
218
#define MHD_COMMENT 2
220
#define MHD_PACK_COMMENT 16
222
#define MHD_PROTECT 64
224
#define LHD_SPLIT_BEFORE 1
225
#define LHD_SPLIT_AFTER 2
226
#define LHD_PASSWORD 4
227
#define LHD_COMMENT 8
230
#define LHD_WINDOWMASK 0x00e0
231
#define LHD_WINDOW64 0
232
#define LHD_WINDOW128 32
233
#define LHD_WINDOW256 64
234
#define LHD_WINDOW512 96
235
#define LHD_WINDOW1024 128
236
#define LHD_DIRECTORY 0x00e0
238
#define LONG_BLOCK 0x8000
239
#define READSUBBLOCK 0x8000
241
enum { ALL_HEAD=0,MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,
242
COMM_HEAD=0x75,AV_HEAD=0x76,SUB_HEAD=0x77,PROTECT_HEAD=0x78};
243
enum { EA_HEAD=0x100 };
244
enum { MS_DOS=0,OS2=1,WIN_32=2,UNIX=3 };
253
struct NewMainArchiveHeader
295
unsigned int DecodeLen[16];
296
unsigned int DecodePos[16];
297
unsigned int DecodeNum[2];
301
static struct MarkHeader MarkHead;
302
static struct NewMainArchiveHeader NewMhd;
303
static struct NewFileHeader NewLhd;
304
static struct BlockHeader BlockHead;
306
static UBYTE *TempMemory = NULL; /* temporary unpack-buffer */
307
static char *CommMemory = NULL;
310
static UBYTE *UnpMemory = NULL;
311
static char ArgName[NM]; /* current file in rar archive */
312
static char ArcFileName[NM]; /* file to decompress */
314
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
315
static MemoryFile *MemRARFile; /* pointer to RAR file in memory*/
317
static FILE *ArcPtr; /* input RAR file handler */
319
static char Password[255]; /* password to decrypt files */
321
static unsigned char *temp_output_buffer; /* extract files to this pointer*/
322
static unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */
324
static int MainHeadSize;
326
static long CurBlockPos,NextBlockPos;
328
static unsigned long CurUnpRead, CurUnpWrite;
329
static long UnpPackedSize;
330
static long DestUnpSize;
332
static UDWORD HeaderCRC;
333
static int Encryption;
335
static unsigned int UnpPtr,WrPtr;
337
static unsigned char PN1,PN2,PN3;
338
static unsigned short OldKey[4];
342
/* function header definitions */
343
static int ReadHeader(int BlockType);
344
static BOOL ExtrFile(int desc);
345
static int tread(void *stream,void *buf,unsigned len);
346
static int tseek(void *stream,long offset,int fromwhere);
347
static BOOL UnstoreFile(void);
348
static int IsArchive(void);
349
static int ReadBlock(int BlockType);
350
static unsigned int UnpRead(unsigned char *Addr,unsigned int Count);
351
static void UnpInitData(void);
352
static void Unpack(unsigned char *UnpAddr, BOOL FileFound);
353
static UBYTE DecodeAudio(int Delta);
354
static void DecodeNumber(struct Decode *Dec);
355
static void UpdKeys(UBYTE *Buf);
356
static void SetCryptKeys(char* NewPassword);
357
static void SetOldKeys(char *NewPassword);
358
static void DecryptBlock(unsigned char *Buf);
359
static void InitCRC(void);
360
static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);
361
static void UnpReadBuf(int FirstBuf);
362
static void ReadTables(void);
363
static void ReadLastTables(void);
364
static void MakeDecodeTables(unsigned char *LenTab,
367
static int stricomp(char *Str1,char *Str2);
368
/* ------------------------------------------------------------------------ */
371
/* -- global functions ---------------------------------------------------- */
373
int urarlib_get(void *output,
378
/* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
379
* does everything from allocating memory, decrypting and unpacking the file
380
* from the archive. TRUE is returned if the file could be successfully
381
* extracted, else a FALSE indicates a failure.
384
BOOL retcode = FALSE;
387
int str_offs; /* used for debug-strings */
388
char DebugMsg[500]; /* used to compose debug msg */
390
if(debug_log_first_start)
392
debug_log_first_start=FALSE; /* only create a new log file */
393
debug_init(_DEBUG_LOG_FILE); /* on startup */
398
InitCRC(); /* init some vars */
400
strcpy(ArgName, filename); /* set file(s) to extract */
401
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
402
MemRARFile = rarfile; /* set pointer to mem-RAR file */
404
if(libpassword != NULL)
405
strcpy(Password, libpassword); /* init password */
407
temp_output_buffer = NULL;
408
temp_output_buffer_offset=size; /* set size of the temp buffer */
410
retcode = ExtrFile(desc); /* unpack file now! */
413
memset(Password,0,sizeof(Password)); /* clear password */
415
#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
417
/* FIXME: possible FILE* leak */
418
cli_dbgmsg("%s:%d NOT Close ArcPtr from fd %d\n", __FILE__, __LINE__, desc);
421
lseek(desc, 0, SEEK_SET);
443
if(temp_output_buffer)
444
free(temp_output_buffer); /* free memory and return NULL */
445
temp_output_buffer=NULL;
446
*(DWORD*)output=0; /* pointer on errors */
451
/* sorry for this ugly code, but older SunOS gcc compilers don't support */
452
/* white spaces within strings */
453
str_offs = sprintf(DebugMsg, "Error - couldn't extract ");
454
str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename);
455
str_offs += sprintf(DebugMsg + str_offs, " and allocated ");
456
str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size);
457
str_offs += sprintf(DebugMsg + str_offs, " of unused memory!");
461
sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
467
*(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
474
int urarlib_list(int desc, ArchiveList_struct *list)
476
ArchiveList_struct *tmp_List = NULL;
477
int NoOfFilesInArchive = 0; /* number of files in archive */
481
if(debug_log_first_start)
483
debug_log_first_start=FALSE; /* only create a new log file */
484
debug_init(_DEBUG_LOG_FILE); /* on startup */
488
InitCRC(); /* init some vars */
490
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
491
MemRARFile = rarfile; /* assign pointer to RAR file */
492
MemRARFile->offset = 0;
495
debug_log("Not a RAR file");
496
return NoOfFilesInArchive; /* error => exit! */
499
/* open and identify archive */
501
cli_dbgmsg("ExtrFile(): dup(%d) = %d\n", desc, newdesc);
502
if ((ArcPtr=fdopen(newdesc,READBINARY))!=NULL)
506
cli_dbgmsg("urarlib_list(): Not a valid archive.");
507
debug_log("Not a RAR file");
509
lseek(desc, 0, SEEK_SET);
511
return NoOfFilesInArchive; /* error => exit! */
515
cli_dbgmsg("urarlib_list(): Error opening file: %s", strerror(errno));
516
debug_log("Error opening file.");
517
cli_dbgmsg("%s:%d Close fd %d\n", __FILE__, __LINE__, newdesc);
519
return NoOfFilesInArchive;
523
if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
525
cli_dbgmsg("urarlib_list(): out of memory.");
526
debug_log("Can't allocate memory for decompression!");
528
return NoOfFilesInArchive;
531
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
532
MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
534
tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
536
(*(DWORD*)list) = (DWORD)NULL; /* init file list */
537
/* do while file is not extracted and there's no error */
541
if ((ReadBlockResult = ReadBlock(FILE_HEAD | READSUBBLOCK)) <= 0) /* read name of the next */
542
{ /* file within the RAR archive */
543
cli_dbgmsg("Couldn't read next filename from archive (I/O error): %d\n", ReadBlockResult);
544
break; /* error, file not found in */
545
} /* archive or I/O error */
546
if (BlockHead.HeadType==SUB_HEAD)
548
debug_log("Sorry, sub-headers not supported.");
549
NoOfFilesInArchive = 0;
550
break; /* error => exit */
553
if((void*)(*(DWORD*)list) == NULL) /* first entry */
555
tmp_List = malloc(sizeof(ArchiveList_struct));
556
tmp_List->next = NULL;
558
(*(DWORD*)list) = (DWORD)tmp_List;
560
} else /* add entry */
562
tmp_List->next = malloc(sizeof(ArchiveList_struct));
563
tmp_List = (ArchiveList_struct*) tmp_List->next;
564
tmp_List->next = NULL;
567
tmp_List->item.Name = malloc(NewLhd.NameSize + 1);
568
strcpy(tmp_List->item.Name, ArcFileName);
569
tmp_List->item.NameSize = NewLhd.NameSize;
570
tmp_List->item.PackSize = NewLhd.PackSize;
571
tmp_List->item.UnpSize = NewLhd.UnpSize;
572
tmp_List->item.HostOS = NewLhd.HostOS;
573
tmp_List->item.FileCRC = NewLhd.FileCRC;
574
tmp_List->item.FileTime = NewLhd.FileTime;
575
tmp_List->item.UnpVer = NewLhd.UnpVer;
576
tmp_List->item.Method = NewLhd.Method;
577
tmp_List->item.FileAttr = NewLhd.FileAttr;
578
tmp_List->item.Flags = NewLhd.Flags;
580
NoOfFilesInArchive++; /* count files */
582
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
583
MemRARFile->offset = NextBlockPos;
585
if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
590
/* free memory, clear password and close archive */
591
memset(Password,0,sizeof(Password)); /* clear password */
592
#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
596
lseek(desc, 0, SEEK_SET);
613
return NoOfFilesInArchive;
619
* (after the suggestion and code of Duy Nguyen, Sean O'Blarney
620
* and Johannes Winkelmann who independently wrote a patch)
621
* free the memory of a ArchiveList_struct created by urarlib_list.
623
* input: *list pointer to an ArchiveList_struct
627
void urarlib_freelist(ArchiveList_struct *list)
629
ArchiveList_struct* tmp = list;
633
free( list->item.Name );
640
/* ------------------------------------------------------------------------ */
658
/****************************************************************************
659
****************************************************************************
660
****************************************************************************
661
****************************************************************************
665
******* B L O C K I / O *******
669
****************************************************************************
670
****************************************************************************
671
****************************************************************************
672
****************************************************************************/
676
#define GetHeaderByte(N) Header[N]
678
#define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
680
#define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
681
((UDWORD)Header[N+2]<<16)+\
682
((UDWORD)Header[N+3]<<24))
685
int ReadBlock(int BlockType)
687
struct NewFileHeader SaveFileHead;
688
int Size=0,ReadSubBlock=0;
689
static int LastBlock;
690
memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
691
if (BlockType & READSUBBLOCK) {
698
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
699
CurBlockPos=MemRARFile->offset; /* get offset of mem-file */
701
CurBlockPos=ftell(ArcPtr);
703
Size=ReadHeader(FILE_HEAD);
706
if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
708
NextBlockPos=CurBlockPos+NewLhd.HeadSize;
709
if (NewLhd.Flags & LONG_BLOCK)
710
NextBlockPos+=NewLhd.PackSize;
711
if (NextBlockPos<=CurBlockPos)
715
if (Size > 0 && BlockType!=SUB_HEAD)
717
if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
718
(NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
720
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
721
MemRARFile->offset = NextBlockPos;
723
tseek(ArcPtr, NextBlockPos, SEEK_SET);
728
BlockHead.HeadCRC=NewLhd.HeadCRC;
729
BlockHead.HeadType=NewLhd.HeadType;
730
BlockHead.Flags=NewLhd.Flags;
731
BlockHead.HeadSize=NewLhd.HeadSize;
732
BlockHead.DataSize=NewLhd.PackSize;
734
if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
736
if((FILE_HEAD == BlockType) && (Size>0))
738
NewLhd.NameSize=Min(NewLhd.NameSize,sizeof(ArcFileName)-1);
739
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
740
tread(MemRARFile, ArcFileName, NewLhd.NameSize);
742
tread(ArcPtr,ArcFileName,NewLhd.NameSize);
744
ArcFileName[NewLhd.NameSize]=0;
746
if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
749
debug_log("file header broken");
752
Size+=NewLhd.NameSize;
755
memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
756
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
757
MemRARFile->offset = CurBlockPos;
759
tseek(ArcPtr,CurBlockPos,SEEK_SET);
768
int ReadHeader(int BlockType)
771
unsigned char Header[64];
772
memset(Header, 0, sizeof(Header));
776
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
777
Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
779
Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
781
NewMhd.HeadCRC=(unsigned short)GetHeaderWord(0);
782
NewMhd.HeadType=GetHeaderByte(2);
783
NewMhd.Flags=(unsigned short)GetHeaderWord(3);
784
NewMhd.HeadSize=(unsigned short)GetHeaderWord(5);
785
NewMhd.Reserved=(unsigned short)GetHeaderWord(7);
786
NewMhd.Reserved1=GetHeaderDword(9);
787
HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWMHD-2);
790
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
791
Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
793
Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
795
NewLhd.HeadCRC=(unsigned short)GetHeaderWord(0);
796
NewLhd.HeadType=GetHeaderByte(2);
797
NewLhd.Flags=(unsigned short)GetHeaderWord(3);
798
NewLhd.HeadSize=(unsigned short)GetHeaderWord(5);
799
NewLhd.PackSize=GetHeaderDword(7);
800
NewLhd.UnpSize=GetHeaderDword(11);
801
NewLhd.HostOS=GetHeaderByte(15);
802
NewLhd.FileCRC=GetHeaderDword(16);
803
NewLhd.FileTime=GetHeaderDword(20);
804
NewLhd.UnpVer=GetHeaderByte(24);
805
NewLhd.Method=GetHeaderByte(25);
806
NewLhd.NameSize=(unsigned short)GetHeaderWord(26);
807
NewLhd.FileAttr=GetHeaderDword(28);
808
HeaderCRC=CalcCRC32(0xFFFFFFFFL,Header+2,SIZEOF_NEWLHD-2);
812
case COMM_HEAD: /* log errors in case of debug */
813
debug_log("Comment headers not supported! "\
814
"Please create archives without comments.");
817
debug_log("Protected headers not supported!");
820
debug_log("ShortBlockHeader not supported!");
823
debug_log("Unknown//unsupported !");
825
default: /* else do nothing */
832
/* **************************************************************************
833
****************************************************************************
834
****************************************************************************
835
************************************************************************** */
853
/* **************************************************************************
854
****************************************************************************
855
****************************************************************************
856
****************************************************************************
860
******* E X T R A C T L O O P *******
864
****************************************************************************
865
****************************************************************************
866
****************************************************************************
867
************************************************************************** */
873
int str_offs; /* used for debug-strings */
874
char DebugMsg[500]; /* used to compose debug msg */
877
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
878
if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD) {
879
debug_log("IsArchive(): short read: FALSE");
883
if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) {
884
debug_log("IsArchive(): short read: FALSE");
888
/* Old archive => error */
889
if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
890
MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
892
debug_log("Attention: format as OLD detected! Can't handle archive!");
895
/* original RAR v2.0 */
896
if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original */
897
MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
898
MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
899
MarkHead.Mark[6]==0x00) ||
900
/* "UniquE!" - header */
901
(MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' && /* "UniquE!" */
902
MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' && /* header */
903
MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
904
MarkHead.Mark[6]=='!'))
907
if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD) {
908
debug_log("IsArchive(): ReadHeader() failed");
915
/* sorry for this ugly code, but older SunOS gcc compilers don't */
916
/* support white spaces within strings */
917
str_offs = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
918
str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
919
str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
920
str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
928
MainHeadSize=SIZEOF_NEWMHD;
934
BOOL ExtrFile(int desc)
936
BOOL ReturnCode=TRUE;
937
BOOL FileFound=FALSE; /* TRUE=use current extracted */
938
/* data FALSE=throw data away, */
942
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
943
MemRARFile->offset = 0; /* start reading from offset 0 */
946
debug_log("Not a RAR file");
947
return FALSE; /* error => exit! */
951
/* open and identify archive */
953
cli_dbgmsg("ExtrFile(): dup(%d) = %d\n", desc, newdesc);
954
if ((ArcPtr=fdopen(newdesc,READBINARY))!=NULL)
958
debug_log("Not a RAR file");
961
return FALSE; /* error => exit! */
965
debug_log("Error opening file.");
971
if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
973
cli_dbgmsg("unrarlib: Can't allocate memory for decompression!");
975
} else cli_dbgmsg("unrarlib: Allocated %d bytes.\n", UNP_MEMORY);
977
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
978
MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
980
tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
983
/* do while file is not extracted and there's no error */
987
if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
988
{ /* file within the RAR archive */
991
* 21.11.2000 UnQ There's a problem with some linux distros when a file
992
* can not be found in an archive.
993
* 07.09.2004 ThL Seems more like a logical bug in this lib, since it
994
* appears to occur once for every archive.
998
debug_log("Couldn't read next filename from archive (I/O error).");
1001
break; /* error, file not found in */
1002
} /* archive or I/O error */
1003
if (BlockHead.HeadType==SUB_HEAD)
1005
debug_log("Sorry, sub-headers not supported.");
1007
break; /* error => exit */
1011
if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
1012
/* *** file found! *** */
1015
cli_dbgmsg("unrarlib: Allocating %d bytes\n", NewLhd.UnpSize);
1016
if((temp_output_buffer=malloc(NewLhd.UnpSize)) == NULL) { ;/* allocate memory for the*/
1017
cli_errmsg("unrarlib: Can't malloc %d bytes\n", NewLhd.UnpSize);
1022
*temp_output_buffer_offset=0; /* file. The default offset */
1023
/* within the buffer is 0 */
1026
/* in case of a solid archive, we need to decompress any single file till
1027
* we have found the one we are looking for. In case of normal archives
1028
* (recommended!!), we skip the files until we are sure that it is the
1031
if((NewMhd.Flags & 0x08) || FileFound)
1033
if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
1035
cli_dbgmsg("unknown compression method: %d (min=13 max=%d)\n", NewLhd.UnpVer, UNP_VER);
1037
break; /* error, can't extract file! */
1040
CurUnpRead=CurUnpWrite=0;
1041
if ((*Password!=0) && (NewLhd.Flags & LHD_PASSWORD))
1042
Encryption=NewLhd.UnpVer;
1045
if (Encryption) SetCryptKeys(Password);
1047
UnpPackedSize=NewLhd.PackSize;
1048
DestUnpSize=NewLhd.UnpSize;
1050
if (NewLhd.Method==0x30)
1052
cli_dbgmsg("unrarlib: Unstore method temporarily not supported\n");
1053
/* UnstoreFile(); */
1055
break; /* error, can't extract file! */
1058
cli_dbgmsg("unrarlib: Unpack()\n");
1059
Unpack(UnpMemory, FileFound);
1063
#ifdef _DO_CRC32_CHECK /* calculate CRC32 */
1064
if((UBYTE*)temp_output_buffer != NULL)
1066
if(NewLhd.FileCRC!=~CalcCRC32(0xFFFFFFFFL,
1067
(UBYTE*)temp_output_buffer,
1070
debug_log("CRC32 error - file couldn't be decompressed correctly!");
1072
break; /* error, can't extract file! */
1079
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1080
MemRARFile->offset = NextBlockPos;
1082
if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
1084
} while(stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */
1086
/* free memory, clear password and close archive */
1091
#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1094
lseek(desc, 0, SEEK_SET);
1102
/* **************************************************************************
1103
****************************************************************************
1104
****************************************************************************
1105
************************************************************************** */
1124
/* **************************************************************************
1125
****************************************************************************
1126
****************************************************************************
1127
****************************************************************************
1131
******* G L O B A L F U N C T I O N S *******
1135
****************************************************************************
1136
****************************************************************************
1137
****************************************************************************
1138
************************************************************************** */
1141
int tread(void *stream,void *buf,unsigned len)
1143
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1145
if(((MemRARFile->offset + len) > MemRARFile->size) || (len == 0))
1149
(BYTE*)(((MemoryFile*)stream)->data)+((MemoryFile*)stream)->offset,
1150
len % ((((MemoryFile*)stream)->size) - 1));
1152
MemRARFile->offset+=len; /* update read pointer */
1153
return len % ((((MemoryFile*)stream)->size) - 1);
1155
return(fread(buf,1,len,(FILE*)stream));
1160
#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1161
int tseek(void *stream,long offset,int fromwhere)
1163
return(fseek((FILE*)stream,offset,fromwhere));
1168
static char* strupper(char *Str)
1171
for (ChPtr=Str;*ChPtr;ChPtr++)
1172
*ChPtr=(char)toupper(*ChPtr);
1177
int stricomp(char *Str1,char *Str2)
1178
/* compare strings without regard of '\' and '/' */
1180
char S1[512],S2[512];
1183
strncpy(S1,Str1,sizeof(S1));
1184
strncpy(S2,Str2,sizeof(S2));
1186
while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash */
1191
while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash */
1196
while((chptr = strchr(S1, '/')) != NULL) /* ignore slash */
1201
while((chptr = strchr(S2, '/')) != NULL) /* ignore slash */
1206
return(strcmp(strupper(S1),strupper(S2)));
1210
/* **************************************************************************
1211
****************************************************************************
1212
****************************************************************************
1213
************************************************************************** */
1232
/* **************************************************************************
1233
****************************************************************************
1234
****************************************************************************
1235
****************************************************************************
1239
******* U N P A C K C O D E *******
1243
****************************************************************************
1244
****************************************************************************
1245
****************************************************************************
1246
************************************************************************** */
1249
/* *****************************
1250
* ** unpack stored RAR files **
1251
* *****************************/
1253
BOOL UnstoreFile(void)
1255
if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
1256
NewLhd.UnpSize))==-1)
1258
cli_dbgmsg("unrarlib: Read error of stored file!");
1267
/* ****************************************
1268
* ** RAR decompression code starts here **
1269
* ****************************************/
1271
#define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
1277
enum {CODE_HUFFMAN=0,CODE_LZ=1,CODE_LZ2=2,CODE_REPEATLZ=3,CODE_CACHELZ=4,
1278
CODE_STARTFILE=5,CODE_ENDFILE=6,CODE_STARTMM=8,CODE_ENDMM=7,
1281
struct AudioVariables
1286
unsigned int Dif[11];
1287
unsigned int ByteCount;
1292
#define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
1299
static struct AudioVariables AudV[4];
1302
BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
1303
( (UWORD) InBuf[InAddr+1] << 8 ) | \
1304
( InBuf[InAddr+2] ) ) \
1305
>> (8-InBit) ) & 0xffff;
1308
#define AddBits(Bits) \
1309
InAddr += ( InBit + (Bits) ) >> 3; \
1310
InBit = ( InBit + (Bits) ) & 7;
1312
static unsigned char *UnpBuf;
1313
static unsigned int BitField;
1314
static unsigned int Number;
1316
static unsigned char InBuf[8192]; /* input read buffer */
1318
static unsigned char UnpOldTable[MC*4];
1320
static unsigned int InAddr,InBit,ReadTop;
1322
static unsigned int LastDist,LastLength;
1323
static unsigned int Length,Distance;
1325
static unsigned int OldDist[4],OldDistPtr;
1328
static struct LitDecode
1330
unsigned int MaxNum;
1331
unsigned int DecodeLen[16];
1332
unsigned int DecodePos[16];
1333
unsigned int DecodeNum[NC];
1336
static struct DistDecode
1338
unsigned int MaxNum;
1339
unsigned int DecodeLen[16];
1340
unsigned int DecodePos[16];
1341
unsigned int DecodeNum[DC];
1344
static struct RepDecode
1346
unsigned int MaxNum;
1347
unsigned int DecodeLen[16];
1348
unsigned int DecodePos[16];
1349
unsigned int DecodeNum[RC];
1352
static struct MultDecode
1354
unsigned int MaxNum;
1355
unsigned int DecodeLen[16];
1356
unsigned int DecodePos[16];
1357
unsigned int DecodeNum[MC];
1360
static struct BitDecode
1362
unsigned int MaxNum;
1363
unsigned int DecodeLen[16];
1364
unsigned int DecodePos[16];
1365
unsigned int DecodeNum[BC];
1368
static struct MultDecode *MDPtr[4]={&MD[0],&MD[1],&MD[2],&MD[3]};
1370
static int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
1373
void Unpack(unsigned char *UnpAddr, BOOL FileFound)
1374
/* *** 38.3% of all CPU time is spent within this function!!! */
1376
static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
1377
40,48,56,64,80,96,112,128,160,192,224};
1378
static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
1379
3,3,3,4,4,4,4,5,5,5,5};
1380
static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
1381
512,768,1024,1536,2048,3072,4096,6144,8192,12288,
1382
16384,24576,32768U,49152U,65536,98304,131072,196608,
1383
262144,327680,393216,458752,524288,589824,655360,
1384
720896,786432,851968,917504,983040};
1385
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,
1386
9,10,10,11,11,12,12,13,13,14,14,15,15,16,
1387
16,16,16,16,16,16,16,16,16,16,16,16,16};
1388
static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
1389
static unsigned char SDBits[]={2,2,3, 4, 5, 6, 6, 6};
1393
UnpBuf=UnpAddr; /* UnpAddr is a pointer to the */
1394
UnpInitData(); /* unpack buffer */
1396
if (!(NewLhd.Flags & LHD_SOLID))
1400
while (DestUnpSize>=0)
1404
if (InAddr>sizeof(InBuf)-30)
1406
if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
1415
if((*temp_output_buffer_offset + ((0-WrPtr) & MAXWINMASK) + UnpPtr) > NewLhd.UnpSize)
1417
debug_log("Fatal! Buffer overrun during decompression!");
1422
/* copy extracted data to output buffer */
1423
memcpy(temp_output_buffer + *temp_output_buffer_offset,
1424
&UnpBuf[WrPtr], (0-WrPtr) & MAXWINMASK);
1425
/* update offset within buffer */
1426
*temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
1427
/* copy extracted data to output buffer */
1428
memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
1430
/* update offset within buffer */
1431
*temp_output_buffer_offset+=UnpPtr;
1435
if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1437
debug_log("Fatal! Buffer overrun during decompression!");
1441
/* copy extracted data to output buffer */
1442
memcpy(temp_output_buffer + *temp_output_buffer_offset,
1443
&UnpBuf[WrPtr], UnpPtr-WrPtr);
1444
*temp_output_buffer_offset+=UnpPtr-WrPtr; /* update offset within buffer */
1455
DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1461
UnpBuf[UnpPtr++]=DecodeAudio(Number);
1462
if (++CurChannel==UnpChannels)
1468
DecodeNumber((struct Decode *)&LD);
1471
UnpBuf[UnpPtr++]=(UBYTE)Number;
1477
Length=LDecode[Number-=270]+3;
1478
if ((Bits=LBits[Number])>0)
1481
Length+=BitField>>(16-Bits);
1485
DecodeNumber((struct Decode *)&DD);
1486
Distance=DDecode[Number]+1;
1487
if ((Bits=DBits[Number])>0)
1490
Distance+=BitField>>(16-Bits);
1494
if (Distance>=0x40000L)
1497
if (Distance>=0x2000)
1500
LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1501
DestUnpSize-=(LastLength=Length);
1504
UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1505
UnpPtr=(UnpPtr+1) & MAXWINMASK;
1519
LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1520
DestUnpSize-=(LastLength=Length);
1523
UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1524
UnpPtr=(UnpPtr+1) & MAXWINMASK;
1530
Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
1531
DecodeNumber((struct Decode *)&RD);
1532
Length=LDecode[Number]+2;
1533
if ((Bits=LBits[Number])>0)
1536
Length+=BitField>>(16-Bits);
1539
if (Distance>=0x40000)
1541
if (Distance>=0x2000)
1543
if (Distance>=0x101)
1545
LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1546
DestUnpSize-=(LastLength=Length);
1549
UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1550
UnpPtr=(UnpPtr+1) & MAXWINMASK;
1556
Distance=SDDecode[Number-=261]+1;
1557
if ((Bits=SDBits[Number])>0)
1560
Distance+=BitField>>(16-Bits);
1564
LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1565
DestUnpSize-=(LastLength=Length);
1568
UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1569
UnpPtr=(UnpPtr+1) & MAXWINMASK;
1576
if (FileFound) /* flush buffer */
1581
if((*temp_output_buffer_offset + ((0-WrPtr) & MAXWINMASK) + UnpPtr) > NewLhd.UnpSize)
1583
debug_log("Fatal! Buffer overrun during decompression!");
1587
/* copy extracted data to output buffer */
1588
memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
1589
(0-WrPtr) & MAXWINMASK);
1590
/* update offset within buffer */
1591
*temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
1592
/* copy extracted data to output buffer */
1593
memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf, UnpPtr);
1594
/* update offset within buffer */
1595
*temp_output_buffer_offset+=UnpPtr;
1599
if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1601
debug_log("Fatal! Buffer overrun during decompression!");
1605
/* copy extracted data to output buffer */
1606
memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
1608
/* update offset within buffer */
1609
*temp_output_buffer_offset+=UnpPtr-WrPtr;
1618
unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
1621
unsigned int I,ReadSize,TotalRead=0;
1622
unsigned char *ReadAddr;
1626
ReadSize=(unsigned int)((Count>(unsigned long)UnpPackedSize) ?
1627
UnpPackedSize : Count);
1628
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1629
cli_dbgmsg("unrarlib: UnpREAD: Using memory->memory decompression\n");
1630
if(MemRARFile->data == NULL)
1632
RetCode=tread(MemRARFile, ReadAddr, ReadSize);
1636
RetCode=tread(ArcPtr,ReadAddr,ReadSize);
1638
CurUnpRead+=RetCode;
1642
UnpPackedSize-=RetCode;
1646
cli_dbgmsg("CurUnpRead == %d, TotalRead == %d, Count == %d, UnpPackedSize == %d\n", CurUnpRead, TotalRead, Count, UnpPackedSize);
1655
cli_dbgmsg("unrarlib: Old Crypt() not supported!");
1659
for (I=0;I<(unsigned int)RetCode;I+=16)
1660
DecryptBlock(&Addr[I]);
1668
void UnpReadBuf(int FirstBuf)
1673
ReadTop=UnpRead(InBuf,sizeof(InBuf));
1678
memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
1680
RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
1689
void ReadTables(void)
1691
UBYTE BitLength[BC];
1692
unsigned char Table[MC*4];
1694
if (InAddr>sizeof(InBuf)-25)
1697
UnpAudioBlock=(BitField & 0x8000);
1699
if (!(BitField & 0x4000))
1700
memset(UnpOldTable,0,sizeof(UnpOldTable));
1706
UnpChannels=((BitField>>12) & 3)+1;
1707
if (CurChannel>=UnpChannels)
1710
TableSize=MC*UnpChannels;
1719
BitLength[I]=(UBYTE)(BitField >> 12);
1722
MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
1726
if (InAddr>sizeof(InBuf)-5)
1728
DecodeNumber((struct Decode *)&BD);
1730
Table[I]=(Number+UnpOldTable[I]) & 0xf;
1737
N=(BitField >> 14)+3;
1739
while (N-- > 0 && I<TableSize)
1741
Table[I]=Table[I-1];
1750
N=(BitField >> 13)+3;
1756
N=(BitField >> 9)+11;
1759
while (N-- > 0 && I<TableSize)
1764
for (I=0;I<UnpChannels;I++)
1765
MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
1768
MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
1769
MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
1770
MakeDecodeTables(&Table[NC+DC],(struct Decode *)&RD,RC);
1772
memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
1776
static void ReadLastTables(void)
1778
if (ReadTop>=InAddr+5)
1782
DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1788
DecodeNumber((struct Decode *)&LD);
1796
static void MakeDecodeTables(unsigned char *LenTab,
1800
int LenCount[16],TmpPos[16],I;
1802
memset(LenCount,0,sizeof(LenCount));
1803
for (I=0;I<Size;I++)
1804
LenCount[LenTab[I] & 0xF]++;
1807
for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
1809
N=2*(N+LenCount[I]);
1813
Dec->DecodeLen[I]=(unsigned int)M;
1814
TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
1817
for (I=0;I<Size;I++)
1819
Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
1824
static void DecodeNumber(struct Decode *Deco)
1825
/* *** 52.6% of all CPU time is spent within this function!!! */
1828
register unsigned int N;
1837
mov eax, BitField /* N=BitField & 0xFFFE; */
1840
mov edx, [Deco] /* EAX=N, EDX=Deco */
1842
cmp eax, dword ptr[edx + 8*4 + 4] /* if (N<Dec->DecodeLen[8]) */
1845
cmp eax, dword ptr[edx + 4*4 + 4] /* if (N<Dec->DecodeLen[4]) */
1849
cmp eax, dword ptr[edx + 2*4 + 4] /* if (N<Dec->DecodeLen[2]) */
1852
cmp eax, dword ptr[edx + 1*4 + 4] /* if (N<Dec->DecodeLen[1]) */
1863
cmp eax, dword ptr[edx + 3*4 + 4] /* if (N<Dec->DecodeLen[3]) */
1877
cmp eax, dword ptr[edx + 6*4 + 4] /* if (N<Dec->DecodeLen[6]) */
1880
cmp eax, dword ptr[edx + 5*4 + 4] /* if (N<Dec->DecodeLen[5]) */
1891
cmp eax, dword ptr[edx + 7*4 + 4] /* if (N<Dec->DecodeLen[7]) */
1906
cmp eax, dword ptr[edx + 12*4 + 4] /* if (N<Dec->DecodeLen[12]) */
1909
cmp eax, dword ptr[edx + 10*4 + 4] /* if (N<Dec->DecodeLen[10]) */
1912
cmp eax, dword ptr[edx + 9*4 + 4] /* if (N<Dec->DecodeLen[9]) */
1917
mov I, 10 /* I=10; */
1923
cmp eax, dword ptr[edx + 11*4 + 4] /* if (N<Dec->DecodeLen[11]) */
1925
mov I, 11 /* I=11; */
1928
mov I, 12 /* I=12; */
1937
cmp eax, dword ptr[edx + 14*4 + 4] /* if (N<Dec->DecodeLen[14]) */
1940
cmp eax, dword ptr[edx + 13*4 + 4] /* if (N<Dec->DecodeLen[13]) */
1942
mov I, 13 /* I=13; */
1945
mov I, 14 /* I=14; */
1950
mov I, 15 /* I=15; */
1957
__asm__ __volatile__ (
1958
"andl $0xFFFFFFFE, %%eax"
1960
" cmpl 8*4(%%edx), %%eax /* 5379 */"
1963
" cmpl 4*4(%%edx), %%eax"
1966
" cmpl 2*4(%%edx), %%eax"
1969
" cmpl 1*4(%%edx), %%eax"
1981
" cmpl 3*4(%%edx), %%eax "
1994
" cmpl 6*4(%%edx), %%eax"
1997
" cmpl 5*4(%%edx), %%eax"
2008
" cmpl 7*4(%%edx), %%eax"
2023
" cmpl 12*4(%%edx), %%eax"
2026
" cmpl 10*4(%%edx), %%eax"
2029
" cmpl 9*4(%%edx), %%eax"
2040
" cmpl 11*4(%%edx), %%eax"
2055
" cmpl 14*4(%%edx), %%eax"
2058
" cmpl 13*4(%%edx), %%eax"
2074
: "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
2077
#endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
2080
N=BitField & 0xFFFE;
2081
if (N<Deco->DecodeLen[8]) {
2082
if (N<Deco->DecodeLen[4]) {
2083
if (N<Deco->DecodeLen[2]) {
2084
if (N<Deco->DecodeLen[1])
2089
if (N<Deco->DecodeLen[3])
2095
if (N<Deco->DecodeLen[6]) {
2096
if (N<Deco->DecodeLen[5])
2101
if (N<Deco->DecodeLen[7])
2108
if (N<Deco->DecodeLen[12]) {
2109
if (N<Deco->DecodeLen[10]) {
2110
if (N<Deco->DecodeLen[9])
2115
if (N<Deco->DecodeLen[11])
2121
if (N<Deco->DecodeLen[14]) {
2122
if (N<Deco->DecodeLen[13])
2136
if ((N=Deco->DecodePos[I]+((N-Deco->DecodeLen[I-1])>>(16-I)))>=Deco->MaxNum)
2138
Number=Deco->DecodeNum[N];
2145
if (!(NewLhd.Flags & LHD_SOLID))
2147
ChannelDelta=CurChannel=0;
2151
#ifdef _WIN_32 /* Win32 with VisualC */
2158
cld /* increment EDI and ESI */
2161
mov edi, Offset AudV
2162
rep stosb /* clear memory */
2164
mov ecx, SIZE OldDist
2165
mov edi, Offset OldDist
2166
rep stosb /* clear memory */
2168
mov ecx, SIZE UnpOldTable
2169
mov edi, Offset UnpOldTable
2170
rep stosb /* clear memory */
2189
memset(UnpBuf,0,MAXWINSIZE);
2192
#else /* unix/linux on i386 cpus */
2193
__asm__ __volatile (
2194
" cld /* increment EDI and ESI */"
2199
" stosb /* clear memory */"
2204
" stosb /* clear memory */"
2209
" stosb /* clear memory */"
2211
" movl $0, (OldDistPtr)"
2212
" movl $0, (LastDist)"
2213
" movl $0, (LastLength)"
2214
" movl $0, (UnpPtr)"
2216
" movl $0, (OldDistPtr)"
2217
" movl $0, (LastLength)"
2218
" movl $0, (LastDist)"
2219
" movl $0, (UnpPtr)"
2222
: "m" ((long)sizeof(AudV)),
2224
"m" ((long)sizeof(OldDist)),
2225
"m" ((long)OldDist),
2226
"m" ((long)sizeof(UnpOldTable)),
2227
"m" ((long)UnpOldTable)
2228
: "memory", "edi", "eax", "ecx"
2230
memset(UnpBuf,0,MAXWINSIZE);
2233
#else /* unix/linux on non-i386 cpu */
2234
memset(AudV,0,sizeof(AudV));
2235
memset(OldDist,0,sizeof(OldDist));
2237
LastDist=LastLength=0;
2238
memset(UnpBuf,0,MAXWINSIZE);
2239
memset(UnpOldTable,0,sizeof(UnpOldTable));
2247
UBYTE DecodeAudio(int Delta)
2249
struct AudioVariables *V;
2251
unsigned int NumMinDif,MinDif;
2254
V=&AudV[CurChannel];
2258
V->D2=V->LastDelta-V->D1;
2260
PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+
2261
V->K3*V->D3+V->K4*V->D4+V->K5*ChannelDelta;
2262
PCh=(PCh>>3) & 0xFF;
2266
I=((signed char)Delta)<<3;
2269
V->Dif[1]+=abs(I-V->D1);
2270
V->Dif[2]+=abs(I+V->D1);
2271
V->Dif[3]+=abs(I-V->D2);
2272
V->Dif[4]+=abs(I+V->D2);
2273
V->Dif[5]+=abs(I-V->D3);
2274
V->Dif[6]+=abs(I+V->D3);
2275
V->Dif[7]+=abs(I-V->D4);
2276
V->Dif[8]+=abs(I+V->D4);
2277
V->Dif[9]+=abs(I-ChannelDelta);
2278
V->Dif[10]+=abs(I+ChannelDelta);
2280
ChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
2283
if ((V->ByteCount & 0x1F)==0)
2288
for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
2290
if (V->Dif[I]<MinDif)
2350
/* ***************************************************
2351
* ** CRCCrypt Code - decryption engine starts here **
2352
* ***************************************************/
2357
#define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
2358
#define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
2360
#define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
2361
((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
2362
((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
2363
((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
2366
static UDWORD CRCTab[256];
2368
static UBYTE SubstTable[256];
2369
static const UBYTE InitSubstTable[256]={
2370
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
2371
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
2372
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
2373
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
2374
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
2375
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
2376
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
2377
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
2378
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
2379
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
2380
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
2381
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
2382
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
2383
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
2384
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
2385
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
2388
static UDWORD Key[4];
2391
static void EncryptBlock(UBYTE *Buf)
2395
UDWORD A,B,C,D,T,TA,TB;
2396
#ifdef NON_INTEL_BYTE_ORDER
2397
A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
2398
((UDWORD)Buf[3]<<24))^Key[0];
2399
B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
2400
((UDWORD)Buf[7]<<24))^Key[1];
2401
C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
2402
((UDWORD)Buf[11]<<24))^Key[2];
2403
D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
2404
((UDWORD)Buf[15]<<24))^Key[3];
2407
BufPtr=(UDWORD *)Buf;
2413
for(I=0;I<NROUNDS;I++)
2415
T=((C+rol(D,11))^Key[I&3]);
2417
T=((D^rol(C,17))+Key[I&3]);
2424
#ifdef NON_INTEL_BYTE_ORDER
2427
Buf[1]=(UBYTE)(C>>8);
2428
Buf[2]=(UBYTE)(C>>16);
2429
Buf[3]=(UBYTE)(C>>24);
2432
Buf[5]=(UBYTE)(D>>8);
2433
Buf[6]=(UBYTE)(D>>16);
2434
Buf[7]=(UBYTE)(D>>24);
2437
Buf[9]=(UBYTE)(A>>8);
2438
Buf[10]=(UBYTE)(A>>16);
2439
Buf[11]=(UBYTE)(A>>24);
2442
Buf[13]=(UBYTE)(B>>8);
2443
Buf[14]=(UBYTE)(B>>16);
2444
Buf[15]=(UBYTE)(B>>24);
2455
void DecryptBlock(UBYTE *Buf)
2459
UDWORD A,B,C,D,T,TA,TB;
2460
#ifdef NON_INTEL_BYTE_ORDER
2461
A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
2462
((UDWORD)Buf[3]<<24))^Key[0];
2463
B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
2464
((UDWORD)Buf[7]<<24))^Key[1];
2465
C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
2466
((UDWORD)Buf[11]<<24))^Key[2];
2467
D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
2468
((UDWORD)Buf[15]<<24))^Key[3];
2471
BufPtr=(UDWORD *)Buf;
2472
A=BufPtr[0]^Key[0]; /* xxx may be this can be */
2473
B=BufPtr[1]^Key[1]; /* optimized in assembler */
2477
memcpy(InBuf,Buf,sizeof(InBuf));
2478
for(I=NROUNDS-1;I>=0;I--)
2480
T=((C+rol(D,11))^Key[I&3]);
2482
T=((D^rol(C,17))+Key[I&3]);
2489
#ifdef NON_INTEL_BYTE_ORDER
2492
Buf[1]=(UBYTE)(C>>8);
2493
Buf[2]=(UBYTE)(C>>16);
2494
Buf[3]=(UBYTE)(C>>24);
2497
Buf[5]=(UBYTE)(D>>8);
2498
Buf[6]=(UBYTE)(D>>16);
2499
Buf[7]=(UBYTE)(D>>24);
2502
Buf[9]=(UBYTE)(A>>8);
2503
Buf[10]=(UBYTE)(A>>16);
2504
Buf[11]=(UBYTE)(A>>24);
2507
Buf[13]=(UBYTE)(B>>8);
2508
Buf[14]=(UBYTE)(B>>16);
2509
Buf[15]=(UBYTE)(B>>24);
2520
void UpdKeys(UBYTE *Buf)
2525
Key[0]^=CRCTab[Buf[I]]; /* xxx may be I'll rewrite this */
2526
Key[1]^=CRCTab[Buf[I+1]]; /* in asm for speedup */
2527
Key[2]^=CRCTab[Buf[I+2]];
2528
Key[3]^=CRCTab[Buf[I+3]];
2532
static void SetCryptKeys(char *NewPassword)
2534
unsigned int I,J,K,PswLength;
2535
unsigned char N1,N2;
2536
unsigned char Psw[256];
2538
#if !defined _USE_ASM
2542
SetOldKeys(NewPassword);
2548
memset(Psw,0,sizeof(Psw));
2549
strcpy((char *)Psw,NewPassword);
2550
PswLength=strlen(NewPassword);
2551
memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
2554
for (I=0;I<PswLength;I+=2)
2556
N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xFF];
2557
for (K=1, N1=(unsigned char)CRCTab[(Psw[I]-J)&0xFF];
2566
mov ebx, Offset SubstTable
2569
xor ecx, ecx /* read SubstTable[N1]... */
2572
mov al, byte ptr[ebx]
2574
mov cl, N1 /* read SubstTable[(N1+I+K)&0xFF]... */
2579
mov ah, byte ptr[edx]
2581
mov byte ptr[ebx], ah /* and write back */
2582
mov byte ptr[edx], al
2586
__asm__ __volatile__ (
2587
" xorl %%ecx, %%ecx"
2588
" movl %2, %%ecx /* ecx = N1 */"
2590
" addl %%ecx, %%ebx"
2594
" andl $0x000000FF, %%ecx"
2595
" addl %%ecx, %%edx"
2597
" movb (%%ebx), %%al"
2598
" movb (%%edx), %%ah"
2600
" movb %%ah, (%%ebx) /* and write back */"
2601
" movb %%al, (%%edx)"
2605
"ebx"((long)SubstTable)
2612
/* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
2614
SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
2615
SubstTable[(N1+I+K)&0xFF]=Ch;
2619
for (I=0;I<PswLength;I+=16)
2620
EncryptBlock(&Psw[I]);
2624
void SetOldKeys(char *NewPassword)
2628
PswCRC=CalcCRC32(0xFFFFFFFFL,(UBYTE*)NewPassword,strlen(NewPassword));
2629
OldKey[0]=(UWORD)PswCRC;
2630
OldKey[1]=(UWORD)(PswCRC>>16);
2631
OldKey[2]=OldKey[3]=0;
2633
while ((Ch=*NewPassword)!=0)
2638
PN3=(UBYTE)rol(PN3,1);
2639
OldKey[2]^=((UWORD)(Ch^CRCTab[Ch]));
2640
OldKey[3]+=((UWORD)(Ch+(CRCTab[Ch]>>16)));
2645
static short crcInitialized = 0;
2650
if (crcInitialized) return;
2652
cli_dbgmsg("%s:%d:%s Initialize CRC table\n", __FILE__, __LINE__, "InitCRC");
2655
for (C=I,J=0;J<8;J++)
2656
C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
2663
static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
2666
for (I=0; I<Size; I++)
2667
StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
2672
/* **************************************************************************
2673
****************************************************************************
2674
****************************************************************************
2675
************************************************************************** */
2701
/* **************************************************************************
2702
****************************************************************************
2703
****************************************************************************
2704
****************************************************************************
2708
******* D E B U G F U N C T I O N S *******
2712
****************************************************************************
2713
****************************************************************************
2714
****************************************************************************
2715
************************************************************************** */
2719
/* -- global stuff -------------------------------------------------------- */
2720
char log_file_name[256]; /* file name for the log file */
2721
DWORD debug_start_time; /* starttime of debug */
2722
BOOL debug_started = FALSE; /* debug_log writes only if */
2724
/* ------------------------------------------------------------------------ */
2727
/* -- global functions ---------------------------------------------------- */
2728
void debug_init_proc(char *file_name)
2729
/* Create/Rewrite a log file */
2732
char date[] = __DATE__;
2733
char time[] = __TIME__;
2735
debug_start_time = GetTickCount(); /* get start time */
2736
strcpy(log_file_name, file_name); /* save file name */
2738
if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
2740
debug_started = TRUE; /* enable debug */
2741
fprintf(fp, "Debug log of UniquE's RARFileLib\n"\
2742
"~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
2743
fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time);
2749
void debug_log_proc(char *text, char *sourcefile, int sourceline)
2750
/* add a line to the log file */
2754
if(debug_started == FALSE) return; /* exit if not initialized */
2756
if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile */
2759
fprintf(fp, " %8u ms (line %u in %s):\n - %s\n",
2760
(unsigned int)(GetTickCount() - debug_start_time),
2761
sourceline, sourcefile, text);
2766
/* ------------------------------------------------------------------------ */
2768
/* **************************************************************************
2769
****************************************************************************
2770
****************************************************************************
2771
************************************************************************** */
2774
/* end of file urarlib.c */