10l: comparison of char* ptrs with string literals
[mplayer.git] / unrarlib.c
blobbe67e7528e843d3ad67c2f799bded00c98f9650e
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 ** Modified for use with MPlayer, detailed changelog at
9 ** http://svn.mplayerhq.hu/mplayer/trunk/
10 ** $Id$
12 ** The contents of this file are subject to the UniquE RAR File Library
13 ** License (the "unrarlib-license.txt"). You may not use this file except
14 ** in compliance with the License. You may obtain a copy of the License
15 ** at http://www.unrarlib.org/license.html.
16 ** Software distributed under the License is distributed on an "AS IS"
17 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
19 ** Alternatively, the contents of this file may be used under the terms
20 ** of the GNU General Public License Version 2 or later (the "GPL"), in
21 ** which case the provisions of the GPL are applicable instead of those
22 ** above. If you wish to allow use of your version of this file only
23 ** under the terms of the GPL and not to allow others to use your version
24 ** of this file under the terms of the UniquE RAR File Library License,
25 ** indicate your decision by deleting the provisions above and replace
26 ** them with the notice and other provisions required by the GPL. If you
27 ** do not delete the provisions above, a recipient may use your version
28 ** of this file under the terms of the GPL or the UniquE RAR File Library
29 ** License.
31 ************************************************************************** */
33 /* ***************************************************************************
35 ** UniquE RAR File Library
36 ** The free file lib for the demoscene
37 ** multi-OS version (Win32, Linux and SunOS)
39 *****************************************************************************
41 ** ==> Please configure the program in "unrarlib.h". <==
43 ** RAR decompression code:
44 ** (C) Eugene Roshal
45 ** Modifications to a FileLib:
46 ** (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
47 ** Linux port:
48 ** (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
50 ** The UniquE RAR File Library gives you the ability to access RAR archives
51 ** (any compression method supported in RAR v2.0 including Multimedia
52 ** Compression and encryption) directly from your program with ease an by
53 ** adding only 12kB (6kB UPX-compressed) additional code to your program.
54 ** Both solid and normal (recommended for fast random access to the files!)
55 ** archives are supported. This FileLib is made for the Demo scene, so it's
56 ** designed for easy use within your demos and intros.
57 ** Please read "licence.txt" to learn more about how you may use URARFileLib
58 ** in your productions.
60 *****************************************************************************
62 ** ==> see the "CHANGES" file to see what's new
64 ************************************************************************** */
66 /* -- include files ------------------------------------------------------- */
67 #include "unrarlib.h" /* include global configuration */
68 /* ------------------------------------------------------------------------ */
72 /* -- global stuff -------------------------------------------------------- */
73 #ifdef _WIN_32
75 #include <windows.h> /* WIN32 definitions */
76 #include <stdio.h>
77 #include <string.h>
80 #define ENABLE_ACCESS
82 #define HOST_OS WIN_32
84 #define FM_NORMAL 0x00
85 #define FM_RDONLY 0x01
86 #define FM_HIDDEN 0x02
87 #define FM_SYSTEM 0x04
88 #define FM_LABEL 0x08
89 #define FM_DIREC 0x10
90 #define FM_ARCH 0x20
92 #define PATHDIVIDER "\\"
93 #define CPATHDIVIDER '\\'
94 #define MASKALL "*.*"
96 #define READBINARY "rb"
97 #define READTEXT "rt"
98 #define UPDATEBINARY "r+b"
99 #define CREATEBINARY "w+b"
100 #define CREATETEXT "w"
101 #define APPENDTEXT "at"
103 #endif
105 #ifdef _UNIX
107 #include <stdio.h> /* LINUX/UNIX definitions */
108 #include <stdlib.h>
109 #include <ctype.h>
110 #include <string.h>
112 #define ENABLE_ACCESS
114 #define HOST_OS UNIX
116 #define FM_LABEL 0x0000
117 #define FM_DIREC 0x4000
119 #define PATHDIVIDER "/"
120 #define CPATHDIVIDER '/'
121 #define MASKALL "*.*"
123 #define READBINARY "r"
124 #define READTEXT "r"
125 #define UPDATEBINARY "r+"
126 #define CREATEBINARY "w+"
127 #define CREATETEXT "w"
128 #define APPENDTEXT "a"
131 /* emulation of the windows API and data types */
132 /* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
134 typedef long DWORD;
135 typedef short BOOL;
136 #define TRUE 1
137 #define FALSE 0
140 #ifdef _DEBUG_LOG /* define macros for debugging */
141 #include <unistd.h>
142 #include <sys/time.h>
144 DWORD GetTickCount()
146 struct timeval tv;
147 gettimeofday( &tv, 0 );
148 return (tv.tv_usec / 1000);
150 #endif
152 #endif
158 #ifdef _DEBUG_LOG /* define macros for debugging */
160 BOOL debug_log_first_start = TRUE;
162 #define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
163 #define debug_init(a); debug_init_proc(a);
165 void debug_log_proc(char *text, char *sourcefile, int sourceline);
166 void debug_init_proc(char *file_name);
168 #else
169 #define debug_log(a); /* no debug this time */
170 #define debug_init(a); /* no debug this time */
171 #endif
177 #define MAXWINSIZE 0x100000
178 #define MAXWINMASK (MAXWINSIZE-1)
179 #define UNP_MEMORY MAXWINSIZE
180 #define Min(x,y) (((x)<(y)) ? (x):(y))
181 #define Max(x,y) (((x)>(y)) ? (x):(y))
182 #define NM 260
184 #define SIZEOF_MARKHEAD 7
185 #define SIZEOF_OLDMHD 7
186 #define SIZEOF_NEWMHD 13
187 #define SIZEOF_OLDLHD 21
188 #define SIZEOF_NEWLHD 32
189 #define SIZEOF_SHORTBLOCKHEAD 7
190 #define SIZEOF_LONGBLOCKHEAD 11
191 #define SIZEOF_COMMHEAD 13
192 #define SIZEOF_PROTECTHEAD 26
195 #define PACK_VER 20 /* version of decompression code*/
196 #define UNP_VER 20
197 #define PROTECT_VER 20
200 enum { M_DENYREAD,M_DENYWRITE,M_DENYNONE,M_DENYALL };
201 enum { FILE_EMPTY,FILE_ADD,FILE_UPDATE,FILE_COPYOLD,FILE_COPYBLOCK };
202 enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
203 OPEN_ERROR,USER_ERROR,MEMORY_ERROR,USER_BREAK=255,IMM_ABORT=0x8000 };
204 enum { EN_LOCK=1,EN_VOL=2 };
205 enum { SD_MEMORY=1,SD_FILES=2 };
206 enum { NAMES_DONTCHANGE };
207 enum { LOG_ARC=1,LOG_FILE=2 };
208 enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
209 enum { OLD_UNPACK,NEW_UNPACK };
212 #define MHD_COMMENT 2
213 #define MHD_LOCK 4
214 #define MHD_PACK_COMMENT 16
215 #define MHD_AV 32
216 #define MHD_PROTECT 64
218 #define LHD_SPLIT_BEFORE 1
219 #define LHD_SPLIT_AFTER 2
220 #define LHD_PASSWORD 4
221 #define LHD_COMMENT 8
222 #define LHD_SOLID 16
224 #define LHD_WINDOWMASK 0x00e0
225 #define LHD_WINDOW64 0
226 #define LHD_WINDOW128 32
227 #define LHD_WINDOW256 64
228 #define LHD_WINDOW512 96
229 #define LHD_WINDOW1024 128
230 #define LHD_DIRECTORY 0x00e0
232 #define LONG_BLOCK 0x8000
233 #define READSUBBLOCK 0x8000
235 enum { ALL_HEAD=0,MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,
236 COMM_HEAD=0x75,AV_HEAD=0x76,SUB_HEAD=0x77,PROTECT_HEAD=0x78};
237 enum { EA_HEAD=0x100 };
238 enum { MS_DOS=0,OS2=1,WIN_32=2,UNIX=3 };
241 struct MarkHeader
243 UBYTE Mark[7];
247 struct NewMainArchiveHeader
249 UWORD HeadCRC;
250 UBYTE HeadType;
251 UWORD Flags;
252 UWORD HeadSize;
253 UWORD Reserved;
254 UDWORD Reserved1;
258 struct NewFileHeader
260 UWORD HeadCRC;
261 UBYTE HeadType;
262 UWORD Flags;
263 UWORD HeadSize;
264 UDWORD PackSize;
265 UDWORD UnpSize;
266 UBYTE HostOS;
267 UDWORD FileCRC;
268 UDWORD FileTime;
269 UBYTE UnpVer;
270 UBYTE Method;
271 UWORD NameSize;
272 UDWORD FileAttr;
276 struct BlockHeader
278 UWORD HeadCRC;
279 UBYTE HeadType;
280 UWORD Flags;
281 UWORD HeadSize;
282 UDWORD DataSize;
286 struct Decode
288 unsigned int MaxNum;
289 unsigned int DecodeLen[16];
290 unsigned int DecodePos[16];
291 unsigned int DecodeNum[2];
295 struct MarkHeader MarkHead;
296 struct NewMainArchiveHeader NewMhd;
297 struct NewFileHeader NewLhd;
298 struct BlockHeader BlockHead;
300 static UBYTE *TempMemory = NULL; /* temporary unpack-buffer */
301 static char *CommMemory = NULL;
304 static UBYTE *UnpMemory = NULL;
305 static char* ArgName = NULL; /* current file in rar archive */
306 static char* ArcFileName = NULL; /* file to decompress */
308 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
309 static MemoryFile *MemRARFile; /* pointer to RAR file in memory*/
310 #else
311 static char* ArcName = NULL; /* RAR archive name */
312 static FILE *ArcPtr; /* input RAR file handler */
313 #endif
314 static char *Password = NULL; /* password to decrypt files */
316 static unsigned char *temp_output_buffer; /* extract files to this pointer*/
317 static unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */
319 static BOOL FileFound; /* TRUE=use current extracted */
320 /* data FALSE=throw data away, */
321 /* wrong file */
322 static int MainHeadSize;
323 static long CurBlockPos,NextBlockPos;
325 static unsigned long CurUnpRead, CurUnpWrite;
326 static long UnpPackedSize;
327 static long DestUnpSize;
329 static UDWORD HeaderCRC;
330 static int Encryption;
332 //static unsigned int UnpWrSize;
333 //static unsigned char *UnpWrAddr;
334 static unsigned int UnpPtr,WrPtr;
336 static unsigned char PN1,PN2,PN3;
337 static unsigned short OldKey[4];
341 /* function header definitions */
342 static int ReadHeader(int BlockType);
343 static BOOL ExtrFile(void);
344 //BOOL ListFile(void);
345 static int tread(void *stream,void *buf,unsigned len);
346 static int tseek(void *stream,long offset,int fromwhere);
347 static BOOL UnstoreFile(void);
348 static int IsArchive(void);
349 static int ReadBlock(int BlockType);
350 static unsigned int UnpRead(unsigned char *Addr,unsigned int Count);
351 static void UnpInitData(void);
352 static void Unpack(unsigned char *UnpAddr);
353 static UBYTE DecodeAudio(int Delta);
354 static void DecodeNumber(struct Decode *Dec);
355 static void UpdKeys(UBYTE *Buf);
356 static void SetCryptKeys(char *Password);
357 static void SetOldKeys(char *Password);
358 static void DecryptBlock(unsigned char *Buf);
359 static void InitCRC(void);
360 static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);
361 static void UnpReadBuf(int FirstBuf);
362 static void ReadTables(void);
363 static void ReadLastTables(void);
364 static void MakeDecodeTables(unsigned char *LenTab,
365 struct Decode *Dec,
366 int Size);
367 static int my_stricomp(char *Str1,char *Str2);
368 /* ------------------------------------------------------------------------ */
371 /* -- global functions ---------------------------------------------------- */
373 int urarlib_get(void *output,
374 unsigned long *size,
375 char *filename,
376 void *rarfile,
377 char *libpassword)
378 /* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
379 * does everything from allocating memory, decrypting and unpacking the file
380 * from the archive. TRUE is returned if the file could be successfully
381 * extracted, else a FALSE indicates a failure.
384 BOOL retcode = FALSE;
386 #ifdef _DEBUG_LOG
387 int str_offs; /* used for debug-strings */
388 char DebugMsg[500]; /* used to compose debug msg */
390 if(debug_log_first_start)
392 debug_log_first_start=FALSE; /* only create a new log file */
393 debug_init(_DEBUG_LOG_FILE); /* on startup */
396 #endif
398 InitCRC(); /* init some vars */
400 if(ArgName) free(ArgName);
401 ArgName = strdup(filename); /* set file(s) to extract */
402 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
403 MemRARFile = rarfile; /* set pointer to mem-RAR file */
404 #else
405 if(ArcName) free(ArcName);
406 ArcName = strdup(rarfile); /* set RAR file name */
407 #endif
408 if(Password) free(Password);
409 if(libpassword != NULL)
410 Password = strdup(libpassword); /* init password */
411 else
412 Password = strdup("");
414 temp_output_buffer = NULL;
415 temp_output_buffer_offset=size; /* set size of the temp buffer */
417 #ifdef _DEBUG_LOG
418 sprintf(DebugMsg, "Extracting >%s< from >%s< (password is >%s<)...",
419 filename, (char*)rarfile, libpassword);
420 debug_log(DebugMsg);
421 #endif
423 retcode = ExtrFile(); /* unpack file now! */
425 //memset(Password,0,sizeof(Password)); /* clear password */
427 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
428 if (ArcPtr!=NULL){
429 fclose(ArcPtr);
430 ArcPtr = NULL;
432 #endif
434 if(UnpMemory) free(UnpMemory); /* free memory */
435 if(TempMemory) free(TempMemory);
436 if(CommMemory) free(CommMemory);
437 UnpMemory=NULL;
438 TempMemory=NULL;
439 CommMemory=NULL;
442 if(retcode == FALSE)
444 if(temp_output_buffer) /* free memory and return NULL */
445 free(temp_output_buffer);
446 temp_output_buffer=NULL;
447 *(DWORD*)output=0; /* pointer on errors */
448 *size=0;
449 #ifdef _DEBUG_LOG
452 /* sorry for this ugly code, but older SunOS gcc compilers don't support */
453 /* white spaces within strings */
454 str_offs = sprintf(DebugMsg, "Error - couldn't extract ");
455 str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename);
456 str_offs += sprintf(DebugMsg + str_offs, " and allocated ");
457 str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size);
458 str_offs += sprintf(DebugMsg + str_offs, " of unused memory!");
460 } else
462 sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
464 debug_log(DebugMsg);
465 #else
467 #endif
468 *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
469 /* data */
471 return retcode;
475 int urarlib_list(void *rarfile, ArchiveList_struct *list)
477 ArchiveList_struct *tmp_List = NULL;
478 int NoOfFilesInArchive = 0; /* number of files in archive */
480 #ifdef _DEBUG_LOG
481 if(debug_log_first_start)
483 debug_log_first_start=FALSE; /* only create a new log file */
484 debug_init(_DEBUG_LOG_FILE); /* on startup */
486 #endif
488 InitCRC(); /* init some vars */
490 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
491 MemRARFile = rarfile; /* assign pointer to RAR file */
492 MemRARFile->offset = 0;
493 if (!IsArchive())
495 debug_log("Not a RAR file");
496 return NoOfFilesInArchive; /* error => exit! */
498 #else
499 /* open and identify archive */
500 if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL)
502 if (!IsArchive())
504 debug_log("Not a RAR file");
505 fclose(ArcPtr);
506 ArcPtr = NULL;
507 return NoOfFilesInArchive; /* error => exit! */
510 else {
511 debug_log("Error opening file.");
512 return NoOfFilesInArchive;
514 #endif
516 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
518 debug_log("Can't allocate memory for decompression!");
519 return NoOfFilesInArchive;
522 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
523 MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
524 #else
525 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
526 #endif
527 (*(DWORD*)list) = (DWORD)NULL; /* init file list */
528 /* do while file is not extracted and there's no error */
529 while (TRUE)
531 if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
532 { /* file within the RAR archive */
533 debug_log("Couldn't read next filename from archive (I/O error).");
534 break; /* error, file not found in */
535 } /* archive or I/O error */
536 if (BlockHead.HeadType==SUB_HEAD)
538 debug_log("Sorry, sub-headers not supported.");
539 break; /* error => exit */
542 if((void*)(*(DWORD*)list) == NULL) /* first entry */
544 tmp_List = malloc(sizeof(ArchiveList_struct));
545 tmp_List->next = NULL;
547 (*(DWORD*)list) = (DWORD)tmp_List;
549 } else /* add entry */
551 tmp_List->next = malloc(sizeof(ArchiveList_struct));
552 tmp_List = (ArchiveList_struct*) tmp_List->next;
553 tmp_List->next = NULL;
556 tmp_List->item.Name = malloc(NewLhd.NameSize + 1);
557 strcpy(tmp_List->item.Name, ArcFileName);
558 tmp_List->item.NameSize = NewLhd.NameSize;
559 tmp_List->item.PackSize = NewLhd.PackSize;
560 tmp_List->item.UnpSize = NewLhd.UnpSize;
561 tmp_List->item.HostOS = NewLhd.HostOS;
562 tmp_List->item.FileCRC = NewLhd.FileCRC;
563 tmp_List->item.FileTime = NewLhd.FileTime;
564 tmp_List->item.UnpVer = NewLhd.UnpVer;
565 tmp_List->item.Method = NewLhd.Method;
566 tmp_List->item.FileAttr = NewLhd.FileAttr;
568 NoOfFilesInArchive++; /* count files */
570 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
571 MemRARFile->offset = NextBlockPos;
572 #else
573 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
574 #endif
578 /* free memory, clear password and close archive */
579 memset(Password,0,sizeof(Password)); /* clear password */
580 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
581 if (ArcPtr!=NULL){
582 fclose(ArcPtr);
583 ArcPtr = NULL;
585 #endif
587 free(UnpMemory); /* free memory */
588 free(TempMemory);
589 free(CommMemory);
590 UnpMemory=NULL;
591 TempMemory=NULL;
592 CommMemory=NULL;
594 return NoOfFilesInArchive;
599 /* urarlib_freelist:
600 * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
601 * and Johannes Winkelmann who independently wrote a patch)
602 * free the memory of a ArchiveList_struct created by urarlib_list.
604 * input: *list pointer to an ArchiveList_struct
605 * output: -
608 void urarlib_freelist(ArchiveList_struct *list)
610 ArchiveList_struct* tmp = list;
612 while ( list ) {
613 tmp = list->next;
614 free( list->item.Name );
615 free( list );
616 list = tmp;
621 /* ------------------------------------------------------------------------ */
639 /****************************************************************************
640 ****************************************************************************
641 ****************************************************************************
642 ****************************************************************************
643 ******* *******
644 ******* *******
645 ******* *******
646 ******* B L O C K I / O *******
647 ******* *******
648 ******* *******
649 ******* *******
650 ****************************************************************************
651 ****************************************************************************
652 ****************************************************************************
653 ****************************************************************************/
657 #define GetHeaderByte(N) Header[N]
659 #define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
661 #define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
662 ((UDWORD)Header[N+2]<<16)+\
663 ((UDWORD)Header[N+3]<<24))
666 int ReadBlock(int BlockType)
668 struct NewFileHeader SaveFileHead;
669 int Size=0,ReadSubBlock=0;
670 static int LastBlock;
671 memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
672 if (BlockType & READSUBBLOCK)
673 ReadSubBlock=1;
674 BlockType &= 0xff;
676 while (1)
678 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
679 CurBlockPos=MemRARFile->offset; /* get offset of mem-file */
680 #else
681 CurBlockPos=ftell(ArcPtr);
682 #endif
683 Size=ReadHeader(FILE_HEAD);
684 if (Size!=0)
686 if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
687 return(0);
688 NextBlockPos=CurBlockPos+NewLhd.HeadSize;
689 if (NewLhd.Flags & LONG_BLOCK)
690 NextBlockPos+=NewLhd.PackSize;
691 if (NextBlockPos<=CurBlockPos)
692 return(0);
695 if (Size > 0 && BlockType!=SUB_HEAD)
696 LastBlock=BlockType;
697 if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
698 (NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
699 break;
700 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
701 MemRARFile->offset = NextBlockPos;
702 #else
703 tseek(ArcPtr, NextBlockPos, SEEK_SET);
704 #endif
708 BlockHead.HeadCRC=NewLhd.HeadCRC;
709 BlockHead.HeadType=NewLhd.HeadType;
710 BlockHead.Flags=NewLhd.Flags;
711 BlockHead.HeadSize=NewLhd.HeadSize;
712 BlockHead.DataSize=NewLhd.PackSize;
714 if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
716 if((FILE_HEAD == BlockType) && (Size>0))
718 ArcFileName=realloc(ArcFileName,NewLhd.NameSize+1);
719 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
720 tread(MemRARFile, ArcFileName, NewLhd.NameSize);
721 #else
722 tread(ArcPtr,ArcFileName,NewLhd.NameSize);
723 #endif
724 ArcFileName[NewLhd.NameSize]=0;
725 #ifdef _DEBUG_LOG
726 if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
727 NewLhd.NameSize))
729 debug_log("file header broken");
731 #endif
732 Size+=NewLhd.NameSize;
733 } else
735 memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
736 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
737 MemRARFile->offset = CurBlockPos;
738 #else
739 tseek(ArcPtr,CurBlockPos,SEEK_SET);
740 #endif
744 return(Size);
748 int ReadHeader(int BlockType)
750 int Size = 0;
751 unsigned char Header[64];
752 switch(BlockType)
754 case MAIN_HEAD:
755 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
756 Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
757 #else
758 Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
759 #endif
760 NewMhd.HeadCRC=(unsigned short)GetHeaderWord(0);
761 NewMhd.HeadType=GetHeaderByte(2);
762 NewMhd.Flags=(unsigned short)GetHeaderWord(3);
763 NewMhd.HeadSize=(unsigned short)GetHeaderWord(5);
764 NewMhd.Reserved=(unsigned short)GetHeaderWord(7);
765 NewMhd.Reserved1=GetHeaderDword(9);
766 HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWMHD-2);
767 break;
768 case FILE_HEAD:
769 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
770 Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
771 #else
772 Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
773 #endif
774 NewLhd.HeadCRC=(unsigned short)GetHeaderWord(0);
775 NewLhd.HeadType=GetHeaderByte(2);
776 NewLhd.Flags=(unsigned short)GetHeaderWord(3);
777 NewLhd.HeadSize=(unsigned short)GetHeaderWord(5);
778 NewLhd.PackSize=GetHeaderDword(7);
779 NewLhd.UnpSize=GetHeaderDword(11);
780 NewLhd.HostOS=GetHeaderByte(15);
781 NewLhd.FileCRC=GetHeaderDword(16);
782 NewLhd.FileTime=GetHeaderDword(20);
783 NewLhd.UnpVer=GetHeaderByte(24);
784 NewLhd.Method=GetHeaderByte(25);
785 NewLhd.NameSize=(unsigned short)GetHeaderWord(26);
786 NewLhd.FileAttr=GetHeaderDword(28);
787 HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWLHD-2);
788 break;
790 #ifdef _DEBUG_LOG
791 case COMM_HEAD: /* log errors in case of debug */
792 debug_log("Comment headers not supported! "\
793 "Please create archives without comments.");
794 break;
795 case PROTECT_HEAD:
796 debug_log("Protected headers not supported!");
797 break;
798 case ALL_HEAD:
799 debug_log("ShortBlockHeader not supported!");
800 break;
801 default:
802 debug_log("Unknown//unsupported !");
803 #else
804 default: /* else do nothing */
805 break;
806 #endif
808 return(Size);
811 /* **************************************************************************
812 ****************************************************************************
813 ****************************************************************************
814 ************************************************************************** */
832 /* **************************************************************************
833 ****************************************************************************
834 ****************************************************************************
835 ****************************************************************************
836 ******* *******
837 ******* *******
838 ******* *******
839 ******* E X T R A C T L O O P *******
840 ******* *******
841 ******* *******
842 ******* *******
843 ****************************************************************************
844 ****************************************************************************
845 ****************************************************************************
846 ************************************************************************** */
849 int IsArchive(void)
851 #ifdef _DEBUG_LOG
852 int str_offs; /* used for debug-strings */
853 char DebugMsg[500]; /* used to compose debug msg */
854 #endif
856 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
857 if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD)
858 return(FALSE);
859 #else
860 if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
861 return(FALSE);
862 #endif
863 /* Old archive => error */
864 if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
865 MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
867 debug_log("Attention: format as OLD detected! Can't handel archive!");
869 else
870 /* original RAR v2.0 */
871 if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original */
872 MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
873 MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
874 MarkHead.Mark[6]==0x00) ||
875 /* "UniquE!" - header */
876 (MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' && /* "UniquE!" */
877 MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' && /* header */
878 MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
879 MarkHead.Mark[6]=='!'))
882 if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD)
883 return(FALSE);
884 } else
887 #ifdef _DEBUG_LOG
888 /* sorry for this ugly code, but older SunOS gcc compilers don't */
889 /* support white spaces within strings */
890 str_offs = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
891 str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
892 str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
893 str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
895 debug_log(DebugMsg);
896 #endif
901 MainHeadSize=SIZEOF_NEWMHD;
903 return(TRUE);
907 BOOL ExtrFile(void)
909 BOOL ReturnCode=TRUE;
910 FileFound=FALSE; /* no file found by default */
912 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
913 MemRARFile->offset = 0; /* start reading from offset 0 */
914 if (!IsArchive())
916 debug_log("Not a RAR file");
917 return FALSE; /* error => exit! */
920 #else
921 /* open and identify archive */
922 if ((ArcPtr=fopen(ArcName,READBINARY))!=NULL)
924 if (!IsArchive())
926 debug_log("Not a RAR file");
927 fclose(ArcPtr);
928 ArcPtr = NULL;
929 return FALSE; /* error => exit! */
931 } else
933 debug_log("Error opening file.");
934 return FALSE;
936 #endif
939 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
941 debug_log("Can't allocate memory for decompression!");
942 return FALSE;
945 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
946 MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
947 #else
948 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
949 #endif
951 /* do while file is not extracted and there's no error */
955 if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
956 { /* file within the RAR archive */
959 * 21.11.2000 UnQ There's a problem with some linux distros when a file
960 * can not be found in an archive.
962 * debug_log("Couldn't read next filename from archive (I/O error).");
965 ReturnCode=FALSE;
966 break; /* error, file not found in */
967 } /* archive or I/O error */
968 if (BlockHead.HeadType==SUB_HEAD)
970 debug_log("Sorry, sub-headers not supported.");
971 ReturnCode=FALSE;
972 break; /* error => exit */
976 if(TRUE == (FileFound=(my_stricomp(ArgName, ArcFileName) == 0)))
977 /* *** file found! *** */
980 temp_output_buffer=malloc(NewLhd.UnpSize);/* allocate memory for the*/
982 *temp_output_buffer_offset=0; /* file. The default offset */
983 /* within the buffer is 0 */
985 if(temp_output_buffer == NULL)
987 debug_log("can't allocate memory for the file decompression");
988 ReturnCode=FALSE;
989 break; /* error, can't extract file! */
995 /* in case of a solid archive, we need to decompress any single file till
996 * we have found the one we are looking for. In case of normal archives
997 * (recommended!!), we skip the files until we are sure that it is the
998 * one we want.
1000 if((NewMhd.Flags & 0x08) || FileFound)
1002 if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
1004 debug_log("unknown compression method");
1005 ReturnCode=FALSE;
1006 break; /* error, can't extract file! */
1009 CurUnpRead=CurUnpWrite=0;
1010 if ((*Password!=0) && (NewLhd.Flags & LHD_PASSWORD))
1011 Encryption=NewLhd.UnpVer;
1012 else
1013 Encryption=0;
1014 if (Encryption) SetCryptKeys(Password);
1016 UnpPackedSize=NewLhd.PackSize;
1017 DestUnpSize=NewLhd.UnpSize;
1019 if (NewLhd.Method==0x30)
1021 UnstoreFile();
1022 } else
1024 Unpack(UnpMemory);
1029 #ifdef _DO_CRC32_CHECK /* calculate CRC32 */
1030 if((UBYTE*)temp_output_buffer != NULL)
1032 if(NewLhd.FileCRC!=~CalcCRC32(0xFFFFFFFFL,
1033 (UBYTE*)temp_output_buffer,
1034 NewLhd.UnpSize))
1036 debug_log("CRC32 error - file couldn't be decompressed correctly!");
1037 ReturnCode=FALSE;
1038 break; /* error, can't extract file! */
1041 #endif
1045 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1046 MemRARFile->offset = NextBlockPos;
1047 #else
1048 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
1049 #endif
1050 } while(my_stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */
1052 /* free memory, clear password and close archive */
1053 free(UnpMemory);
1054 UnpMemory=NULL;
1055 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1056 if (ArcPtr!=NULL){
1057 fclose(ArcPtr);
1058 ArcPtr = NULL;
1060 #endif
1062 return ReturnCode; /* file extracted successful! */
1065 /* **************************************************************************
1066 ****************************************************************************
1067 ****************************************************************************
1068 ************************************************************************** */
1087 /* **************************************************************************
1088 ****************************************************************************
1089 ****************************************************************************
1090 ****************************************************************************
1091 ******* *******
1092 ******* *******
1093 ******* *******
1094 ******* G L O B A L F U N C T I O N S *******
1095 ******* *******
1096 ******* *******
1097 ******* *******
1098 ****************************************************************************
1099 ****************************************************************************
1100 ****************************************************************************
1101 ************************************************************************** */
1104 int tread(void *stream,void *buf,unsigned len)
1106 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1108 if(((MemRARFile->offset + len) > MemRARFile->size) || (len == 0))
1109 return 0;
1111 memcpy(buf,
1112 (BYTE*)(((MemoryFile*)stream)->data)+((MemoryFile*)stream)->offset,
1113 len % ((((MemoryFile*)stream)->size) - 1));
1115 MemRARFile->offset+=len; /* update read pointer */
1116 return len % ((((MemoryFile*)stream)->size) - 1);
1117 #else
1118 return(fread(buf,1,len,(FILE*)stream));
1119 #endif
1123 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1124 int tseek(void *stream,long offset,int fromwhere)
1126 return(fseek((FILE*)stream,offset,fromwhere));
1128 #endif
1131 static char* my_strupper(char *Str)
1133 char *ChPtr;
1134 for (ChPtr=Str;*ChPtr;ChPtr++)
1135 *ChPtr=(char)toupper(*ChPtr);
1136 return(Str);
1140 static int my_stricomp(char *Str1,char *Str2)
1141 /* compare strings without regard of '\' and '/' */
1143 char S1[512],S2[512];
1144 char *chptr;
1146 strncpy(S1,Str1,sizeof(S1));
1147 strncpy(S2,Str2,sizeof(S2));
1149 while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash */
1151 *chptr = '_';
1154 while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash */
1156 *chptr = '_';
1159 while((chptr = strchr(S1, '/')) != NULL) /* ignore slash */
1161 *chptr = '_';
1164 while((chptr = strchr(S2, '/')) != NULL) /* ignore slash */
1166 *chptr = '_';
1169 return(strcmp(my_strupper(S1),my_strupper(S2)));
1173 /* **************************************************************************
1174 ****************************************************************************
1175 ****************************************************************************
1176 ************************************************************************** */
1195 /* **************************************************************************
1196 ****************************************************************************
1197 ****************************************************************************
1198 ****************************************************************************
1199 ******* *******
1200 ******* *******
1201 ******* *******
1202 ******* U N P A C K C O D E *******
1203 ******* *******
1204 ******* *******
1205 ******* *******
1206 ****************************************************************************
1207 ****************************************************************************
1208 ****************************************************************************
1209 ************************************************************************** */
1212 /* *****************************
1213 * ** unpack stored RAR files **
1214 * *****************************/
1216 BOOL UnstoreFile(void)
1218 if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
1219 NewLhd.UnpSize))==-1)
1221 debug_log("Read error of stored file!");
1222 return FALSE;
1224 return TRUE;
1230 /* ****************************************
1231 * ** RAR decompression code starts here **
1232 * ****************************************/
1234 #define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
1235 #define DC 48
1236 #define RC 28
1237 #define BC 19
1238 #define MC 257
1240 enum {CODE_HUFFMAN=0,CODE_LZ=1,CODE_LZ2=2,CODE_REPEATLZ=3,CODE_CACHELZ=4,
1241 CODE_STARTFILE=5,CODE_ENDFILE=6,CODE_STARTMM=8,CODE_ENDMM=7,
1242 CODE_MMDELTA=9};
1244 struct AudioVariables
1246 int K1,K2,K3,K4,K5;
1247 int D1,D2,D3,D4;
1248 int LastDelta;
1249 unsigned int Dif[11];
1250 unsigned int ByteCount;
1251 int LastChar;
1255 #define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
1256 #define DC 48
1257 #define RC 28
1258 #define BC 19
1259 #define MC 257
1262 struct AudioVariables AudV[4];
1264 #define GetBits() \
1265 BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
1266 ( (UWORD) InBuf[InAddr+1] << 8 ) | \
1267 ( InBuf[InAddr+2] ) ) \
1268 >> (8-InBit) ) & 0xffff;
1271 #define AddBits(Bits) \
1272 InAddr += ( InBit + (Bits) ) >> 3; \
1273 InBit = ( InBit + (Bits) ) & 7;
1275 static unsigned char *UnpBuf;
1276 static unsigned int BitField;
1277 static unsigned int Number;
1279 unsigned char InBuf[8192]; /* input read buffer */
1281 unsigned char UnpOldTable[MC*4];
1283 unsigned int InAddr,InBit,ReadTop;
1285 unsigned int LastDist,LastLength;
1286 static unsigned int Length,Distance;
1288 unsigned int OldDist[4],OldDistPtr;
1291 struct LitDecode
1293 unsigned int MaxNum;
1294 unsigned int DecodeLen[16];
1295 unsigned int DecodePos[16];
1296 unsigned int DecodeNum[NC];
1297 } LD;
1299 struct DistDecode
1301 unsigned int MaxNum;
1302 unsigned int DecodeLen[16];
1303 unsigned int DecodePos[16];
1304 unsigned int DecodeNum[DC];
1305 } DD;
1307 struct RepDecode
1309 unsigned int MaxNum;
1310 unsigned int DecodeLen[16];
1311 unsigned int DecodePos[16];
1312 unsigned int DecodeNum[RC];
1313 } RD;
1315 struct MultDecode
1317 unsigned int MaxNum;
1318 unsigned int DecodeLen[16];
1319 unsigned int DecodePos[16];
1320 unsigned int DecodeNum[MC];
1321 } MD[4];
1323 struct BitDecode
1325 unsigned int MaxNum;
1326 unsigned int DecodeLen[16];
1327 unsigned int DecodePos[16];
1328 unsigned int DecodeNum[BC];
1329 } BD;
1331 static struct MultDecode *MDPtr[4]={&MD[0],&MD[1],&MD[2],&MD[3]};
1333 int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
1336 void Unpack(unsigned char *UnpAddr)
1337 /* *** 38.3% of all CPU time is spent within this function!!! */
1339 static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
1340 40,48,56,64,80,96,112,128,160,192,224};
1341 static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
1342 3,3,3,4,4,4,4,5,5,5,5};
1343 static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
1344 512,768,1024,1536,2048,3072,4096,6144,8192,12288,
1345 16384,24576,32768U,49152U,65536,98304,131072,196608,
1346 262144,327680,393216,458752,524288,589824,655360,
1347 720896,786432,851968,917504,983040};
1348 static unsigned char DBits[]= {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,
1349 9,10,10,11,11,12,12,13,13,14,14,15,15,16,
1350 16,16,16,16,16,16,16,16,16,16,16,16,16};
1351 static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
1352 static unsigned char SDBits[]={2,2,3, 4, 5, 6, 6, 6};
1353 unsigned int Bits;
1356 UnpBuf=UnpAddr; /* UnpAddr is a pointer to the */
1357 UnpInitData(); /* unpack buffer */
1358 UnpReadBuf(1);
1359 if (!(NewLhd.Flags & LHD_SOLID))
1360 ReadTables();
1361 DestUnpSize--;
1363 while (DestUnpSize>=0)
1365 UnpPtr&=MAXWINMASK;
1367 if (InAddr>sizeof(InBuf)-30)
1368 UnpReadBuf(0);
1369 if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
1373 if (FileFound)
1376 if (UnpPtr<WrPtr)
1378 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1380 debug_log("Fatal! Buffer overrun during decompression!");
1381 DestUnpSize=-1;
1383 } else
1385 /* copy extracted data to output buffer */
1386 memcpy(temp_output_buffer + *temp_output_buffer_offset,
1387 &UnpBuf[WrPtr], (0-WrPtr) & MAXWINMASK);
1388 /* update offset within buffer */
1389 *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
1390 /* copy extracted data to output buffer */
1391 memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
1392 UnpPtr);
1393 /* update offset within buffer */
1394 *temp_output_buffer_offset+=UnpPtr;
1396 } else
1398 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1400 debug_log("Fatal! Buffer overrun during decompression!");
1401 DestUnpSize=-1;
1402 } else
1404 /* copy extracted data to output buffer */
1405 memcpy(temp_output_buffer + *temp_output_buffer_offset,
1406 &UnpBuf[WrPtr], UnpPtr-WrPtr);
1407 *temp_output_buffer_offset+=UnpPtr-WrPtr; /* update offset within buffer */
1413 WrPtr=UnpPtr;
1416 if (UnpAudioBlock)
1418 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1419 if (Number==256)
1421 ReadTables();
1422 continue;
1424 UnpBuf[UnpPtr++]=DecodeAudio(Number);
1425 if (++CurChannel==UnpChannels)
1426 CurChannel=0;
1427 DestUnpSize--;
1428 continue;
1431 DecodeNumber((struct Decode *)&LD);
1432 if (Number<256)
1434 UnpBuf[UnpPtr++]=(UBYTE)Number;
1435 DestUnpSize--;
1436 continue;
1438 if (Number>269)
1440 Length=LDecode[Number-=270]+3;
1441 if ((Bits=LBits[Number])>0)
1443 GetBits();
1444 Length+=BitField>>(16-Bits);
1445 AddBits(Bits);
1448 DecodeNumber((struct Decode *)&DD);
1449 Distance=DDecode[Number]+1;
1450 if ((Bits=DBits[Number])>0)
1452 GetBits();
1453 Distance+=BitField>>(16-Bits);
1454 AddBits(Bits);
1457 if (Distance>=0x40000L)
1458 Length++;
1460 if (Distance>=0x2000)
1461 Length++;
1463 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1464 DestUnpSize-=(LastLength=Length);
1465 while (Length--)
1467 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1468 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1471 continue;
1473 if (Number==269)
1475 ReadTables();
1476 continue;
1478 if (Number==256)
1480 Length=LastLength;
1481 Distance=LastDist;
1482 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1483 DestUnpSize-=(LastLength=Length);
1484 while (Length--)
1486 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1487 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1489 continue;
1491 if (Number<261)
1493 Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
1494 DecodeNumber((struct Decode *)&RD);
1495 Length=LDecode[Number]+2;
1496 if ((Bits=LBits[Number])>0)
1498 GetBits();
1499 Length+=BitField>>(16-Bits);
1500 AddBits(Bits);
1502 if (Distance>=0x40000)
1503 Length++;
1504 if (Distance>=0x2000)
1505 Length++;
1506 if (Distance>=0x101)
1507 Length++;
1508 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1509 DestUnpSize-=(LastLength=Length);
1510 while (Length--)
1512 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1513 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1515 continue;
1517 if (Number<270)
1519 Distance=SDDecode[Number-=261]+1;
1520 if ((Bits=SDBits[Number])>0)
1522 GetBits();
1523 Distance+=BitField>>(16-Bits);
1524 AddBits(Bits);
1526 Length=2;
1527 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1528 DestUnpSize-=(LastLength=Length);
1529 while (Length--)
1531 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1532 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1534 continue;
1537 ReadLastTables();
1539 if (FileFound) /* flush buffer */
1542 if (UnpPtr<WrPtr)
1544 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1546 debug_log("Fatal! Buffer overrun during decompression!");
1547 DestUnpSize=-1;
1548 } else
1550 /* copy extracted data to output buffer */
1551 memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
1552 (0-WrPtr) & MAXWINMASK);
1553 /* update offset within buffer */
1554 *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
1555 /* copy extracted data to output buffer */
1556 memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf, UnpPtr);
1557 /* update offset within buffer */
1558 *temp_output_buffer_offset+=UnpPtr;
1560 } else
1562 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1564 debug_log("Fatal! Buffer overrun during decompression!");
1565 DestUnpSize=-1;
1566 } else
1568 /* copy extracted data to output buffer */
1569 memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
1570 UnpPtr-WrPtr);
1571 /* update offset within buffer */
1572 *temp_output_buffer_offset+=UnpPtr-WrPtr;
1577 WrPtr=UnpPtr;
1581 unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
1583 int RetCode=0;
1584 unsigned int I,ReadSize,TotalRead=0;
1585 unsigned char *ReadAddr;
1586 ReadAddr=Addr;
1587 while (Count > 0)
1589 ReadSize=(unsigned int)((Count>(unsigned long)UnpPackedSize) ?
1590 (unsigned int)UnpPackedSize : Count);
1591 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1592 if(MemRARFile->data == NULL)
1593 return(0);
1594 RetCode=tread(MemRARFile, ReadAddr, ReadSize);
1595 #else
1596 if (ArcPtr==NULL)
1597 return(0);
1598 RetCode=tread(ArcPtr,ReadAddr,ReadSize);
1599 #endif
1600 CurUnpRead+=RetCode;
1601 ReadAddr+=RetCode;
1602 TotalRead+=RetCode;
1603 Count-=RetCode;
1604 UnpPackedSize-=RetCode;
1605 break;
1607 if (RetCode!= -1)
1609 RetCode=TotalRead;
1610 if (Encryption)
1612 if (Encryption<20)
1614 debug_log("Old Crypt() not supported!");
1616 else
1618 for (I=0;I<(unsigned int)RetCode;I+=16)
1619 DecryptBlock(&Addr[I]);
1623 return(RetCode);
1627 void UnpReadBuf(int FirstBuf)
1629 int RetCode;
1630 if (FirstBuf)
1632 ReadTop=UnpRead(InBuf,sizeof(InBuf));
1633 InAddr=0;
1635 else
1637 memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
1638 InAddr&=0x1f;
1639 RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
1640 if (RetCode>0)
1641 ReadTop=RetCode+32;
1642 else
1643 ReadTop=InAddr;
1648 void ReadTables(void)
1650 UBYTE BitLength[BC];
1651 unsigned char Table[MC*4];
1652 int TableSize,N,I;
1653 if (InAddr>sizeof(InBuf)-25)
1654 UnpReadBuf(0);
1655 GetBits();
1656 UnpAudioBlock=(BitField & 0x8000);
1658 if (!(BitField & 0x4000))
1659 memset(UnpOldTable,0,sizeof(UnpOldTable));
1660 AddBits(2);
1663 if (UnpAudioBlock)
1665 UnpChannels=((BitField>>12) & 3)+1;
1666 if (CurChannel>=UnpChannels)
1667 CurChannel=0;
1668 AddBits(2);
1669 TableSize=MC*UnpChannels;
1671 else
1672 TableSize=NC+DC+RC;
1675 for (I=0;I<BC;I++)
1677 GetBits();
1678 BitLength[I]=(UBYTE)(BitField >> 12);
1679 AddBits(4);
1681 MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
1682 I=0;
1683 while (I<TableSize)
1685 if (InAddr>sizeof(InBuf)-5)
1686 UnpReadBuf(0);
1687 DecodeNumber((struct Decode *)&BD);
1688 if (Number<16)
1690 Table[I]=(Number+UnpOldTable[I]) & 0xf;
1691 I++;
1693 else
1694 if (Number==16)
1696 GetBits();
1697 N=(BitField >> 14)+3;
1698 AddBits(2);
1699 while (N-- > 0 && I<TableSize)
1701 Table[I]=Table[I-1];
1702 I++;
1705 else
1707 if (Number==17)
1709 GetBits();
1710 N=(BitField >> 13)+3;
1711 AddBits(3);
1713 else
1715 GetBits();
1716 N=(BitField >> 9)+11;
1717 AddBits(7);
1719 while (N-- > 0 && I<TableSize)
1720 Table[I++]=0;
1723 if (UnpAudioBlock)
1724 for (I=0;I<UnpChannels;I++)
1725 MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
1726 else
1728 MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
1729 MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
1730 MakeDecodeTables(&Table[NC+DC],(struct Decode *)&RD,RC);
1732 memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
1736 static void ReadLastTables(void)
1738 if (ReadTop>=InAddr+5)
1740 if (UnpAudioBlock)
1742 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1743 if (Number==256)
1744 ReadTables();
1746 else
1748 DecodeNumber((struct Decode *)&LD);
1749 if (Number==269)
1750 ReadTables();
1756 static void MakeDecodeTables(unsigned char *LenTab,
1757 struct Decode *Dec,
1758 int Size)
1760 int LenCount[16],TmpPos[16],I;
1761 long M,N;
1762 memset(LenCount,0,sizeof(LenCount));
1763 for (I=0;I<Size;I++)
1764 LenCount[LenTab[I] & 0xF]++;
1766 LenCount[0]=0;
1767 for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
1769 N=2*(N+LenCount[I]);
1770 M=N<<(15-I);
1771 if (M>0xFFFF)
1772 M=0xFFFF;
1773 Dec->DecodeLen[I]=(unsigned int)M;
1774 TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
1777 for (I=0;I<Size;I++)
1778 if (LenTab[I]!=0)
1779 Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
1780 Dec->MaxNum=Size;
1784 static void DecodeNumber(struct Decode *Deco)
1785 /* *** 52.6% of all CPU time is spent within this function!!! */
1787 unsigned int I;
1788 register unsigned int N;
1789 GetBits();
1791 #ifdef _USE_ASM
1793 #ifdef _WIN_32
1794 __asm {
1796 xor eax, eax
1797 mov eax, BitField // N=BitField & 0xFFFE;
1798 and eax, 0xFFFFFFFE
1799 mov [N], eax
1800 mov edx, [Deco] // EAX=N, EDX=Deco
1802 cmp eax, dword ptr[edx + 8*4 + 4]// if (N<Dec->DecodeLen[8])
1803 jae else_G
1805 cmp eax, dword ptr[edx + 4*4 + 4]// if (N<Dec->DecodeLen[4])
1806 jae else_F
1809 cmp eax, dword ptr[edx + 2*4 + 4]// if (N<Dec->DecodeLen[2])
1810 jae else_C
1812 cmp eax, dword ptr[edx + 1*4 + 4]// if (N<Dec->DecodeLen[1])
1813 jae else_1
1814 mov I, 1 // I=1;
1815 jmp next_1
1816 else_1: // else
1817 mov I, 2 // I=2;
1818 next_1:
1820 jmp next_C
1821 else_C: // else
1823 cmp eax, dword ptr[edx + 3*4 + 4]// if (N<Dec->DecodeLen[3])
1824 jae else_2
1825 mov I, 3 // I=3;
1826 jmp next_2
1827 else_2: // else
1828 mov I, 4 // I=4;
1829 next_2:
1831 next_C: // else
1833 jmp next_F
1834 else_F:
1837 cmp eax, dword ptr[edx + 6*4 + 4]// if (N<Dec->DecodeLen[6])
1838 jae else_E
1840 cmp eax, dword ptr[edx + 5*4 + 4]// if (N<Dec->DecodeLen[5])
1841 jae else_3
1842 mov I, 5 // I=5;
1843 jmp next_3
1844 else_3: // else
1845 mov I, 6 // I=6;
1846 next_3:
1848 jmp next_E
1849 else_E: // else
1851 cmp eax, dword ptr[edx + 7*4 + 4]// if (N<Dec->DecodeLen[7])
1852 jae else_4
1853 mov I, 7 // I=7;
1854 jmp next_4
1855 else_4: // else
1856 mov I, 8 // I=8;
1857 next_4:
1859 next_E:
1861 next_F:
1863 jmp next_G
1864 else_G:
1866 cmp eax, dword ptr[edx + 12*4 + 4] // if (N<Dec->DecodeLen[12])
1867 jae else_D
1869 cmp eax, dword ptr[edx + 10*4 + 4]// if (N<Dec->DecodeLen[10])
1870 jae else_B
1872 cmp eax, dword ptr[edx + 9*4 + 4]// if (N<Dec->DecodeLen[9])
1873 jae else_5
1874 mov I, 9 // I=9;
1875 jmp next_5
1876 else_5: // else
1877 mov I, 10 // I=10;
1878 next_5:
1880 jmp next_B
1881 else_B: // else
1883 cmp eax, dword ptr[edx + 11*4 + 4]// if (N<Dec->DecodeLen[11])
1884 jae else_6
1885 mov I, 11 // I=11;
1886 jmp next_6
1887 else_6: // else
1888 mov I, 12 // I=12;
1889 next_6:
1891 next_B:
1894 jmp next_D
1895 else_D: // else
1897 cmp eax, dword ptr[edx + 14*4 + 4]// if (N<Dec->DecodeLen[14])
1898 jae else_A
1900 cmp eax, dword ptr[edx + 13*4 + 4]// if (N<Dec->DecodeLen[13])
1901 jae else_7
1902 mov I, 13 // I=13;
1903 jmp next_7
1904 else_7: // else
1905 mov I, 14 // I=14;
1906 next_7:
1908 jmp next_A
1909 else_A: // else
1910 mov I, 15 // I=15;
1911 next_A:
1913 next_D:
1914 next_G:
1916 #else
1917 __asm__ __volatile__ (
1918 "andl $0xFFFFFFFE, %%eax"
1919 " movl %%eax, %1"
1920 " cmpl 8*4(%%edx), %%eax /* 5379 */"
1921 " jae else_G"
1923 " cmpl 4*4(%%edx), %%eax"
1924 " jae else_F"
1926 " cmpl 2*4(%%edx), %%eax"
1927 " jae else_C"
1929 " cmpl 1*4(%%edx), %%eax"
1931 " jae else_1"
1932 " movl $1, %0"
1933 " jmp next_1"
1934 " else_1: "
1935 " movl $2, %0"
1936 " next_1:"
1938 " jmp next_C"
1939 " else_C: "
1941 " cmpl 3*4(%%edx), %%eax "
1942 " jae else_2"
1943 " movl $3, %0"
1944 " jmp next_2"
1945 " else_2: "
1946 " movl $4, %0"
1947 " next_2:"
1949 " next_C: "
1951 " jmp next_F"
1952 " else_F:"
1954 " cmpl 6*4(%%edx), %%eax"
1955 " jae else_E"
1957 " cmpl 5*4(%%edx), %%eax"
1958 " jae else_3"
1959 " movl $5, %0 "
1960 " jmp next_3"
1961 " else_3: "
1962 " movl $6, %0 "
1963 " next_3:"
1965 " jmp next_E"
1966 " else_E: "
1968 " cmpl 7*4(%%edx), %%eax"
1969 " jae else_4"
1970 " movl $7, %0 "
1971 " jmp next_4"
1972 " else_4: "
1973 " movl $8, %0 "
1974 " next_4:"
1976 " next_E:"
1978 " next_F:"
1980 " jmp next_G"
1981 " else_G:"
1983 " cmpl 12*4(%%edx), %%eax"
1984 " jae else_D"
1986 " cmpl 10*4(%%edx), %%eax"
1987 " jae else_B"
1989 " cmpl 9*4(%%edx), %%eax"
1990 " jae else_5"
1991 " movl $9, %0 "
1992 " jmp next_5"
1993 " else_5: "
1994 " movl $10, %0 "
1995 " next_5:"
1997 " jmp next_B"
1998 " else_B: "
2000 " cmpl 11*4(%%edx), %%eax"
2002 " jae else_6"
2003 " movl $11, %0 "
2004 " jmp next_6"
2005 " else_6: "
2006 " movl $12, %0 "
2007 " next_6:"
2009 " next_B:"
2012 " jmp next_D"
2013 " else_D: "
2015 " cmpl 14*4(%%edx), %%eax"
2016 " jae else_A"
2018 " cmpl 13*4(%%edx), %%eax"
2019 " jae else_7"
2020 " movl $13, %0"
2021 " jmp next_7"
2022 " else_7: "
2023 " movl $14, %0"
2024 " next_7:"
2026 " jmp next_A"
2027 " else_A: "
2028 " movl $15, %0 "
2029 " next_A:"
2031 " next_D: "
2032 " next_G:"
2033 : "=g" (I), "=r"(N)
2034 : "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
2035 : "memory"
2037 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
2039 #else
2040 N=BitField & 0xFFFE;
2041 if (N<Deco->DecodeLen[8]) {
2042 if (N<Deco->DecodeLen[4]) {
2043 if (N<Deco->DecodeLen[2]) {
2044 if (N<Deco->DecodeLen[1])
2045 I=1;
2046 else
2047 I=2;
2048 } else {
2049 if (N<Deco->DecodeLen[3])
2050 I=3;
2051 else
2052 I=4;
2054 } else {
2055 if (N<Deco->DecodeLen[6]) {
2056 if (N<Deco->DecodeLen[5])
2057 I=5;
2058 else
2059 I=6;
2060 } else {
2061 if (N<Deco->DecodeLen[7])
2062 I=7;
2063 else
2064 I=8;
2067 } else {
2068 if (N<Deco->DecodeLen[12]) {
2069 if (N<Deco->DecodeLen[10]) {
2070 if (N<Deco->DecodeLen[9])
2071 I=9;
2072 else
2073 I=10;
2074 } else {
2075 if (N<Deco->DecodeLen[11])
2076 I=11;
2077 else
2078 I=12;
2080 } else {
2081 if (N<Deco->DecodeLen[14]) {
2082 if (N<Deco->DecodeLen[13])
2083 I=13;
2084 else
2085 I=14;
2087 } else {
2088 I=15;
2093 #endif
2095 AddBits(I);
2096 if ((N=Deco->DecodePos[I]+((N-Deco->DecodeLen[I-1])>>(16-I)))>=Deco->MaxNum)
2097 N=0;
2098 Number=Deco->DecodeNum[N];
2102 void UnpInitData()
2104 InAddr=InBit=0;
2105 if (!(NewLhd.Flags & LHD_SOLID))
2107 ChannelDelta=CurChannel=0;
2109 #ifdef _USE_ASM
2111 #ifdef _WIN_32 /* Win32 with VisualC */
2113 __asm {
2114 push edi
2115 push eax
2116 push ecx
2118 cld /* increment EDI and ESI */
2119 mov al, 0x00
2120 mov ecx, SIZE AudV
2121 mov edi, Offset AudV
2122 rep stosb /* clear memory */
2124 mov ecx, SIZE OldDist
2125 mov edi, Offset OldDist
2126 rep stosb /* clear memory */
2128 mov ecx, SIZE UnpOldTable
2129 mov edi, Offset UnpOldTable
2130 rep stosb /* clear memory */
2132 pop ecx
2133 pop eax
2134 pop edi
2137 mov [OldDistPtr], 0
2138 mov [LastDist], 0
2139 mov [LastLength], 0
2140 mov [UnpPtr], 0
2141 mov [WrPtr], 0
2142 mov [OldDistPtr], 0
2143 mov [LastLength], 0
2144 mov [LastDist], 0
2145 mov [UnpPtr], 0
2146 mov [WrPtr], 0
2149 memset(UnpBuf,0,MAXWINSIZE);
2152 #else /* unix/linux on i386 cpus */
2153 __asm__ __volatile (
2154 " cld /* increment EDI and ESI */"
2155 " movb $0x00, %%al"
2156 " movl %0, %%ecx"
2157 " movl %1, %%edi"
2158 " rep "
2159 " stosb /* clear memory */"
2161 " movl %2, %%ecx"
2162 " mov %3, %%edi"
2163 " rep "
2164 " stosb /* clear memory */"
2166 " movl %4, %%ecx"
2167 " movl %5, %%edi"
2168 " rep "
2169 " stosb /* clear memory */"
2171 " movl $0, (OldDistPtr)"
2172 " movl $0, (LastDist)"
2173 " movl $0, (LastLength)"
2174 " movl $0, (UnpPtr)"
2175 " movl $0, (WrPtr)"
2176 " movl $0, (OldDistPtr)"
2177 " movl $0, (LastLength)"
2178 " movl $0, (LastDist)"
2179 " movl $0, (UnpPtr)"
2180 " movl $0, (WrPtr)"
2182 : "m" ((long)sizeof(AudV)),
2183 "m" ((long)AudV),
2184 "m" ((long)sizeof(OldDist)),
2185 "m" ((long)OldDist),
2186 "m" ((long)sizeof(UnpOldTable)),
2187 "m" ((long)UnpOldTable)
2188 : "memory", "edi", "eax", "ecx"
2190 memset(UnpBuf,0,MAXWINSIZE);
2191 #endif
2193 #else /* unix/linux on non-i386 cpu */
2194 memset(AudV,0,sizeof(AudV));
2195 memset(OldDist,0,sizeof(OldDist));
2196 OldDistPtr=0;
2197 LastDist=LastLength=0;
2198 memset(UnpBuf,0,MAXWINSIZE);
2199 memset(UnpOldTable,0,sizeof(UnpOldTable));
2200 UnpPtr=WrPtr=0;
2201 #endif
2207 UBYTE DecodeAudio(int Delta)
2209 struct AudioVariables *V;
2210 unsigned int Ch;
2211 unsigned int NumMinDif,MinDif;
2212 int PCh,I;
2214 V=&AudV[CurChannel];
2215 V->ByteCount++;
2216 V->D4=V->D3;
2217 V->D3=V->D2;
2218 V->D2=V->LastDelta-V->D1;
2219 V->D1=V->LastDelta;
2220 PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+
2221 V->K3*V->D3+V->K4*V->D4+V->K5*ChannelDelta;
2222 PCh=(PCh>>3) & 0xFF;
2224 Ch=PCh-Delta;
2226 I=((signed char)Delta)<<3;
2228 V->Dif[0]+=abs(I);
2229 V->Dif[1]+=abs(I-V->D1);
2230 V->Dif[2]+=abs(I+V->D1);
2231 V->Dif[3]+=abs(I-V->D2);
2232 V->Dif[4]+=abs(I+V->D2);
2233 V->Dif[5]+=abs(I-V->D3);
2234 V->Dif[6]+=abs(I+V->D3);
2235 V->Dif[7]+=abs(I-V->D4);
2236 V->Dif[8]+=abs(I+V->D4);
2237 V->Dif[9]+=abs(I-ChannelDelta);
2238 V->Dif[10]+=abs(I+ChannelDelta);
2240 ChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
2241 V->LastChar=Ch;
2243 if ((V->ByteCount & 0x1F)==0)
2245 MinDif=V->Dif[0];
2246 NumMinDif=0;
2247 V->Dif[0]=0;
2248 for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
2250 if (V->Dif[I]<MinDif)
2252 MinDif=V->Dif[I];
2253 NumMinDif=I;
2255 V->Dif[I]=0;
2257 switch(NumMinDif)
2259 case 1:
2260 if (V->K1>=-16)
2261 V->K1--;
2262 break;
2263 case 2:
2264 if (V->K1<16)
2265 V->K1++;
2266 break;
2267 case 3:
2268 if (V->K2>=-16)
2269 V->K2--;
2270 break;
2271 case 4:
2272 if (V->K2<16)
2273 V->K2++;
2274 break;
2275 case 5:
2276 if (V->K3>=-16)
2277 V->K3--;
2278 break;
2279 case 6:
2280 if (V->K3<16)
2281 V->K3++;
2282 break;
2283 case 7:
2284 if (V->K4>=-16)
2285 V->K4--;
2286 break;
2287 case 8:
2288 if (V->K4<16)
2289 V->K4++;
2290 break;
2291 case 9:
2292 if (V->K5>=-16)
2293 V->K5--;
2294 break;
2295 case 10:
2296 if (V->K5<16)
2297 V->K5++;
2298 break;
2301 return((UBYTE)Ch);
2310 /* ***************************************************
2311 * ** CRCCrypt Code - decryption engine starts here **
2312 * ***************************************************/
2315 #define NROUNDS 32
2317 #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
2318 #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
2320 #define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
2321 ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
2322 ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
2323 ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
2326 UDWORD CRCTab[256];
2328 UBYTE SubstTable[256];
2329 UBYTE InitSubstTable[256]={
2330 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
2331 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
2332 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
2333 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
2334 107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
2335 158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
2336 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
2337 164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
2338 207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
2339 122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
2340 131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
2341 224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
2342 118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
2343 161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
2344 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
2345 116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
2348 UDWORD Key[4];
2351 void EncryptBlock(UBYTE *Buf)
2353 int I;
2355 UDWORD A,B,C,D,T,TA,TB;
2356 #ifdef NON_INTEL_BYTE_ORDER
2357 A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
2358 ((UDWORD)Buf[3]<<24))^Key[0];
2359 B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
2360 ((UDWORD)Buf[7]<<24))^Key[1];
2361 C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
2362 ((UDWORD)Buf[11]<<24))^Key[2];
2363 D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
2364 ((UDWORD)Buf[15]<<24))^Key[3];
2365 #else
2366 UDWORD *BufPtr;
2367 BufPtr=(UDWORD *)Buf;
2368 A=BufPtr[0]^Key[0];
2369 B=BufPtr[1]^Key[1];
2370 C=BufPtr[2]^Key[2];
2371 D=BufPtr[3]^Key[3];
2372 #endif
2373 for(I=0;I<NROUNDS;I++)
2375 T=((C+rol(D,11))^Key[I&3]);
2376 TA=A^substLong(T);
2377 T=((D^rol(C,17))+Key[I&3]);
2378 TB=B^substLong(T);
2379 A=C;
2380 B=D;
2381 C=TA;
2382 D=TB;
2384 #ifdef NON_INTEL_BYTE_ORDER
2385 C^=Key[0];
2386 Buf[0]=(UBYTE)C;
2387 Buf[1]=(UBYTE)(C>>8);
2388 Buf[2]=(UBYTE)(C>>16);
2389 Buf[3]=(UBYTE)(C>>24);
2390 D^=Key[1];
2391 Buf[4]=(UBYTE)D;
2392 Buf[5]=(UBYTE)(D>>8);
2393 Buf[6]=(UBYTE)(D>>16);
2394 Buf[7]=(UBYTE)(D>>24);
2395 A^=Key[2];
2396 Buf[8]=(UBYTE)A;
2397 Buf[9]=(UBYTE)(A>>8);
2398 Buf[10]=(UBYTE)(A>>16);
2399 Buf[11]=(UBYTE)(A>>24);
2400 B^=Key[3];
2401 Buf[12]=(UBYTE)B;
2402 Buf[13]=(UBYTE)(B>>8);
2403 Buf[14]=(UBYTE)(B>>16);
2404 Buf[15]=(UBYTE)(B>>24);
2405 #else
2406 BufPtr[0]=C^Key[0];
2407 BufPtr[1]=D^Key[1];
2408 BufPtr[2]=A^Key[2];
2409 BufPtr[3]=B^Key[3];
2410 #endif
2411 UpdKeys(Buf);
2415 void DecryptBlock(UBYTE *Buf)
2417 int I;
2418 UBYTE InBuf[16];
2419 UDWORD A,B,C,D,T,TA,TB;
2420 #ifdef NON_INTEL_BYTE_ORDER
2421 A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
2422 ((UDWORD)Buf[3]<<24))^Key[0];
2423 B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
2424 ((UDWORD)Buf[7]<<24))^Key[1];
2425 C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
2426 ((UDWORD)Buf[11]<<24))^Key[2];
2427 D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
2428 ((UDWORD)Buf[15]<<24))^Key[3];
2429 #else
2430 UDWORD *BufPtr;
2431 BufPtr=(UDWORD *)Buf;
2432 A=BufPtr[0]^Key[0]; /* xxx may be this can be */
2433 B=BufPtr[1]^Key[1]; /* optimized in assembler */
2434 C=BufPtr[2]^Key[2];
2435 D=BufPtr[3]^Key[3];
2436 #endif
2437 memcpy(InBuf,Buf,sizeof(InBuf));
2438 for(I=NROUNDS-1;I>=0;I--)
2440 T=((C+rol(D,11))^Key[I&3]);
2441 TA=A^substLong(T);
2442 T=((D^rol(C,17))+Key[I&3]);
2443 TB=B^substLong(T);
2444 A=C;
2445 B=D;
2446 C=TA;
2447 D=TB;
2449 #ifdef NON_INTEL_BYTE_ORDER
2450 C^=Key[0];
2451 Buf[0]=(UBYTE)C;
2452 Buf[1]=(UBYTE)(C>>8);
2453 Buf[2]=(UBYTE)(C>>16);
2454 Buf[3]=(UBYTE)(C>>24);
2455 D^=Key[1];
2456 Buf[4]=(UBYTE)D;
2457 Buf[5]=(UBYTE)(D>>8);
2458 Buf[6]=(UBYTE)(D>>16);
2459 Buf[7]=(UBYTE)(D>>24);
2460 A^=Key[2];
2461 Buf[8]=(UBYTE)A;
2462 Buf[9]=(UBYTE)(A>>8);
2463 Buf[10]=(UBYTE)(A>>16);
2464 Buf[11]=(UBYTE)(A>>24);
2465 B^=Key[3];
2466 Buf[12]=(UBYTE)B;
2467 Buf[13]=(UBYTE)(B>>8);
2468 Buf[14]=(UBYTE)(B>>16);
2469 Buf[15]=(UBYTE)(B>>24);
2470 #else
2471 BufPtr[0]=C^Key[0];
2472 BufPtr[1]=D^Key[1];
2473 BufPtr[2]=A^Key[2];
2474 BufPtr[3]=B^Key[3];
2475 #endif
2476 UpdKeys(InBuf);
2480 void UpdKeys(UBYTE *Buf)
2482 int I;
2483 for (I=0;I<16;I+=4)
2485 Key[0]^=CRCTab[Buf[I]]; /* xxx may be I'll rewrite this */
2486 Key[1]^=CRCTab[Buf[I+1]]; /* in asm for speedup */
2487 Key[2]^=CRCTab[Buf[I+2]];
2488 Key[3]^=CRCTab[Buf[I+3]];
2492 void SetCryptKeys(char *Password)
2494 unsigned int I,J,K,PswLength;
2495 unsigned char N1,N2;
2496 unsigned char Psw[256];
2498 #if !defined _USE_ASM
2499 UBYTE Ch;
2500 #endif
2502 SetOldKeys(Password);
2504 Key[0]=0xD3A3B879L;
2505 Key[1]=0x3F6D12F7L;
2506 Key[2]=0x7515A235L;
2507 Key[3]=0xA4E7F123L;
2508 memset(Psw,0,sizeof(Psw));
2509 strcpy((char *)Psw,Password);
2510 PswLength=strlen(Password);
2511 memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
2513 for (J=0;J<256;J++)
2514 for (I=0;I<PswLength;I+=2)
2516 N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xFF];
2517 for (K=1, N1=(unsigned char)CRCTab[(Psw[I]-J)&0xFF];
2518 (N1!=N2) && (N1 < 256); /* I had to add "&& (N1 < 256)", */
2519 N1++, K++) /* because the system crashed with */
2520 { /* encrypted RARs */
2521 #ifdef _USE_ASM
2523 #ifdef _WIN_32
2524 __asm {
2526 mov ebx, Offset SubstTable
2527 mov edx, ebx
2529 xor ecx, ecx // read SubstTable[N1]...
2530 mov cl, N1
2531 add ebx, ecx
2532 mov al, byte ptr[ebx]
2534 mov cl, N1 // read SubstTable[(N1+I+K)&0xFF]...
2535 add ecx, I
2536 add ecx, K
2537 and ecx, 0xFF
2538 add edx, ecx
2539 mov ah, byte ptr[edx]
2541 mov byte ptr[ebx], ah // and write back
2542 mov byte ptr[edx], al
2545 #else
2546 __asm__ __volatile__ (
2547 " xorl %%ecx, %%ecx"
2548 " movl %2, %%ecx /* ecx = N1 */"
2549 " mov %%ebx, %%edx"
2550 " addl %%ecx, %%ebx"
2552 " addl %0, %%ecx"
2553 " addl %1, %%ecx"
2554 " andl $0x000000FF, %%ecx"
2555 " addl %%ecx, %%edx"
2557 " movb (%%ebx), %%al"
2558 " movb (%%edx), %%ah"
2560 " movb %%ah, (%%ebx) /* and write back */"
2561 " movb %%al, (%%edx)"
2562 : : "g" ((long)I),
2563 "g" ((long)K),
2564 "g" ((long)N1),
2565 "ebx"((long)SubstTable)
2566 : "ecx", "edx"
2569 #endif
2571 #else
2572 /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
2573 Ch=SubstTable[N1];
2574 SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
2575 SubstTable[(N1+I+K)&0xFF]=Ch;
2576 #endif
2579 for (I=0;I<PswLength;I+=16)
2580 EncryptBlock(&Psw[I]);
2584 void SetOldKeys(char *Password)
2586 UDWORD PswCRC;
2587 UBYTE Ch;
2588 PswCRC=CalcCRC32(0xFFFFFFFFL,(UBYTE*)Password,strlen(Password));
2589 OldKey[0]=(UWORD)PswCRC;
2590 OldKey[1]=(UWORD)(PswCRC>>16);
2591 OldKey[2]=OldKey[3]=0;
2592 PN1=PN2=PN3=0;
2593 while ((Ch=*Password)!=0)
2595 PN1+=Ch;
2596 PN2^=Ch;
2597 PN3+=Ch;
2598 PN3=(UBYTE)rol(PN3,1);
2599 OldKey[2]^=((UWORD)(Ch^CRCTab[Ch]));
2600 OldKey[3]+=((UWORD)(Ch+(CRCTab[Ch]>>16)));
2601 Password++;
2605 void InitCRC(void)
2607 int I, J;
2608 UDWORD C;
2609 for (I=0;I<256;I++)
2611 for (C=I,J=0;J<8;J++)
2612 C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
2613 CRCTab[I]=C;
2618 UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
2620 unsigned int I;
2621 for (I=0; I<Size; I++)
2622 StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
2623 return(StartCRC);
2627 /* **************************************************************************
2628 ****************************************************************************
2629 ****************************************************************************
2630 ************************************************************************** */
2656 /* **************************************************************************
2657 ****************************************************************************
2658 ****************************************************************************
2659 ****************************************************************************
2660 ******* *******
2661 ******* *******
2662 ******* *******
2663 ******* D E B U G F U N C T I O N S *******
2664 ******* *******
2665 ******* *******
2666 ******* *******
2667 ****************************************************************************
2668 ****************************************************************************
2669 ****************************************************************************
2670 ************************************************************************** */
2671 #ifdef _DEBUG_LOG
2674 /* -- global stuff -------------------------------------------------------- */
2675 char log_file_name[256]; /* file name for the log file */
2676 DWORD debug_start_time; /* starttime of debug */
2677 BOOL debug_started = FALSE; /* debug_log writes only if */
2678 /* this is TRUE */
2679 /* ------------------------------------------------------------------------ */
2682 /* -- global functions ---------------------------------------------------- */
2683 void debug_init_proc(char *file_name)
2684 /* Create/Rewrite a log file */
2686 FILE *fp;
2687 char date[] = __DATE__;
2688 char time[] = __TIME__;
2690 debug_start_time = GetTickCount(); /* get start time */
2691 strcpy(log_file_name, file_name); /* save file name */
2693 if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
2695 debug_started = TRUE; /* enable debug */
2696 fprintf(fp, "Debug log of UniquE's RARFileLib\n"\
2697 "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
2698 fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time);
2699 fclose(fp);
2704 void debug_log_proc(char *text, char *sourcefile, int sourceline)
2705 /* add a line to the log file */
2707 FILE *fp;
2709 if(debug_started == FALSE) return; /* exit if not initialized */
2711 if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile */
2714 fprintf(fp, " %8u ms (line %u in %s):\n - %s\n",
2715 (unsigned int)(GetTickCount() - debug_start_time),
2716 sourceline, sourcefile, text);
2717 fclose(fp);
2721 /* ------------------------------------------------------------------------ */
2722 #endif
2723 /* **************************************************************************
2724 ****************************************************************************
2725 ****************************************************************************
2726 ************************************************************************** */
2729 /* end of file urarlib.c */