10l fix by Jindrich Makovicka
[mplayer/greg.git] / unrarlib.c
blobb965abb9ac9221ca8c64f1cc766806d070a9c073
1 /* ***************************************************************************
2 **
3 ** This file is part of the UniquE RAR File Library.
4 **
5 ** Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
6 ** UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
7 **
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
25 ** License.
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:
40 ** (C) Eugene Roshal
41 ** Modifications to a FileLib:
42 ** (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
43 ** Linux port:
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 -------------------------------------------------------- */
69 #ifdef _WIN_32
71 #include <windows.h> /* WIN32 definitions */
72 #include <stdio.h>
73 #include <string.h>
76 #define ENABLE_ACCESS
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
84 #define FM_LABEL 0x08
85 #define FM_DIREC 0x10
86 #define FM_ARCH 0x20
88 #define PATHDIVIDER "\\"
89 #define CPATHDIVIDER '\\'
90 #define MASKALL "*.*"
92 #define READBINARY "rb"
93 #define READTEXT "rt"
94 #define UPDATEBINARY "r+b"
95 #define CREATEBINARY "w+b"
96 #define CREATETEXT "w"
97 #define APPENDTEXT "at"
99 #endif
101 #ifdef _UNIX
103 #include <stdio.h> /* LINUX/UNIX definitions */
104 #include <stdlib.h>
105 #include <ctype.h>
106 #include <string.h>
108 #define ENABLE_ACCESS
110 #define HOST_OS UNIX
112 #define FM_LABEL 0x0000
113 #define FM_DIREC 0x4000
115 #define PATHDIVIDER "/"
116 #define CPATHDIVIDER '/'
117 #define MASKALL "*.*"
119 #define READBINARY "r"
120 #define READTEXT "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 */
130 typedef long DWORD;
131 typedef short BOOL;
132 #define TRUE 1
133 #define FALSE 0
136 #ifdef _DEBUG_LOG /* define macros for debugging */
137 #include <unistd.h>
138 #include <sys/time.h>
140 DWORD GetTickCount()
142 struct timeval tv;
143 gettimeofday( &tv, 0 );
144 return (tv.tv_usec / 1000);
146 #endif
148 #endif
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);
164 #else
165 #define debug_log(a); /* no debug this time */
166 #define debug_init(a); /* no debug this time */
167 #endif
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))
178 #define NM 260
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*/
192 #define UNP_VER 20
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
209 #define MHD_LOCK 4
210 #define MHD_PACK_COMMENT 16
211 #define MHD_AV 32
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
218 #define LHD_SOLID 16
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 };
237 struct MarkHeader
239 UBYTE Mark[7];
243 struct NewMainArchiveHeader
245 UWORD HeadCRC;
246 UBYTE HeadType;
247 UWORD Flags;
248 UWORD HeadSize;
249 UWORD Reserved;
250 UDWORD Reserved1;
254 struct NewFileHeader
256 UWORD HeadCRC;
257 UBYTE HeadType;
258 UWORD Flags;
259 UWORD HeadSize;
260 UDWORD PackSize;
261 UDWORD UnpSize;
262 UBYTE HostOS;
263 UDWORD FileCRC;
264 UDWORD FileTime;
265 UBYTE UnpVer;
266 UBYTE Method;
267 UWORD NameSize;
268 UDWORD FileAttr;
272 struct BlockHeader
274 UWORD HeadCRC;
275 UBYTE HeadType;
276 UWORD Flags;
277 UWORD HeadSize;
278 UDWORD DataSize;
282 struct Decode
284 unsigned int MaxNum;
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*/
306 #else
307 static char* ArcName = NULL; /* RAR archive name */
308 static FILE *ArcPtr; /* input RAR file handler */
309 #endif
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, */
317 /* wrong file */
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,
361 struct Decode *Dec,
362 int Size);
363 static int my_stricomp(char *Str1,char *Str2);
364 /* ------------------------------------------------------------------------ */
367 /* -- global functions ---------------------------------------------------- */
369 int urarlib_get(void *output,
370 unsigned long *size,
371 char *filename,
372 void *rarfile,
373 char *libpassword)
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;
382 #ifdef _DEBUG_LOG
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 */
392 #endif
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 */
400 #else
401 if(ArcName) free(ArcName);
402 ArcName = strdup(rarfile); /* set RAR file name */
403 #endif
404 if(Password) free(Password);
405 if(libpassword != NULL)
406 Password = strdup(libpassword); /* init password */
407 else
408 Password = strdup("");
410 temp_output_buffer = NULL;
411 temp_output_buffer_offset=size; /* set size of the temp buffer */
413 #ifdef _DEBUG_LOG
414 sprintf(DebugMsg, "Extracting >%s< from >%s< (password is >%s<)...",
415 filename, (char*)rarfile, libpassword);
416 debug_log(DebugMsg);
417 #endif
419 retcode = ExtrFile(); /* unpack file now! */
421 //memset(Password,0,sizeof(Password)); /* clear password */
423 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
424 if (ArcPtr!=NULL){
425 fclose(ArcPtr);
426 ArcPtr = NULL;
428 #endif
430 if(UnpMemory) free(UnpMemory); /* free memory */
431 if(TempMemory) free(TempMemory);
432 if(CommMemory) free(CommMemory);
433 UnpMemory=NULL;
434 TempMemory=NULL;
435 CommMemory=NULL;
438 if(retcode == FALSE)
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 */
444 *size=0;
445 #ifdef _DEBUG_LOG
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!");
456 } else
458 sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
460 debug_log(DebugMsg);
461 #else
463 #endif
464 *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
465 /* data */
467 return retcode;
471 int urarlib_list(void *rarfile, ArchiveList_struct *list)
473 ArchiveList_struct *tmp_List = NULL;
474 int NoOfFilesInArchive = 0; /* number of files in archive */
476 #ifdef _DEBUG_LOG
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 */
482 #endif
484 InitCRC(); /* init some vars */
486 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
487 MemRARFile = rarfile; /* assign pointer to RAR file */
488 MemRARFile->offset = 0;
489 if (!IsArchive())
491 debug_log("Not a RAR file");
492 return NoOfFilesInArchive; /* error => exit! */
494 #else
495 /* open and identify archive */
496 if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL)
498 if (!IsArchive())
500 debug_log("Not a RAR file");
501 fclose(ArcPtr);
502 ArcPtr = NULL;
503 return NoOfFilesInArchive; /* error => exit! */
506 else {
507 debug_log("Error opening file.");
508 return NoOfFilesInArchive;
510 #endif
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;
520 #else
521 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
522 #endif
523 (*(DWORD*)list) = (DWORD)NULL; /* init file list */
524 /* do while file is not extracted and there's no error */
525 while (TRUE)
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;
568 #else
569 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
570 #endif
574 /* free memory, clear password and close archive */
575 memset(Password,0,sizeof(Password)); /* clear password */
576 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
577 if (ArcPtr!=NULL){
578 fclose(ArcPtr);
579 ArcPtr = NULL;
581 #endif
583 free(UnpMemory); /* free memory */
584 free(TempMemory);
585 free(CommMemory);
586 UnpMemory=NULL;
587 TempMemory=NULL;
588 CommMemory=NULL;
590 return NoOfFilesInArchive;
595 /* urarlib_freelist:
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
601 * output: -
604 void urarlib_freelist(ArchiveList_struct *list)
606 ArchiveList_struct* tmp = list;
608 while ( list ) {
609 tmp = list->next;
610 free( list->item.Name );
611 free( list );
612 list = tmp;
617 /* ------------------------------------------------------------------------ */
635 /****************************************************************************
636 ****************************************************************************
637 ****************************************************************************
638 ****************************************************************************
639 ******* *******
640 ******* *******
641 ******* *******
642 ******* B L O C K I / O *******
643 ******* *******
644 ******* *******
645 ******* *******
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)
669 ReadSubBlock=1;
670 BlockType &= 0xff;
672 while (1)
674 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
675 CurBlockPos=MemRARFile->offset; /* get offset of mem-file */
676 #else
677 CurBlockPos=ftell(ArcPtr);
678 #endif
679 Size=ReadHeader(FILE_HEAD);
680 if (Size!=0)
682 if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
683 return(0);
684 NextBlockPos=CurBlockPos+NewLhd.HeadSize;
685 if (NewLhd.Flags & LONG_BLOCK)
686 NextBlockPos+=NewLhd.PackSize;
687 if (NextBlockPos<=CurBlockPos)
688 return(0);
691 if (Size > 0 && BlockType!=SUB_HEAD)
692 LastBlock=BlockType;
693 if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
694 (NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
695 break;
696 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
697 MemRARFile->offset = NextBlockPos;
698 #else
699 tseek(ArcPtr, NextBlockPos, SEEK_SET);
700 #endif
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);
717 #else
718 tread(ArcPtr,ArcFileName,NewLhd.NameSize);
719 #endif
720 ArcFileName[NewLhd.NameSize]=0;
721 #ifdef _DEBUG_LOG
722 if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
723 NewLhd.NameSize))
725 debug_log("file header broken");
727 #endif
728 Size+=NewLhd.NameSize;
729 } else
731 memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
732 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
733 MemRARFile->offset = CurBlockPos;
734 #else
735 tseek(ArcPtr,CurBlockPos,SEEK_SET);
736 #endif
740 return(Size);
744 int ReadHeader(int BlockType)
746 int Size = 0;
747 unsigned char Header[64];
748 switch(BlockType)
750 case MAIN_HEAD:
751 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
752 Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
753 #else
754 Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
755 #endif
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);
763 break;
764 case FILE_HEAD:
765 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
766 Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
767 #else
768 Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
769 #endif
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);
784 break;
786 #ifdef _DEBUG_LOG
787 case COMM_HEAD: /* log errors in case of debug */
788 debug_log("Comment headers not supported! "\
789 "Please create archives without comments.");
790 break;
791 case PROTECT_HEAD:
792 debug_log("Protected headers not supported!");
793 break;
794 case ALL_HEAD:
795 debug_log("ShortBlockHeader not supported!");
796 break;
797 default:
798 debug_log("Unknown//unsupported !");
799 #else
800 default: /* else do nothing */
801 break;
802 #endif
804 return(Size);
807 /* **************************************************************************
808 ****************************************************************************
809 ****************************************************************************
810 ************************************************************************** */
828 /* **************************************************************************
829 ****************************************************************************
830 ****************************************************************************
831 ****************************************************************************
832 ******* *******
833 ******* *******
834 ******* *******
835 ******* E X T R A C T L O O P *******
836 ******* *******
837 ******* *******
838 ******* *******
839 ****************************************************************************
840 ****************************************************************************
841 ****************************************************************************
842 ************************************************************************** */
845 int IsArchive(void)
847 #ifdef _DEBUG_LOG
848 int str_offs; /* used for debug-strings */
849 char DebugMsg[500]; /* used to compose debug msg */
850 #endif
852 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
853 if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD)
854 return(FALSE);
855 #else
856 if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
857 return(FALSE);
858 #endif
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!");
865 else
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)
879 return(FALSE);
880 } else
883 #ifdef _DEBUG_LOG
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!)");
891 debug_log(DebugMsg);
892 #endif
897 MainHeadSize=SIZEOF_NEWMHD;
899 return(TRUE);
903 BOOL ExtrFile(void)
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 */
910 if (!IsArchive())
912 debug_log("Not a RAR file");
913 return FALSE; /* error => exit! */
916 #else
917 /* open and identify archive */
918 if ((ArcPtr=fopen(ArcName,READBINARY))!=NULL)
920 if (!IsArchive())
922 debug_log("Not a RAR file");
923 fclose(ArcPtr);
924 ArcPtr = NULL;
925 return FALSE; /* error => exit! */
927 } else
929 debug_log("Error opening file.");
930 return FALSE;
932 #endif
935 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
937 debug_log("Can't allocate memory for decompression!");
938 return FALSE;
941 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
942 MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
943 #else
944 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
945 #endif
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).");
961 ReturnCode=FALSE;
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.");
967 ReturnCode=FALSE;
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");
984 ReturnCode=FALSE;
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
994 * one we want.
996 if((NewMhd.Flags & 0x08) || FileFound)
998 if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
1000 debug_log("unknown compression method");
1001 ReturnCode=FALSE;
1002 break; /* error, can't extract file! */
1005 CurUnpRead=CurUnpWrite=0;
1006 if ((*Password!=0) && (NewLhd.Flags & LHD_PASSWORD))
1007 Encryption=NewLhd.UnpVer;
1008 else
1009 Encryption=0;
1010 if (Encryption) SetCryptKeys(Password);
1012 UnpPackedSize=NewLhd.PackSize;
1013 DestUnpSize=NewLhd.UnpSize;
1015 if (NewLhd.Method==0x30)
1017 UnstoreFile();
1018 } else
1020 Unpack(UnpMemory);
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,
1030 NewLhd.UnpSize))
1032 debug_log("CRC32 error - file couldn't be decompressed correctly!");
1033 ReturnCode=FALSE;
1034 break; /* error, can't extract file! */
1037 #endif
1041 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1042 MemRARFile->offset = NextBlockPos;
1043 #else
1044 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
1045 #endif
1046 } while(my_stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */
1048 /* free memory, clear password and close archive */
1049 free(UnpMemory);
1050 UnpMemory=NULL;
1051 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1052 if (ArcPtr!=NULL){
1053 fclose(ArcPtr);
1054 ArcPtr = NULL;
1056 #endif
1058 return ReturnCode; /* file extracted successful! */
1061 /* **************************************************************************
1062 ****************************************************************************
1063 ****************************************************************************
1064 ************************************************************************** */
1083 /* **************************************************************************
1084 ****************************************************************************
1085 ****************************************************************************
1086 ****************************************************************************
1087 ******* *******
1088 ******* *******
1089 ******* *******
1090 ******* G L O B A L F U N C T I O N S *******
1091 ******* *******
1092 ******* *******
1093 ******* *******
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))
1105 return 0;
1107 memcpy(buf,
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);
1113 #else
1114 return(fread(buf,1,len,(FILE*)stream));
1115 #endif
1119 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1120 int tseek(void *stream,long offset,int fromwhere)
1122 return(fseek((FILE*)stream,offset,fromwhere));
1124 #endif
1127 static char* my_strupper(char *Str)
1129 char *ChPtr;
1130 for (ChPtr=Str;*ChPtr;ChPtr++)
1131 *ChPtr=(char)toupper(*ChPtr);
1132 return(Str);
1136 static int my_stricomp(char *Str1,char *Str2)
1137 /* compare strings without regard of '\' and '/' */
1139 char S1[512],S2[512];
1140 char *chptr;
1142 strncpy(S1,Str1,sizeof(S1));
1143 strncpy(S2,Str2,sizeof(S2));
1145 while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash */
1147 *chptr = '_';
1150 while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash */
1152 *chptr = '_';
1155 while((chptr = strchr(S1, '/')) != NULL) /* ignore slash */
1157 *chptr = '_';
1160 while((chptr = strchr(S2, '/')) != NULL) /* ignore slash */
1162 *chptr = '_';
1165 return(strcmp(my_strupper(S1),my_strupper(S2)));
1169 /* **************************************************************************
1170 ****************************************************************************
1171 ****************************************************************************
1172 ************************************************************************** */
1191 /* **************************************************************************
1192 ****************************************************************************
1193 ****************************************************************************
1194 ****************************************************************************
1195 ******* *******
1196 ******* *******
1197 ******* *******
1198 ******* U N P A C K C O D E *******
1199 ******* *******
1200 ******* *******
1201 ******* *******
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!");
1218 return FALSE;
1220 return TRUE;
1226 /* ****************************************
1227 * ** RAR decompression code starts here **
1228 * ****************************************/
1230 #define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
1231 #define DC 48
1232 #define RC 28
1233 #define BC 19
1234 #define MC 257
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,
1238 CODE_MMDELTA=9};
1240 struct AudioVariables
1242 int K1,K2,K3,K4,K5;
1243 int D1,D2,D3,D4;
1244 int LastDelta;
1245 unsigned int Dif[11];
1246 unsigned int ByteCount;
1247 int LastChar;
1251 #define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
1252 #define DC 48
1253 #define RC 28
1254 #define BC 19
1255 #define MC 257
1258 struct AudioVariables AudV[4];
1260 #define GetBits() \
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;
1287 struct LitDecode
1289 unsigned int MaxNum;
1290 unsigned int DecodeLen[16];
1291 unsigned int DecodePos[16];
1292 unsigned int DecodeNum[NC];
1293 } LD;
1295 struct DistDecode
1297 unsigned int MaxNum;
1298 unsigned int DecodeLen[16];
1299 unsigned int DecodePos[16];
1300 unsigned int DecodeNum[DC];
1301 } DD;
1303 struct RepDecode
1305 unsigned int MaxNum;
1306 unsigned int DecodeLen[16];
1307 unsigned int DecodePos[16];
1308 unsigned int DecodeNum[RC];
1309 } RD;
1311 struct MultDecode
1313 unsigned int MaxNum;
1314 unsigned int DecodeLen[16];
1315 unsigned int DecodePos[16];
1316 unsigned int DecodeNum[MC];
1317 } MD[4];
1319 struct BitDecode
1321 unsigned int MaxNum;
1322 unsigned int DecodeLen[16];
1323 unsigned int DecodePos[16];
1324 unsigned int DecodeNum[BC];
1325 } BD;
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};
1349 unsigned int Bits;
1352 UnpBuf=UnpAddr; /* UnpAddr is a pointer to the */
1353 UnpInitData(); /* unpack buffer */
1354 UnpReadBuf(1);
1355 if (!(NewLhd.Flags & LHD_SOLID))
1356 ReadTables();
1357 DestUnpSize--;
1359 while (DestUnpSize>=0)
1361 UnpPtr&=MAXWINMASK;
1363 if (InAddr>sizeof(InBuf)-30)
1364 UnpReadBuf(0);
1365 if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
1369 if (FileFound)
1372 if (UnpPtr<WrPtr)
1374 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1376 debug_log("Fatal! Buffer overrun during decompression!");
1377 DestUnpSize=-1;
1379 } else
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,
1388 UnpPtr);
1389 /* update offset within buffer */
1390 *temp_output_buffer_offset+=UnpPtr;
1392 } else
1394 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1396 debug_log("Fatal! Buffer overrun during decompression!");
1397 DestUnpSize=-1;
1398 } else
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 */
1409 WrPtr=UnpPtr;
1412 if (UnpAudioBlock)
1414 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1415 if (Number==256)
1417 ReadTables();
1418 continue;
1420 UnpBuf[UnpPtr++]=DecodeAudio(Number);
1421 if (++CurChannel==UnpChannels)
1422 CurChannel=0;
1423 DestUnpSize--;
1424 continue;
1427 DecodeNumber((struct Decode *)&LD);
1428 if (Number<256)
1430 UnpBuf[UnpPtr++]=(UBYTE)Number;
1431 DestUnpSize--;
1432 continue;
1434 if (Number>269)
1436 Length=LDecode[Number-=270]+3;
1437 if ((Bits=LBits[Number])>0)
1439 GetBits();
1440 Length+=BitField>>(16-Bits);
1441 AddBits(Bits);
1444 DecodeNumber((struct Decode *)&DD);
1445 Distance=DDecode[Number]+1;
1446 if ((Bits=DBits[Number])>0)
1448 GetBits();
1449 Distance+=BitField>>(16-Bits);
1450 AddBits(Bits);
1453 if (Distance>=0x40000L)
1454 Length++;
1456 if (Distance>=0x2000)
1457 Length++;
1459 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1460 DestUnpSize-=(LastLength=Length);
1461 while (Length--)
1463 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1464 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1467 continue;
1469 if (Number==269)
1471 ReadTables();
1472 continue;
1474 if (Number==256)
1476 Length=LastLength;
1477 Distance=LastDist;
1478 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1479 DestUnpSize-=(LastLength=Length);
1480 while (Length--)
1482 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1483 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1485 continue;
1487 if (Number<261)
1489 Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
1490 DecodeNumber((struct Decode *)&RD);
1491 Length=LDecode[Number]+2;
1492 if ((Bits=LBits[Number])>0)
1494 GetBits();
1495 Length+=BitField>>(16-Bits);
1496 AddBits(Bits);
1498 if (Distance>=0x40000)
1499 Length++;
1500 if (Distance>=0x2000)
1501 Length++;
1502 if (Distance>=0x101)
1503 Length++;
1504 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1505 DestUnpSize-=(LastLength=Length);
1506 while (Length--)
1508 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1509 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1511 continue;
1513 if (Number<270)
1515 Distance=SDDecode[Number-=261]+1;
1516 if ((Bits=SDBits[Number])>0)
1518 GetBits();
1519 Distance+=BitField>>(16-Bits);
1520 AddBits(Bits);
1522 Length=2;
1523 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1524 DestUnpSize-=(LastLength=Length);
1525 while (Length--)
1527 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1528 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1530 continue;
1533 ReadLastTables();
1535 if (FileFound) /* flush buffer */
1538 if (UnpPtr<WrPtr)
1540 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1542 debug_log("Fatal! Buffer overrun during decompression!");
1543 DestUnpSize=-1;
1544 } else
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;
1556 } else
1558 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1560 debug_log("Fatal! Buffer overrun during decompression!");
1561 DestUnpSize=-1;
1562 } else
1564 /* copy extracted data to output buffer */
1565 memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
1566 UnpPtr-WrPtr);
1567 /* update offset within buffer */
1568 *temp_output_buffer_offset+=UnpPtr-WrPtr;
1573 WrPtr=UnpPtr;
1577 unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
1579 int RetCode=0;
1580 unsigned int I,ReadSize,TotalRead=0;
1581 unsigned char *ReadAddr;
1582 ReadAddr=Addr;
1583 while (Count > 0)
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)
1589 return(0);
1590 RetCode=tread(MemRARFile, ReadAddr, ReadSize);
1591 #else
1592 if (ArcPtr==NULL)
1593 return(0);
1594 RetCode=tread(ArcPtr,ReadAddr,ReadSize);
1595 #endif
1596 CurUnpRead+=RetCode;
1597 ReadAddr+=RetCode;
1598 TotalRead+=RetCode;
1599 Count-=RetCode;
1600 UnpPackedSize-=RetCode;
1601 break;
1603 if (RetCode!= -1)
1605 RetCode=TotalRead;
1606 if (Encryption)
1608 if (Encryption<20)
1610 debug_log("Old Crypt() not supported!");
1612 else
1614 for (I=0;I<(unsigned int)RetCode;I+=16)
1615 DecryptBlock(&Addr[I]);
1619 return(RetCode);
1623 void UnpReadBuf(int FirstBuf)
1625 int RetCode;
1626 if (FirstBuf)
1628 ReadTop=UnpRead(InBuf,sizeof(InBuf));
1629 InAddr=0;
1631 else
1633 memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
1634 InAddr&=0x1f;
1635 RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
1636 if (RetCode>0)
1637 ReadTop=RetCode+32;
1638 else
1639 ReadTop=InAddr;
1644 void ReadTables(void)
1646 UBYTE BitLength[BC];
1647 unsigned char Table[MC*4];
1648 int TableSize,N,I;
1649 if (InAddr>sizeof(InBuf)-25)
1650 UnpReadBuf(0);
1651 GetBits();
1652 UnpAudioBlock=(BitField & 0x8000);
1654 if (!(BitField & 0x4000))
1655 memset(UnpOldTable,0,sizeof(UnpOldTable));
1656 AddBits(2);
1659 if (UnpAudioBlock)
1661 UnpChannels=((BitField>>12) & 3)+1;
1662 if (CurChannel>=UnpChannels)
1663 CurChannel=0;
1664 AddBits(2);
1665 TableSize=MC*UnpChannels;
1667 else
1668 TableSize=NC+DC+RC;
1671 for (I=0;I<BC;I++)
1673 GetBits();
1674 BitLength[I]=(UBYTE)(BitField >> 12);
1675 AddBits(4);
1677 MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
1678 I=0;
1679 while (I<TableSize)
1681 if (InAddr>sizeof(InBuf)-5)
1682 UnpReadBuf(0);
1683 DecodeNumber((struct Decode *)&BD);
1684 if (Number<16)
1686 Table[I]=(Number+UnpOldTable[I]) & 0xf;
1687 I++;
1689 else
1690 if (Number==16)
1692 GetBits();
1693 N=(BitField >> 14)+3;
1694 AddBits(2);
1695 while (N-- > 0 && I<TableSize)
1697 Table[I]=Table[I-1];
1698 I++;
1701 else
1703 if (Number==17)
1705 GetBits();
1706 N=(BitField >> 13)+3;
1707 AddBits(3);
1709 else
1711 GetBits();
1712 N=(BitField >> 9)+11;
1713 AddBits(7);
1715 while (N-- > 0 && I<TableSize)
1716 Table[I++]=0;
1719 if (UnpAudioBlock)
1720 for (I=0;I<UnpChannels;I++)
1721 MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
1722 else
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)
1736 if (UnpAudioBlock)
1738 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1739 if (Number==256)
1740 ReadTables();
1742 else
1744 DecodeNumber((struct Decode *)&LD);
1745 if (Number==269)
1746 ReadTables();
1752 static void MakeDecodeTables(unsigned char *LenTab,
1753 struct Decode *Dec,
1754 int Size)
1756 int LenCount[16],TmpPos[16],I;
1757 long M,N;
1758 memset(LenCount,0,sizeof(LenCount));
1759 for (I=0;I<Size;I++)
1760 LenCount[LenTab[I] & 0xF]++;
1762 LenCount[0]=0;
1763 for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
1765 N=2*(N+LenCount[I]);
1766 M=N<<(15-I);
1767 if (M>0xFFFF)
1768 M=0xFFFF;
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++)
1774 if (LenTab[I]!=0)
1775 Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
1776 Dec->MaxNum=Size;
1780 static void DecodeNumber(struct Decode *Deco)
1781 /* *** 52.6% of all CPU time is spent within this function!!! */
1783 unsigned int I;
1784 register unsigned int N;
1785 GetBits();
1787 #ifdef _USE_ASM
1789 #ifdef _WIN_32
1790 __asm {
1792 xor eax, eax
1793 mov eax, BitField // N=BitField & 0xFFFE;
1794 and eax, 0xFFFFFFFE
1795 mov [N], eax
1796 mov edx, [Deco] // EAX=N, EDX=Deco
1798 cmp eax, dword ptr[edx + 8*4 + 4]// if (N<Dec->DecodeLen[8])
1799 jae else_G
1801 cmp eax, dword ptr[edx + 4*4 + 4]// if (N<Dec->DecodeLen[4])
1802 jae else_F
1805 cmp eax, dword ptr[edx + 2*4 + 4]// if (N<Dec->DecodeLen[2])
1806 jae else_C
1808 cmp eax, dword ptr[edx + 1*4 + 4]// if (N<Dec->DecodeLen[1])
1809 jae else_1
1810 mov I, 1 // I=1;
1811 jmp next_1
1812 else_1: // else
1813 mov I, 2 // I=2;
1814 next_1:
1816 jmp next_C
1817 else_C: // else
1819 cmp eax, dword ptr[edx + 3*4 + 4]// if (N<Dec->DecodeLen[3])
1820 jae else_2
1821 mov I, 3 // I=3;
1822 jmp next_2
1823 else_2: // else
1824 mov I, 4 // I=4;
1825 next_2:
1827 next_C: // else
1829 jmp next_F
1830 else_F:
1833 cmp eax, dword ptr[edx + 6*4 + 4]// if (N<Dec->DecodeLen[6])
1834 jae else_E
1836 cmp eax, dword ptr[edx + 5*4 + 4]// if (N<Dec->DecodeLen[5])
1837 jae else_3
1838 mov I, 5 // I=5;
1839 jmp next_3
1840 else_3: // else
1841 mov I, 6 // I=6;
1842 next_3:
1844 jmp next_E
1845 else_E: // else
1847 cmp eax, dword ptr[edx + 7*4 + 4]// if (N<Dec->DecodeLen[7])
1848 jae else_4
1849 mov I, 7 // I=7;
1850 jmp next_4
1851 else_4: // else
1852 mov I, 8 // I=8;
1853 next_4:
1855 next_E:
1857 next_F:
1859 jmp next_G
1860 else_G:
1862 cmp eax, dword ptr[edx + 12*4 + 4] // if (N<Dec->DecodeLen[12])
1863 jae else_D
1865 cmp eax, dword ptr[edx + 10*4 + 4]// if (N<Dec->DecodeLen[10])
1866 jae else_B
1868 cmp eax, dword ptr[edx + 9*4 + 4]// if (N<Dec->DecodeLen[9])
1869 jae else_5
1870 mov I, 9 // I=9;
1871 jmp next_5
1872 else_5: // else
1873 mov I, 10 // I=10;
1874 next_5:
1876 jmp next_B
1877 else_B: // else
1879 cmp eax, dword ptr[edx + 11*4 + 4]// if (N<Dec->DecodeLen[11])
1880 jae else_6
1881 mov I, 11 // I=11;
1882 jmp next_6
1883 else_6: // else
1884 mov I, 12 // I=12;
1885 next_6:
1887 next_B:
1890 jmp next_D
1891 else_D: // else
1893 cmp eax, dword ptr[edx + 14*4 + 4]// if (N<Dec->DecodeLen[14])
1894 jae else_A
1896 cmp eax, dword ptr[edx + 13*4 + 4]// if (N<Dec->DecodeLen[13])
1897 jae else_7
1898 mov I, 13 // I=13;
1899 jmp next_7
1900 else_7: // else
1901 mov I, 14 // I=14;
1902 next_7:
1904 jmp next_A
1905 else_A: // else
1906 mov I, 15 // I=15;
1907 next_A:
1909 next_D:
1910 next_G:
1912 #else
1913 __asm__ __volatile__ (
1914 "andl $0xFFFFFFFE, %%eax"
1915 " movl %%eax, %1"
1916 " cmpl 8*4(%%edx), %%eax /* 5379 */"
1917 " jae else_G"
1919 " cmpl 4*4(%%edx), %%eax"
1920 " jae else_F"
1922 " cmpl 2*4(%%edx), %%eax"
1923 " jae else_C"
1925 " cmpl 1*4(%%edx), %%eax"
1927 " jae else_1"
1928 " movl $1, %0"
1929 " jmp next_1"
1930 " else_1: "
1931 " movl $2, %0"
1932 " next_1:"
1934 " jmp next_C"
1935 " else_C: "
1937 " cmpl 3*4(%%edx), %%eax "
1938 " jae else_2"
1939 " movl $3, %0"
1940 " jmp next_2"
1941 " else_2: "
1942 " movl $4, %0"
1943 " next_2:"
1945 " next_C: "
1947 " jmp next_F"
1948 " else_F:"
1950 " cmpl 6*4(%%edx), %%eax"
1951 " jae else_E"
1953 " cmpl 5*4(%%edx), %%eax"
1954 " jae else_3"
1955 " movl $5, %0 "
1956 " jmp next_3"
1957 " else_3: "
1958 " movl $6, %0 "
1959 " next_3:"
1961 " jmp next_E"
1962 " else_E: "
1964 " cmpl 7*4(%%edx), %%eax"
1965 " jae else_4"
1966 " movl $7, %0 "
1967 " jmp next_4"
1968 " else_4: "
1969 " movl $8, %0 "
1970 " next_4:"
1972 " next_E:"
1974 " next_F:"
1976 " jmp next_G"
1977 " else_G:"
1979 " cmpl 12*4(%%edx), %%eax"
1980 " jae else_D"
1982 " cmpl 10*4(%%edx), %%eax"
1983 " jae else_B"
1985 " cmpl 9*4(%%edx), %%eax"
1986 " jae else_5"
1987 " movl $9, %0 "
1988 " jmp next_5"
1989 " else_5: "
1990 " movl $10, %0 "
1991 " next_5:"
1993 " jmp next_B"
1994 " else_B: "
1996 " cmpl 11*4(%%edx), %%eax"
1998 " jae else_6"
1999 " movl $11, %0 "
2000 " jmp next_6"
2001 " else_6: "
2002 " movl $12, %0 "
2003 " next_6:"
2005 " next_B:"
2008 " jmp next_D"
2009 " else_D: "
2011 " cmpl 14*4(%%edx), %%eax"
2012 " jae else_A"
2014 " cmpl 13*4(%%edx), %%eax"
2015 " jae else_7"
2016 " movl $13, %0"
2017 " jmp next_7"
2018 " else_7: "
2019 " movl $14, %0"
2020 " next_7:"
2022 " jmp next_A"
2023 " else_A: "
2024 " movl $15, %0 "
2025 " next_A:"
2027 " next_D: "
2028 " next_G:"
2029 : "=g" (I), "=r"(N)
2030 : "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
2031 : "memory"
2033 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
2035 #else
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])
2041 I=1;
2042 else
2043 I=2;
2044 } else {
2045 if (N<Deco->DecodeLen[3])
2046 I=3;
2047 else
2048 I=4;
2050 } else {
2051 if (N<Deco->DecodeLen[6]) {
2052 if (N<Deco->DecodeLen[5])
2053 I=5;
2054 else
2055 I=6;
2056 } else {
2057 if (N<Deco->DecodeLen[7])
2058 I=7;
2059 else
2060 I=8;
2063 } else {
2064 if (N<Deco->DecodeLen[12]) {
2065 if (N<Deco->DecodeLen[10]) {
2066 if (N<Deco->DecodeLen[9])
2067 I=9;
2068 else
2069 I=10;
2070 } else {
2071 if (N<Deco->DecodeLen[11])
2072 I=11;
2073 else
2074 I=12;
2076 } else {
2077 if (N<Deco->DecodeLen[14]) {
2078 if (N<Deco->DecodeLen[13])
2079 I=13;
2080 else
2081 I=14;
2083 } else {
2084 I=15;
2089 #endif
2091 AddBits(I);
2092 if ((N=Deco->DecodePos[I]+((N-Deco->DecodeLen[I-1])>>(16-I)))>=Deco->MaxNum)
2093 N=0;
2094 Number=Deco->DecodeNum[N];
2098 void UnpInitData()
2100 InAddr=InBit=0;
2101 if (!(NewLhd.Flags & LHD_SOLID))
2103 ChannelDelta=CurChannel=0;
2105 #ifdef _USE_ASM
2107 #ifdef _WIN_32 /* Win32 with VisualC */
2109 __asm {
2110 push edi
2111 push eax
2112 push ecx
2114 cld /* increment EDI and ESI */
2115 mov al, 0x00
2116 mov ecx, SIZE AudV
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 */
2128 pop ecx
2129 pop eax
2130 pop edi
2133 mov [OldDistPtr], 0
2134 mov [LastDist], 0
2135 mov [LastLength], 0
2136 mov [UnpPtr], 0
2137 mov [WrPtr], 0
2138 mov [OldDistPtr], 0
2139 mov [LastLength], 0
2140 mov [LastDist], 0
2141 mov [UnpPtr], 0
2142 mov [WrPtr], 0
2145 memset(UnpBuf,0,MAXWINSIZE);
2148 #else /* unix/linux on i386 cpus */
2149 __asm__ __volatile (
2150 " cld /* increment EDI and ESI */"
2151 " movb $0x00, %%al"
2152 " movl %0, %%ecx"
2153 " movl %1, %%edi"
2154 " rep "
2155 " stosb /* clear memory */"
2157 " movl %2, %%ecx"
2158 " mov %3, %%edi"
2159 " rep "
2160 " stosb /* clear memory */"
2162 " movl %4, %%ecx"
2163 " movl %5, %%edi"
2164 " rep "
2165 " stosb /* clear memory */"
2167 " movl $0, (OldDistPtr)"
2168 " movl $0, (LastDist)"
2169 " movl $0, (LastLength)"
2170 " movl $0, (UnpPtr)"
2171 " movl $0, (WrPtr)"
2172 " movl $0, (OldDistPtr)"
2173 " movl $0, (LastLength)"
2174 " movl $0, (LastDist)"
2175 " movl $0, (UnpPtr)"
2176 " movl $0, (WrPtr)"
2178 : "m" ((long)sizeof(AudV)),
2179 "m" ((long)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);
2187 #endif
2189 #else /* unix/linux on non-i386 cpu */
2190 memset(AudV,0,sizeof(AudV));
2191 memset(OldDist,0,sizeof(OldDist));
2192 OldDistPtr=0;
2193 LastDist=LastLength=0;
2194 memset(UnpBuf,0,MAXWINSIZE);
2195 memset(UnpOldTable,0,sizeof(UnpOldTable));
2196 UnpPtr=WrPtr=0;
2197 #endif
2203 UBYTE DecodeAudio(int Delta)
2205 struct AudioVariables *V;
2206 unsigned int Ch;
2207 unsigned int NumMinDif,MinDif;
2208 int PCh,I;
2210 V=&AudV[CurChannel];
2211 V->ByteCount++;
2212 V->D4=V->D3;
2213 V->D3=V->D2;
2214 V->D2=V->LastDelta-V->D1;
2215 V->D1=V->LastDelta;
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;
2220 Ch=PCh-Delta;
2222 I=((signed char)Delta)<<3;
2224 V->Dif[0]+=abs(I);
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);
2237 V->LastChar=Ch;
2239 if ((V->ByteCount & 0x1F)==0)
2241 MinDif=V->Dif[0];
2242 NumMinDif=0;
2243 V->Dif[0]=0;
2244 for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
2246 if (V->Dif[I]<MinDif)
2248 MinDif=V->Dif[I];
2249 NumMinDif=I;
2251 V->Dif[I]=0;
2253 switch(NumMinDif)
2255 case 1:
2256 if (V->K1>=-16)
2257 V->K1--;
2258 break;
2259 case 2:
2260 if (V->K1<16)
2261 V->K1++;
2262 break;
2263 case 3:
2264 if (V->K2>=-16)
2265 V->K2--;
2266 break;
2267 case 4:
2268 if (V->K2<16)
2269 V->K2++;
2270 break;
2271 case 5:
2272 if (V->K3>=-16)
2273 V->K3--;
2274 break;
2275 case 6:
2276 if (V->K3<16)
2277 V->K3++;
2278 break;
2279 case 7:
2280 if (V->K4>=-16)
2281 V->K4--;
2282 break;
2283 case 8:
2284 if (V->K4<16)
2285 V->K4++;
2286 break;
2287 case 9:
2288 if (V->K5>=-16)
2289 V->K5--;
2290 break;
2291 case 10:
2292 if (V->K5<16)
2293 V->K5++;
2294 break;
2297 return((UBYTE)Ch);
2306 /* ***************************************************
2307 * ** CRCCrypt Code - decryption engine starts here **
2308 * ***************************************************/
2311 #define NROUNDS 32
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) )
2322 UDWORD CRCTab[256];
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
2344 UDWORD Key[4];
2347 void EncryptBlock(UBYTE *Buf)
2349 int I;
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];
2361 #else
2362 UDWORD *BufPtr;
2363 BufPtr=(UDWORD *)Buf;
2364 A=BufPtr[0]^Key[0];
2365 B=BufPtr[1]^Key[1];
2366 C=BufPtr[2]^Key[2];
2367 D=BufPtr[3]^Key[3];
2368 #endif
2369 for(I=0;I<NROUNDS;I++)
2371 T=((C+rol(D,11))^Key[I&3]);
2372 TA=A^substLong(T);
2373 T=((D^rol(C,17))+Key[I&3]);
2374 TB=B^substLong(T);
2375 A=C;
2376 B=D;
2377 C=TA;
2378 D=TB;
2380 #ifdef NON_INTEL_BYTE_ORDER
2381 C^=Key[0];
2382 Buf[0]=(UBYTE)C;
2383 Buf[1]=(UBYTE)(C>>8);
2384 Buf[2]=(UBYTE)(C>>16);
2385 Buf[3]=(UBYTE)(C>>24);
2386 D^=Key[1];
2387 Buf[4]=(UBYTE)D;
2388 Buf[5]=(UBYTE)(D>>8);
2389 Buf[6]=(UBYTE)(D>>16);
2390 Buf[7]=(UBYTE)(D>>24);
2391 A^=Key[2];
2392 Buf[8]=(UBYTE)A;
2393 Buf[9]=(UBYTE)(A>>8);
2394 Buf[10]=(UBYTE)(A>>16);
2395 Buf[11]=(UBYTE)(A>>24);
2396 B^=Key[3];
2397 Buf[12]=(UBYTE)B;
2398 Buf[13]=(UBYTE)(B>>8);
2399 Buf[14]=(UBYTE)(B>>16);
2400 Buf[15]=(UBYTE)(B>>24);
2401 #else
2402 BufPtr[0]=C^Key[0];
2403 BufPtr[1]=D^Key[1];
2404 BufPtr[2]=A^Key[2];
2405 BufPtr[3]=B^Key[3];
2406 #endif
2407 UpdKeys(Buf);
2411 void DecryptBlock(UBYTE *Buf)
2413 int I;
2414 UBYTE InBuf[16];
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];
2425 #else
2426 UDWORD *BufPtr;
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 */
2430 C=BufPtr[2]^Key[2];
2431 D=BufPtr[3]^Key[3];
2432 #endif
2433 memcpy(InBuf,Buf,sizeof(InBuf));
2434 for(I=NROUNDS-1;I>=0;I--)
2436 T=((C+rol(D,11))^Key[I&3]);
2437 TA=A^substLong(T);
2438 T=((D^rol(C,17))+Key[I&3]);
2439 TB=B^substLong(T);
2440 A=C;
2441 B=D;
2442 C=TA;
2443 D=TB;
2445 #ifdef NON_INTEL_BYTE_ORDER
2446 C^=Key[0];
2447 Buf[0]=(UBYTE)C;
2448 Buf[1]=(UBYTE)(C>>8);
2449 Buf[2]=(UBYTE)(C>>16);
2450 Buf[3]=(UBYTE)(C>>24);
2451 D^=Key[1];
2452 Buf[4]=(UBYTE)D;
2453 Buf[5]=(UBYTE)(D>>8);
2454 Buf[6]=(UBYTE)(D>>16);
2455 Buf[7]=(UBYTE)(D>>24);
2456 A^=Key[2];
2457 Buf[8]=(UBYTE)A;
2458 Buf[9]=(UBYTE)(A>>8);
2459 Buf[10]=(UBYTE)(A>>16);
2460 Buf[11]=(UBYTE)(A>>24);
2461 B^=Key[3];
2462 Buf[12]=(UBYTE)B;
2463 Buf[13]=(UBYTE)(B>>8);
2464 Buf[14]=(UBYTE)(B>>16);
2465 Buf[15]=(UBYTE)(B>>24);
2466 #else
2467 BufPtr[0]=C^Key[0];
2468 BufPtr[1]=D^Key[1];
2469 BufPtr[2]=A^Key[2];
2470 BufPtr[3]=B^Key[3];
2471 #endif
2472 UpdKeys(InBuf);
2476 void UpdKeys(UBYTE *Buf)
2478 int I;
2479 for (I=0;I<16;I+=4)
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
2495 UBYTE Ch;
2496 #endif
2498 SetOldKeys(Password);
2500 Key[0]=0xD3A3B879L;
2501 Key[1]=0x3F6D12F7L;
2502 Key[2]=0x7515A235L;
2503 Key[3]=0xA4E7F123L;
2504 memset(Psw,0,sizeof(Psw));
2505 strcpy((char *)Psw,Password);
2506 PswLength=strlen(Password);
2507 memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
2509 for (J=0;J<256;J++)
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 */
2517 #ifdef _USE_ASM
2519 #ifdef _WIN_32
2520 __asm {
2522 mov ebx, Offset SubstTable
2523 mov edx, ebx
2525 xor ecx, ecx // read SubstTable[N1]...
2526 mov cl, N1
2527 add ebx, ecx
2528 mov al, byte ptr[ebx]
2530 mov cl, N1 // read SubstTable[(N1+I+K)&0xFF]...
2531 add ecx, I
2532 add ecx, K
2533 and ecx, 0xFF
2534 add edx, ecx
2535 mov ah, byte ptr[edx]
2537 mov byte ptr[ebx], ah // and write back
2538 mov byte ptr[edx], al
2541 #else
2542 __asm__ __volatile__ (
2543 " xorl %%ecx, %%ecx"
2544 " movl %2, %%ecx /* ecx = N1 */"
2545 " mov %%ebx, %%edx"
2546 " addl %%ecx, %%ebx"
2548 " addl %0, %%ecx"
2549 " addl %1, %%ecx"
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)"
2558 : : "g" ((long)I),
2559 "g" ((long)K),
2560 "g" ((long)N1),
2561 "ebx"((long)SubstTable)
2562 : "ecx", "edx"
2565 #endif
2567 #else
2568 /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
2569 Ch=SubstTable[N1];
2570 SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
2571 SubstTable[(N1+I+K)&0xFF]=Ch;
2572 #endif
2575 for (I=0;I<PswLength;I+=16)
2576 EncryptBlock(&Psw[I]);
2580 void SetOldKeys(char *Password)
2582 UDWORD PswCRC;
2583 UBYTE Ch;
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;
2588 PN1=PN2=PN3=0;
2589 while ((Ch=*Password)!=0)
2591 PN1+=Ch;
2592 PN2^=Ch;
2593 PN3+=Ch;
2594 PN3=(UBYTE)rol(PN3,1);
2595 OldKey[2]^=((UWORD)(Ch^CRCTab[Ch]));
2596 OldKey[3]+=((UWORD)(Ch+(CRCTab[Ch]>>16)));
2597 Password++;
2601 void InitCRC(void)
2603 int I, J;
2604 UDWORD C;
2605 for (I=0;I<256;I++)
2607 for (C=I,J=0;J<8;J++)
2608 C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
2609 CRCTab[I]=C;
2614 UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
2616 unsigned int I;
2617 for (I=0; I<Size; I++)
2618 StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
2619 return(StartCRC);
2623 /* **************************************************************************
2624 ****************************************************************************
2625 ****************************************************************************
2626 ************************************************************************** */
2652 /* **************************************************************************
2653 ****************************************************************************
2654 ****************************************************************************
2655 ****************************************************************************
2656 ******* *******
2657 ******* *******
2658 ******* *******
2659 ******* D E B U G F U N C T I O N S *******
2660 ******* *******
2661 ******* *******
2662 ******* *******
2663 ****************************************************************************
2664 ****************************************************************************
2665 ****************************************************************************
2666 ************************************************************************** */
2667 #ifdef _DEBUG_LOG
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 */
2674 /* this is TRUE */
2675 /* ------------------------------------------------------------------------ */
2678 /* -- global functions ---------------------------------------------------- */
2679 void debug_init_proc(char *file_name)
2680 /* Create/Rewrite a log file */
2682 FILE *fp;
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);
2695 fclose(fp);
2700 void debug_log_proc(char *text, char *sourcefile, int sourceline)
2701 /* add a line to the log file */
2703 FILE *fp;
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);
2713 fclose(fp);
2717 /* ------------------------------------------------------------------------ */
2718 #endif
2719 /* **************************************************************************
2720 ****************************************************************************
2721 ****************************************************************************
2722 ************************************************************************** */
2725 /* end of file urarlib.c */