Mercurial > mplayer.hg
view unrarlib.c @ 14758:94456deb0624
finally the dreaded white-noise-with-floats bug is fixed!!!!
the problem is that lrintf was not prototyped on some systems, but
it's easier and faster just not to use it at all. looks like the cola
goes to our friends the glibc developers for forgetting to put lrintf
in math.h in some versions. :))) i'm sure there are other broken libcs
too though.
also fixed a minor bug in the int->float conversion where the range
for float samples was exceeded...
author | rfelker |
---|---|
date | Tue, 22 Feb 2005 02:12:58 +0000 |
parents | 49818f04efb9 |
children | 775330fe3889 |
line wrap: on
line source
/* *************************************************************************** ** ** 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 ------------------------------------------------------- */ #include "unrarlib.h" /* include global configuration */ /* ------------------------------------------------------------------------ */ /* -- 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 <ctype.h> #include <string.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 <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); /* no debug this time */ #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]; }; struct MarkHeader MarkHead; struct NewMainArchiveHeader NewMhd; struct NewFileHeader NewLhd; struct BlockHeader BlockHead; static UBYTE *TempMemory = NULL; /* temporary unpack-buffer */ static char *CommMemory = NULL; static UBYTE *UnpMemory = NULL; static char* ArgName = NULL; /* current file in rar archive */ static char* ArcFileName = NULL; /* file to decompress */ #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */ static MemoryFile *MemRARFile; /* pointer to RAR file in memory*/ #else static char* ArcName = NULL; /* RAR archive name */ static FILE *ArcPtr; /* input RAR file handler */ #endif static char *Password = NULL; /* 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 BOOL FileFound; /* TRUE=use current extracted */ /* data FALSE=throw data away, */ /* wrong file */ static int MainHeadSize; static long CurBlockPos,NextBlockPos; static unsigned long CurUnpRead, CurUnpWrite; static long UnpPackedSize; static long DestUnpSize; static UDWORD HeaderCRC; static int Encryption; //static unsigned int UnpWrSize; //static unsigned char *UnpWrAddr; 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(void); //BOOL ListFile(void); 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); static UBYTE DecodeAudio(int Delta); static void DecodeNumber(struct Decode *Dec); static void UpdKeys(UBYTE *Buf); static void SetCryptKeys(char *Password); static void SetOldKeys(char *Password); 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 my_stricomp(char *Str1,char *Str2); /* ------------------------------------------------------------------------ */ /* -- global functions ---------------------------------------------------- */ int urarlib_get(void *output, unsigned long *size, char *filename, void *rarfile, 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 */ if(ArgName) free(ArgName); ArgName = strdup(filename); /* set file(s) to extract */ #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION MemRARFile = rarfile; /* set pointer to mem-RAR file */ #else if(ArcName) free(ArcName); ArcName = strdup(rarfile); /* set RAR file name */ #endif if(Password) free(Password); if(libpassword != NULL) Password = strdup(libpassword); /* init password */ else Password = strdup(""); temp_output_buffer = NULL; temp_output_buffer_offset=size; /* set size of the temp buffer */ #ifdef _DEBUG_LOG sprintf(DebugMsg, "Extracting >%s< from >%s< (password is >%s<)...", filename, (char*)rarfile, libpassword); debug_log(DebugMsg); #endif retcode = ExtrFile(); /* unpack file now! */ //memset(Password,0,sizeof(Password)); /* clear password */ #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION if (ArcPtr!=NULL){ fclose(ArcPtr); ArcPtr = NULL; } #endif if(UnpMemory) free(UnpMemory); /* free memory */ if(TempMemory) free(TempMemory); if(CommMemory) free(CommMemory); UnpMemory=NULL; TempMemory=NULL; CommMemory=NULL; if(retcode == FALSE) { if(temp_output_buffer) /* free memory and return NULL */ free(temp_output_buffer); 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(void *rarfile, ArchiveList_struct *list) { ArchiveList_struct *tmp_List = NULL; int NoOfFilesInArchive = 0; /* number of files in archive */ #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 */ if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL) { if (!IsArchive()) { debug_log("Not a RAR file"); fclose(ArcPtr); ArcPtr = NULL; return NoOfFilesInArchive; /* error => exit! */ } } else { debug_log("Error opening file."); return NoOfFilesInArchive; } #endif if ((UnpMemory=malloc(UNP_MEMORY))==NULL) { debug_log("Can't allocate memory for decompression!"); 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 */ while (TRUE) { if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */ { /* file within the RAR archive */ debug_log("Couldn't read next filename from archive (I/O error)."); break; /* error, file not found in */ } /* archive or I/O error */ if (BlockHead.HeadType==SUB_HEAD) { debug_log("Sorry, sub-headers not supported."); 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; 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; } #endif free(UnpMemory); /* free memory */ free(TempMemory); 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 } } 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)) { ArcFileName=realloc(ArcFileName,NewLhd.NameSize+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"); } #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]; 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); } /* ************************************************************************** **************************************************************************** **************************************************************************** ************************************************************************** */ /* ************************************************************************** **************************************************************************** **************************************************************************** **************************************************************************** ******* ******* ******* ******* ******* ******* ******* 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) return(FALSE); #else if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) 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 handel 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) 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(void) { BOOL ReturnCode=TRUE; FileFound=FALSE; /* no file found by default */ #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 */ if ((ArcPtr=fopen(ArcName,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) { debug_log("Can't allocate memory for decompression!"); return FALSE; } #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. * * 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=(my_stricomp(ArgName, ArcFileName) == 0))) /* *** file found! *** */ { { temp_output_buffer=malloc(NewLhd.UnpSize);/* allocate memory for the*/ } *temp_output_buffer_offset=0; /* file. The default offset */ /* within the buffer is 0 */ if(temp_output_buffer == NULL) { debug_log("can't allocate memory for the file decompression"); ReturnCode=FALSE; break; /* error, can't extract file! */ } } /* 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) { debug_log("unknown compression method"); ReturnCode=FALSE; break; /* error, can't extract file! */ } CurUnpRead=CurUnpWrite=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) { UnstoreFile(); } else { Unpack(UnpMemory); } #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(my_stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */ /* free memory, clear password and close archive */ free(UnpMemory); UnpMemory=NULL; #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION if (ArcPtr!=NULL){ fclose(ArcPtr); ArcPtr = NULL; } #endif return ReturnCode; /* file extracted successful! */ } /* ************************************************************************** **************************************************************************** **************************************************************************** ************************************************************************** */ /* ************************************************************************** **************************************************************************** **************************************************************************** **************************************************************************** ******* ******* ******* ******* ******* ******* ******* 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* my_strupper(char *Str) { char *ChPtr; for (ChPtr=Str;*ChPtr;ChPtr++) *ChPtr=(char)toupper(*ChPtr); return(Str); } static int my_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(my_strupper(S1),my_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) { debug_log("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 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; unsigned char InBuf[8192]; /* input read buffer */ unsigned char UnpOldTable[MC*4]; unsigned int InAddr,InBit,ReadTop; unsigned int LastDist,LastLength; static unsigned int Length,Distance; unsigned int OldDist[4],OldDistPtr; struct LitDecode { unsigned int MaxNum; unsigned int DecodeLen[16]; unsigned int DecodePos[16]; unsigned int DecodeNum[NC]; } LD; struct DistDecode { unsigned int MaxNum; unsigned int DecodeLen[16]; unsigned int DecodePos[16]; unsigned int DecodeNum[DC]; } DD; struct RepDecode { unsigned int MaxNum; unsigned int DecodeLen[16]; unsigned int DecodePos[16]; unsigned int DecodeNum[RC]; } RD; struct MultDecode { unsigned int MaxNum; unsigned int DecodeLen[16]; unsigned int DecodePos[16]; unsigned int DecodeNum[MC]; } MD[4]; 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]}; int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta; void Unpack(unsigned char *UnpAddr) /* *** 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 + 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 + 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) ? (unsigned int)UnpPackedSize : Count); #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION 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; } if (RetCode!= -1) { RetCode=TotalRead; if (Encryption) { if (Encryption<20) { debug_log("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) ) UDWORD CRCTab[256]; UBYTE SubstTable[256]; 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 }; UDWORD Key[4]; 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]]; } } void SetCryptKeys(char *Password) { unsigned int I,J,K,PswLength; unsigned char N1,N2; unsigned char Psw[256]; #if !defined _USE_ASM UBYTE Ch; #endif SetOldKeys(Password); Key[0]=0xD3A3B879L; Key[1]=0x3F6D12F7L; Key[2]=0x7515A235L; Key[3]=0xA4E7F123L; memset(Psw,0,sizeof(Psw)); strcpy((char *)Psw,Password); PswLength=strlen(Password); 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 < 256); /* I had to add "&& (N1 < 256)", */ N1++, K++) /* because the system crashed with */ { /* encrypted RARs */ #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 *Password) { UDWORD PswCRC; UBYTE Ch; PswCRC=CalcCRC32(0xFFFFFFFFL,(UBYTE*)Password,strlen(Password)); OldKey[0]=(UWORD)PswCRC; OldKey[1]=(UWORD)(PswCRC>>16); OldKey[2]=OldKey[3]=0; PN1=PN2=PN3=0; while ((Ch=*Password)!=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))); Password++; } } void InitCRC(void) { int I, J; UDWORD C; 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; } } 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 */