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 ** The contents of this file are subject to the UniquE RAR File Library
9 ** License (the "unrarlib-license.txt"). You may not use this file except
10 ** in compliance with the License. You may obtain a copy of the License
11 ** at http://www.unrarlib.org/license.html.
12 ** Software distributed under the License is distributed on an "AS IS"
13 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
15 ** Alternatively, the contents of this file may be used under the terms
16 ** of the GNU General Public License Version 2 or later (the "GPL"), in
17 ** which case the provisions of the GPL are applicable instead of those
18 ** above. If you wish to allow use of your version of this file only
19 ** under the terms of the GPL and not to allow others to use your version
20 ** of this file under the terms of the UniquE RAR File Library License,
21 ** indicate your decision by deleting the provisions above and replace
22 ** them with the notice and other provisions required by the GPL. If you
23 ** do not delete the provisions above, a recipient may use your version
24 ** of this file under the terms of the GPL or the UniquE RAR File Library
27 ************************************************************************** */
29 /* ***************************************************************************
31 ** UniquE RAR File Library
32 ** The free file lib for the demoscene
33 ** multi-OS version (Win32, Linux and SunOS)
35 *****************************************************************************
37 ** ==> Please configure the program in "unrarlib.h". <==
39 ** RAR decompression code:
41 ** Modifications to a FileLib:
42 ** (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
44 ** (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
46 ** The UniquE RAR File Library gives you the ability to access RAR archives
47 ** (any compression method supported in RAR v2.0 including Multimedia
48 ** Compression and encryption) directly from your program with ease an by
49 ** adding only 12kB (6kB UPX-compressed) additional code to your program.
50 ** Both solid and normal (recommended for fast random access to the files!)
51 ** archives are supported. This FileLib is made for the Demo scene, so it's
52 ** designed for easy use within your demos and intros.
53 ** Please read "licence.txt" to learn more about how you may use URARFileLib
54 ** in your productions.
56 *****************************************************************************
58 ** ==> see the "CHANGES" file to see what's new
60 ************************************************************************** */
62 /* -- include files ------------------------------------------------------- */
63 #include "unrarlib.h" /* include global configuration */
64 /* ------------------------------------------------------------------------ */
68 /* -- global stuff -------------------------------------------------------- */
71 #include <windows.h> /* WIN32 definitions */
78 #define HOST_OS WIN_32
80 #define FM_NORMAL 0x00
81 #define FM_RDONLY 0x01
82 #define FM_HIDDEN 0x02
83 #define FM_SYSTEM 0x04
88 #define PATHDIVIDER "\\"
89 #define CPATHDIVIDER '\\'
92 #define READBINARY "rb"
94 #define UPDATEBINARY "r+b"
95 #define CREATEBINARY "w+b"
96 #define CREATETEXT "w"
97 #define APPENDTEXT "at"
103 #include <stdio.h> /* LINUX/UNIX definitions */
108 #define ENABLE_ACCESS
112 #define FM_LABEL 0x0000
113 #define FM_DIREC 0x4000
115 #define PATHDIVIDER "/"
116 #define CPATHDIVIDER '/'
117 #define MASKALL "*.*"
119 #define READBINARY "r"
121 #define UPDATEBINARY "r+"
122 #define CREATEBINARY "w+"
123 #define CREATETEXT "w"
124 #define APPENDTEXT "a"
127 /* emulation of the windows API and data types */
128 /* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
136 #ifdef _DEBUG_LOG /* define macros for debugging */
138 #include <sys/time.h>
143 gettimeofday( &tv
, 0 );
144 return (tv
.tv_usec
/ 1000);
154 #ifdef _DEBUG_LOG /* define macros for debugging */
156 BOOL debug_log_first_start
= TRUE
;
158 #define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
159 #define debug_init(a); debug_init_proc(a);
161 void debug_log_proc(char *text
, char *sourcefile
, int sourceline
);
162 void debug_init_proc(char *file_name
);
165 #define debug_log(a); /* no debug this time */
166 #define debug_init(a); /* no debug this time */
173 #define MAXWINSIZE 0x100000
174 #define MAXWINMASK (MAXWINSIZE-1)
175 #define UNP_MEMORY MAXWINSIZE
176 #define Min(x,y) (((x)<(y)) ? (x):(y))
177 #define Max(x,y) (((x)>(y)) ? (x):(y))
180 #define SIZEOF_MARKHEAD 7
181 #define SIZEOF_OLDMHD 7
182 #define SIZEOF_NEWMHD 13
183 #define SIZEOF_OLDLHD 21
184 #define SIZEOF_NEWLHD 32
185 #define SIZEOF_SHORTBLOCKHEAD 7
186 #define SIZEOF_LONGBLOCKHEAD 11
187 #define SIZEOF_COMMHEAD 13
188 #define SIZEOF_PROTECTHEAD 26
191 #define PACK_VER 20 /* version of decompression code*/
193 #define PROTECT_VER 20
196 enum { M_DENYREAD
,M_DENYWRITE
,M_DENYNONE
,M_DENYALL
};
197 enum { FILE_EMPTY
,FILE_ADD
,FILE_UPDATE
,FILE_COPYOLD
,FILE_COPYBLOCK
};
198 enum { SUCCESS
,WARNING
,FATAL_ERROR
,CRC_ERROR
,LOCK_ERROR
,WRITE_ERROR
,
199 OPEN_ERROR
,USER_ERROR
,MEMORY_ERROR
,USER_BREAK
=255,IMM_ABORT
=0x8000 };
200 enum { EN_LOCK
=1,EN_VOL
=2 };
201 enum { SD_MEMORY
=1,SD_FILES
=2 };
202 enum { NAMES_DONTCHANGE
};
203 enum { LOG_ARC
=1,LOG_FILE
=2 };
204 enum { OLD_DECODE
=0,OLD_ENCODE
=1,NEW_CRYPT
=2 };
205 enum { OLD_UNPACK
,NEW_UNPACK
};
208 #define MHD_COMMENT 2
210 #define MHD_PACK_COMMENT 16
212 #define MHD_PROTECT 64
214 #define LHD_SPLIT_BEFORE 1
215 #define LHD_SPLIT_AFTER 2
216 #define LHD_PASSWORD 4
217 #define LHD_COMMENT 8
220 #define LHD_WINDOWMASK 0x00e0
221 #define LHD_WINDOW64 0
222 #define LHD_WINDOW128 32
223 #define LHD_WINDOW256 64
224 #define LHD_WINDOW512 96
225 #define LHD_WINDOW1024 128
226 #define LHD_DIRECTORY 0x00e0
228 #define LONG_BLOCK 0x8000
229 #define READSUBBLOCK 0x8000
231 enum { ALL_HEAD
=0,MARK_HEAD
=0x72,MAIN_HEAD
=0x73,FILE_HEAD
=0x74,
232 COMM_HEAD
=0x75,AV_HEAD
=0x76,SUB_HEAD
=0x77,PROTECT_HEAD
=0x78};
233 enum { EA_HEAD
=0x100 };
234 enum { MS_DOS
=0,OS2
=1,WIN_32
=2,UNIX
=3 };
243 struct NewMainArchiveHeader
285 unsigned int DecodeLen
[16];
286 unsigned int DecodePos
[16];
287 unsigned int DecodeNum
[2];
291 struct MarkHeader MarkHead
;
292 struct NewMainArchiveHeader NewMhd
;
293 struct NewFileHeader NewLhd
;
294 struct BlockHeader BlockHead
;
296 static UBYTE
*TempMemory
= NULL
; /* temporary unpack-buffer */
297 static char *CommMemory
= NULL
;
300 static UBYTE
*UnpMemory
= NULL
;
301 static char* ArgName
= NULL
; /* current file in rar archive */
302 static char* ArcFileName
= NULL
; /* file to decompress */
304 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
305 static MemoryFile
*MemRARFile
; /* pointer to RAR file in memory*/
307 static char* ArcName
= NULL
; /* RAR archive name */
308 static FILE *ArcPtr
; /* input RAR file handler */
310 static char *Password
= NULL
; /* password to decrypt files */
312 static unsigned char *temp_output_buffer
; /* extract files to this pointer*/
313 static unsigned long *temp_output_buffer_offset
; /* size of temp. extract buffer */
315 static BOOL FileFound
; /* TRUE=use current extracted */
316 /* data FALSE=throw data away, */
318 static int MainHeadSize
;
319 static long CurBlockPos
,NextBlockPos
;
321 static unsigned long CurUnpRead
, CurUnpWrite
;
322 static long UnpPackedSize
;
323 static long DestUnpSize
;
325 static UDWORD HeaderCRC
;
326 static int Encryption
;
328 //static unsigned int UnpWrSize;
329 //static unsigned char *UnpWrAddr;
330 static unsigned int UnpPtr
,WrPtr
;
332 static unsigned char PN1
,PN2
,PN3
;
333 static unsigned short OldKey
[4];
337 /* function header definitions */
338 static int ReadHeader(int BlockType
);
339 static BOOL
ExtrFile(void);
340 //BOOL ListFile(void);
341 static int tread(void *stream
,void *buf
,unsigned len
);
342 static int tseek(void *stream
,long offset
,int fromwhere
);
343 static BOOL
UnstoreFile(void);
344 static int IsArchive(void);
345 static int ReadBlock(int BlockType
);
346 static unsigned int UnpRead(unsigned char *Addr
,unsigned int Count
);
347 static void UnpInitData(void);
348 static void Unpack(unsigned char *UnpAddr
);
349 static UBYTE
DecodeAudio(int Delta
);
350 static void DecodeNumber(struct Decode
*Dec
);
351 static void UpdKeys(UBYTE
*Buf
);
352 static void SetCryptKeys(char *Password
);
353 static void SetOldKeys(char *Password
);
354 static void DecryptBlock(unsigned char *Buf
);
355 static void InitCRC(void);
356 static UDWORD
CalcCRC32(UDWORD StartCRC
,UBYTE
*Addr
,UDWORD Size
);
357 static void UnpReadBuf(int FirstBuf
);
358 static void ReadTables(void);
359 static void ReadLastTables(void);
360 static void MakeDecodeTables(unsigned char *LenTab
,
363 static int my_stricomp(char *Str1
,char *Str2
);
364 /* ------------------------------------------------------------------------ */
367 /* -- global functions ---------------------------------------------------- */
369 int urarlib_get(void *output
,
374 /* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
375 * does everything from allocating memory, decrypting and unpacking the file
376 * from the archive. TRUE is returned if the file could be successfully
377 * extracted, else a FALSE indicates a failure.
380 BOOL retcode
= FALSE
;
383 int str_offs
; /* used for debug-strings */
384 char DebugMsg
[500]; /* used to compose debug msg */
386 if(debug_log_first_start
)
388 debug_log_first_start
=FALSE
; /* only create a new log file */
389 debug_init(_DEBUG_LOG_FILE
); /* on startup */
394 InitCRC(); /* init some vars */
396 if(ArgName
) free(ArgName
);
397 ArgName
= strdup(filename
); /* set file(s) to extract */
398 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
399 MemRARFile
= rarfile
; /* set pointer to mem-RAR file */
401 if(ArcName
) free(ArcName
);
402 ArcName
= strdup(rarfile
); /* set RAR file name */
404 if(Password
) free(Password
);
405 if(libpassword
!= NULL
)
406 Password
= strdup(libpassword
); /* init password */
408 Password
= strdup("");
410 temp_output_buffer
= NULL
;
411 temp_output_buffer_offset
=size
; /* set size of the temp buffer */
414 sprintf(DebugMsg
, "Extracting >%s< from >%s< (password is >%s<)...",
415 filename
, (char*)rarfile
, libpassword
);
419 retcode
= ExtrFile(); /* unpack file now! */
421 //memset(Password,0,sizeof(Password)); /* clear password */
423 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
430 if(UnpMemory
) free(UnpMemory
); /* free memory */
431 if(TempMemory
) free(TempMemory
);
432 if(CommMemory
) free(CommMemory
);
440 if(temp_output_buffer
) /* free memory and return NULL */
441 free(temp_output_buffer
);
442 temp_output_buffer
=NULL
;
443 *(DWORD
*)output
=0; /* pointer on errors */
448 /* sorry for this ugly code, but older SunOS gcc compilers don't support */
449 /* white spaces within strings */
450 str_offs
= sprintf(DebugMsg
, "Error - couldn't extract ");
451 str_offs
+= sprintf(DebugMsg
+ str_offs
, ">%s<", filename
);
452 str_offs
+= sprintf(DebugMsg
+ str_offs
, " and allocated ");
453 str_offs
+= sprintf(DebugMsg
+ str_offs
, "%u Bytes", (unsigned int)*size
);
454 str_offs
+= sprintf(DebugMsg
+ str_offs
, " of unused memory!");
458 sprintf(DebugMsg
, "Extracted %u Bytes.", (unsigned int)*size
);
464 *(DWORD
*)output
=(DWORD
)temp_output_buffer
;/* return pointer for unpacked*/
471 int urarlib_list(void *rarfile
, ArchiveList_struct
*list
)
473 ArchiveList_struct
*tmp_List
= NULL
;
474 int NoOfFilesInArchive
= 0; /* number of files in archive */
477 if(debug_log_first_start
)
479 debug_log_first_start
=FALSE
; /* only create a new log file */
480 debug_init(_DEBUG_LOG_FILE
); /* on startup */
484 InitCRC(); /* init some vars */
486 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
487 MemRARFile
= rarfile
; /* assign pointer to RAR file */
488 MemRARFile
->offset
= 0;
491 debug_log("Not a RAR file");
492 return NoOfFilesInArchive
; /* error => exit! */
495 /* open and identify archive */
496 if ((ArcPtr
=fopen(rarfile
,READBINARY
))!=NULL
)
500 debug_log("Not a RAR file");
503 return NoOfFilesInArchive
; /* error => exit! */
507 debug_log("Error opening file.");
508 return NoOfFilesInArchive
;
512 if ((UnpMemory
=malloc(UNP_MEMORY
))==NULL
)
514 debug_log("Can't allocate memory for decompression!");
515 return NoOfFilesInArchive
;
518 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
519 MemRARFile
->offset
+=NewMhd
.HeadSize
-MainHeadSize
;
521 tseek(ArcPtr
,NewMhd
.HeadSize
-MainHeadSize
,SEEK_CUR
);
523 (*(DWORD
*)list
) = (DWORD
)NULL
; /* init file list */
524 /* do while file is not extracted and there's no error */
527 if (ReadBlock(FILE_HEAD
| READSUBBLOCK
) <= 0) /* read name of the next */
528 { /* file within the RAR archive */
529 debug_log("Couldn't read next filename from archive (I/O error).");
530 break; /* error, file not found in */
531 } /* archive or I/O error */
532 if (BlockHead
.HeadType
==SUB_HEAD
)
534 debug_log("Sorry, sub-headers not supported.");
535 break; /* error => exit */
538 if((void*)(*(DWORD
*)list
) == NULL
) /* first entry */
540 tmp_List
= malloc(sizeof(ArchiveList_struct
));
541 tmp_List
->next
= NULL
;
543 (*(DWORD
*)list
) = (DWORD
)tmp_List
;
545 } else /* add entry */
547 tmp_List
->next
= malloc(sizeof(ArchiveList_struct
));
548 tmp_List
= (ArchiveList_struct
*) tmp_List
->next
;
549 tmp_List
->next
= NULL
;
552 tmp_List
->item
.Name
= malloc(NewLhd
.NameSize
+ 1);
553 strcpy(tmp_List
->item
.Name
, ArcFileName
);
554 tmp_List
->item
.NameSize
= NewLhd
.NameSize
;
555 tmp_List
->item
.PackSize
= NewLhd
.PackSize
;
556 tmp_List
->item
.UnpSize
= NewLhd
.UnpSize
;
557 tmp_List
->item
.HostOS
= NewLhd
.HostOS
;
558 tmp_List
->item
.FileCRC
= NewLhd
.FileCRC
;
559 tmp_List
->item
.FileTime
= NewLhd
.FileTime
;
560 tmp_List
->item
.UnpVer
= NewLhd
.UnpVer
;
561 tmp_List
->item
.Method
= NewLhd
.Method
;
562 tmp_List
->item
.FileAttr
= NewLhd
.FileAttr
;
564 NoOfFilesInArchive
++; /* count files */
566 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
567 MemRARFile
->offset
= NextBlockPos
;
569 if (ArcPtr
!=NULL
) tseek(ArcPtr
,NextBlockPos
,SEEK_SET
);
574 /* free memory, clear password and close archive */
575 memset(Password
,0,sizeof(Password
)); /* clear password */
576 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
583 free(UnpMemory
); /* free memory */
590 return NoOfFilesInArchive
;
596 * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
597 * and Johannes Winkelmann who independently wrote a patch)
598 * free the memory of a ArchiveList_struct created by urarlib_list.
600 * input: *list pointer to an ArchiveList_struct
604 void urarlib_freelist(ArchiveList_struct
*list
)
606 ArchiveList_struct
* tmp
= list
;
610 free( list
->item
.Name
);
617 /* ------------------------------------------------------------------------ */
635 /****************************************************************************
636 ****************************************************************************
637 ****************************************************************************
638 ****************************************************************************
642 ******* B L O C K I / O *******
646 ****************************************************************************
647 ****************************************************************************
648 ****************************************************************************
649 ****************************************************************************/
653 #define GetHeaderByte(N) Header[N]
655 #define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
657 #define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
658 ((UDWORD)Header[N+2]<<16)+\
659 ((UDWORD)Header[N+3]<<24))
662 int ReadBlock(int BlockType
)
664 struct NewFileHeader SaveFileHead
;
665 int Size
=0,ReadSubBlock
=0;
666 static int LastBlock
;
667 memcpy(&SaveFileHead
,&NewLhd
,sizeof(SaveFileHead
));
668 if (BlockType
& READSUBBLOCK
)
674 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
675 CurBlockPos
=MemRARFile
->offset
; /* get offset of mem-file */
677 CurBlockPos
=ftell(ArcPtr
);
679 Size
=ReadHeader(FILE_HEAD
);
682 if (NewLhd
.HeadSize
<SIZEOF_SHORTBLOCKHEAD
)
684 NextBlockPos
=CurBlockPos
+NewLhd
.HeadSize
;
685 if (NewLhd
.Flags
& LONG_BLOCK
)
686 NextBlockPos
+=NewLhd
.PackSize
;
687 if (NextBlockPos
<=CurBlockPos
)
691 if (Size
> 0 && BlockType
!=SUB_HEAD
)
693 if (Size
==0 || BlockType
==ALL_HEAD
|| NewLhd
.HeadType
==BlockType
||
694 (NewLhd
.HeadType
==SUB_HEAD
&& ReadSubBlock
&& LastBlock
==BlockType
))
696 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
697 MemRARFile
->offset
= NextBlockPos
;
699 tseek(ArcPtr
, NextBlockPos
, SEEK_SET
);
704 BlockHead
.HeadCRC
=NewLhd
.HeadCRC
;
705 BlockHead
.HeadType
=NewLhd
.HeadType
;
706 BlockHead
.Flags
=NewLhd
.Flags
;
707 BlockHead
.HeadSize
=NewLhd
.HeadSize
;
708 BlockHead
.DataSize
=NewLhd
.PackSize
;
710 if (BlockType
!=NewLhd
.HeadType
) BlockType
=ALL_HEAD
;
712 if((FILE_HEAD
== BlockType
) && (Size
>0))
714 ArcFileName
=realloc(ArcFileName
,NewLhd
.NameSize
+1);
715 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
716 tread(MemRARFile
, ArcFileName
, NewLhd
.NameSize
);
718 tread(ArcPtr
,ArcFileName
,NewLhd
.NameSize
);
720 ArcFileName
[NewLhd
.NameSize
]=0;
722 if (NewLhd
.HeadCRC
!=(UWORD
)~CalcCRC32(HeaderCRC
,(UBYTE
*)&ArcFileName
[0],
725 debug_log("file header broken");
728 Size
+=NewLhd
.NameSize
;
731 memcpy(&NewLhd
,&SaveFileHead
,sizeof(NewLhd
));
732 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
733 MemRARFile
->offset
= CurBlockPos
;
735 tseek(ArcPtr
,CurBlockPos
,SEEK_SET
);
744 int ReadHeader(int BlockType
)
747 unsigned char Header
[64];
751 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
752 Size
=tread(MemRARFile
, Header
, SIZEOF_NEWMHD
);
754 Size
=tread(ArcPtr
,Header
,SIZEOF_NEWMHD
);
756 NewMhd
.HeadCRC
=(unsigned short)GetHeaderWord(0);
757 NewMhd
.HeadType
=GetHeaderByte(2);
758 NewMhd
.Flags
=(unsigned short)GetHeaderWord(3);
759 NewMhd
.HeadSize
=(unsigned short)GetHeaderWord(5);
760 NewMhd
.Reserved
=(unsigned short)GetHeaderWord(7);
761 NewMhd
.Reserved1
=GetHeaderDword(9);
762 HeaderCRC
=CalcCRC32(0xFFFFFFFFL
,&Header
[2],SIZEOF_NEWMHD
-2);
765 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
766 Size
=tread(MemRARFile
, Header
, SIZEOF_NEWLHD
);
768 Size
=tread(ArcPtr
,Header
,SIZEOF_NEWLHD
);
770 NewLhd
.HeadCRC
=(unsigned short)GetHeaderWord(0);
771 NewLhd
.HeadType
=GetHeaderByte(2);
772 NewLhd
.Flags
=(unsigned short)GetHeaderWord(3);
773 NewLhd
.HeadSize
=(unsigned short)GetHeaderWord(5);
774 NewLhd
.PackSize
=GetHeaderDword(7);
775 NewLhd
.UnpSize
=GetHeaderDword(11);
776 NewLhd
.HostOS
=GetHeaderByte(15);
777 NewLhd
.FileCRC
=GetHeaderDword(16);
778 NewLhd
.FileTime
=GetHeaderDword(20);
779 NewLhd
.UnpVer
=GetHeaderByte(24);
780 NewLhd
.Method
=GetHeaderByte(25);
781 NewLhd
.NameSize
=(unsigned short)GetHeaderWord(26);
782 NewLhd
.FileAttr
=GetHeaderDword(28);
783 HeaderCRC
=CalcCRC32(0xFFFFFFFFL
,&Header
[2],SIZEOF_NEWLHD
-2);
787 case COMM_HEAD
: /* log errors in case of debug */
788 debug_log("Comment headers not supported! "\
789 "Please create archives without comments.");
792 debug_log("Protected headers not supported!");
795 debug_log("ShortBlockHeader not supported!");
798 debug_log("Unknown//unsupported !");
800 default: /* else do nothing */
807 /* **************************************************************************
808 ****************************************************************************
809 ****************************************************************************
810 ************************************************************************** */
828 /* **************************************************************************
829 ****************************************************************************
830 ****************************************************************************
831 ****************************************************************************
835 ******* E X T R A C T L O O P *******
839 ****************************************************************************
840 ****************************************************************************
841 ****************************************************************************
842 ************************************************************************** */
848 int str_offs
; /* used for debug-strings */
849 char DebugMsg
[500]; /* used to compose debug msg */
852 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
853 if (tread(MemRARFile
, MarkHead
.Mark
, SIZEOF_MARKHEAD
) != SIZEOF_MARKHEAD
)
856 if (tread(ArcPtr
,MarkHead
.Mark
,SIZEOF_MARKHEAD
)!=SIZEOF_MARKHEAD
)
859 /* Old archive => error */
860 if (MarkHead
.Mark
[0]==0x52 && MarkHead
.Mark
[1]==0x45 &&
861 MarkHead
.Mark
[2]==0x7e && MarkHead
.Mark
[3]==0x5e)
863 debug_log("Attention: format as OLD detected! Can't handel archive!");
866 /* original RAR v2.0 */
867 if ((MarkHead
.Mark
[0]==0x52 && MarkHead
.Mark
[1]==0x61 && /* original */
868 MarkHead
.Mark
[2]==0x72 && MarkHead
.Mark
[3]==0x21 && /* RAR header*/
869 MarkHead
.Mark
[4]==0x1a && MarkHead
.Mark
[5]==0x07 &&
870 MarkHead
.Mark
[6]==0x00) ||
871 /* "UniquE!" - header */
872 (MarkHead
.Mark
[0]=='U' && MarkHead
.Mark
[1]=='n' && /* "UniquE!" */
873 MarkHead
.Mark
[2]=='i' && MarkHead
.Mark
[3]=='q' && /* header */
874 MarkHead
.Mark
[4]=='u' && MarkHead
.Mark
[5]=='E' &&
875 MarkHead
.Mark
[6]=='!'))
878 if (ReadHeader(MAIN_HEAD
)!=SIZEOF_NEWMHD
)
884 /* sorry for this ugly code, but older SunOS gcc compilers don't */
885 /* support white spaces within strings */
886 str_offs
= sprintf(DebugMsg
, "unknown archive type (only plain RAR ");
887 str_offs
+= sprintf(DebugMsg
+ str_offs
, "supported (normal and solid ");
888 str_offs
+= sprintf(DebugMsg
+ str_offs
, "archives), SFX and Volumes ");
889 str_offs
+= sprintf(DebugMsg
+ str_offs
, "are NOT supported!)");
897 MainHeadSize
=SIZEOF_NEWMHD
;
905 BOOL ReturnCode
=TRUE
;
906 FileFound
=FALSE
; /* no file found by default */
908 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
909 MemRARFile
->offset
= 0; /* start reading from offset 0 */
912 debug_log("Not a RAR file");
913 return FALSE
; /* error => exit! */
917 /* open and identify archive */
918 if ((ArcPtr
=fopen(ArcName
,READBINARY
))!=NULL
)
922 debug_log("Not a RAR file");
925 return FALSE
; /* error => exit! */
929 debug_log("Error opening file.");
935 if ((UnpMemory
=malloc(UNP_MEMORY
))==NULL
)
937 debug_log("Can't allocate memory for decompression!");
941 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
942 MemRARFile
->offset
+=NewMhd
.HeadSize
-MainHeadSize
;
944 tseek(ArcPtr
,NewMhd
.HeadSize
-MainHeadSize
,SEEK_CUR
);
947 /* do while file is not extracted and there's no error */
951 if (ReadBlock(FILE_HEAD
| READSUBBLOCK
) <= 0) /* read name of the next */
952 { /* file within the RAR archive */
955 * 21.11.2000 UnQ There's a problem with some linux distros when a file
956 * can not be found in an archive.
958 * debug_log("Couldn't read next filename from archive (I/O error).");
962 break; /* error, file not found in */
963 } /* archive or I/O error */
964 if (BlockHead
.HeadType
==SUB_HEAD
)
966 debug_log("Sorry, sub-headers not supported.");
968 break; /* error => exit */
972 if(TRUE
== (FileFound
=(my_stricomp(ArgName
, ArcFileName
) == 0)))
973 /* *** file found! *** */
976 temp_output_buffer
=malloc(NewLhd
.UnpSize
);/* allocate memory for the*/
978 *temp_output_buffer_offset
=0; /* file. The default offset */
979 /* within the buffer is 0 */
981 if(temp_output_buffer
== NULL
)
983 debug_log("can't allocate memory for the file decompression");
985 break; /* error, can't extract file! */
991 /* in case of a solid archive, we need to decompress any single file till
992 * we have found the one we are looking for. In case of normal archives
993 * (recommended!!), we skip the files until we are sure that it is the
996 if((NewMhd
.Flags
& 0x08) || FileFound
)
998 if (NewLhd
.UnpVer
<13 || NewLhd
.UnpVer
>UNP_VER
)
1000 debug_log("unknown compression method");
1002 break; /* error, can't extract file! */
1005 CurUnpRead
=CurUnpWrite
=0;
1006 if ((*Password
!=0) && (NewLhd
.Flags
& LHD_PASSWORD
))
1007 Encryption
=NewLhd
.UnpVer
;
1010 if (Encryption
) SetCryptKeys(Password
);
1012 UnpPackedSize
=NewLhd
.PackSize
;
1013 DestUnpSize
=NewLhd
.UnpSize
;
1015 if (NewLhd
.Method
==0x30)
1025 #ifdef _DO_CRC32_CHECK /* calculate CRC32 */
1026 if((UBYTE
*)temp_output_buffer
!= NULL
)
1028 if(NewLhd
.FileCRC
!=~CalcCRC32(0xFFFFFFFFL
,
1029 (UBYTE
*)temp_output_buffer
,
1032 debug_log("CRC32 error - file couldn't be decompressed correctly!");
1034 break; /* error, can't extract file! */
1041 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1042 MemRARFile
->offset
= NextBlockPos
;
1044 if (ArcPtr
!=NULL
) tseek(ArcPtr
,NextBlockPos
,SEEK_SET
);
1046 } while(my_stricomp(ArgName
, ArcFileName
) != 0);/* exit if file is extracted */
1048 /* free memory, clear password and close archive */
1051 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1058 return ReturnCode
; /* file extracted successful! */
1061 /* **************************************************************************
1062 ****************************************************************************
1063 ****************************************************************************
1064 ************************************************************************** */
1083 /* **************************************************************************
1084 ****************************************************************************
1085 ****************************************************************************
1086 ****************************************************************************
1090 ******* G L O B A L F U N C T I O N S *******
1094 ****************************************************************************
1095 ****************************************************************************
1096 ****************************************************************************
1097 ************************************************************************** */
1100 int tread(void *stream
,void *buf
,unsigned len
)
1102 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1104 if(((MemRARFile
->offset
+ len
) > MemRARFile
->size
) || (len
== 0))
1108 (BYTE
*)(((MemoryFile
*)stream
)->data
)+((MemoryFile
*)stream
)->offset
,
1109 len
% ((((MemoryFile
*)stream
)->size
) - 1));
1111 MemRARFile
->offset
+=len
; /* update read pointer */
1112 return len
% ((((MemoryFile
*)stream
)->size
) - 1);
1114 return(fread(buf
,1,len
,(FILE*)stream
));
1119 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1120 int tseek(void *stream
,long offset
,int fromwhere
)
1122 return(fseek((FILE*)stream
,offset
,fromwhere
));
1127 static char* my_strupper(char *Str
)
1130 for (ChPtr
=Str
;*ChPtr
;ChPtr
++)
1131 *ChPtr
=(char)toupper(*ChPtr
);
1136 static int my_stricomp(char *Str1
,char *Str2
)
1137 /* compare strings without regard of '\' and '/' */
1139 char S1
[512],S2
[512];
1142 strncpy(S1
,Str1
,sizeof(S1
));
1143 strncpy(S2
,Str2
,sizeof(S2
));
1145 while((chptr
= strchr(S1
, '\\')) != NULL
) /* ignore backslash */
1150 while((chptr
= strchr(S2
, '\\')) != NULL
) /* ignore backslash */
1155 while((chptr
= strchr(S1
, '/')) != NULL
) /* ignore slash */
1160 while((chptr
= strchr(S2
, '/')) != NULL
) /* ignore slash */
1165 return(strcmp(my_strupper(S1
),my_strupper(S2
)));
1169 /* **************************************************************************
1170 ****************************************************************************
1171 ****************************************************************************
1172 ************************************************************************** */
1191 /* **************************************************************************
1192 ****************************************************************************
1193 ****************************************************************************
1194 ****************************************************************************
1198 ******* U N P A C K C O D E *******
1202 ****************************************************************************
1203 ****************************************************************************
1204 ****************************************************************************
1205 ************************************************************************** */
1208 /* *****************************
1209 * ** unpack stored RAR files **
1210 * *****************************/
1212 BOOL
UnstoreFile(void)
1214 if ((long)(*temp_output_buffer_offset
=UnpRead(temp_output_buffer
,
1215 NewLhd
.UnpSize
))==-1)
1217 debug_log("Read error of stored file!");
1226 /* ****************************************
1227 * ** RAR decompression code starts here **
1228 * ****************************************/
1230 #define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
1236 enum {CODE_HUFFMAN
=0,CODE_LZ
=1,CODE_LZ2
=2,CODE_REPEATLZ
=3,CODE_CACHELZ
=4,
1237 CODE_STARTFILE
=5,CODE_ENDFILE
=6,CODE_STARTMM
=8,CODE_ENDMM
=7,
1240 struct AudioVariables
1245 unsigned int Dif
[11];
1246 unsigned int ByteCount
;
1251 #define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
1258 struct AudioVariables AudV
[4];
1261 BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
1262 ( (UWORD) InBuf[InAddr+1] << 8 ) | \
1263 ( InBuf[InAddr+2] ) ) \
1264 >> (8-InBit) ) & 0xffff;
1267 #define AddBits(Bits) \
1268 InAddr += ( InBit + (Bits) ) >> 3; \
1269 InBit = ( InBit + (Bits) ) & 7;
1271 static unsigned char *UnpBuf
;
1272 static unsigned int BitField
;
1273 static unsigned int Number
;
1275 unsigned char InBuf
[8192]; /* input read buffer */
1277 unsigned char UnpOldTable
[MC
*4];
1279 unsigned int InAddr
,InBit
,ReadTop
;
1281 unsigned int LastDist
,LastLength
;
1282 static unsigned int Length
,Distance
;
1284 unsigned int OldDist
[4],OldDistPtr
;
1289 unsigned int MaxNum
;
1290 unsigned int DecodeLen
[16];
1291 unsigned int DecodePos
[16];
1292 unsigned int DecodeNum
[NC
];
1297 unsigned int MaxNum
;
1298 unsigned int DecodeLen
[16];
1299 unsigned int DecodePos
[16];
1300 unsigned int DecodeNum
[DC
];
1305 unsigned int MaxNum
;
1306 unsigned int DecodeLen
[16];
1307 unsigned int DecodePos
[16];
1308 unsigned int DecodeNum
[RC
];
1313 unsigned int MaxNum
;
1314 unsigned int DecodeLen
[16];
1315 unsigned int DecodePos
[16];
1316 unsigned int DecodeNum
[MC
];
1321 unsigned int MaxNum
;
1322 unsigned int DecodeLen
[16];
1323 unsigned int DecodePos
[16];
1324 unsigned int DecodeNum
[BC
];
1327 static struct MultDecode
*MDPtr
[4]={&MD
[0],&MD
[1],&MD
[2],&MD
[3]};
1329 int UnpAudioBlock
,UnpChannels
,CurChannel
,ChannelDelta
;
1332 void Unpack(unsigned char *UnpAddr
)
1333 /* *** 38.3% of all CPU time is spent within this function!!! */
1335 static unsigned char LDecode
[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
1336 40,48,56,64,80,96,112,128,160,192,224};
1337 static unsigned char LBits
[]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
1338 3,3,3,4,4,4,4,5,5,5,5};
1339 static int DDecode
[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
1340 512,768,1024,1536,2048,3072,4096,6144,8192,12288,
1341 16384,24576,32768U,49152U,65536,98304,131072,196608,
1342 262144,327680,393216,458752,524288,589824,655360,
1343 720896,786432,851968,917504,983040};
1344 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,
1345 9,10,10,11,11,12,12,13,13,14,14,15,15,16,
1346 16,16,16,16,16,16,16,16,16,16,16,16,16};
1347 static unsigned char SDDecode
[]={0,4,8,16,32,64,128,192};
1348 static unsigned char SDBits
[]={2,2,3, 4, 5, 6, 6, 6};
1352 UnpBuf
=UnpAddr
; /* UnpAddr is a pointer to the */
1353 UnpInitData(); /* unpack buffer */
1355 if (!(NewLhd
.Flags
& LHD_SOLID
))
1359 while (DestUnpSize
>=0)
1363 if (InAddr
>sizeof(InBuf
)-30)
1365 if (((WrPtr
-UnpPtr
) & MAXWINMASK
)<270 && WrPtr
!=UnpPtr
)
1374 if((*temp_output_buffer_offset
+ UnpPtr
) > NewLhd
.UnpSize
)
1376 debug_log("Fatal! Buffer overrun during decompression!");
1381 /* copy extracted data to output buffer */
1382 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
,
1383 &UnpBuf
[WrPtr
], (0-WrPtr
) & MAXWINMASK
);
1384 /* update offset within buffer */
1385 *temp_output_buffer_offset
+= (0-WrPtr
) & MAXWINMASK
;
1386 /* copy extracted data to output buffer */
1387 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, UnpBuf
,
1389 /* update offset within buffer */
1390 *temp_output_buffer_offset
+=UnpPtr
;
1394 if((*temp_output_buffer_offset
+ (UnpPtr
-WrPtr
)) > NewLhd
.UnpSize
)
1396 debug_log("Fatal! Buffer overrun during decompression!");
1400 /* copy extracted data to output buffer */
1401 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
,
1402 &UnpBuf
[WrPtr
], UnpPtr
-WrPtr
);
1403 *temp_output_buffer_offset
+=UnpPtr
-WrPtr
; /* update offset within buffer */
1414 DecodeNumber((struct Decode
*)MDPtr
[CurChannel
]);
1420 UnpBuf
[UnpPtr
++]=DecodeAudio(Number
);
1421 if (++CurChannel
==UnpChannels
)
1427 DecodeNumber((struct Decode
*)&LD
);
1430 UnpBuf
[UnpPtr
++]=(UBYTE
)Number
;
1436 Length
=LDecode
[Number
-=270]+3;
1437 if ((Bits
=LBits
[Number
])>0)
1440 Length
+=BitField
>>(16-Bits
);
1444 DecodeNumber((struct Decode
*)&DD
);
1445 Distance
=DDecode
[Number
]+1;
1446 if ((Bits
=DBits
[Number
])>0)
1449 Distance
+=BitField
>>(16-Bits
);
1453 if (Distance
>=0x40000L
)
1456 if (Distance
>=0x2000)
1459 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1460 DestUnpSize
-=(LastLength
=Length
);
1463 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1464 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1478 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1479 DestUnpSize
-=(LastLength
=Length
);
1482 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1483 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1489 Distance
=OldDist
[(OldDistPtr
-(Number
-256)) & 3];
1490 DecodeNumber((struct Decode
*)&RD
);
1491 Length
=LDecode
[Number
]+2;
1492 if ((Bits
=LBits
[Number
])>0)
1495 Length
+=BitField
>>(16-Bits
);
1498 if (Distance
>=0x40000)
1500 if (Distance
>=0x2000)
1502 if (Distance
>=0x101)
1504 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1505 DestUnpSize
-=(LastLength
=Length
);
1508 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1509 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1515 Distance
=SDDecode
[Number
-=261]+1;
1516 if ((Bits
=SDBits
[Number
])>0)
1519 Distance
+=BitField
>>(16-Bits
);
1523 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1524 DestUnpSize
-=(LastLength
=Length
);
1527 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1528 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1535 if (FileFound
) /* flush buffer */
1540 if((*temp_output_buffer_offset
+ UnpPtr
) > NewLhd
.UnpSize
)
1542 debug_log("Fatal! Buffer overrun during decompression!");
1546 /* copy extracted data to output buffer */
1547 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, &UnpBuf
[WrPtr
],
1548 (0-WrPtr
) & MAXWINMASK
);
1549 /* update offset within buffer */
1550 *temp_output_buffer_offset
+= (0-WrPtr
) & MAXWINMASK
;
1551 /* copy extracted data to output buffer */
1552 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, UnpBuf
, UnpPtr
);
1553 /* update offset within buffer */
1554 *temp_output_buffer_offset
+=UnpPtr
;
1558 if((*temp_output_buffer_offset
+ (UnpPtr
-WrPtr
)) > NewLhd
.UnpSize
)
1560 debug_log("Fatal! Buffer overrun during decompression!");
1564 /* copy extracted data to output buffer */
1565 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, &UnpBuf
[WrPtr
],
1567 /* update offset within buffer */
1568 *temp_output_buffer_offset
+=UnpPtr
-WrPtr
;
1577 unsigned int UnpRead(unsigned char *Addr
,unsigned int Count
)
1580 unsigned int I
,ReadSize
,TotalRead
=0;
1581 unsigned char *ReadAddr
;
1585 ReadSize
=(unsigned int)((Count
>(unsigned long)UnpPackedSize
) ?
1586 (unsigned int)UnpPackedSize
: Count
);
1587 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1588 if(MemRARFile
->data
== NULL
)
1590 RetCode
=tread(MemRARFile
, ReadAddr
, ReadSize
);
1594 RetCode
=tread(ArcPtr
,ReadAddr
,ReadSize
);
1596 CurUnpRead
+=RetCode
;
1600 UnpPackedSize
-=RetCode
;
1610 debug_log("Old Crypt() not supported!");
1614 for (I
=0;I
<(unsigned int)RetCode
;I
+=16)
1615 DecryptBlock(&Addr
[I
]);
1623 void UnpReadBuf(int FirstBuf
)
1628 ReadTop
=UnpRead(InBuf
,sizeof(InBuf
));
1633 memcpy(InBuf
,&InBuf
[sizeof(InBuf
)-32],32);
1635 RetCode
=UnpRead(&InBuf
[32],sizeof(InBuf
)-32);
1644 void ReadTables(void)
1646 UBYTE BitLength
[BC
];
1647 unsigned char Table
[MC
*4];
1649 if (InAddr
>sizeof(InBuf
)-25)
1652 UnpAudioBlock
=(BitField
& 0x8000);
1654 if (!(BitField
& 0x4000))
1655 memset(UnpOldTable
,0,sizeof(UnpOldTable
));
1661 UnpChannels
=((BitField
>>12) & 3)+1;
1662 if (CurChannel
>=UnpChannels
)
1665 TableSize
=MC
*UnpChannels
;
1674 BitLength
[I
]=(UBYTE
)(BitField
>> 12);
1677 MakeDecodeTables(BitLength
,(struct Decode
*)&BD
,BC
);
1681 if (InAddr
>sizeof(InBuf
)-5)
1683 DecodeNumber((struct Decode
*)&BD
);
1686 Table
[I
]=(Number
+UnpOldTable
[I
]) & 0xf;
1693 N
=(BitField
>> 14)+3;
1695 while (N
-- > 0 && I
<TableSize
)
1697 Table
[I
]=Table
[I
-1];
1706 N
=(BitField
>> 13)+3;
1712 N
=(BitField
>> 9)+11;
1715 while (N
-- > 0 && I
<TableSize
)
1720 for (I
=0;I
<UnpChannels
;I
++)
1721 MakeDecodeTables(&Table
[I
*MC
],(struct Decode
*)MDPtr
[I
],MC
);
1724 MakeDecodeTables(&Table
[0],(struct Decode
*)&LD
,NC
);
1725 MakeDecodeTables(&Table
[NC
],(struct Decode
*)&DD
,DC
);
1726 MakeDecodeTables(&Table
[NC
+DC
],(struct Decode
*)&RD
,RC
);
1728 memcpy(UnpOldTable
,Table
,sizeof(UnpOldTable
));
1732 static void ReadLastTables(void)
1734 if (ReadTop
>=InAddr
+5)
1738 DecodeNumber((struct Decode
*)MDPtr
[CurChannel
]);
1744 DecodeNumber((struct Decode
*)&LD
);
1752 static void MakeDecodeTables(unsigned char *LenTab
,
1756 int LenCount
[16],TmpPos
[16],I
;
1758 memset(LenCount
,0,sizeof(LenCount
));
1759 for (I
=0;I
<Size
;I
++)
1760 LenCount
[LenTab
[I
] & 0xF]++;
1763 for (TmpPos
[0]=Dec
->DecodePos
[0]=Dec
->DecodeLen
[0]=0,N
=0,I
=1;I
<16;I
++)
1765 N
=2*(N
+LenCount
[I
]);
1769 Dec
->DecodeLen
[I
]=(unsigned int)M
;
1770 TmpPos
[I
]=Dec
->DecodePos
[I
]=Dec
->DecodePos
[I
-1]+LenCount
[I
-1];
1773 for (I
=0;I
<Size
;I
++)
1775 Dec
->DecodeNum
[TmpPos
[LenTab
[I
] & 0xF]++]=I
;
1780 static void DecodeNumber(struct Decode
*Deco
)
1781 /* *** 52.6% of all CPU time is spent within this function!!! */
1784 register unsigned int N
;
1793 mov eax
, BitField
// N=BitField & 0xFFFE;
1796 mov edx
, [Deco
] // EAX=N, EDX=Deco
1798 cmp eax
, dword ptr
[edx
+ 8*4 + 4]// if (N<Dec->DecodeLen[8])
1801 cmp eax
, dword ptr
[edx
+ 4*4 + 4]// if (N<Dec->DecodeLen[4])
1805 cmp eax
, dword ptr
[edx
+ 2*4 + 4]// if (N<Dec->DecodeLen[2])
1808 cmp eax
, dword ptr
[edx
+ 1*4 + 4]// if (N<Dec->DecodeLen[1])
1819 cmp eax
, dword ptr
[edx
+ 3*4 + 4]// if (N<Dec->DecodeLen[3])
1833 cmp eax
, dword ptr
[edx
+ 6*4 + 4]// if (N<Dec->DecodeLen[6])
1836 cmp eax
, dword ptr
[edx
+ 5*4 + 4]// if (N<Dec->DecodeLen[5])
1847 cmp eax
, dword ptr
[edx
+ 7*4 + 4]// if (N<Dec->DecodeLen[7])
1862 cmp eax
, dword ptr
[edx
+ 12*4 + 4] // if (N<Dec->DecodeLen[12])
1865 cmp eax
, dword ptr
[edx
+ 10*4 + 4]// if (N<Dec->DecodeLen[10])
1868 cmp eax
, dword ptr
[edx
+ 9*4 + 4]// if (N<Dec->DecodeLen[9])
1879 cmp eax
, dword ptr
[edx
+ 11*4 + 4]// if (N<Dec->DecodeLen[11])
1893 cmp eax
, dword ptr
[edx
+ 14*4 + 4]// if (N<Dec->DecodeLen[14])
1896 cmp eax
, dword ptr
[edx
+ 13*4 + 4]// if (N<Dec->DecodeLen[13])
1913 __asm__
__volatile__ (
1914 "andl $0xFFFFFFFE, %%eax"
1916 " cmpl 8*4(%%edx), %%eax /* 5379 */"
1919 " cmpl 4*4(%%edx), %%eax"
1922 " cmpl 2*4(%%edx), %%eax"
1925 " cmpl 1*4(%%edx), %%eax"
1937 " cmpl 3*4(%%edx), %%eax "
1950 " cmpl 6*4(%%edx), %%eax"
1953 " cmpl 5*4(%%edx), %%eax"
1964 " cmpl 7*4(%%edx), %%eax"
1979 " cmpl 12*4(%%edx), %%eax"
1982 " cmpl 10*4(%%edx), %%eax"
1985 " cmpl 9*4(%%edx), %%eax"
1996 " cmpl 11*4(%%edx), %%eax"
2011 " cmpl 14*4(%%edx), %%eax"
2014 " cmpl 13*4(%%edx), %%eax"
2030 : "eax" ((long)BitField
), "edx"((long)Deco
->DecodeLen
)
2033 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
2036 N
=BitField
& 0xFFFE;
2037 if (N
<Deco
->DecodeLen
[8]) {
2038 if (N
<Deco
->DecodeLen
[4]) {
2039 if (N
<Deco
->DecodeLen
[2]) {
2040 if (N
<Deco
->DecodeLen
[1])
2045 if (N
<Deco
->DecodeLen
[3])
2051 if (N
<Deco
->DecodeLen
[6]) {
2052 if (N
<Deco
->DecodeLen
[5])
2057 if (N
<Deco
->DecodeLen
[7])
2064 if (N
<Deco
->DecodeLen
[12]) {
2065 if (N
<Deco
->DecodeLen
[10]) {
2066 if (N
<Deco
->DecodeLen
[9])
2071 if (N
<Deco
->DecodeLen
[11])
2077 if (N
<Deco
->DecodeLen
[14]) {
2078 if (N
<Deco
->DecodeLen
[13])
2092 if ((N
=Deco
->DecodePos
[I
]+((N
-Deco
->DecodeLen
[I
-1])>>(16-I
)))>=Deco
->MaxNum
)
2094 Number
=Deco
->DecodeNum
[N
];
2101 if (!(NewLhd
.Flags
& LHD_SOLID
))
2103 ChannelDelta
=CurChannel
=0;
2107 #ifdef _WIN_32 /* Win32 with VisualC */
2114 cld
/* increment EDI and ESI */
2117 mov edi
, Offset AudV
2118 rep stosb
/* clear memory */
2120 mov ecx
, SIZE OldDist
2121 mov edi
, Offset OldDist
2122 rep stosb
/* clear memory */
2124 mov ecx
, SIZE UnpOldTable
2125 mov edi
, Offset UnpOldTable
2126 rep stosb
/* clear memory */
2145 memset(UnpBuf
,0,MAXWINSIZE
);
2148 #else /* unix/linux on i386 cpus */
2149 __asm__
__volatile (
2150 " cld /* increment EDI and ESI */"
2155 " stosb /* clear memory */"
2160 " stosb /* clear memory */"
2165 " stosb /* clear memory */"
2167 " movl $0, (OldDistPtr)"
2168 " movl $0, (LastDist)"
2169 " movl $0, (LastLength)"
2170 " movl $0, (UnpPtr)"
2172 " movl $0, (OldDistPtr)"
2173 " movl $0, (LastLength)"
2174 " movl $0, (LastDist)"
2175 " movl $0, (UnpPtr)"
2178 : "m" ((long)sizeof(AudV
)),
2180 "m" ((long)sizeof(OldDist
)),
2181 "m" ((long)OldDist
),
2182 "m" ((long)sizeof(UnpOldTable
)),
2183 "m" ((long)UnpOldTable
)
2184 : "memory", "edi", "eax", "ecx"
2186 memset(UnpBuf
,0,MAXWINSIZE
);
2189 #else /* unix/linux on non-i386 cpu */
2190 memset(AudV
,0,sizeof(AudV
));
2191 memset(OldDist
,0,sizeof(OldDist
));
2193 LastDist
=LastLength
=0;
2194 memset(UnpBuf
,0,MAXWINSIZE
);
2195 memset(UnpOldTable
,0,sizeof(UnpOldTable
));
2203 UBYTE
DecodeAudio(int Delta
)
2205 struct AudioVariables
*V
;
2207 unsigned int NumMinDif
,MinDif
;
2210 V
=&AudV
[CurChannel
];
2214 V
->D2
=V
->LastDelta
-V
->D1
;
2216 PCh
=8*V
->LastChar
+V
->K1
*V
->D1
+V
->K2
*V
->D2
+
2217 V
->K3
*V
->D3
+V
->K4
*V
->D4
+V
->K5
*ChannelDelta
;
2218 PCh
=(PCh
>>3) & 0xFF;
2222 I
=((signed char)Delta
)<<3;
2225 V
->Dif
[1]+=abs(I
-V
->D1
);
2226 V
->Dif
[2]+=abs(I
+V
->D1
);
2227 V
->Dif
[3]+=abs(I
-V
->D2
);
2228 V
->Dif
[4]+=abs(I
+V
->D2
);
2229 V
->Dif
[5]+=abs(I
-V
->D3
);
2230 V
->Dif
[6]+=abs(I
+V
->D3
);
2231 V
->Dif
[7]+=abs(I
-V
->D4
);
2232 V
->Dif
[8]+=abs(I
+V
->D4
);
2233 V
->Dif
[9]+=abs(I
-ChannelDelta
);
2234 V
->Dif
[10]+=abs(I
+ChannelDelta
);
2236 ChannelDelta
=V
->LastDelta
=(signed char)(Ch
-V
->LastChar
);
2239 if ((V
->ByteCount
& 0x1F)==0)
2244 for (I
=1;(unsigned int)I
<sizeof(V
->Dif
)/sizeof(V
->Dif
[0]);I
++)
2246 if (V
->Dif
[I
]<MinDif
)
2306 /* ***************************************************
2307 * ** CRCCrypt Code - decryption engine starts here **
2308 * ***************************************************/
2313 #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
2314 #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
2316 #define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
2317 ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
2318 ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
2319 ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
2324 UBYTE SubstTable
[256];
2325 UBYTE InitSubstTable
[256]={
2326 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
2327 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
2328 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
2329 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
2330 107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
2331 158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
2332 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
2333 164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
2334 207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
2335 122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
2336 131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
2337 224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
2338 118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
2339 161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
2340 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
2341 116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
2347 void EncryptBlock(UBYTE
*Buf
)
2351 UDWORD A
,B
,C
,D
,T
,TA
,TB
;
2352 #ifdef NON_INTEL_BYTE_ORDER
2353 A
=((UDWORD
)Buf
[0]|((UDWORD
)Buf
[1]<<8)|((UDWORD
)Buf
[2]<<16)|
2354 ((UDWORD
)Buf
[3]<<24))^Key
[0];
2355 B
=((UDWORD
)Buf
[4]|((UDWORD
)Buf
[5]<<8)|((UDWORD
)Buf
[6]<<16)|
2356 ((UDWORD
)Buf
[7]<<24))^Key
[1];
2357 C
=((UDWORD
)Buf
[8]|((UDWORD
)Buf
[9]<<8)|((UDWORD
)Buf
[10]<<16)|
2358 ((UDWORD
)Buf
[11]<<24))^Key
[2];
2359 D
=((UDWORD
)Buf
[12]|((UDWORD
)Buf
[13]<<8)|((UDWORD
)Buf
[14]<<16)|
2360 ((UDWORD
)Buf
[15]<<24))^Key
[3];
2363 BufPtr
=(UDWORD
*)Buf
;
2369 for(I
=0;I
<NROUNDS
;I
++)
2371 T
=((C
+rol(D
,11))^Key
[I
&3]);
2373 T
=((D
^rol(C
,17))+Key
[I
&3]);
2380 #ifdef NON_INTEL_BYTE_ORDER
2383 Buf
[1]=(UBYTE
)(C
>>8);
2384 Buf
[2]=(UBYTE
)(C
>>16);
2385 Buf
[3]=(UBYTE
)(C
>>24);
2388 Buf
[5]=(UBYTE
)(D
>>8);
2389 Buf
[6]=(UBYTE
)(D
>>16);
2390 Buf
[7]=(UBYTE
)(D
>>24);
2393 Buf
[9]=(UBYTE
)(A
>>8);
2394 Buf
[10]=(UBYTE
)(A
>>16);
2395 Buf
[11]=(UBYTE
)(A
>>24);
2398 Buf
[13]=(UBYTE
)(B
>>8);
2399 Buf
[14]=(UBYTE
)(B
>>16);
2400 Buf
[15]=(UBYTE
)(B
>>24);
2411 void DecryptBlock(UBYTE
*Buf
)
2415 UDWORD A
,B
,C
,D
,T
,TA
,TB
;
2416 #ifdef NON_INTEL_BYTE_ORDER
2417 A
=((UDWORD
)Buf
[0]|((UDWORD
)Buf
[1]<<8)|((UDWORD
)Buf
[2]<<16)|
2418 ((UDWORD
)Buf
[3]<<24))^Key
[0];
2419 B
=((UDWORD
)Buf
[4]|((UDWORD
)Buf
[5]<<8)|((UDWORD
)Buf
[6]<<16)|
2420 ((UDWORD
)Buf
[7]<<24))^Key
[1];
2421 C
=((UDWORD
)Buf
[8]|((UDWORD
)Buf
[9]<<8)|((UDWORD
)Buf
[10]<<16)|
2422 ((UDWORD
)Buf
[11]<<24))^Key
[2];
2423 D
=((UDWORD
)Buf
[12]|((UDWORD
)Buf
[13]<<8)|((UDWORD
)Buf
[14]<<16)|
2424 ((UDWORD
)Buf
[15]<<24))^Key
[3];
2427 BufPtr
=(UDWORD
*)Buf
;
2428 A
=BufPtr
[0]^Key
[0]; /* xxx may be this can be */
2429 B
=BufPtr
[1]^Key
[1]; /* optimized in assembler */
2433 memcpy(InBuf
,Buf
,sizeof(InBuf
));
2434 for(I
=NROUNDS
-1;I
>=0;I
--)
2436 T
=((C
+rol(D
,11))^Key
[I
&3]);
2438 T
=((D
^rol(C
,17))+Key
[I
&3]);
2445 #ifdef NON_INTEL_BYTE_ORDER
2448 Buf
[1]=(UBYTE
)(C
>>8);
2449 Buf
[2]=(UBYTE
)(C
>>16);
2450 Buf
[3]=(UBYTE
)(C
>>24);
2453 Buf
[5]=(UBYTE
)(D
>>8);
2454 Buf
[6]=(UBYTE
)(D
>>16);
2455 Buf
[7]=(UBYTE
)(D
>>24);
2458 Buf
[9]=(UBYTE
)(A
>>8);
2459 Buf
[10]=(UBYTE
)(A
>>16);
2460 Buf
[11]=(UBYTE
)(A
>>24);
2463 Buf
[13]=(UBYTE
)(B
>>8);
2464 Buf
[14]=(UBYTE
)(B
>>16);
2465 Buf
[15]=(UBYTE
)(B
>>24);
2476 void UpdKeys(UBYTE
*Buf
)
2481 Key
[0]^=CRCTab
[Buf
[I
]]; /* xxx may be I'll rewrite this */
2482 Key
[1]^=CRCTab
[Buf
[I
+1]]; /* in asm for speedup */
2483 Key
[2]^=CRCTab
[Buf
[I
+2]];
2484 Key
[3]^=CRCTab
[Buf
[I
+3]];
2488 void SetCryptKeys(char *Password
)
2490 unsigned int I
,J
,K
,PswLength
;
2491 unsigned char N1
,N2
;
2492 unsigned char Psw
[256];
2494 #if !defined _USE_ASM
2498 SetOldKeys(Password
);
2504 memset(Psw
,0,sizeof(Psw
));
2505 strcpy((char *)Psw
,Password
);
2506 PswLength
=strlen(Password
);
2507 memcpy(SubstTable
,InitSubstTable
,sizeof(SubstTable
));
2510 for (I
=0;I
<PswLength
;I
+=2)
2512 N2
=(unsigned char)CRCTab
[(Psw
[I
+1]+J
)&0xFF];
2513 for (K
=1, N1
=(unsigned char)CRCTab
[(Psw
[I
]-J
)&0xFF];
2514 (N1
!=N2
) && (N1
< 256); /* I had to add "&& (N1 < 256)", */
2515 N1
++, K
++) /* because the system crashed with */
2516 { /* encrypted RARs */
2522 mov ebx
, Offset SubstTable
2525 xor ecx
, ecx
// read SubstTable[N1]...
2528 mov al
, byte ptr
[ebx
]
2530 mov cl
, N1
// read SubstTable[(N1+I+K)&0xFF]...
2535 mov ah
, byte ptr
[edx
]
2537 mov byte ptr
[ebx
], ah
// and write back
2538 mov byte ptr
[edx
], al
2542 __asm__
__volatile__ (
2543 " xorl %%ecx, %%ecx"
2544 " movl %2, %%ecx /* ecx = N1 */"
2546 " addl %%ecx, %%ebx"
2550 " andl $0x000000FF, %%ecx"
2551 " addl %%ecx, %%edx"
2553 " movb (%%ebx), %%al"
2554 " movb (%%edx), %%ah"
2556 " movb %%ah, (%%ebx) /* and write back */"
2557 " movb %%al, (%%edx)"
2561 "ebx"((long)SubstTable
)
2568 /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
2570 SubstTable
[N1
]=SubstTable
[(N1
+I
+K
)&0xFF];
2571 SubstTable
[(N1
+I
+K
)&0xFF]=Ch
;
2575 for (I
=0;I
<PswLength
;I
+=16)
2576 EncryptBlock(&Psw
[I
]);
2580 void SetOldKeys(char *Password
)
2584 PswCRC
=CalcCRC32(0xFFFFFFFFL
,(UBYTE
*)Password
,strlen(Password
));
2585 OldKey
[0]=(UWORD
)PswCRC
;
2586 OldKey
[1]=(UWORD
)(PswCRC
>>16);
2587 OldKey
[2]=OldKey
[3]=0;
2589 while ((Ch
=*Password
)!=0)
2594 PN3
=(UBYTE
)rol(PN3
,1);
2595 OldKey
[2]^=((UWORD
)(Ch
^CRCTab
[Ch
]));
2596 OldKey
[3]+=((UWORD
)(Ch
+(CRCTab
[Ch
]>>16)));
2607 for (C
=I
,J
=0;J
<8;J
++)
2608 C
=(C
& 1) ? (C
>>1)^0xEDB88320L
: (C
>>1);
2614 UDWORD
CalcCRC32(UDWORD StartCRC
,UBYTE
*Addr
,UDWORD Size
)
2617 for (I
=0; I
<Size
; I
++)
2618 StartCRC
= CRCTab
[(UBYTE
)StartCRC
^ Addr
[I
]] ^ (StartCRC
>> 8);
2623 /* **************************************************************************
2624 ****************************************************************************
2625 ****************************************************************************
2626 ************************************************************************** */
2652 /* **************************************************************************
2653 ****************************************************************************
2654 ****************************************************************************
2655 ****************************************************************************
2659 ******* D E B U G F U N C T I O N S *******
2663 ****************************************************************************
2664 ****************************************************************************
2665 ****************************************************************************
2666 ************************************************************************** */
2670 /* -- global stuff -------------------------------------------------------- */
2671 char log_file_name
[256]; /* file name for the log file */
2672 DWORD debug_start_time
; /* starttime of debug */
2673 BOOL debug_started
= FALSE
; /* debug_log writes only if */
2675 /* ------------------------------------------------------------------------ */
2678 /* -- global functions ---------------------------------------------------- */
2679 void debug_init_proc(char *file_name
)
2680 /* Create/Rewrite a log file */
2683 char date
[] = __DATE__
;
2684 char time
[] = __TIME__
;
2686 debug_start_time
= GetTickCount(); /* get start time */
2687 strcpy(log_file_name
, file_name
); /* save file name */
2689 if((fp
= fopen(log_file_name
, CREATETEXT
)) != NULL
)
2691 debug_started
= TRUE
; /* enable debug */
2692 fprintf(fp
, "Debug log of UniquE's RARFileLib\n"\
2693 "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
2694 fprintf(fp
, "(executable compiled on %s at %s)\n\n", date
, time
);
2700 void debug_log_proc(char *text
, char *sourcefile
, int sourceline
)
2701 /* add a line to the log file */
2705 if(debug_started
== FALSE
) return; /* exit if not initialized */
2707 if((fp
= fopen(log_file_name
, APPENDTEXT
)) != NULL
) /* append to logfile */
2710 fprintf(fp
, " %8u ms (line %u in %s):\n - %s\n",
2711 (unsigned int)(GetTickCount() - debug_start_time
),
2712 sourceline
, sourcefile
, text
);
2717 /* ------------------------------------------------------------------------ */
2719 /* **************************************************************************
2720 ****************************************************************************
2721 ****************************************************************************
2722 ************************************************************************** */
2725 /* end of file urarlib.c */