1 /* ***************************************************************************
3 ** This file is part of the UniquE RAR File Library.
5 ** Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
6 ** UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
8 ** Modified for use with MPlayer, detailed changelog at
9 ** http://svn.mplayerhq.hu/mplayer/trunk/
12 ** The contents of this file are subject to the UniquE RAR File Library
13 ** License (the "unrarlib-license.txt"). You may not use this file except
14 ** in compliance with the License. You may obtain a copy of the License
15 ** at http://www.unrarlib.org/license.html.
16 ** Software distributed under the License is distributed on an "AS IS"
17 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
19 ** Alternatively, the contents of this file may be used under the terms
20 ** of the GNU General Public License Version 2 or later (the "GPL"), in
21 ** which case the provisions of the GPL are applicable instead of those
22 ** above. If you wish to allow use of your version of this file only
23 ** under the terms of the GPL and not to allow others to use your version
24 ** of this file under the terms of the UniquE RAR File Library License,
25 ** indicate your decision by deleting the provisions above and replace
26 ** them with the notice and other provisions required by the GPL. If you
27 ** do not delete the provisions above, a recipient may use your version
28 ** of this file under the terms of the GPL or the UniquE RAR File Library
31 ************************************************************************** */
33 /* ***************************************************************************
35 ** UniquE RAR File Library
36 ** The free file lib for the demoscene
37 ** multi-OS version (Win32, Linux and SunOS)
39 *****************************************************************************
41 ** ==> Please configure the program in "unrarlib.h". <==
43 ** RAR decompression code:
45 ** Modifications to a FileLib:
46 ** (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
48 ** (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
50 ** The UniquE RAR File Library gives you the ability to access RAR archives
51 ** (any compression method supported in RAR v2.0 including Multimedia
52 ** Compression and encryption) directly from your program with ease an by
53 ** adding only 12kB (6kB UPX-compressed) additional code to your program.
54 ** Both solid and normal (recommended for fast random access to the files!)
55 ** archives are supported. This FileLib is made for the Demo scene, so it's
56 ** designed for easy use within your demos and intros.
57 ** Please read "licence.txt" to learn more about how you may use URARFileLib
58 ** in your productions.
60 *****************************************************************************
62 ** ==> see the "CHANGES" file to see what's new
64 ************************************************************************** */
66 /* -- include files ------------------------------------------------------- */
67 #include "unrarlib.h" /* include global configuration */
68 /* ------------------------------------------------------------------------ */
72 /* -- global stuff -------------------------------------------------------- */
75 #include <windows.h> /* WIN32 definitions */
82 #define HOST_OS WIN_32
84 #define FM_NORMAL 0x00
85 #define FM_RDONLY 0x01
86 #define FM_HIDDEN 0x02
87 #define FM_SYSTEM 0x04
92 #define PATHDIVIDER "\\"
93 #define CPATHDIVIDER '\\'
96 #define READBINARY "rb"
98 #define UPDATEBINARY "r+b"
99 #define CREATEBINARY "w+b"
100 #define CREATETEXT "w"
101 #define APPENDTEXT "at"
107 #include <stdio.h> /* LINUX/UNIX definitions */
112 #define ENABLE_ACCESS
116 #define FM_LABEL 0x0000
117 #define FM_DIREC 0x4000
119 #define PATHDIVIDER "/"
120 #define CPATHDIVIDER '/'
121 #define MASKALL "*.*"
123 #define READBINARY "r"
125 #define UPDATEBINARY "r+"
126 #define CREATEBINARY "w+"
127 #define CREATETEXT "w"
128 #define APPENDTEXT "a"
131 /* emulation of the windows API and data types */
132 /* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
140 #ifdef _DEBUG_LOG /* define macros for debugging */
142 #include <sys/time.h>
147 gettimeofday( &tv
, 0 );
148 return (tv
.tv_usec
/ 1000);
158 #ifdef _DEBUG_LOG /* define macros for debugging */
160 BOOL debug_log_first_start
= TRUE
;
162 #define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
163 #define debug_init(a); debug_init_proc(a);
165 void debug_log_proc(char *text
, char *sourcefile
, int sourceline
);
166 void debug_init_proc(char *file_name
);
169 #define debug_log(a); /* no debug this time */
170 #define debug_init(a); /* no debug this time */
177 #define MAXWINSIZE 0x100000
178 #define MAXWINMASK (MAXWINSIZE-1)
179 #define UNP_MEMORY MAXWINSIZE
180 #define Min(x,y) (((x)<(y)) ? (x):(y))
181 #define Max(x,y) (((x)>(y)) ? (x):(y))
184 #define SIZEOF_MARKHEAD 7
185 #define SIZEOF_OLDMHD 7
186 #define SIZEOF_NEWMHD 13
187 #define SIZEOF_OLDLHD 21
188 #define SIZEOF_NEWLHD 32
189 #define SIZEOF_SHORTBLOCKHEAD 7
190 #define SIZEOF_LONGBLOCKHEAD 11
191 #define SIZEOF_COMMHEAD 13
192 #define SIZEOF_PROTECTHEAD 26
195 #define PACK_VER 20 /* version of decompression code*/
197 #define PROTECT_VER 20
200 enum { M_DENYREAD
,M_DENYWRITE
,M_DENYNONE
,M_DENYALL
};
201 enum { FILE_EMPTY
,FILE_ADD
,FILE_UPDATE
,FILE_COPYOLD
,FILE_COPYBLOCK
};
202 enum { SUCCESS
,WARNING
,FATAL_ERROR
,CRC_ERROR
,LOCK_ERROR
,WRITE_ERROR
,
203 OPEN_ERROR
,USER_ERROR
,MEMORY_ERROR
,USER_BREAK
=255,IMM_ABORT
=0x8000 };
204 enum { EN_LOCK
=1,EN_VOL
=2 };
205 enum { SD_MEMORY
=1,SD_FILES
=2 };
206 enum { NAMES_DONTCHANGE
};
207 enum { LOG_ARC
=1,LOG_FILE
=2 };
208 enum { OLD_DECODE
=0,OLD_ENCODE
=1,NEW_CRYPT
=2 };
209 enum { OLD_UNPACK
,NEW_UNPACK
};
212 #define MHD_COMMENT 2
214 #define MHD_PACK_COMMENT 16
216 #define MHD_PROTECT 64
218 #define LHD_SPLIT_BEFORE 1
219 #define LHD_SPLIT_AFTER 2
220 #define LHD_PASSWORD 4
221 #define LHD_COMMENT 8
224 #define LHD_WINDOWMASK 0x00e0
225 #define LHD_WINDOW64 0
226 #define LHD_WINDOW128 32
227 #define LHD_WINDOW256 64
228 #define LHD_WINDOW512 96
229 #define LHD_WINDOW1024 128
230 #define LHD_DIRECTORY 0x00e0
232 #define LONG_BLOCK 0x8000
233 #define READSUBBLOCK 0x8000
235 enum { ALL_HEAD
=0,MARK_HEAD
=0x72,MAIN_HEAD
=0x73,FILE_HEAD
=0x74,
236 COMM_HEAD
=0x75,AV_HEAD
=0x76,SUB_HEAD
=0x77,PROTECT_HEAD
=0x78};
237 enum { EA_HEAD
=0x100 };
238 enum { MS_DOS
=0,OS2
=1,WIN_32
=2,UNIX
=3 };
247 struct NewMainArchiveHeader
289 unsigned int DecodeLen
[16];
290 unsigned int DecodePos
[16];
291 unsigned int DecodeNum
[2];
295 struct MarkHeader MarkHead
;
296 struct NewMainArchiveHeader NewMhd
;
297 struct NewFileHeader NewLhd
;
298 struct BlockHeader BlockHead
;
300 static UBYTE
*TempMemory
= NULL
; /* temporary unpack-buffer */
301 static char *CommMemory
= NULL
;
304 static UBYTE
*UnpMemory
= NULL
;
305 static char* ArgName
= NULL
; /* current file in rar archive */
306 static char* ArcFileName
= NULL
; /* file to decompress */
308 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
309 static MemoryFile
*MemRARFile
; /* pointer to RAR file in memory*/
311 static char* ArcName
= NULL
; /* RAR archive name */
312 static FILE *ArcPtr
; /* input RAR file handler */
314 static char *Password
= NULL
; /* password to decrypt files */
316 static unsigned char *temp_output_buffer
; /* extract files to this pointer*/
317 static unsigned long *temp_output_buffer_offset
; /* size of temp. extract buffer */
319 static BOOL FileFound
; /* TRUE=use current extracted */
320 /* data FALSE=throw data away, */
322 static int MainHeadSize
;
323 static long CurBlockPos
,NextBlockPos
;
325 static unsigned long CurUnpRead
, CurUnpWrite
;
326 static long UnpPackedSize
;
327 static long DestUnpSize
;
329 static UDWORD HeaderCRC
;
330 static int Encryption
;
332 //static unsigned int UnpWrSize;
333 //static unsigned char *UnpWrAddr;
334 static unsigned int UnpPtr
,WrPtr
;
336 static unsigned char PN1
,PN2
,PN3
;
337 static unsigned short OldKey
[4];
341 /* function header definitions */
342 static int ReadHeader(int BlockType
);
343 static BOOL
ExtrFile(void);
344 //BOOL ListFile(void);
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
);
353 static UBYTE
DecodeAudio(int Delta
);
354 static void DecodeNumber(struct Decode
*Dec
);
355 static void UpdKeys(UBYTE
*Buf
);
356 static void SetCryptKeys(char *Password
);
357 static void SetOldKeys(char *Password
);
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 my_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 if(ArgName
) free(ArgName
);
401 ArgName
= strdup(filename
); /* set file(s) to extract */
402 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
403 MemRARFile
= rarfile
; /* set pointer to mem-RAR file */
405 if(ArcName
) free(ArcName
);
406 ArcName
= strdup(rarfile
); /* set RAR file name */
408 if(Password
) free(Password
);
409 if(libpassword
!= NULL
)
410 Password
= strdup(libpassword
); /* init password */
412 Password
= strdup("");
414 temp_output_buffer
= NULL
;
415 temp_output_buffer_offset
=size
; /* set size of the temp buffer */
418 sprintf(DebugMsg
, "Extracting >%s< from >%s< (password is >%s<)...",
419 filename
, (char*)rarfile
, libpassword
);
423 retcode
= ExtrFile(); /* unpack file now! */
425 //memset(Password,0,sizeof(Password)); /* clear password */
427 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
434 if(UnpMemory
) free(UnpMemory
); /* free memory */
435 if(TempMemory
) free(TempMemory
);
436 if(CommMemory
) free(CommMemory
);
444 if(temp_output_buffer
) /* free memory and return NULL */
445 free(temp_output_buffer
);
446 temp_output_buffer
=NULL
;
447 *(DWORD
*)output
=0; /* pointer on errors */
452 /* sorry for this ugly code, but older SunOS gcc compilers don't support */
453 /* white spaces within strings */
454 str_offs
= sprintf(DebugMsg
, "Error - couldn't extract ");
455 str_offs
+= sprintf(DebugMsg
+ str_offs
, ">%s<", filename
);
456 str_offs
+= sprintf(DebugMsg
+ str_offs
, " and allocated ");
457 str_offs
+= sprintf(DebugMsg
+ str_offs
, "%u Bytes", (unsigned int)*size
);
458 str_offs
+= sprintf(DebugMsg
+ str_offs
, " of unused memory!");
462 sprintf(DebugMsg
, "Extracted %u Bytes.", (unsigned int)*size
);
468 *(DWORD
*)output
=(DWORD
)temp_output_buffer
;/* return pointer for unpacked*/
475 int urarlib_list(void *rarfile
, ArchiveList_struct
*list
)
477 ArchiveList_struct
*tmp_List
= NULL
;
478 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 */
500 if ((ArcPtr
=fopen(rarfile
,READBINARY
))!=NULL
)
504 debug_log("Not a RAR file");
507 return NoOfFilesInArchive
; /* error => exit! */
511 debug_log("Error opening file.");
512 return NoOfFilesInArchive
;
516 if ((UnpMemory
=malloc(UNP_MEMORY
))==NULL
)
518 debug_log("Can't allocate memory for decompression!");
519 return NoOfFilesInArchive
;
522 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
523 MemRARFile
->offset
+=NewMhd
.HeadSize
-MainHeadSize
;
525 tseek(ArcPtr
,NewMhd
.HeadSize
-MainHeadSize
,SEEK_CUR
);
527 (*(DWORD
*)list
) = (DWORD
)NULL
; /* init file list */
528 /* do while file is not extracted and there's no error */
531 if (ReadBlock(FILE_HEAD
| READSUBBLOCK
) <= 0) /* read name of the next */
532 { /* file within the RAR archive */
533 debug_log("Couldn't read next filename from archive (I/O error).");
534 break; /* error, file not found in */
535 } /* archive or I/O error */
536 if (BlockHead
.HeadType
==SUB_HEAD
)
538 debug_log("Sorry, sub-headers not supported.");
539 break; /* error => exit */
542 if((void*)(*(DWORD
*)list
) == NULL
) /* first entry */
544 tmp_List
= malloc(sizeof(ArchiveList_struct
));
545 tmp_List
->next
= NULL
;
547 (*(DWORD
*)list
) = (DWORD
)tmp_List
;
549 } else /* add entry */
551 tmp_List
->next
= malloc(sizeof(ArchiveList_struct
));
552 tmp_List
= (ArchiveList_struct
*) tmp_List
->next
;
553 tmp_List
->next
= NULL
;
556 tmp_List
->item
.Name
= malloc(NewLhd
.NameSize
+ 1);
557 strcpy(tmp_List
->item
.Name
, ArcFileName
);
558 tmp_List
->item
.NameSize
= NewLhd
.NameSize
;
559 tmp_List
->item
.PackSize
= NewLhd
.PackSize
;
560 tmp_List
->item
.UnpSize
= NewLhd
.UnpSize
;
561 tmp_List
->item
.HostOS
= NewLhd
.HostOS
;
562 tmp_List
->item
.FileCRC
= NewLhd
.FileCRC
;
563 tmp_List
->item
.FileTime
= NewLhd
.FileTime
;
564 tmp_List
->item
.UnpVer
= NewLhd
.UnpVer
;
565 tmp_List
->item
.Method
= NewLhd
.Method
;
566 tmp_List
->item
.FileAttr
= NewLhd
.FileAttr
;
568 NoOfFilesInArchive
++; /* count files */
570 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
571 MemRARFile
->offset
= NextBlockPos
;
573 if (ArcPtr
!=NULL
) tseek(ArcPtr
,NextBlockPos
,SEEK_SET
);
578 /* free memory, clear password and close archive */
579 memset(Password
,0,sizeof(Password
)); /* clear password */
580 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
587 free(UnpMemory
); /* free memory */
594 return NoOfFilesInArchive
;
600 * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
601 * and Johannes Winkelmann who independently wrote a patch)
602 * free the memory of a ArchiveList_struct created by urarlib_list.
604 * input: *list pointer to an ArchiveList_struct
608 void urarlib_freelist(ArchiveList_struct
*list
)
610 ArchiveList_struct
* tmp
= list
;
614 free( list
->item
.Name
);
621 /* ------------------------------------------------------------------------ */
639 /****************************************************************************
640 ****************************************************************************
641 ****************************************************************************
642 ****************************************************************************
646 ******* B L O C K I / O *******
650 ****************************************************************************
651 ****************************************************************************
652 ****************************************************************************
653 ****************************************************************************/
657 #define GetHeaderByte(N) Header[N]
659 #define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
661 #define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
662 ((UDWORD)Header[N+2]<<16)+\
663 ((UDWORD)Header[N+3]<<24))
666 int ReadBlock(int BlockType
)
668 struct NewFileHeader SaveFileHead
;
669 int Size
=0,ReadSubBlock
=0;
670 static int LastBlock
;
671 memcpy(&SaveFileHead
,&NewLhd
,sizeof(SaveFileHead
));
672 if (BlockType
& READSUBBLOCK
)
678 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
679 CurBlockPos
=MemRARFile
->offset
; /* get offset of mem-file */
681 CurBlockPos
=ftell(ArcPtr
);
683 Size
=ReadHeader(FILE_HEAD
);
686 if (NewLhd
.HeadSize
<SIZEOF_SHORTBLOCKHEAD
)
688 NextBlockPos
=CurBlockPos
+NewLhd
.HeadSize
;
689 if (NewLhd
.Flags
& LONG_BLOCK
)
690 NextBlockPos
+=NewLhd
.PackSize
;
691 if (NextBlockPos
<=CurBlockPos
)
695 if (Size
> 0 && BlockType
!=SUB_HEAD
)
697 if (Size
==0 || BlockType
==ALL_HEAD
|| NewLhd
.HeadType
==BlockType
||
698 (NewLhd
.HeadType
==SUB_HEAD
&& ReadSubBlock
&& LastBlock
==BlockType
))
700 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
701 MemRARFile
->offset
= NextBlockPos
;
703 tseek(ArcPtr
, NextBlockPos
, SEEK_SET
);
708 BlockHead
.HeadCRC
=NewLhd
.HeadCRC
;
709 BlockHead
.HeadType
=NewLhd
.HeadType
;
710 BlockHead
.Flags
=NewLhd
.Flags
;
711 BlockHead
.HeadSize
=NewLhd
.HeadSize
;
712 BlockHead
.DataSize
=NewLhd
.PackSize
;
714 if (BlockType
!=NewLhd
.HeadType
) BlockType
=ALL_HEAD
;
716 if((FILE_HEAD
== BlockType
) && (Size
>0))
718 ArcFileName
=realloc(ArcFileName
,NewLhd
.NameSize
+1);
719 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
720 tread(MemRARFile
, ArcFileName
, NewLhd
.NameSize
);
722 tread(ArcPtr
,ArcFileName
,NewLhd
.NameSize
);
724 ArcFileName
[NewLhd
.NameSize
]=0;
726 if (NewLhd
.HeadCRC
!=(UWORD
)~CalcCRC32(HeaderCRC
,(UBYTE
*)&ArcFileName
[0],
729 debug_log("file header broken");
732 Size
+=NewLhd
.NameSize
;
735 memcpy(&NewLhd
,&SaveFileHead
,sizeof(NewLhd
));
736 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
737 MemRARFile
->offset
= CurBlockPos
;
739 tseek(ArcPtr
,CurBlockPos
,SEEK_SET
);
748 int ReadHeader(int BlockType
)
751 unsigned char Header
[64];
755 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
756 Size
=tread(MemRARFile
, Header
, SIZEOF_NEWMHD
);
758 Size
=tread(ArcPtr
,Header
,SIZEOF_NEWMHD
);
760 NewMhd
.HeadCRC
=(unsigned short)GetHeaderWord(0);
761 NewMhd
.HeadType
=GetHeaderByte(2);
762 NewMhd
.Flags
=(unsigned short)GetHeaderWord(3);
763 NewMhd
.HeadSize
=(unsigned short)GetHeaderWord(5);
764 NewMhd
.Reserved
=(unsigned short)GetHeaderWord(7);
765 NewMhd
.Reserved1
=GetHeaderDword(9);
766 HeaderCRC
=CalcCRC32(0xFFFFFFFFL
,&Header
[2],SIZEOF_NEWMHD
-2);
769 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
770 Size
=tread(MemRARFile
, Header
, SIZEOF_NEWLHD
);
772 Size
=tread(ArcPtr
,Header
,SIZEOF_NEWLHD
);
774 NewLhd
.HeadCRC
=(unsigned short)GetHeaderWord(0);
775 NewLhd
.HeadType
=GetHeaderByte(2);
776 NewLhd
.Flags
=(unsigned short)GetHeaderWord(3);
777 NewLhd
.HeadSize
=(unsigned short)GetHeaderWord(5);
778 NewLhd
.PackSize
=GetHeaderDword(7);
779 NewLhd
.UnpSize
=GetHeaderDword(11);
780 NewLhd
.HostOS
=GetHeaderByte(15);
781 NewLhd
.FileCRC
=GetHeaderDword(16);
782 NewLhd
.FileTime
=GetHeaderDword(20);
783 NewLhd
.UnpVer
=GetHeaderByte(24);
784 NewLhd
.Method
=GetHeaderByte(25);
785 NewLhd
.NameSize
=(unsigned short)GetHeaderWord(26);
786 NewLhd
.FileAttr
=GetHeaderDword(28);
787 HeaderCRC
=CalcCRC32(0xFFFFFFFFL
,&Header
[2],SIZEOF_NEWLHD
-2);
791 case COMM_HEAD
: /* log errors in case of debug */
792 debug_log("Comment headers not supported! "\
793 "Please create archives without comments.");
796 debug_log("Protected headers not supported!");
799 debug_log("ShortBlockHeader not supported!");
802 debug_log("Unknown//unsupported !");
804 default: /* else do nothing */
811 /* **************************************************************************
812 ****************************************************************************
813 ****************************************************************************
814 ************************************************************************** */
832 /* **************************************************************************
833 ****************************************************************************
834 ****************************************************************************
835 ****************************************************************************
839 ******* E X T R A C T L O O P *******
843 ****************************************************************************
844 ****************************************************************************
845 ****************************************************************************
846 ************************************************************************** */
852 int str_offs
; /* used for debug-strings */
853 char DebugMsg
[500]; /* used to compose debug msg */
856 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
857 if (tread(MemRARFile
, MarkHead
.Mark
, SIZEOF_MARKHEAD
) != SIZEOF_MARKHEAD
)
860 if (tread(ArcPtr
,MarkHead
.Mark
,SIZEOF_MARKHEAD
)!=SIZEOF_MARKHEAD
)
863 /* Old archive => error */
864 if (MarkHead
.Mark
[0]==0x52 && MarkHead
.Mark
[1]==0x45 &&
865 MarkHead
.Mark
[2]==0x7e && MarkHead
.Mark
[3]==0x5e)
867 debug_log("Attention: format as OLD detected! Can't handel archive!");
870 /* original RAR v2.0 */
871 if ((MarkHead
.Mark
[0]==0x52 && MarkHead
.Mark
[1]==0x61 && /* original */
872 MarkHead
.Mark
[2]==0x72 && MarkHead
.Mark
[3]==0x21 && /* RAR header*/
873 MarkHead
.Mark
[4]==0x1a && MarkHead
.Mark
[5]==0x07 &&
874 MarkHead
.Mark
[6]==0x00) ||
875 /* "UniquE!" - header */
876 (MarkHead
.Mark
[0]=='U' && MarkHead
.Mark
[1]=='n' && /* "UniquE!" */
877 MarkHead
.Mark
[2]=='i' && MarkHead
.Mark
[3]=='q' && /* header */
878 MarkHead
.Mark
[4]=='u' && MarkHead
.Mark
[5]=='E' &&
879 MarkHead
.Mark
[6]=='!'))
882 if (ReadHeader(MAIN_HEAD
)!=SIZEOF_NEWMHD
)
888 /* sorry for this ugly code, but older SunOS gcc compilers don't */
889 /* support white spaces within strings */
890 str_offs
= sprintf(DebugMsg
, "unknown archive type (only plain RAR ");
891 str_offs
+= sprintf(DebugMsg
+ str_offs
, "supported (normal and solid ");
892 str_offs
+= sprintf(DebugMsg
+ str_offs
, "archives), SFX and Volumes ");
893 str_offs
+= sprintf(DebugMsg
+ str_offs
, "are NOT supported!)");
901 MainHeadSize
=SIZEOF_NEWMHD
;
909 BOOL ReturnCode
=TRUE
;
910 FileFound
=FALSE
; /* no file found by default */
912 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
913 MemRARFile
->offset
= 0; /* start reading from offset 0 */
916 debug_log("Not a RAR file");
917 return FALSE
; /* error => exit! */
921 /* open and identify archive */
922 if ((ArcPtr
=fopen(ArcName
,READBINARY
))!=NULL
)
926 debug_log("Not a RAR file");
929 return FALSE
; /* error => exit! */
933 debug_log("Error opening file.");
939 if ((UnpMemory
=malloc(UNP_MEMORY
))==NULL
)
941 debug_log("Can't allocate memory for decompression!");
945 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
946 MemRARFile
->offset
+=NewMhd
.HeadSize
-MainHeadSize
;
948 tseek(ArcPtr
,NewMhd
.HeadSize
-MainHeadSize
,SEEK_CUR
);
951 /* do while file is not extracted and there's no error */
955 if (ReadBlock(FILE_HEAD
| READSUBBLOCK
) <= 0) /* read name of the next */
956 { /* file within the RAR archive */
959 * 21.11.2000 UnQ There's a problem with some linux distros when a file
960 * can not be found in an archive.
962 * debug_log("Couldn't read next filename from archive (I/O error).");
966 break; /* error, file not found in */
967 } /* archive or I/O error */
968 if (BlockHead
.HeadType
==SUB_HEAD
)
970 debug_log("Sorry, sub-headers not supported.");
972 break; /* error => exit */
976 if(TRUE
== (FileFound
=(my_stricomp(ArgName
, ArcFileName
) == 0)))
977 /* *** file found! *** */
980 temp_output_buffer
=malloc(NewLhd
.UnpSize
);/* allocate memory for the*/
982 *temp_output_buffer_offset
=0; /* file. The default offset */
983 /* within the buffer is 0 */
985 if(temp_output_buffer
== NULL
)
987 debug_log("can't allocate memory for the file decompression");
989 break; /* error, can't extract file! */
995 /* in case of a solid archive, we need to decompress any single file till
996 * we have found the one we are looking for. In case of normal archives
997 * (recommended!!), we skip the files until we are sure that it is the
1000 if((NewMhd
.Flags
& 0x08) || FileFound
)
1002 if (NewLhd
.UnpVer
<13 || NewLhd
.UnpVer
>UNP_VER
)
1004 debug_log("unknown compression method");
1006 break; /* error, can't extract file! */
1009 CurUnpRead
=CurUnpWrite
=0;
1010 if ((*Password
!=0) && (NewLhd
.Flags
& LHD_PASSWORD
))
1011 Encryption
=NewLhd
.UnpVer
;
1014 if (Encryption
) SetCryptKeys(Password
);
1016 UnpPackedSize
=NewLhd
.PackSize
;
1017 DestUnpSize
=NewLhd
.UnpSize
;
1019 if (NewLhd
.Method
==0x30)
1029 #ifdef _DO_CRC32_CHECK /* calculate CRC32 */
1030 if((UBYTE
*)temp_output_buffer
!= NULL
)
1032 if(NewLhd
.FileCRC
!=~CalcCRC32(0xFFFFFFFFL
,
1033 (UBYTE
*)temp_output_buffer
,
1036 debug_log("CRC32 error - file couldn't be decompressed correctly!");
1038 break; /* error, can't extract file! */
1045 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1046 MemRARFile
->offset
= NextBlockPos
;
1048 if (ArcPtr
!=NULL
) tseek(ArcPtr
,NextBlockPos
,SEEK_SET
);
1050 } while(my_stricomp(ArgName
, ArcFileName
) != 0);/* exit if file is extracted */
1052 /* free memory, clear password and close archive */
1055 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1062 return ReturnCode
; /* file extracted successful! */
1065 /* **************************************************************************
1066 ****************************************************************************
1067 ****************************************************************************
1068 ************************************************************************** */
1087 /* **************************************************************************
1088 ****************************************************************************
1089 ****************************************************************************
1090 ****************************************************************************
1094 ******* G L O B A L F U N C T I O N S *******
1098 ****************************************************************************
1099 ****************************************************************************
1100 ****************************************************************************
1101 ************************************************************************** */
1104 int tread(void *stream
,void *buf
,unsigned len
)
1106 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1108 if(((MemRARFile
->offset
+ len
) > MemRARFile
->size
) || (len
== 0))
1112 (BYTE
*)(((MemoryFile
*)stream
)->data
)+((MemoryFile
*)stream
)->offset
,
1113 len
% ((((MemoryFile
*)stream
)->size
) - 1));
1115 MemRARFile
->offset
+=len
; /* update read pointer */
1116 return len
% ((((MemoryFile
*)stream
)->size
) - 1);
1118 return(fread(buf
,1,len
,(FILE*)stream
));
1123 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1124 int tseek(void *stream
,long offset
,int fromwhere
)
1126 return(fseek((FILE*)stream
,offset
,fromwhere
));
1131 static char* my_strupper(char *Str
)
1134 for (ChPtr
=Str
;*ChPtr
;ChPtr
++)
1135 *ChPtr
=(char)toupper(*ChPtr
);
1140 static int my_stricomp(char *Str1
,char *Str2
)
1141 /* compare strings without regard of '\' and '/' */
1143 char S1
[512],S2
[512];
1146 strncpy(S1
,Str1
,sizeof(S1
));
1147 strncpy(S2
,Str2
,sizeof(S2
));
1149 while((chptr
= strchr(S1
, '\\')) != NULL
) /* ignore backslash */
1154 while((chptr
= strchr(S2
, '\\')) != NULL
) /* ignore backslash */
1159 while((chptr
= strchr(S1
, '/')) != NULL
) /* ignore slash */
1164 while((chptr
= strchr(S2
, '/')) != NULL
) /* ignore slash */
1169 return(strcmp(my_strupper(S1
),my_strupper(S2
)));
1173 /* **************************************************************************
1174 ****************************************************************************
1175 ****************************************************************************
1176 ************************************************************************** */
1195 /* **************************************************************************
1196 ****************************************************************************
1197 ****************************************************************************
1198 ****************************************************************************
1202 ******* U N P A C K C O D E *******
1206 ****************************************************************************
1207 ****************************************************************************
1208 ****************************************************************************
1209 ************************************************************************** */
1212 /* *****************************
1213 * ** unpack stored RAR files **
1214 * *****************************/
1216 BOOL
UnstoreFile(void)
1218 if ((long)(*temp_output_buffer_offset
=UnpRead(temp_output_buffer
,
1219 NewLhd
.UnpSize
))==-1)
1221 debug_log("Read error of stored file!");
1230 /* ****************************************
1231 * ** RAR decompression code starts here **
1232 * ****************************************/
1234 #define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
1240 enum {CODE_HUFFMAN
=0,CODE_LZ
=1,CODE_LZ2
=2,CODE_REPEATLZ
=3,CODE_CACHELZ
=4,
1241 CODE_STARTFILE
=5,CODE_ENDFILE
=6,CODE_STARTMM
=8,CODE_ENDMM
=7,
1244 struct AudioVariables
1249 unsigned int Dif
[11];
1250 unsigned int ByteCount
;
1255 #define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
1262 struct AudioVariables AudV
[4];
1265 BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
1266 ( (UWORD) InBuf[InAddr+1] << 8 ) | \
1267 ( InBuf[InAddr+2] ) ) \
1268 >> (8-InBit) ) & 0xffff;
1271 #define AddBits(Bits) \
1272 InAddr += ( InBit + (Bits) ) >> 3; \
1273 InBit = ( InBit + (Bits) ) & 7;
1275 static unsigned char *UnpBuf
;
1276 static unsigned int BitField
;
1277 static unsigned int Number
;
1279 unsigned char InBuf
[8192]; /* input read buffer */
1281 unsigned char UnpOldTable
[MC
*4];
1283 unsigned int InAddr
,InBit
,ReadTop
;
1285 unsigned int LastDist
,LastLength
;
1286 static unsigned int Length
,Distance
;
1288 unsigned int OldDist
[4],OldDistPtr
;
1293 unsigned int MaxNum
;
1294 unsigned int DecodeLen
[16];
1295 unsigned int DecodePos
[16];
1296 unsigned int DecodeNum
[NC
];
1301 unsigned int MaxNum
;
1302 unsigned int DecodeLen
[16];
1303 unsigned int DecodePos
[16];
1304 unsigned int DecodeNum
[DC
];
1309 unsigned int MaxNum
;
1310 unsigned int DecodeLen
[16];
1311 unsigned int DecodePos
[16];
1312 unsigned int DecodeNum
[RC
];
1317 unsigned int MaxNum
;
1318 unsigned int DecodeLen
[16];
1319 unsigned int DecodePos
[16];
1320 unsigned int DecodeNum
[MC
];
1325 unsigned int MaxNum
;
1326 unsigned int DecodeLen
[16];
1327 unsigned int DecodePos
[16];
1328 unsigned int DecodeNum
[BC
];
1331 static struct MultDecode
*MDPtr
[4]={&MD
[0],&MD
[1],&MD
[2],&MD
[3]};
1333 int UnpAudioBlock
,UnpChannels
,CurChannel
,ChannelDelta
;
1336 void Unpack(unsigned char *UnpAddr
)
1337 /* *** 38.3% of all CPU time is spent within this function!!! */
1339 static unsigned char LDecode
[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
1340 40,48,56,64,80,96,112,128,160,192,224};
1341 static unsigned char LBits
[]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
1342 3,3,3,4,4,4,4,5,5,5,5};
1343 static int DDecode
[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
1344 512,768,1024,1536,2048,3072,4096,6144,8192,12288,
1345 16384,24576,32768U,49152U,65536,98304,131072,196608,
1346 262144,327680,393216,458752,524288,589824,655360,
1347 720896,786432,851968,917504,983040};
1348 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,
1349 9,10,10,11,11,12,12,13,13,14,14,15,15,16,
1350 16,16,16,16,16,16,16,16,16,16,16,16,16};
1351 static unsigned char SDDecode
[]={0,4,8,16,32,64,128,192};
1352 static unsigned char SDBits
[]={2,2,3, 4, 5, 6, 6, 6};
1356 UnpBuf
=UnpAddr
; /* UnpAddr is a pointer to the */
1357 UnpInitData(); /* unpack buffer */
1359 if (!(NewLhd
.Flags
& LHD_SOLID
))
1363 while (DestUnpSize
>=0)
1367 if (InAddr
>sizeof(InBuf
)-30)
1369 if (((WrPtr
-UnpPtr
) & MAXWINMASK
)<270 && WrPtr
!=UnpPtr
)
1378 if((*temp_output_buffer_offset
+ UnpPtr
) > NewLhd
.UnpSize
)
1380 debug_log("Fatal! Buffer overrun during decompression!");
1385 /* copy extracted data to output buffer */
1386 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
,
1387 &UnpBuf
[WrPtr
], (0-WrPtr
) & MAXWINMASK
);
1388 /* update offset within buffer */
1389 *temp_output_buffer_offset
+= (0-WrPtr
) & MAXWINMASK
;
1390 /* copy extracted data to output buffer */
1391 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, UnpBuf
,
1393 /* update offset within buffer */
1394 *temp_output_buffer_offset
+=UnpPtr
;
1398 if((*temp_output_buffer_offset
+ (UnpPtr
-WrPtr
)) > NewLhd
.UnpSize
)
1400 debug_log("Fatal! Buffer overrun during decompression!");
1404 /* copy extracted data to output buffer */
1405 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
,
1406 &UnpBuf
[WrPtr
], UnpPtr
-WrPtr
);
1407 *temp_output_buffer_offset
+=UnpPtr
-WrPtr
; /* update offset within buffer */
1418 DecodeNumber((struct Decode
*)MDPtr
[CurChannel
]);
1424 UnpBuf
[UnpPtr
++]=DecodeAudio(Number
);
1425 if (++CurChannel
==UnpChannels
)
1431 DecodeNumber((struct Decode
*)&LD
);
1434 UnpBuf
[UnpPtr
++]=(UBYTE
)Number
;
1440 Length
=LDecode
[Number
-=270]+3;
1441 if ((Bits
=LBits
[Number
])>0)
1444 Length
+=BitField
>>(16-Bits
);
1448 DecodeNumber((struct Decode
*)&DD
);
1449 Distance
=DDecode
[Number
]+1;
1450 if ((Bits
=DBits
[Number
])>0)
1453 Distance
+=BitField
>>(16-Bits
);
1457 if (Distance
>=0x40000L
)
1460 if (Distance
>=0x2000)
1463 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1464 DestUnpSize
-=(LastLength
=Length
);
1467 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1468 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1482 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1483 DestUnpSize
-=(LastLength
=Length
);
1486 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1487 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1493 Distance
=OldDist
[(OldDistPtr
-(Number
-256)) & 3];
1494 DecodeNumber((struct Decode
*)&RD
);
1495 Length
=LDecode
[Number
]+2;
1496 if ((Bits
=LBits
[Number
])>0)
1499 Length
+=BitField
>>(16-Bits
);
1502 if (Distance
>=0x40000)
1504 if (Distance
>=0x2000)
1506 if (Distance
>=0x101)
1508 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1509 DestUnpSize
-=(LastLength
=Length
);
1512 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1513 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1519 Distance
=SDDecode
[Number
-=261]+1;
1520 if ((Bits
=SDBits
[Number
])>0)
1523 Distance
+=BitField
>>(16-Bits
);
1527 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1528 DestUnpSize
-=(LastLength
=Length
);
1531 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1532 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1539 if (FileFound
) /* flush buffer */
1544 if((*temp_output_buffer_offset
+ UnpPtr
) > NewLhd
.UnpSize
)
1546 debug_log("Fatal! Buffer overrun during decompression!");
1550 /* copy extracted data to output buffer */
1551 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, &UnpBuf
[WrPtr
],
1552 (0-WrPtr
) & MAXWINMASK
);
1553 /* update offset within buffer */
1554 *temp_output_buffer_offset
+= (0-WrPtr
) & MAXWINMASK
;
1555 /* copy extracted data to output buffer */
1556 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, UnpBuf
, UnpPtr
);
1557 /* update offset within buffer */
1558 *temp_output_buffer_offset
+=UnpPtr
;
1562 if((*temp_output_buffer_offset
+ (UnpPtr
-WrPtr
)) > NewLhd
.UnpSize
)
1564 debug_log("Fatal! Buffer overrun during decompression!");
1568 /* copy extracted data to output buffer */
1569 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, &UnpBuf
[WrPtr
],
1571 /* update offset within buffer */
1572 *temp_output_buffer_offset
+=UnpPtr
-WrPtr
;
1581 unsigned int UnpRead(unsigned char *Addr
,unsigned int Count
)
1584 unsigned int I
,ReadSize
,TotalRead
=0;
1585 unsigned char *ReadAddr
;
1589 ReadSize
=(unsigned int)((Count
>(unsigned long)UnpPackedSize
) ?
1590 (unsigned int)UnpPackedSize
: Count
);
1591 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1592 if(MemRARFile
->data
== NULL
)
1594 RetCode
=tread(MemRARFile
, ReadAddr
, ReadSize
);
1598 RetCode
=tread(ArcPtr
,ReadAddr
,ReadSize
);
1600 CurUnpRead
+=RetCode
;
1604 UnpPackedSize
-=RetCode
;
1614 debug_log("Old Crypt() not supported!");
1618 for (I
=0;I
<(unsigned int)RetCode
;I
+=16)
1619 DecryptBlock(&Addr
[I
]);
1627 void UnpReadBuf(int FirstBuf
)
1632 ReadTop
=UnpRead(InBuf
,sizeof(InBuf
));
1637 memcpy(InBuf
,&InBuf
[sizeof(InBuf
)-32],32);
1639 RetCode
=UnpRead(&InBuf
[32],sizeof(InBuf
)-32);
1648 void ReadTables(void)
1650 UBYTE BitLength
[BC
];
1651 unsigned char Table
[MC
*4];
1653 if (InAddr
>sizeof(InBuf
)-25)
1656 UnpAudioBlock
=(BitField
& 0x8000);
1658 if (!(BitField
& 0x4000))
1659 memset(UnpOldTable
,0,sizeof(UnpOldTable
));
1665 UnpChannels
=((BitField
>>12) & 3)+1;
1666 if (CurChannel
>=UnpChannels
)
1669 TableSize
=MC
*UnpChannels
;
1678 BitLength
[I
]=(UBYTE
)(BitField
>> 12);
1681 MakeDecodeTables(BitLength
,(struct Decode
*)&BD
,BC
);
1685 if (InAddr
>sizeof(InBuf
)-5)
1687 DecodeNumber((struct Decode
*)&BD
);
1690 Table
[I
]=(Number
+UnpOldTable
[I
]) & 0xf;
1697 N
=(BitField
>> 14)+3;
1699 while (N
-- > 0 && I
<TableSize
)
1701 Table
[I
]=Table
[I
-1];
1710 N
=(BitField
>> 13)+3;
1716 N
=(BitField
>> 9)+11;
1719 while (N
-- > 0 && I
<TableSize
)
1724 for (I
=0;I
<UnpChannels
;I
++)
1725 MakeDecodeTables(&Table
[I
*MC
],(struct Decode
*)MDPtr
[I
],MC
);
1728 MakeDecodeTables(&Table
[0],(struct Decode
*)&LD
,NC
);
1729 MakeDecodeTables(&Table
[NC
],(struct Decode
*)&DD
,DC
);
1730 MakeDecodeTables(&Table
[NC
+DC
],(struct Decode
*)&RD
,RC
);
1732 memcpy(UnpOldTable
,Table
,sizeof(UnpOldTable
));
1736 static void ReadLastTables(void)
1738 if (ReadTop
>=InAddr
+5)
1742 DecodeNumber((struct Decode
*)MDPtr
[CurChannel
]);
1748 DecodeNumber((struct Decode
*)&LD
);
1756 static void MakeDecodeTables(unsigned char *LenTab
,
1760 int LenCount
[16],TmpPos
[16],I
;
1762 memset(LenCount
,0,sizeof(LenCount
));
1763 for (I
=0;I
<Size
;I
++)
1764 LenCount
[LenTab
[I
] & 0xF]++;
1767 for (TmpPos
[0]=Dec
->DecodePos
[0]=Dec
->DecodeLen
[0]=0,N
=0,I
=1;I
<16;I
++)
1769 N
=2*(N
+LenCount
[I
]);
1773 Dec
->DecodeLen
[I
]=(unsigned int)M
;
1774 TmpPos
[I
]=Dec
->DecodePos
[I
]=Dec
->DecodePos
[I
-1]+LenCount
[I
-1];
1777 for (I
=0;I
<Size
;I
++)
1779 Dec
->DecodeNum
[TmpPos
[LenTab
[I
] & 0xF]++]=I
;
1784 static void DecodeNumber(struct Decode
*Deco
)
1785 /* *** 52.6% of all CPU time is spent within this function!!! */
1788 register unsigned int N
;
1797 mov eax
, BitField
// N=BitField & 0xFFFE;
1800 mov edx
, [Deco
] // EAX=N, EDX=Deco
1802 cmp eax
, dword ptr
[edx
+ 8*4 + 4]// if (N<Dec->DecodeLen[8])
1805 cmp eax
, dword ptr
[edx
+ 4*4 + 4]// if (N<Dec->DecodeLen[4])
1809 cmp eax
, dword ptr
[edx
+ 2*4 + 4]// if (N<Dec->DecodeLen[2])
1812 cmp eax
, dword ptr
[edx
+ 1*4 + 4]// if (N<Dec->DecodeLen[1])
1823 cmp eax
, dword ptr
[edx
+ 3*4 + 4]// if (N<Dec->DecodeLen[3])
1837 cmp eax
, dword ptr
[edx
+ 6*4 + 4]// if (N<Dec->DecodeLen[6])
1840 cmp eax
, dword ptr
[edx
+ 5*4 + 4]// if (N<Dec->DecodeLen[5])
1851 cmp eax
, dword ptr
[edx
+ 7*4 + 4]// if (N<Dec->DecodeLen[7])
1866 cmp eax
, dword ptr
[edx
+ 12*4 + 4] // if (N<Dec->DecodeLen[12])
1869 cmp eax
, dword ptr
[edx
+ 10*4 + 4]// if (N<Dec->DecodeLen[10])
1872 cmp eax
, dword ptr
[edx
+ 9*4 + 4]// if (N<Dec->DecodeLen[9])
1883 cmp eax
, dword ptr
[edx
+ 11*4 + 4]// if (N<Dec->DecodeLen[11])
1897 cmp eax
, dword ptr
[edx
+ 14*4 + 4]// if (N<Dec->DecodeLen[14])
1900 cmp eax
, dword ptr
[edx
+ 13*4 + 4]// if (N<Dec->DecodeLen[13])
1917 __asm__
__volatile__ (
1918 "andl $0xFFFFFFFE, %%eax"
1920 " cmpl 8*4(%%edx), %%eax /* 5379 */"
1923 " cmpl 4*4(%%edx), %%eax"
1926 " cmpl 2*4(%%edx), %%eax"
1929 " cmpl 1*4(%%edx), %%eax"
1941 " cmpl 3*4(%%edx), %%eax "
1954 " cmpl 6*4(%%edx), %%eax"
1957 " cmpl 5*4(%%edx), %%eax"
1968 " cmpl 7*4(%%edx), %%eax"
1983 " cmpl 12*4(%%edx), %%eax"
1986 " cmpl 10*4(%%edx), %%eax"
1989 " cmpl 9*4(%%edx), %%eax"
2000 " cmpl 11*4(%%edx), %%eax"
2015 " cmpl 14*4(%%edx), %%eax"
2018 " cmpl 13*4(%%edx), %%eax"
2034 : "eax" ((long)BitField
), "edx"((long)Deco
->DecodeLen
)
2037 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
2040 N
=BitField
& 0xFFFE;
2041 if (N
<Deco
->DecodeLen
[8]) {
2042 if (N
<Deco
->DecodeLen
[4]) {
2043 if (N
<Deco
->DecodeLen
[2]) {
2044 if (N
<Deco
->DecodeLen
[1])
2049 if (N
<Deco
->DecodeLen
[3])
2055 if (N
<Deco
->DecodeLen
[6]) {
2056 if (N
<Deco
->DecodeLen
[5])
2061 if (N
<Deco
->DecodeLen
[7])
2068 if (N
<Deco
->DecodeLen
[12]) {
2069 if (N
<Deco
->DecodeLen
[10]) {
2070 if (N
<Deco
->DecodeLen
[9])
2075 if (N
<Deco
->DecodeLen
[11])
2081 if (N
<Deco
->DecodeLen
[14]) {
2082 if (N
<Deco
->DecodeLen
[13])
2096 if ((N
=Deco
->DecodePos
[I
]+((N
-Deco
->DecodeLen
[I
-1])>>(16-I
)))>=Deco
->MaxNum
)
2098 Number
=Deco
->DecodeNum
[N
];
2105 if (!(NewLhd
.Flags
& LHD_SOLID
))
2107 ChannelDelta
=CurChannel
=0;
2111 #ifdef _WIN_32 /* Win32 with VisualC */
2118 cld
/* increment EDI and ESI */
2121 mov edi
, Offset AudV
2122 rep stosb
/* clear memory */
2124 mov ecx
, SIZE OldDist
2125 mov edi
, Offset OldDist
2126 rep stosb
/* clear memory */
2128 mov ecx
, SIZE UnpOldTable
2129 mov edi
, Offset UnpOldTable
2130 rep stosb
/* clear memory */
2149 memset(UnpBuf
,0,MAXWINSIZE
);
2152 #else /* unix/linux on i386 cpus */
2153 __asm__
__volatile (
2154 " cld /* increment EDI and ESI */"
2159 " stosb /* clear memory */"
2164 " stosb /* clear memory */"
2169 " stosb /* clear memory */"
2171 " movl $0, (OldDistPtr)"
2172 " movl $0, (LastDist)"
2173 " movl $0, (LastLength)"
2174 " movl $0, (UnpPtr)"
2176 " movl $0, (OldDistPtr)"
2177 " movl $0, (LastLength)"
2178 " movl $0, (LastDist)"
2179 " movl $0, (UnpPtr)"
2182 : "m" ((long)sizeof(AudV
)),
2184 "m" ((long)sizeof(OldDist
)),
2185 "m" ((long)OldDist
),
2186 "m" ((long)sizeof(UnpOldTable
)),
2187 "m" ((long)UnpOldTable
)
2188 : "memory", "edi", "eax", "ecx"
2190 memset(UnpBuf
,0,MAXWINSIZE
);
2193 #else /* unix/linux on non-i386 cpu */
2194 memset(AudV
,0,sizeof(AudV
));
2195 memset(OldDist
,0,sizeof(OldDist
));
2197 LastDist
=LastLength
=0;
2198 memset(UnpBuf
,0,MAXWINSIZE
);
2199 memset(UnpOldTable
,0,sizeof(UnpOldTable
));
2207 UBYTE
DecodeAudio(int Delta
)
2209 struct AudioVariables
*V
;
2211 unsigned int NumMinDif
,MinDif
;
2214 V
=&AudV
[CurChannel
];
2218 V
->D2
=V
->LastDelta
-V
->D1
;
2220 PCh
=8*V
->LastChar
+V
->K1
*V
->D1
+V
->K2
*V
->D2
+
2221 V
->K3
*V
->D3
+V
->K4
*V
->D4
+V
->K5
*ChannelDelta
;
2222 PCh
=(PCh
>>3) & 0xFF;
2226 I
=((signed char)Delta
)<<3;
2229 V
->Dif
[1]+=abs(I
-V
->D1
);
2230 V
->Dif
[2]+=abs(I
+V
->D1
);
2231 V
->Dif
[3]+=abs(I
-V
->D2
);
2232 V
->Dif
[4]+=abs(I
+V
->D2
);
2233 V
->Dif
[5]+=abs(I
-V
->D3
);
2234 V
->Dif
[6]+=abs(I
+V
->D3
);
2235 V
->Dif
[7]+=abs(I
-V
->D4
);
2236 V
->Dif
[8]+=abs(I
+V
->D4
);
2237 V
->Dif
[9]+=abs(I
-ChannelDelta
);
2238 V
->Dif
[10]+=abs(I
+ChannelDelta
);
2240 ChannelDelta
=V
->LastDelta
=(signed char)(Ch
-V
->LastChar
);
2243 if ((V
->ByteCount
& 0x1F)==0)
2248 for (I
=1;(unsigned int)I
<sizeof(V
->Dif
)/sizeof(V
->Dif
[0]);I
++)
2250 if (V
->Dif
[I
]<MinDif
)
2310 /* ***************************************************
2311 * ** CRCCrypt Code - decryption engine starts here **
2312 * ***************************************************/
2317 #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
2318 #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
2320 #define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
2321 ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
2322 ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
2323 ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
2328 UBYTE SubstTable
[256];
2329 UBYTE InitSubstTable
[256]={
2330 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
2331 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
2332 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
2333 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
2334 107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
2335 158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
2336 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
2337 164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
2338 207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
2339 122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
2340 131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
2341 224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
2342 118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
2343 161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
2344 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
2345 116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
2351 void EncryptBlock(UBYTE
*Buf
)
2355 UDWORD A
,B
,C
,D
,T
,TA
,TB
;
2356 #ifdef NON_INTEL_BYTE_ORDER
2357 A
=((UDWORD
)Buf
[0]|((UDWORD
)Buf
[1]<<8)|((UDWORD
)Buf
[2]<<16)|
2358 ((UDWORD
)Buf
[3]<<24))^Key
[0];
2359 B
=((UDWORD
)Buf
[4]|((UDWORD
)Buf
[5]<<8)|((UDWORD
)Buf
[6]<<16)|
2360 ((UDWORD
)Buf
[7]<<24))^Key
[1];
2361 C
=((UDWORD
)Buf
[8]|((UDWORD
)Buf
[9]<<8)|((UDWORD
)Buf
[10]<<16)|
2362 ((UDWORD
)Buf
[11]<<24))^Key
[2];
2363 D
=((UDWORD
)Buf
[12]|((UDWORD
)Buf
[13]<<8)|((UDWORD
)Buf
[14]<<16)|
2364 ((UDWORD
)Buf
[15]<<24))^Key
[3];
2367 BufPtr
=(UDWORD
*)Buf
;
2373 for(I
=0;I
<NROUNDS
;I
++)
2375 T
=((C
+rol(D
,11))^Key
[I
&3]);
2377 T
=((D
^rol(C
,17))+Key
[I
&3]);
2384 #ifdef NON_INTEL_BYTE_ORDER
2387 Buf
[1]=(UBYTE
)(C
>>8);
2388 Buf
[2]=(UBYTE
)(C
>>16);
2389 Buf
[3]=(UBYTE
)(C
>>24);
2392 Buf
[5]=(UBYTE
)(D
>>8);
2393 Buf
[6]=(UBYTE
)(D
>>16);
2394 Buf
[7]=(UBYTE
)(D
>>24);
2397 Buf
[9]=(UBYTE
)(A
>>8);
2398 Buf
[10]=(UBYTE
)(A
>>16);
2399 Buf
[11]=(UBYTE
)(A
>>24);
2402 Buf
[13]=(UBYTE
)(B
>>8);
2403 Buf
[14]=(UBYTE
)(B
>>16);
2404 Buf
[15]=(UBYTE
)(B
>>24);
2415 void DecryptBlock(UBYTE
*Buf
)
2419 UDWORD A
,B
,C
,D
,T
,TA
,TB
;
2420 #ifdef NON_INTEL_BYTE_ORDER
2421 A
=((UDWORD
)Buf
[0]|((UDWORD
)Buf
[1]<<8)|((UDWORD
)Buf
[2]<<16)|
2422 ((UDWORD
)Buf
[3]<<24))^Key
[0];
2423 B
=((UDWORD
)Buf
[4]|((UDWORD
)Buf
[5]<<8)|((UDWORD
)Buf
[6]<<16)|
2424 ((UDWORD
)Buf
[7]<<24))^Key
[1];
2425 C
=((UDWORD
)Buf
[8]|((UDWORD
)Buf
[9]<<8)|((UDWORD
)Buf
[10]<<16)|
2426 ((UDWORD
)Buf
[11]<<24))^Key
[2];
2427 D
=((UDWORD
)Buf
[12]|((UDWORD
)Buf
[13]<<8)|((UDWORD
)Buf
[14]<<16)|
2428 ((UDWORD
)Buf
[15]<<24))^Key
[3];
2431 BufPtr
=(UDWORD
*)Buf
;
2432 A
=BufPtr
[0]^Key
[0]; /* xxx may be this can be */
2433 B
=BufPtr
[1]^Key
[1]; /* optimized in assembler */
2437 memcpy(InBuf
,Buf
,sizeof(InBuf
));
2438 for(I
=NROUNDS
-1;I
>=0;I
--)
2440 T
=((C
+rol(D
,11))^Key
[I
&3]);
2442 T
=((D
^rol(C
,17))+Key
[I
&3]);
2449 #ifdef NON_INTEL_BYTE_ORDER
2452 Buf
[1]=(UBYTE
)(C
>>8);
2453 Buf
[2]=(UBYTE
)(C
>>16);
2454 Buf
[3]=(UBYTE
)(C
>>24);
2457 Buf
[5]=(UBYTE
)(D
>>8);
2458 Buf
[6]=(UBYTE
)(D
>>16);
2459 Buf
[7]=(UBYTE
)(D
>>24);
2462 Buf
[9]=(UBYTE
)(A
>>8);
2463 Buf
[10]=(UBYTE
)(A
>>16);
2464 Buf
[11]=(UBYTE
)(A
>>24);
2467 Buf
[13]=(UBYTE
)(B
>>8);
2468 Buf
[14]=(UBYTE
)(B
>>16);
2469 Buf
[15]=(UBYTE
)(B
>>24);
2480 void UpdKeys(UBYTE
*Buf
)
2485 Key
[0]^=CRCTab
[Buf
[I
]]; /* xxx may be I'll rewrite this */
2486 Key
[1]^=CRCTab
[Buf
[I
+1]]; /* in asm for speedup */
2487 Key
[2]^=CRCTab
[Buf
[I
+2]];
2488 Key
[3]^=CRCTab
[Buf
[I
+3]];
2492 void SetCryptKeys(char *Password
)
2494 unsigned int I
,J
,K
,PswLength
;
2495 unsigned char N1
,N2
;
2496 unsigned char Psw
[256];
2498 #if !defined _USE_ASM
2502 SetOldKeys(Password
);
2508 memset(Psw
,0,sizeof(Psw
));
2509 strcpy((char *)Psw
,Password
);
2510 PswLength
=strlen(Password
);
2511 memcpy(SubstTable
,InitSubstTable
,sizeof(SubstTable
));
2514 for (I
=0;I
<PswLength
;I
+=2)
2516 N2
=(unsigned char)CRCTab
[(Psw
[I
+1]+J
)&0xFF];
2517 for (K
=1, N1
=(unsigned char)CRCTab
[(Psw
[I
]-J
)&0xFF];
2518 (N1
!=N2
) && (N1
< 256); /* I had to add "&& (N1 < 256)", */
2519 N1
++, K
++) /* because the system crashed with */
2520 { /* encrypted RARs */
2526 mov ebx
, Offset SubstTable
2529 xor ecx
, ecx
// read SubstTable[N1]...
2532 mov al
, byte ptr
[ebx
]
2534 mov cl
, N1
// read SubstTable[(N1+I+K)&0xFF]...
2539 mov ah
, byte ptr
[edx
]
2541 mov byte ptr
[ebx
], ah
// and write back
2542 mov byte ptr
[edx
], al
2546 __asm__
__volatile__ (
2547 " xorl %%ecx, %%ecx"
2548 " movl %2, %%ecx /* ecx = N1 */"
2550 " addl %%ecx, %%ebx"
2554 " andl $0x000000FF, %%ecx"
2555 " addl %%ecx, %%edx"
2557 " movb (%%ebx), %%al"
2558 " movb (%%edx), %%ah"
2560 " movb %%ah, (%%ebx) /* and write back */"
2561 " movb %%al, (%%edx)"
2565 "ebx"((long)SubstTable
)
2572 /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
2574 SubstTable
[N1
]=SubstTable
[(N1
+I
+K
)&0xFF];
2575 SubstTable
[(N1
+I
+K
)&0xFF]=Ch
;
2579 for (I
=0;I
<PswLength
;I
+=16)
2580 EncryptBlock(&Psw
[I
]);
2584 void SetOldKeys(char *Password
)
2588 PswCRC
=CalcCRC32(0xFFFFFFFFL
,(UBYTE
*)Password
,strlen(Password
));
2589 OldKey
[0]=(UWORD
)PswCRC
;
2590 OldKey
[1]=(UWORD
)(PswCRC
>>16);
2591 OldKey
[2]=OldKey
[3]=0;
2593 while ((Ch
=*Password
)!=0)
2598 PN3
=(UBYTE
)rol(PN3
,1);
2599 OldKey
[2]^=((UWORD
)(Ch
^CRCTab
[Ch
]));
2600 OldKey
[3]+=((UWORD
)(Ch
+(CRCTab
[Ch
]>>16)));
2611 for (C
=I
,J
=0;J
<8;J
++)
2612 C
=(C
& 1) ? (C
>>1)^0xEDB88320L
: (C
>>1);
2618 UDWORD
CalcCRC32(UDWORD StartCRC
,UBYTE
*Addr
,UDWORD Size
)
2621 for (I
=0; I
<Size
; I
++)
2622 StartCRC
= CRCTab
[(UBYTE
)StartCRC
^ Addr
[I
]] ^ (StartCRC
>> 8);
2627 /* **************************************************************************
2628 ****************************************************************************
2629 ****************************************************************************
2630 ************************************************************************** */
2656 /* **************************************************************************
2657 ****************************************************************************
2658 ****************************************************************************
2659 ****************************************************************************
2663 ******* D E B U G F U N C T I O N S *******
2667 ****************************************************************************
2668 ****************************************************************************
2669 ****************************************************************************
2670 ************************************************************************** */
2674 /* -- global stuff -------------------------------------------------------- */
2675 char log_file_name
[256]; /* file name for the log file */
2676 DWORD debug_start_time
; /* starttime of debug */
2677 BOOL debug_started
= FALSE
; /* debug_log writes only if */
2679 /* ------------------------------------------------------------------------ */
2682 /* -- global functions ---------------------------------------------------- */
2683 void debug_init_proc(char *file_name
)
2684 /* Create/Rewrite a log file */
2687 char date
[] = __DATE__
;
2688 char time
[] = __TIME__
;
2690 debug_start_time
= GetTickCount(); /* get start time */
2691 strcpy(log_file_name
, file_name
); /* save file name */
2693 if((fp
= fopen(log_file_name
, CREATETEXT
)) != NULL
)
2695 debug_started
= TRUE
; /* enable debug */
2696 fprintf(fp
, "Debug log of UniquE's RARFileLib\n"\
2697 "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
2698 fprintf(fp
, "(executable compiled on %s at %s)\n\n", date
, time
);
2704 void debug_log_proc(char *text
, char *sourcefile
, int sourceline
)
2705 /* add a line to the log file */
2709 if(debug_started
== FALSE
) return; /* exit if not initialized */
2711 if((fp
= fopen(log_file_name
, APPENDTEXT
)) != NULL
) /* append to logfile */
2714 fprintf(fp
, " %8u ms (line %u in %s):\n - %s\n",
2715 (unsigned int)(GetTickCount() - debug_start_time
),
2716 sourceline
, sourcefile
, text
);
2721 /* ------------------------------------------------------------------------ */
2723 /* **************************************************************************
2724 ****************************************************************************
2725 ****************************************************************************
2726 ************************************************************************** */
2729 /* end of file urarlib.c */