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 UBYTE
*TempMemory
; /* temporary unpack-buffer */
301 char ArgName
[NM
]; /* current file in rar archive */
302 char ArcFileName
[NM
]; /* file to decompress */
304 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
305 MemoryFile
*MemRARFile
; /* pointer to RAR file in memory*/
307 char ArcName
[255]; /* RAR archive name */
308 FILE *ArcPtr
; /* input RAR file handler */
310 char Password
[255]; /* password to decrypt files */
312 unsigned char *temp_output_buffer
; /* extract files to this pointer*/
313 unsigned long *temp_output_buffer_offset
; /* size of temp. extract buffer */
315 BOOL FileFound
; /* TRUE=use current extracted */
316 /* data FALSE=throw data away, */
319 long CurBlockPos
,NextBlockPos
;
321 unsigned long CurUnpRead
, CurUnpWrite
;
328 unsigned int UnpWrSize
;
329 unsigned char *UnpWrAddr
;
330 unsigned int UnpPtr
,WrPtr
;
332 unsigned char PN1
,PN2
,PN3
;
333 unsigned short OldKey
[4];
337 /* function header definitions */
338 int ReadHeader(int BlockType
);
341 int tread(void *stream
,void *buf
,unsigned len
);
342 int tseek(void *stream
,long offset
,int fromwhere
);
343 BOOL
UnstoreFile(void);
345 int ReadBlock(int BlockType
);
346 unsigned int UnpRead(unsigned char *Addr
,unsigned int Count
);
347 void UnpInitData(void);
348 void Unpack(unsigned char *UnpAddr
);
349 UBYTE
DecodeAudio(int Delta
);
350 static void DecodeNumber(struct Decode
*Dec
);
351 void UpdKeys(UBYTE
*Buf
);
352 void SetCryptKeys(char *Password
);
353 void SetOldKeys(char *Password
);
354 void DecryptBlock(unsigned char *Buf
);
356 UDWORD
CalcCRC32(UDWORD StartCRC
,UBYTE
*Addr
,UDWORD Size
);
357 void UnpReadBuf(int FirstBuf
);
358 void ReadTables(void);
359 static void ReadLastTables(void);
360 static void MakeDecodeTables(unsigned char *LenTab
,
363 int 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 strcpy(ArgName
, filename
); /* set file(s) to extract */
397 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
398 MemRARFile
= rarfile
; /* set pointer to mem-RAR file */
400 strcpy(ArcName
, rarfile
); /* set RAR file name */
402 if(libpassword
!= NULL
)
403 strcpy(Password
, libpassword
); /* init password */
405 temp_output_buffer
= NULL
;
406 temp_output_buffer_offset
=size
; /* set size of the temp buffer */
409 sprintf(DebugMsg
, "Extracting >%s< from >%s< (password is >%s<)...",
410 filename
, (char*)rarfile
, libpassword
);
414 retcode
= ExtrFile(); /* unpack file now! */
416 memset(Password
,0,sizeof(Password
)); /* clear password */
418 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
425 free(UnpMemory
); /* free memory */
435 free(temp_output_buffer
); /* free memory and return NULL */
436 temp_output_buffer
=NULL
;
437 *(DWORD
*)output
=0; /* pointer on errors */
442 /* sorry for this ugly code, but older SunOS gcc compilers don't support */
443 /* white spaces within strings */
444 str_offs
= sprintf(DebugMsg
, "Error - couldn't extract ");
445 str_offs
+= sprintf(DebugMsg
+ str_offs
, ">%s<", filename
);
446 str_offs
+= sprintf(DebugMsg
+ str_offs
, " and allocated ");
447 str_offs
+= sprintf(DebugMsg
+ str_offs
, "%u Bytes", (unsigned int)*size
);
448 str_offs
+= sprintf(DebugMsg
+ str_offs
, " of unused memory!");
452 sprintf(DebugMsg
, "Extracted %u Bytes.", (unsigned int)*size
);
458 *(DWORD
*)output
=(DWORD
)temp_output_buffer
;/* return pointer for unpacked*/
465 int urarlib_list(void *rarfile
, ArchiveList_struct
*list
)
467 ArchiveList_struct
*tmp_List
= NULL
;
468 int NoOfFilesInArchive
= 0; /* number of files in archive */
471 if(debug_log_first_start
)
473 debug_log_first_start
=FALSE
; /* only create a new log file */
474 debug_init(_DEBUG_LOG_FILE
); /* on startup */
478 InitCRC(); /* init some vars */
480 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
481 MemRARFile
= rarfile
; /* assign pointer to RAR file */
482 MemRARFile
->offset
= 0;
485 debug_log("Not a RAR file");
486 return NoOfFilesInArchive
; /* error => exit! */
489 /* open and identify archive */
490 if ((ArcPtr
=fopen(rarfile
,READBINARY
))!=NULL
)
494 debug_log("Not a RAR file");
497 return NoOfFilesInArchive
; /* error => exit! */
501 debug_log("Error opening file.");
502 return NoOfFilesInArchive
;
506 if ((UnpMemory
=malloc(UNP_MEMORY
))==NULL
)
508 debug_log("Can't allocate memory for decompression!");
509 return NoOfFilesInArchive
;
512 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
513 MemRARFile
->offset
+=NewMhd
.HeadSize
-MainHeadSize
;
515 tseek(ArcPtr
,NewMhd
.HeadSize
-MainHeadSize
,SEEK_CUR
);
517 (*(DWORD
*)list
) = (DWORD
)NULL
; /* init file list */
518 /* do while file is not extracted and there's no error */
521 if (ReadBlock(FILE_HEAD
| READSUBBLOCK
) <= 0) /* read name of the next */
522 { /* file within the RAR archive */
523 debug_log("Couldn't read next filename from archive (I/O error).");
524 break; /* error, file not found in */
525 } /* archive or I/O error */
526 if (BlockHead
.HeadType
==SUB_HEAD
)
528 debug_log("Sorry, sub-headers not supported.");
529 break; /* error => exit */
532 if((void*)(*(DWORD
*)list
) == NULL
) /* first entry */
534 tmp_List
= malloc(sizeof(ArchiveList_struct
));
535 tmp_List
->next
= NULL
;
537 (*(DWORD
*)list
) = (DWORD
)tmp_List
;
539 } else /* add entry */
541 tmp_List
->next
= malloc(sizeof(ArchiveList_struct
));
542 tmp_List
= (ArchiveList_struct
*) tmp_List
->next
;
543 tmp_List
->next
= NULL
;
546 tmp_List
->item
.Name
= malloc(NewLhd
.NameSize
+ 1);
547 strcpy(tmp_List
->item
.Name
, ArcFileName
);
548 tmp_List
->item
.NameSize
= NewLhd
.NameSize
;
549 tmp_List
->item
.PackSize
= NewLhd
.PackSize
;
550 tmp_List
->item
.UnpSize
= NewLhd
.UnpSize
;
551 tmp_List
->item
.HostOS
= NewLhd
.HostOS
;
552 tmp_List
->item
.FileCRC
= NewLhd
.FileCRC
;
553 tmp_List
->item
.FileTime
= NewLhd
.FileTime
;
554 tmp_List
->item
.UnpVer
= NewLhd
.UnpVer
;
555 tmp_List
->item
.Method
= NewLhd
.Method
;
556 tmp_List
->item
.FileAttr
= NewLhd
.FileAttr
;
558 NoOfFilesInArchive
++; /* count files */
560 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
561 MemRARFile
->offset
= NextBlockPos
;
563 if (ArcPtr
!=NULL
) tseek(ArcPtr
,NextBlockPos
,SEEK_SET
);
568 /* free memory, clear password and close archive */
569 memset(Password
,0,sizeof(Password
)); /* clear password */
570 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
577 free(UnpMemory
); /* free memory */
584 return NoOfFilesInArchive
;
590 * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
591 * and Johannes Winkelmann who independently wrote a patch)
592 * free the memory of a ArchiveList_struct created by urarlib_list.
594 * input: *list pointer to an ArchiveList_struct
598 void urarlib_freelist(ArchiveList_struct
*list
)
600 ArchiveList_struct
* tmp
= list
;
604 free( list
->item
.Name
);
611 /* ------------------------------------------------------------------------ */
629 /****************************************************************************
630 ****************************************************************************
631 ****************************************************************************
632 ****************************************************************************
636 ******* B L O C K I / O *******
640 ****************************************************************************
641 ****************************************************************************
642 ****************************************************************************
643 ****************************************************************************/
647 #define GetHeaderByte(N) Header[N]
649 #define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
651 #define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
652 ((UDWORD)Header[N+2]<<16)+\
653 ((UDWORD)Header[N+3]<<24))
656 int ReadBlock(int BlockType
)
658 struct NewFileHeader SaveFileHead
;
659 int Size
=0,ReadSubBlock
=0;
660 static int LastBlock
;
661 memcpy(&SaveFileHead
,&NewLhd
,sizeof(SaveFileHead
));
662 if (BlockType
& READSUBBLOCK
)
668 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
669 CurBlockPos
=MemRARFile
->offset
; /* get offset of mem-file */
671 CurBlockPos
=ftell(ArcPtr
);
673 Size
=ReadHeader(FILE_HEAD
);
676 if (NewLhd
.HeadSize
<SIZEOF_SHORTBLOCKHEAD
)
678 NextBlockPos
=CurBlockPos
+NewLhd
.HeadSize
;
679 if (NewLhd
.Flags
& LONG_BLOCK
)
680 NextBlockPos
+=NewLhd
.PackSize
;
681 if (NextBlockPos
<=CurBlockPos
)
685 if (Size
> 0 && BlockType
!=SUB_HEAD
)
687 if (Size
==0 || BlockType
==ALL_HEAD
|| NewLhd
.HeadType
==BlockType
||
688 (NewLhd
.HeadType
==SUB_HEAD
&& ReadSubBlock
&& LastBlock
==BlockType
))
690 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
691 MemRARFile
->offset
= NextBlockPos
;
693 tseek(ArcPtr
, NextBlockPos
, SEEK_SET
);
698 BlockHead
.HeadCRC
=NewLhd
.HeadCRC
;
699 BlockHead
.HeadType
=NewLhd
.HeadType
;
700 BlockHead
.Flags
=NewLhd
.Flags
;
701 BlockHead
.HeadSize
=NewLhd
.HeadSize
;
702 BlockHead
.DataSize
=NewLhd
.PackSize
;
704 if (BlockType
!=NewLhd
.HeadType
) BlockType
=ALL_HEAD
;
706 if((FILE_HEAD
== BlockType
) && (Size
>0))
708 NewLhd
.NameSize
=Min(NewLhd
.NameSize
,sizeof(ArcFileName
)-1);
709 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
710 tread(MemRARFile
, ArcFileName
, NewLhd
.NameSize
);
712 tread(ArcPtr
,ArcFileName
,NewLhd
.NameSize
);
714 ArcFileName
[NewLhd
.NameSize
]=0;
716 if (NewLhd
.HeadCRC
!=(UWORD
)~CalcCRC32(HeaderCRC
,(UBYTE
*)&ArcFileName
[0],
719 debug_log("file header broken");
722 Size
+=NewLhd
.NameSize
;
725 memcpy(&NewLhd
,&SaveFileHead
,sizeof(NewLhd
));
726 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
727 MemRARFile
->offset
= CurBlockPos
;
729 tseek(ArcPtr
,CurBlockPos
,SEEK_SET
);
738 int ReadHeader(int BlockType
)
741 unsigned char Header
[64];
745 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
746 Size
=tread(MemRARFile
, Header
, SIZEOF_NEWMHD
);
748 Size
=tread(ArcPtr
,Header
,SIZEOF_NEWMHD
);
750 NewMhd
.HeadCRC
=(unsigned short)GetHeaderWord(0);
751 NewMhd
.HeadType
=GetHeaderByte(2);
752 NewMhd
.Flags
=(unsigned short)GetHeaderWord(3);
753 NewMhd
.HeadSize
=(unsigned short)GetHeaderWord(5);
754 NewMhd
.Reserved
=(unsigned short)GetHeaderWord(7);
755 NewMhd
.Reserved1
=GetHeaderDword(9);
756 HeaderCRC
=CalcCRC32(0xFFFFFFFFL
,&Header
[2],SIZEOF_NEWMHD
-2);
759 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
760 Size
=tread(MemRARFile
, Header
, SIZEOF_NEWLHD
);
762 Size
=tread(ArcPtr
,Header
,SIZEOF_NEWLHD
);
764 NewLhd
.HeadCRC
=(unsigned short)GetHeaderWord(0);
765 NewLhd
.HeadType
=GetHeaderByte(2);
766 NewLhd
.Flags
=(unsigned short)GetHeaderWord(3);
767 NewLhd
.HeadSize
=(unsigned short)GetHeaderWord(5);
768 NewLhd
.PackSize
=GetHeaderDword(7);
769 NewLhd
.UnpSize
=GetHeaderDword(11);
770 NewLhd
.HostOS
=GetHeaderByte(15);
771 NewLhd
.FileCRC
=GetHeaderDword(16);
772 NewLhd
.FileTime
=GetHeaderDword(20);
773 NewLhd
.UnpVer
=GetHeaderByte(24);
774 NewLhd
.Method
=GetHeaderByte(25);
775 NewLhd
.NameSize
=(unsigned short)GetHeaderWord(26);
776 NewLhd
.FileAttr
=GetHeaderDword(28);
777 HeaderCRC
=CalcCRC32(0xFFFFFFFFL
,&Header
[2],SIZEOF_NEWLHD
-2);
781 case COMM_HEAD
: /* log errors in case of debug */
782 debug_log("Comment headers not supported! "\
783 "Please create archives without comments.");
786 debug_log("Protected headers not supported!");
789 debug_log("ShortBlockHeader not supported!");
792 debug_log("Unknown//unsupported !");
794 default: /* else do nothing */
801 /* **************************************************************************
802 ****************************************************************************
803 ****************************************************************************
804 ************************************************************************** */
822 /* **************************************************************************
823 ****************************************************************************
824 ****************************************************************************
825 ****************************************************************************
829 ******* E X T R A C T L O O P *******
833 ****************************************************************************
834 ****************************************************************************
835 ****************************************************************************
836 ************************************************************************** */
842 int str_offs
; /* used for debug-strings */
843 char DebugMsg
[500]; /* used to compose debug msg */
846 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
847 if (tread(MemRARFile
, MarkHead
.Mark
, SIZEOF_MARKHEAD
) != SIZEOF_MARKHEAD
)
850 if (tread(ArcPtr
,MarkHead
.Mark
,SIZEOF_MARKHEAD
)!=SIZEOF_MARKHEAD
)
853 /* Old archive => error */
854 if (MarkHead
.Mark
[0]==0x52 && MarkHead
.Mark
[1]==0x45 &&
855 MarkHead
.Mark
[2]==0x7e && MarkHead
.Mark
[3]==0x5e)
857 debug_log("Attention: format as OLD detected! Can't handel archive!");
860 /* original RAR v2.0 */
861 if ((MarkHead
.Mark
[0]==0x52 && MarkHead
.Mark
[1]==0x61 && /* original */
862 MarkHead
.Mark
[2]==0x72 && MarkHead
.Mark
[3]==0x21 && /* RAR header*/
863 MarkHead
.Mark
[4]==0x1a && MarkHead
.Mark
[5]==0x07 &&
864 MarkHead
.Mark
[6]==0x00) ||
865 /* "UniquE!" - header */
866 (MarkHead
.Mark
[0]=='U' && MarkHead
.Mark
[1]=='n' && /* "UniquE!" */
867 MarkHead
.Mark
[2]=='i' && MarkHead
.Mark
[3]=='q' && /* header */
868 MarkHead
.Mark
[4]=='u' && MarkHead
.Mark
[5]=='E' &&
869 MarkHead
.Mark
[6]=='!'))
872 if (ReadHeader(MAIN_HEAD
)!=SIZEOF_NEWMHD
)
878 /* sorry for this ugly code, but older SunOS gcc compilers don't */
879 /* support white spaces within strings */
880 str_offs
= sprintf(DebugMsg
, "unknown archive type (only plain RAR ");
881 str_offs
+= sprintf(DebugMsg
+ str_offs
, "supported (normal and solid ");
882 str_offs
+= sprintf(DebugMsg
+ str_offs
, "archives), SFX and Volumes ");
883 str_offs
+= sprintf(DebugMsg
+ str_offs
, "are NOT supported!)");
891 MainHeadSize
=SIZEOF_NEWMHD
;
899 BOOL ReturnCode
=TRUE
;
900 FileFound
=FALSE
; /* no file found by default */
902 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
903 MemRARFile
->offset
= 0; /* start reading from offset 0 */
906 debug_log("Not a RAR file");
907 return FALSE
; /* error => exit! */
911 /* open and identify archive */
912 if ((ArcPtr
=fopen(ArcName
,READBINARY
))!=NULL
)
916 debug_log("Not a RAR file");
919 return FALSE
; /* error => exit! */
923 debug_log("Error opening file.");
929 if ((UnpMemory
=malloc(UNP_MEMORY
))==NULL
)
931 debug_log("Can't allocate memory for decompression!");
935 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
936 MemRARFile
->offset
+=NewMhd
.HeadSize
-MainHeadSize
;
938 tseek(ArcPtr
,NewMhd
.HeadSize
-MainHeadSize
,SEEK_CUR
);
941 /* do while file is not extracted and there's no error */
945 if (ReadBlock(FILE_HEAD
| READSUBBLOCK
) <= 0) /* read name of the next */
946 { /* file within the RAR archive */
949 * 21.11.2000 UnQ There's a problem with some linux distros when a file
950 * can not be found in an archive.
952 * debug_log("Couldn't read next filename from archive (I/O error).");
956 break; /* error, file not found in */
957 } /* archive or I/O error */
958 if (BlockHead
.HeadType
==SUB_HEAD
)
960 debug_log("Sorry, sub-headers not supported.");
962 break; /* error => exit */
966 if(TRUE
== (FileFound
=(stricomp(ArgName
, ArcFileName
) == 0)))
967 /* *** file found! *** */
970 temp_output_buffer
=malloc(NewLhd
.UnpSize
);/* allocate memory for the*/
972 *temp_output_buffer_offset
=0; /* file. The default offset */
973 /* within the buffer is 0 */
975 if(temp_output_buffer
== NULL
)
977 debug_log("can't allocate memory for the file decompression");
979 break; /* error, can't extract file! */
985 /* in case of a solid archive, we need to decompress any single file till
986 * we have found the one we are looking for. In case of normal archives
987 * (recommended!!), we skip the files until we are sure that it is the
990 if((NewMhd
.Flags
& 0x08) || FileFound
)
992 if (NewLhd
.UnpVer
<13 || NewLhd
.UnpVer
>UNP_VER
)
994 debug_log("unknown compression method");
996 break; /* error, can't extract file! */
999 CurUnpRead
=CurUnpWrite
=0;
1000 if ((*Password
!=0) && (NewLhd
.Flags
& LHD_PASSWORD
))
1001 Encryption
=NewLhd
.UnpVer
;
1004 if (Encryption
) SetCryptKeys(Password
);
1006 UnpPackedSize
=NewLhd
.PackSize
;
1007 DestUnpSize
=NewLhd
.UnpSize
;
1009 if (NewLhd
.Method
==0x30)
1019 #ifdef _DO_CRC32_CHECK /* calculate CRC32 */
1020 if((UBYTE
*)temp_output_buffer
!= NULL
)
1022 if(NewLhd
.FileCRC
!=~CalcCRC32(0xFFFFFFFFL
,
1023 (UBYTE
*)temp_output_buffer
,
1026 debug_log("CRC32 error - file couldn't be decompressed correctly!");
1028 break; /* error, can't extract file! */
1035 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1036 MemRARFile
->offset
= NextBlockPos
;
1038 if (ArcPtr
!=NULL
) tseek(ArcPtr
,NextBlockPos
,SEEK_SET
);
1040 } while(stricomp(ArgName
, ArcFileName
) != 0);/* exit if file is extracted */
1042 /* free memory, clear password and close archive */
1045 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1052 return ReturnCode
; /* file extracted successful! */
1055 /* **************************************************************************
1056 ****************************************************************************
1057 ****************************************************************************
1058 ************************************************************************** */
1077 /* **************************************************************************
1078 ****************************************************************************
1079 ****************************************************************************
1080 ****************************************************************************
1084 ******* G L O B A L F U N C T I O N S *******
1088 ****************************************************************************
1089 ****************************************************************************
1090 ****************************************************************************
1091 ************************************************************************** */
1094 int tread(void *stream
,void *buf
,unsigned len
)
1096 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1098 if(((MemRARFile
->offset
+ len
) > MemRARFile
->size
) || (len
== 0))
1102 (BYTE
*)(((MemoryFile
*)stream
)->data
)+((MemoryFile
*)stream
)->offset
,
1103 len
% ((((MemoryFile
*)stream
)->size
) - 1));
1105 MemRARFile
->offset
+=len
; /* update read pointer */
1106 return len
% ((((MemoryFile
*)stream
)->size
) - 1);
1108 return(fread(buf
,1,len
,(FILE*)stream
));
1113 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1114 int tseek(void *stream
,long offset
,int fromwhere
)
1116 return(fseek((FILE*)stream
,offset
,fromwhere
));
1121 char* strupper(char *Str
)
1124 for (ChPtr
=Str
;*ChPtr
;ChPtr
++)
1125 *ChPtr
=(char)toupper(*ChPtr
);
1130 int stricomp(char *Str1
,char *Str2
)
1131 /* compare strings without regard of '\' and '/' */
1133 char S1
[512],S2
[512];
1136 strncpy(S1
,Str1
,sizeof(S1
));
1137 strncpy(S2
,Str2
,sizeof(S2
));
1139 while((chptr
= strchr(S1
, '\\')) != NULL
) /* ignore backslash */
1144 while((chptr
= strchr(S2
, '\\')) != NULL
) /* ignore backslash */
1149 while((chptr
= strchr(S1
, '/')) != NULL
) /* ignore slash */
1154 while((chptr
= strchr(S2
, '/')) != NULL
) /* ignore slash */
1159 return(strcmp(strupper(S1
),strupper(S2
)));
1163 /* **************************************************************************
1164 ****************************************************************************
1165 ****************************************************************************
1166 ************************************************************************** */
1185 /* **************************************************************************
1186 ****************************************************************************
1187 ****************************************************************************
1188 ****************************************************************************
1192 ******* U N P A C K C O D E *******
1196 ****************************************************************************
1197 ****************************************************************************
1198 ****************************************************************************
1199 ************************************************************************** */
1202 /* *****************************
1203 * ** unpack stored RAR files **
1204 * *****************************/
1206 BOOL
UnstoreFile(void)
1208 if ((long)(*temp_output_buffer_offset
=UnpRead(temp_output_buffer
,
1209 NewLhd
.UnpSize
))==-1)
1211 debug_log("Read error of stored file!");
1220 /* ****************************************
1221 * ** RAR decompression code starts here **
1222 * ****************************************/
1224 #define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
1230 enum {CODE_HUFFMAN
=0,CODE_LZ
=1,CODE_LZ2
=2,CODE_REPEATLZ
=3,CODE_CACHELZ
=4,
1231 CODE_STARTFILE
=5,CODE_ENDFILE
=6,CODE_STARTMM
=8,CODE_ENDMM
=7,
1234 struct AudioVariables
1239 unsigned int Dif
[11];
1240 unsigned int ByteCount
;
1245 #define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
1252 struct AudioVariables AudV
[4];
1255 BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
1256 ( (UWORD) InBuf[InAddr+1] << 8 ) | \
1257 ( InBuf[InAddr+2] ) ) \
1258 >> (8-InBit) ) & 0xffff;
1261 #define AddBits(Bits) \
1262 InAddr += ( InBit + (Bits) ) >> 3; \
1263 InBit = ( InBit + (Bits) ) & 7;
1265 static unsigned char *UnpBuf
;
1266 static unsigned int BitField
;
1267 static unsigned int Number
;
1269 unsigned char InBuf
[8192]; /* input read buffer */
1271 unsigned char UnpOldTable
[MC
*4];
1273 unsigned int InAddr
,InBit
,ReadTop
;
1275 unsigned int LastDist
,LastLength
;
1276 static unsigned int Length
,Distance
;
1278 unsigned int OldDist
[4],OldDistPtr
;
1283 unsigned int MaxNum
;
1284 unsigned int DecodeLen
[16];
1285 unsigned int DecodePos
[16];
1286 unsigned int DecodeNum
[NC
];
1291 unsigned int MaxNum
;
1292 unsigned int DecodeLen
[16];
1293 unsigned int DecodePos
[16];
1294 unsigned int DecodeNum
[DC
];
1299 unsigned int MaxNum
;
1300 unsigned int DecodeLen
[16];
1301 unsigned int DecodePos
[16];
1302 unsigned int DecodeNum
[RC
];
1307 unsigned int MaxNum
;
1308 unsigned int DecodeLen
[16];
1309 unsigned int DecodePos
[16];
1310 unsigned int DecodeNum
[MC
];
1315 unsigned int MaxNum
;
1316 unsigned int DecodeLen
[16];
1317 unsigned int DecodePos
[16];
1318 unsigned int DecodeNum
[BC
];
1321 static struct MultDecode
*MDPtr
[4]={&MD
[0],&MD
[1],&MD
[2],&MD
[3]};
1323 int UnpAudioBlock
,UnpChannels
,CurChannel
,ChannelDelta
;
1326 void Unpack(unsigned char *UnpAddr
)
1327 /* *** 38.3% of all CPU time is spent within this function!!! */
1329 static unsigned char LDecode
[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
1330 40,48,56,64,80,96,112,128,160,192,224};
1331 static unsigned char LBits
[]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
1332 3,3,3,4,4,4,4,5,5,5,5};
1333 static int DDecode
[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
1334 512,768,1024,1536,2048,3072,4096,6144,8192,12288,
1335 16384,24576,32768U,49152U,65536,98304,131072,196608,
1336 262144,327680,393216,458752,524288,589824,655360,
1337 720896,786432,851968,917504,983040};
1338 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,
1339 9,10,10,11,11,12,12,13,13,14,14,15,15,16,
1340 16,16,16,16,16,16,16,16,16,16,16,16,16};
1341 static unsigned char SDDecode
[]={0,4,8,16,32,64,128,192};
1342 static unsigned char SDBits
[]={2,2,3, 4, 5, 6, 6, 6};
1346 UnpBuf
=UnpAddr
; /* UnpAddr is a pointer to the */
1347 UnpInitData(); /* unpack buffer */
1349 if (!(NewLhd
.Flags
& LHD_SOLID
))
1353 while (DestUnpSize
>=0)
1357 if (InAddr
>sizeof(InBuf
)-30)
1359 if (((WrPtr
-UnpPtr
) & MAXWINMASK
)<270 && WrPtr
!=UnpPtr
)
1368 if((*temp_output_buffer_offset
+ UnpPtr
) > NewLhd
.UnpSize
)
1370 debug_log("Fatal! Buffer overrun during decompression!");
1375 /* copy extracted data to output buffer */
1376 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
,
1377 &UnpBuf
[WrPtr
], (0-WrPtr
) & MAXWINMASK
);
1378 /* update offset within buffer */
1379 *temp_output_buffer_offset
+= (0-WrPtr
) & MAXWINMASK
;
1380 /* copy extracted data to output buffer */
1381 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, UnpBuf
,
1383 /* update offset within buffer */
1384 *temp_output_buffer_offset
+=UnpPtr
;
1388 if((*temp_output_buffer_offset
+ (UnpPtr
-WrPtr
)) > NewLhd
.UnpSize
)
1390 debug_log("Fatal! Buffer overrun during decompression!");
1394 /* copy extracted data to output buffer */
1395 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
,
1396 &UnpBuf
[WrPtr
], UnpPtr
-WrPtr
);
1397 *temp_output_buffer_offset
+=UnpPtr
-WrPtr
; /* update offset within buffer */
1408 DecodeNumber((struct Decode
*)MDPtr
[CurChannel
]);
1414 UnpBuf
[UnpPtr
++]=DecodeAudio(Number
);
1415 if (++CurChannel
==UnpChannels
)
1421 DecodeNumber((struct Decode
*)&LD
);
1424 UnpBuf
[UnpPtr
++]=(UBYTE
)Number
;
1430 Length
=LDecode
[Number
-=270]+3;
1431 if ((Bits
=LBits
[Number
])>0)
1434 Length
+=BitField
>>(16-Bits
);
1438 DecodeNumber((struct Decode
*)&DD
);
1439 Distance
=DDecode
[Number
]+1;
1440 if ((Bits
=DBits
[Number
])>0)
1443 Distance
+=BitField
>>(16-Bits
);
1447 if (Distance
>=0x40000L
)
1450 if (Distance
>=0x2000)
1453 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1454 DestUnpSize
-=(LastLength
=Length
);
1457 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1458 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1472 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1473 DestUnpSize
-=(LastLength
=Length
);
1476 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1477 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1483 Distance
=OldDist
[(OldDistPtr
-(Number
-256)) & 3];
1484 DecodeNumber((struct Decode
*)&RD
);
1485 Length
=LDecode
[Number
]+2;
1486 if ((Bits
=LBits
[Number
])>0)
1489 Length
+=BitField
>>(16-Bits
);
1492 if (Distance
>=0x40000)
1494 if (Distance
>=0x2000)
1496 if (Distance
>=0x101)
1498 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1499 DestUnpSize
-=(LastLength
=Length
);
1502 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1503 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1509 Distance
=SDDecode
[Number
-=261]+1;
1510 if ((Bits
=SDBits
[Number
])>0)
1513 Distance
+=BitField
>>(16-Bits
);
1517 LastDist
=OldDist
[OldDistPtr
++ & 3]=Distance
;
1518 DestUnpSize
-=(LastLength
=Length
);
1521 UnpBuf
[UnpPtr
]=UnpBuf
[(UnpPtr
-Distance
) & MAXWINMASK
];
1522 UnpPtr
=(UnpPtr
+1) & MAXWINMASK
;
1529 if (FileFound
) /* flush buffer */
1534 if((*temp_output_buffer_offset
+ UnpPtr
) > NewLhd
.UnpSize
)
1536 debug_log("Fatal! Buffer overrun during decompression!");
1540 /* copy extracted data to output buffer */
1541 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, &UnpBuf
[WrPtr
],
1542 (0-WrPtr
) & MAXWINMASK
);
1543 /* update offset within buffer */
1544 *temp_output_buffer_offset
+= (0-WrPtr
) & MAXWINMASK
;
1545 /* copy extracted data to output buffer */
1546 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, UnpBuf
, UnpPtr
);
1547 /* update offset within buffer */
1548 *temp_output_buffer_offset
+=UnpPtr
;
1552 if((*temp_output_buffer_offset
+ (UnpPtr
-WrPtr
)) > NewLhd
.UnpSize
)
1554 debug_log("Fatal! Buffer overrun during decompression!");
1558 /* copy extracted data to output buffer */
1559 memcpy(temp_output_buffer
+ *temp_output_buffer_offset
, &UnpBuf
[WrPtr
],
1561 /* update offset within buffer */
1562 *temp_output_buffer_offset
+=UnpPtr
-WrPtr
;
1571 unsigned int UnpRead(unsigned char *Addr
,unsigned int Count
)
1574 unsigned int I
,ReadSize
,TotalRead
=0;
1575 unsigned char *ReadAddr
;
1579 ReadSize
=(unsigned int)((Count
>(unsigned long)UnpPackedSize
) ?
1580 UnpPackedSize
: Count
);
1581 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1582 if(MemRARFile
->data
== NULL
)
1584 RetCode
=tread(MemRARFile
, ReadAddr
, ReadSize
);
1588 RetCode
=tread(ArcPtr
,ReadAddr
,ReadSize
);
1590 CurUnpRead
+=RetCode
;
1594 UnpPackedSize
-=RetCode
;
1604 debug_log("Old Crypt() not supported!");
1608 for (I
=0;I
<(unsigned int)RetCode
;I
+=16)
1609 DecryptBlock(&Addr
[I
]);
1617 void UnpReadBuf(int FirstBuf
)
1622 ReadTop
=UnpRead(InBuf
,sizeof(InBuf
));
1627 memcpy(InBuf
,&InBuf
[sizeof(InBuf
)-32],32);
1629 RetCode
=UnpRead(&InBuf
[32],sizeof(InBuf
)-32);
1638 void ReadTables(void)
1640 UBYTE BitLength
[BC
];
1641 unsigned char Table
[MC
*4];
1643 if (InAddr
>sizeof(InBuf
)-25)
1646 UnpAudioBlock
=(BitField
& 0x8000);
1648 if (!(BitField
& 0x4000))
1649 memset(UnpOldTable
,0,sizeof(UnpOldTable
));
1655 UnpChannels
=((BitField
>>12) & 3)+1;
1656 if (CurChannel
>=UnpChannels
)
1659 TableSize
=MC
*UnpChannels
;
1668 BitLength
[I
]=(UBYTE
)(BitField
>> 12);
1671 MakeDecodeTables(BitLength
,(struct Decode
*)&BD
,BC
);
1675 if (InAddr
>sizeof(InBuf
)-5)
1677 DecodeNumber((struct Decode
*)&BD
);
1679 Table
[I
++]=(Number
+UnpOldTable
[I
]) & 0xf;
1684 N
=(BitField
>> 14)+3;
1686 while (N
-- > 0 && I
<TableSize
)
1688 Table
[I
]=Table
[I
-1];
1697 N
=(BitField
>> 13)+3;
1703 N
=(BitField
>> 9)+11;
1706 while (N
-- > 0 && I
<TableSize
)
1711 for (I
=0;I
<UnpChannels
;I
++)
1712 MakeDecodeTables(&Table
[I
*MC
],(struct Decode
*)MDPtr
[I
],MC
);
1715 MakeDecodeTables(&Table
[0],(struct Decode
*)&LD
,NC
);
1716 MakeDecodeTables(&Table
[NC
],(struct Decode
*)&DD
,DC
);
1717 MakeDecodeTables(&Table
[NC
+DC
],(struct Decode
*)&RD
,RC
);
1719 memcpy(UnpOldTable
,Table
,sizeof(UnpOldTable
));
1723 static void ReadLastTables(void)
1725 if (ReadTop
>=InAddr
+5)
1729 DecodeNumber((struct Decode
*)MDPtr
[CurChannel
]);
1735 DecodeNumber((struct Decode
*)&LD
);
1743 static void MakeDecodeTables(unsigned char *LenTab
,
1747 int LenCount
[16],TmpPos
[16],I
;
1749 memset(LenCount
,0,sizeof(LenCount
));
1750 for (I
=0;I
<Size
;I
++)
1751 LenCount
[LenTab
[I
] & 0xF]++;
1754 for (TmpPos
[0]=Dec
->DecodePos
[0]=Dec
->DecodeLen
[0]=0,N
=0,I
=1;I
<16;I
++)
1756 N
=2*(N
+LenCount
[I
]);
1760 Dec
->DecodeLen
[I
]=(unsigned int)M
;
1761 TmpPos
[I
]=Dec
->DecodePos
[I
]=Dec
->DecodePos
[I
-1]+LenCount
[I
-1];
1764 for (I
=0;I
<Size
;I
++)
1766 Dec
->DecodeNum
[TmpPos
[LenTab
[I
] & 0xF]++]=I
;
1771 static void DecodeNumber(struct Decode
*Deco
)
1772 /* *** 52.6% of all CPU time is spent within this function!!! */
1775 register unsigned int N
;
1784 mov eax
, BitField
// N=BitField & 0xFFFE;
1787 mov edx
, [Deco
] // EAX=N, EDX=Deco
1789 cmp eax
, dword ptr
[edx
+ 8*4 + 4]// if (N<Dec->DecodeLen[8])
1792 cmp eax
, dword ptr
[edx
+ 4*4 + 4]// if (N<Dec->DecodeLen[4])
1796 cmp eax
, dword ptr
[edx
+ 2*4 + 4]// if (N<Dec->DecodeLen[2])
1799 cmp eax
, dword ptr
[edx
+ 1*4 + 4]// if (N<Dec->DecodeLen[1])
1810 cmp eax
, dword ptr
[edx
+ 3*4 + 4]// if (N<Dec->DecodeLen[3])
1824 cmp eax
, dword ptr
[edx
+ 6*4 + 4]// if (N<Dec->DecodeLen[6])
1827 cmp eax
, dword ptr
[edx
+ 5*4 + 4]// if (N<Dec->DecodeLen[5])
1838 cmp eax
, dword ptr
[edx
+ 7*4 + 4]// if (N<Dec->DecodeLen[7])
1853 cmp eax
, dword ptr
[edx
+ 12*4 + 4] // if (N<Dec->DecodeLen[12])
1856 cmp eax
, dword ptr
[edx
+ 10*4 + 4]// if (N<Dec->DecodeLen[10])
1859 cmp eax
, dword ptr
[edx
+ 9*4 + 4]// if (N<Dec->DecodeLen[9])
1870 cmp eax
, dword ptr
[edx
+ 11*4 + 4]// if (N<Dec->DecodeLen[11])
1884 cmp eax
, dword ptr
[edx
+ 14*4 + 4]// if (N<Dec->DecodeLen[14])
1887 cmp eax
, dword ptr
[edx
+ 13*4 + 4]// if (N<Dec->DecodeLen[13])
1904 __asm__
__volatile__ (
1905 "andl $0xFFFFFFFE, %%eax"
1907 " cmpl 8*4(%%edx), %%eax /* 5379 */"
1910 " cmpl 4*4(%%edx), %%eax"
1913 " cmpl 2*4(%%edx), %%eax"
1916 " cmpl 1*4(%%edx), %%eax"
1928 " cmpl 3*4(%%edx), %%eax "
1941 " cmpl 6*4(%%edx), %%eax"
1944 " cmpl 5*4(%%edx), %%eax"
1955 " cmpl 7*4(%%edx), %%eax"
1970 " cmpl 12*4(%%edx), %%eax"
1973 " cmpl 10*4(%%edx), %%eax"
1976 " cmpl 9*4(%%edx), %%eax"
1987 " cmpl 11*4(%%edx), %%eax"
2002 " cmpl 14*4(%%edx), %%eax"
2005 " cmpl 13*4(%%edx), %%eax"
2021 : "eax" ((long)BitField
), "edx"((long)Deco
->DecodeLen
)
2024 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
2027 N
=BitField
& 0xFFFE;
2028 if (N
<Deco
->DecodeLen
[8]) {
2029 if (N
<Deco
->DecodeLen
[4]) {
2030 if (N
<Deco
->DecodeLen
[2]) {
2031 if (N
<Deco
->DecodeLen
[1])
2036 if (N
<Deco
->DecodeLen
[3])
2042 if (N
<Deco
->DecodeLen
[6]) {
2043 if (N
<Deco
->DecodeLen
[5])
2048 if (N
<Deco
->DecodeLen
[7])
2055 if (N
<Deco
->DecodeLen
[12]) {
2056 if (N
<Deco
->DecodeLen
[10]) {
2057 if (N
<Deco
->DecodeLen
[9])
2062 if (N
<Deco
->DecodeLen
[11])
2068 if (N
<Deco
->DecodeLen
[14]) {
2069 if (N
<Deco
->DecodeLen
[13])
2083 if ((N
=Deco
->DecodePos
[I
]+((N
-Deco
->DecodeLen
[I
-1])>>(16-I
)))>=Deco
->MaxNum
)
2085 Number
=Deco
->DecodeNum
[N
];
2092 if (!(NewLhd
.Flags
& LHD_SOLID
))
2094 ChannelDelta
=CurChannel
=0;
2098 #ifdef _WIN_32 /* Win32 with VisualC */
2105 cld
/* increment EDI and ESI */
2108 mov edi
, Offset AudV
2109 rep stosb
/* clear memory */
2111 mov ecx
, SIZE OldDist
2112 mov edi
, Offset OldDist
2113 rep stosb
/* clear memory */
2115 mov ecx
, SIZE UnpOldTable
2116 mov edi
, Offset UnpOldTable
2117 rep stosb
/* clear memory */
2136 memset(UnpBuf
,0,MAXWINSIZE
);
2139 #else /* unix/linux on i386 cpus */
2140 __asm__
__volatile (
2141 " cld /* increment EDI and ESI */"
2146 " stosb /* clear memory */"
2151 " stosb /* clear memory */"
2156 " stosb /* clear memory */"
2158 " movl $0, (OldDistPtr)"
2159 " movl $0, (LastDist)"
2160 " movl $0, (LastLength)"
2161 " movl $0, (UnpPtr)"
2163 " movl $0, (OldDistPtr)"
2164 " movl $0, (LastLength)"
2165 " movl $0, (LastDist)"
2166 " movl $0, (UnpPtr)"
2169 : "m" ((long)sizeof(AudV
)),
2171 "m" ((long)sizeof(OldDist
)),
2172 "m" ((long)OldDist
),
2173 "m" ((long)sizeof(UnpOldTable
)),
2174 "m" ((long)UnpOldTable
)
2175 : "memory", "edi", "eax", "ecx"
2177 memset(UnpBuf
,0,MAXWINSIZE
);
2180 #else /* unix/linux on non-i386 cpu */
2181 memset(AudV
,0,sizeof(AudV
));
2182 memset(OldDist
,0,sizeof(OldDist
));
2184 LastDist
=LastLength
=0;
2185 memset(UnpBuf
,0,MAXWINSIZE
);
2186 memset(UnpOldTable
,0,sizeof(UnpOldTable
));
2194 UBYTE
DecodeAudio(int Delta
)
2196 struct AudioVariables
*V
;
2198 unsigned int NumMinDif
,MinDif
;
2201 V
=&AudV
[CurChannel
];
2205 V
->D2
=V
->LastDelta
-V
->D1
;
2207 PCh
=8*V
->LastChar
+V
->K1
*V
->D1
+V
->K2
*V
->D2
+
2208 V
->K3
*V
->D3
+V
->K4
*V
->D4
+V
->K5
*ChannelDelta
;
2209 PCh
=(PCh
>>3) & 0xFF;
2213 I
=((signed char)Delta
)<<3;
2216 V
->Dif
[1]+=abs(I
-V
->D1
);
2217 V
->Dif
[2]+=abs(I
+V
->D1
);
2218 V
->Dif
[3]+=abs(I
-V
->D2
);
2219 V
->Dif
[4]+=abs(I
+V
->D2
);
2220 V
->Dif
[5]+=abs(I
-V
->D3
);
2221 V
->Dif
[6]+=abs(I
+V
->D3
);
2222 V
->Dif
[7]+=abs(I
-V
->D4
);
2223 V
->Dif
[8]+=abs(I
+V
->D4
);
2224 V
->Dif
[9]+=abs(I
-ChannelDelta
);
2225 V
->Dif
[10]+=abs(I
+ChannelDelta
);
2227 ChannelDelta
=V
->LastDelta
=(signed char)(Ch
-V
->LastChar
);
2230 if ((V
->ByteCount
& 0x1F)==0)
2235 for (I
=1;(unsigned int)I
<sizeof(V
->Dif
)/sizeof(V
->Dif
[0]);I
++)
2237 if (V
->Dif
[I
]<MinDif
)
2297 /* ***************************************************
2298 * ** CRCCrypt Code - decryption engine starts here **
2299 * ***************************************************/
2304 #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
2305 #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
2307 #define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
2308 ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
2309 ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
2310 ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
2315 UBYTE SubstTable
[256];
2316 UBYTE InitSubstTable
[256]={
2317 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
2318 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
2319 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
2320 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
2321 107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
2322 158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
2323 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
2324 164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
2325 207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
2326 122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
2327 131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
2328 224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
2329 118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
2330 161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
2331 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
2332 116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
2338 void EncryptBlock(UBYTE
*Buf
)
2342 UDWORD A
,B
,C
,D
,T
,TA
,TB
;
2343 #ifdef NON_INTEL_BYTE_ORDER
2344 A
=((UDWORD
)Buf
[0]|((UDWORD
)Buf
[1]<<8)|((UDWORD
)Buf
[2]<<16)|
2345 ((UDWORD
)Buf
[3]<<24))^Key
[0];
2346 B
=((UDWORD
)Buf
[4]|((UDWORD
)Buf
[5]<<8)|((UDWORD
)Buf
[6]<<16)|
2347 ((UDWORD
)Buf
[7]<<24))^Key
[1];
2348 C
=((UDWORD
)Buf
[8]|((UDWORD
)Buf
[9]<<8)|((UDWORD
)Buf
[10]<<16)|
2349 ((UDWORD
)Buf
[11]<<24))^Key
[2];
2350 D
=((UDWORD
)Buf
[12]|((UDWORD
)Buf
[13]<<8)|((UDWORD
)Buf
[14]<<16)|
2351 ((UDWORD
)Buf
[15]<<24))^Key
[3];
2354 BufPtr
=(UDWORD
*)Buf
;
2360 for(I
=0;I
<NROUNDS
;I
++)
2362 T
=((C
+rol(D
,11))^Key
[I
&3]);
2364 T
=((D
^rol(C
,17))+Key
[I
&3]);
2371 #ifdef NON_INTEL_BYTE_ORDER
2374 Buf
[1]=(UBYTE
)(C
>>8);
2375 Buf
[2]=(UBYTE
)(C
>>16);
2376 Buf
[3]=(UBYTE
)(C
>>24);
2379 Buf
[5]=(UBYTE
)(D
>>8);
2380 Buf
[6]=(UBYTE
)(D
>>16);
2381 Buf
[7]=(UBYTE
)(D
>>24);
2384 Buf
[9]=(UBYTE
)(A
>>8);
2385 Buf
[10]=(UBYTE
)(A
>>16);
2386 Buf
[11]=(UBYTE
)(A
>>24);
2389 Buf
[13]=(UBYTE
)(B
>>8);
2390 Buf
[14]=(UBYTE
)(B
>>16);
2391 Buf
[15]=(UBYTE
)(B
>>24);
2402 void DecryptBlock(UBYTE
*Buf
)
2406 UDWORD A
,B
,C
,D
,T
,TA
,TB
;
2407 #ifdef NON_INTEL_BYTE_ORDER
2408 A
=((UDWORD
)Buf
[0]|((UDWORD
)Buf
[1]<<8)|((UDWORD
)Buf
[2]<<16)|
2409 ((UDWORD
)Buf
[3]<<24))^Key
[0];
2410 B
=((UDWORD
)Buf
[4]|((UDWORD
)Buf
[5]<<8)|((UDWORD
)Buf
[6]<<16)|
2411 ((UDWORD
)Buf
[7]<<24))^Key
[1];
2412 C
=((UDWORD
)Buf
[8]|((UDWORD
)Buf
[9]<<8)|((UDWORD
)Buf
[10]<<16)|
2413 ((UDWORD
)Buf
[11]<<24))^Key
[2];
2414 D
=((UDWORD
)Buf
[12]|((UDWORD
)Buf
[13]<<8)|((UDWORD
)Buf
[14]<<16)|
2415 ((UDWORD
)Buf
[15]<<24))^Key
[3];
2418 BufPtr
=(UDWORD
*)Buf
;
2419 A
=BufPtr
[0]^Key
[0]; /* xxx may be this can be */
2420 B
=BufPtr
[1]^Key
[1]; /* optimized in assembler */
2424 memcpy(InBuf
,Buf
,sizeof(InBuf
));
2425 for(I
=NROUNDS
-1;I
>=0;I
--)
2427 T
=((C
+rol(D
,11))^Key
[I
&3]);
2429 T
=((D
^rol(C
,17))+Key
[I
&3]);
2436 #ifdef NON_INTEL_BYTE_ORDER
2439 Buf
[1]=(UBYTE
)(C
>>8);
2440 Buf
[2]=(UBYTE
)(C
>>16);
2441 Buf
[3]=(UBYTE
)(C
>>24);
2444 Buf
[5]=(UBYTE
)(D
>>8);
2445 Buf
[6]=(UBYTE
)(D
>>16);
2446 Buf
[7]=(UBYTE
)(D
>>24);
2449 Buf
[9]=(UBYTE
)(A
>>8);
2450 Buf
[10]=(UBYTE
)(A
>>16);
2451 Buf
[11]=(UBYTE
)(A
>>24);
2454 Buf
[13]=(UBYTE
)(B
>>8);
2455 Buf
[14]=(UBYTE
)(B
>>16);
2456 Buf
[15]=(UBYTE
)(B
>>24);
2467 void UpdKeys(UBYTE
*Buf
)
2472 Key
[0]^=CRCTab
[Buf
[I
]]; /* xxx may be I'll rewrite this */
2473 Key
[1]^=CRCTab
[Buf
[I
+1]]; /* in asm for speedup */
2474 Key
[2]^=CRCTab
[Buf
[I
+2]];
2475 Key
[3]^=CRCTab
[Buf
[I
+3]];
2479 void SetCryptKeys(char *Password
)
2481 unsigned int I
,J
,K
,PswLength
;
2482 unsigned char N1
,N2
;
2483 unsigned char Psw
[256];
2485 #if !defined _USE_ASM
2489 SetOldKeys(Password
);
2495 memset(Psw
,0,sizeof(Psw
));
2496 strcpy((char *)Psw
,Password
);
2497 PswLength
=strlen(Password
);
2498 memcpy(SubstTable
,InitSubstTable
,sizeof(SubstTable
));
2501 for (I
=0;I
<PswLength
;I
+=2)
2503 N2
=(unsigned char)CRCTab
[(Psw
[I
+1]+J
)&0xFF];
2504 for (K
=1, N1
=(unsigned char)CRCTab
[(Psw
[I
]-J
)&0xFF];
2505 (N1
!=N2
) && (N1
< 256); /* I had to add "&& (N1 < 256)", */
2506 N1
++, K
++) /* because the system crashed with */
2507 { /* encrypted RARs */
2513 mov ebx
, Offset SubstTable
2516 xor ecx
, ecx
// read SubstTable[N1]...
2519 mov al
, byte ptr
[ebx
]
2521 mov cl
, N1
// read SubstTable[(N1+I+K)&0xFF]...
2526 mov ah
, byte ptr
[edx
]
2528 mov byte ptr
[ebx
], ah
// and write back
2529 mov byte ptr
[edx
], al
2533 __asm__
__volatile__ (
2534 " xorl %%ecx, %%ecx"
2535 " movl %2, %%ecx /* ecx = N1 */"
2537 " addl %%ecx, %%ebx"
2541 " andl $0x000000FF, %%ecx"
2542 " addl %%ecx, %%edx"
2544 " movb (%%ebx), %%al"
2545 " movb (%%edx), %%ah"
2547 " movb %%ah, (%%ebx) /* and write back */"
2548 " movb %%al, (%%edx)"
2552 "ebx"((long)SubstTable
)
2559 /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
2561 SubstTable
[N1
]=SubstTable
[(N1
+I
+K
)&0xFF];
2562 SubstTable
[(N1
+I
+K
)&0xFF]=Ch
;
2566 for (I
=0;I
<PswLength
;I
+=16)
2567 EncryptBlock(&Psw
[I
]);
2571 void SetOldKeys(char *Password
)
2575 PswCRC
=CalcCRC32(0xFFFFFFFFL
,(UBYTE
*)Password
,strlen(Password
));
2576 OldKey
[0]=(UWORD
)PswCRC
;
2577 OldKey
[1]=(UWORD
)(PswCRC
>>16);
2578 OldKey
[2]=OldKey
[3]=0;
2580 while ((Ch
=*Password
)!=0)
2585 PN3
=(UBYTE
)rol(PN3
,1);
2586 OldKey
[2]^=((UWORD
)(Ch
^CRCTab
[Ch
]));
2587 OldKey
[3]+=((UWORD
)(Ch
+(CRCTab
[Ch
]>>16)));
2598 for (C
=I
,J
=0;J
<8;J
++)
2599 C
=(C
& 1) ? (C
>>1)^0xEDB88320L
: (C
>>1);
2605 UDWORD
CalcCRC32(UDWORD StartCRC
,UBYTE
*Addr
,UDWORD Size
)
2608 for (I
=0; I
<Size
; I
++)
2609 StartCRC
= CRCTab
[(UBYTE
)StartCRC
^ Addr
[I
]] ^ (StartCRC
>> 8);
2614 /* **************************************************************************
2615 ****************************************************************************
2616 ****************************************************************************
2617 ************************************************************************** */
2643 /* **************************************************************************
2644 ****************************************************************************
2645 ****************************************************************************
2646 ****************************************************************************
2650 ******* D E B U G F U N C T I O N S *******
2654 ****************************************************************************
2655 ****************************************************************************
2656 ****************************************************************************
2657 ************************************************************************** */
2661 /* -- global stuff -------------------------------------------------------- */
2662 char log_file_name
[256]; /* file name for the log file */
2663 DWORD debug_start_time
; /* starttime of debug */
2664 BOOL debug_started
= FALSE
; /* debug_log writes only if */
2666 /* ------------------------------------------------------------------------ */
2669 /* -- global functions ---------------------------------------------------- */
2670 void debug_init_proc(char *file_name
)
2671 /* Create/Rewrite a log file */
2674 char date
[] = __DATE__
;
2675 char time
[] = __TIME__
;
2677 debug_start_time
= GetTickCount(); /* get start time */
2678 strcpy(log_file_name
, file_name
); /* save file name */
2680 if((fp
= fopen(log_file_name
, CREATETEXT
)) != NULL
)
2682 debug_started
= TRUE
; /* enable debug */
2683 fprintf(fp
, "Debug log of UniquE's RARFileLib\n"\
2684 "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
2685 fprintf(fp
, "(executable compiled on %s at %s)\n\n", date
, time
);
2691 void debug_log_proc(char *text
, char *sourcefile
, int sourceline
)
2692 /* add a line to the log file */
2696 if(debug_started
== FALSE
) return; /* exit if not initialized */
2698 if((fp
= fopen(log_file_name
, APPENDTEXT
)) != NULL
) /* append to logfile */
2701 fprintf(fp
, " %8u ms (line %u in %s):\n - %s\n",
2702 (unsigned int)(GetTickCount() - debug_start_time
),
2703 sourceline
, sourcefile
, text
);
2708 /* ------------------------------------------------------------------------ */
2710 /* **************************************************************************
2711 ****************************************************************************
2712 ****************************************************************************
2713 ************************************************************************** */
2716 /* end of file urarlib.c */