7446
|
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.
|
|
14 **
|
|
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.
|
|
26 **
|
|
27 ************************************************************************** */
|
|
28
|
|
29 /* ***************************************************************************
|
|
30 **
|
|
31 ** UniquE RAR File Library
|
|
32 ** The free file lib for the demoscene
|
|
33 ** multi-OS version (Win32, Linux and SunOS)
|
|
34 **
|
|
35 *****************************************************************************
|
|
36 **
|
|
37 ** ==> Please configure the program in "unrarlib.h". <==
|
|
38 **
|
|
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)
|
|
45 **
|
|
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.
|
|
55 **
|
|
56 *****************************************************************************
|
|
57 **
|
|
58 ** ==> see the "CHANGES" file to see what's new
|
|
59 **
|
|
60 ************************************************************************** */
|
|
61
|
|
62 /* -- include files ------------------------------------------------------- */
|
|
63 #include "unrarlib.h" /* include global configuration */
|
|
64 /* ------------------------------------------------------------------------ */
|
|
65
|
|
66
|
|
67
|
|
68 /* -- global stuff -------------------------------------------------------- */
|
|
69 #ifdef _WIN_32
|
|
70
|
|
71 #include <windows.h> /* WIN32 definitions */
|
|
72 #include <stdio.h>
|
|
73 #include <string.h>
|
|
74
|
|
75
|
|
76 #define ENABLE_ACCESS
|
|
77
|
|
78 #define HOST_OS WIN_32
|
|
79
|
|
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
|
|
87
|
|
88 #define PATHDIVIDER "\\"
|
|
89 #define CPATHDIVIDER '\\'
|
|
90 #define MASKALL "*.*"
|
|
91
|
|
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"
|
|
98
|
|
99 #endif
|
|
100
|
|
101 #ifdef _UNIX
|
|
102
|
|
103 #include <stdio.h> /* LINUX/UNIX definitions */
|
|
104 #include <stdlib.h>
|
|
105 #include <ctype.h>
|
|
106 #include <string.h>
|
|
107
|
|
108 #define ENABLE_ACCESS
|
|
109
|
|
110 #define HOST_OS UNIX
|
|
111
|
|
112 #define FM_LABEL 0x0000
|
|
113 #define FM_DIREC 0x4000
|
|
114
|
|
115 #define PATHDIVIDER "/"
|
|
116 #define CPATHDIVIDER '/'
|
|
117 #define MASKALL "*.*"
|
|
118
|
|
119 #define READBINARY "r"
|
|
120 #define READTEXT "r"
|
|
121 #define UPDATEBINARY "r+"
|
|
122 #define CREATEBINARY "w+"
|
|
123 #define CREATETEXT "w"
|
|
124 #define APPENDTEXT "a"
|
|
125
|
|
126
|
|
127 /* emulation of the windows API and data types */
|
|
128 /* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
|
|
129
|
|
130 typedef long DWORD;
|
|
131 typedef short BOOL;
|
|
132 #define TRUE 1
|
|
133 #define FALSE 0
|
|
134
|
|
135
|
|
136 #ifdef _DEBUG_LOG /* define macros for debugging */
|
|
137 #include <unistd.h>
|
|
138 #include <sys/time.h>
|
|
139
|
|
140 DWORD GetTickCount()
|
|
141 {
|
|
142 struct timeval tv;
|
|
143 gettimeofday( &tv, 0 );
|
|
144 return (tv.tv_usec / 1000);
|
|
145 }
|
|
146 #endif
|
|
147
|
|
148 #endif
|
|
149
|
|
150
|
|
151
|
|
152
|
|
153
|
|
154 #ifdef _DEBUG_LOG /* define macros for debugging */
|
|
155
|
|
156 BOOL debug_log_first_start = TRUE;
|
|
157
|
|
158 #define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
|
|
159 #define debug_init(a); debug_init_proc(a);
|
|
160
|
|
161 void debug_log_proc(char *text, char *sourcefile, int sourceline);
|
|
162 void debug_init_proc(char *file_name);
|
|
163
|
|
164 #else
|
|
165 #define debug_log(a); /* no debug this time */
|
|
166 #define debug_init(a); /* no debug this time */
|
|
167 #endif
|
|
168
|
|
169
|
|
170
|
|
171
|
|
172
|
|
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
|
|
179
|
|
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
|
|
189
|
|
190
|
|
191 #define PACK_VER 20 /* version of decompression code*/
|
|
192 #define UNP_VER 20
|
|
193 #define PROTECT_VER 20
|
|
194
|
|
195
|
|
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 };
|
|
206
|
|
207
|
|
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
|
|
213
|
|
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
|
|
219
|
|
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
|
|
227
|
|
228 #define LONG_BLOCK 0x8000
|
|
229 #define READSUBBLOCK 0x8000
|
|
230
|
|
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 };
|
|
235
|
|
236
|
|
237 struct MarkHeader
|
|
238 {
|
|
239 UBYTE Mark[7];
|
|
240 };
|
|
241
|
|
242
|
|
243 struct NewMainArchiveHeader
|
|
244 {
|
|
245 UWORD HeadCRC;
|
|
246 UBYTE HeadType;
|
|
247 UWORD Flags;
|
|
248 UWORD HeadSize;
|
|
249 UWORD Reserved;
|
|
250 UDWORD Reserved1;
|
|
251 };
|
|
252
|
|
253
|
|
254 struct NewFileHeader
|
|
255 {
|
|
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;
|
|
269 };
|
|
270
|
|
271
|
|
272 struct BlockHeader
|
|
273 {
|
|
274 UWORD HeadCRC;
|
|
275 UBYTE HeadType;
|
|
276 UWORD Flags;
|
|
277 UWORD HeadSize;
|
|
278 UDWORD DataSize;
|
|
279 };
|
|
280
|
|
281
|
|
282 struct Decode
|
|
283 {
|
|
284 unsigned int MaxNum;
|
|
285 unsigned int DecodeLen[16];
|
|
286 unsigned int DecodePos[16];
|
|
287 unsigned int DecodeNum[2];
|
|
288 };
|
|
289
|
|
290
|
|
291 struct MarkHeader MarkHead;
|
|
292 struct NewMainArchiveHeader NewMhd;
|
|
293 struct NewFileHeader NewLhd;
|
|
294 struct BlockHeader BlockHead;
|
|
295
|
|
296 UBYTE *TempMemory; /* temporary unpack-buffer */
|
|
297 char *CommMemory;
|
|
298
|
|
299
|
|
300 UBYTE *UnpMemory;
|
|
301 char ArgName[NM]; /* current file in rar archive */
|
|
302 char ArcFileName[NM]; /* file to decompress */
|
|
303
|
|
304 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
|
|
305 MemoryFile *MemRARFile; /* pointer to RAR file in memory*/
|
|
306 #else
|
|
307 char ArcName[255]; /* RAR archive name */
|
|
308 FILE *ArcPtr; /* input RAR file handler */
|
|
309 #endif
|
|
310 char Password[255]; /* password to decrypt files */
|
|
311
|
|
312 unsigned char *temp_output_buffer; /* extract files to this pointer*/
|
|
313 unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */
|
|
314
|
|
315 BOOL FileFound; /* TRUE=use current extracted */
|
|
316 /* data FALSE=throw data away, */
|
|
317 /* wrong file */
|
|
318 int MainHeadSize;
|
|
319 long CurBlockPos,NextBlockPos;
|
|
320
|
|
321 unsigned long CurUnpRead, CurUnpWrite;
|
|
322 long UnpPackedSize;
|
|
323 long DestUnpSize;
|
|
324
|
|
325 UDWORD HeaderCRC;
|
|
326 int Encryption;
|
|
327
|
|
328 unsigned int UnpWrSize;
|
|
329 unsigned char *UnpWrAddr;
|
|
330 unsigned int UnpPtr,WrPtr;
|
|
331
|
|
332 unsigned char PN1,PN2,PN3;
|
|
333 unsigned short OldKey[4];
|
|
334
|
|
335
|
|
336
|
|
337 /* function header definitions */
|
|
338 int ReadHeader(int BlockType);
|
|
339 BOOL ExtrFile(void);
|
|
340 BOOL ListFile(void);
|
|
341 int tread(void *stream,void *buf,unsigned len);
|
|
342 int tseek(void *stream,long offset,int fromwhere);
|
|
343 BOOL UnstoreFile(void);
|
|
344 int IsArchive(void);
|
|
345 int ReadBlock(int BlockType);
|
|
346 unsigned int UnpRead(unsigned char *Addr,unsigned int Count);
|
|
347 void UnpInitData(void);
|
|
348 void Unpack(unsigned char *UnpAddr);
|
|
349 UBYTE DecodeAudio(int Delta);
|
|
350 static void DecodeNumber(struct Decode *Dec);
|
|
351 void UpdKeys(UBYTE *Buf);
|
|
352 void SetCryptKeys(char *Password);
|
|
353 void SetOldKeys(char *Password);
|
|
354 void DecryptBlock(unsigned char *Buf);
|
|
355 void InitCRC(void);
|
|
356 UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);
|
|
357 void UnpReadBuf(int FirstBuf);
|
|
358 void ReadTables(void);
|
|
359 static void ReadLastTables(void);
|
|
360 static void MakeDecodeTables(unsigned char *LenTab,
|
|
361 struct Decode *Dec,
|
|
362 int Size);
|
|
363 int stricomp(char *Str1,char *Str2);
|
|
364 /* ------------------------------------------------------------------------ */
|
|
365
|
|
366
|
|
367 /* -- global functions ---------------------------------------------------- */
|
|
368
|
|
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.
|
|
378 */
|
|
379 {
|
|
380 BOOL retcode = FALSE;
|
|
381
|
|
382 #ifdef _DEBUG_LOG
|
|
383 int str_offs; /* used for debug-strings */
|
|
384 char DebugMsg[500]; /* used to compose debug msg */
|
|
385
|
|
386 if(debug_log_first_start)
|
|
387 {
|
|
388 debug_log_first_start=FALSE; /* only create a new log file */
|
|
389 debug_init(_DEBUG_LOG_FILE); /* on startup */
|
|
390 }
|
|
391
|
|
392 #endif
|
|
393
|
|
394 InitCRC(); /* init some vars */
|
|
395
|
|
396 strcpy(ArgName, filename); /* set file(s) to extract */
|
|
397 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
398 MemRARFile = rarfile; /* set pointer to mem-RAR file */
|
|
399 #else
|
|
400 strcpy(ArcName, rarfile); /* set RAR file name */
|
|
401 #endif
|
|
402 if(libpassword != NULL)
|
|
403 strcpy(Password, libpassword); /* init password */
|
|
404
|
|
405 temp_output_buffer = NULL;
|
|
406 temp_output_buffer_offset=size; /* set size of the temp buffer */
|
|
407
|
|
408 #ifdef _DEBUG_LOG
|
|
409 sprintf(DebugMsg, "Extracting >%s< from >%s< (password is >%s<)...",
|
|
410 filename, (char*)rarfile, libpassword);
|
|
411 debug_log(DebugMsg);
|
|
412 #endif
|
|
413
|
|
414 retcode = ExtrFile(); /* unpack file now! */
|
|
415
|
|
416 memset(Password,0,sizeof(Password)); /* clear password */
|
|
417
|
|
418 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
419 if (ArcPtr!=NULL){
|
|
420 fclose(ArcPtr);
|
|
421 ArcPtr = NULL;
|
|
422 }
|
|
423 #endif
|
|
424
|
|
425 free(UnpMemory); /* free memory */
|
|
426 free(TempMemory);
|
|
427 free(CommMemory);
|
|
428 UnpMemory=NULL;
|
|
429 TempMemory=NULL;
|
|
430 CommMemory=NULL;
|
|
431
|
|
432
|
|
433 if(retcode == FALSE)
|
|
434 {
|
|
435 free(temp_output_buffer); /* free memory and return NULL */
|
|
436 temp_output_buffer=NULL;
|
|
437 *(DWORD*)output=0; /* pointer on errors */
|
|
438 *size=0;
|
|
439 #ifdef _DEBUG_LOG
|
|
440
|
|
441
|
|
442 /* sorry for this ugly code, but older SunOS gcc compilers don't support */
|
|
443 /* white spaces within strings */
|
|
444 str_offs = sprintf(DebugMsg, "Error - couldn't extract ");
|
|
445 str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename);
|
|
446 str_offs += sprintf(DebugMsg + str_offs, " and allocated ");
|
|
447 str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size);
|
|
448 str_offs += sprintf(DebugMsg + str_offs, " of unused memory!");
|
|
449
|
|
450 } else
|
|
451 {
|
|
452 sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
|
|
453 }
|
|
454 debug_log(DebugMsg);
|
|
455 #else
|
|
456 }
|
|
457 #endif
|
|
458 *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
|
|
459 /* data */
|
|
460
|
|
461 return retcode;
|
|
462 }
|
|
463
|
|
464
|
|
465 int urarlib_list(void *rarfile, ArchiveList_struct *list)
|
|
466 {
|
|
467 ArchiveList_struct *tmp_List = NULL;
|
|
468 int NoOfFilesInArchive = 0; /* number of files in archive */
|
|
469
|
|
470 #ifdef _DEBUG_LOG
|
|
471 if(debug_log_first_start)
|
|
472 {
|
|
473 debug_log_first_start=FALSE; /* only create a new log file */
|
|
474 debug_init(_DEBUG_LOG_FILE); /* on startup */
|
|
475 }
|
|
476 #endif
|
|
477
|
|
478 InitCRC(); /* init some vars */
|
|
479
|
|
480 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
481 MemRARFile = rarfile; /* assign pointer to RAR file */
|
|
482 MemRARFile->offset = 0;
|
|
483 if (!IsArchive())
|
|
484 {
|
|
485 debug_log("Not a RAR file");
|
|
486 return NoOfFilesInArchive; /* error => exit! */
|
|
487 }
|
|
488 #else
|
|
489 /* open and identify archive */
|
|
490 if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL)
|
|
491 {
|
|
492 if (!IsArchive())
|
|
493 {
|
|
494 debug_log("Not a RAR file");
|
|
495 fclose(ArcPtr);
|
|
496 ArcPtr = NULL;
|
|
497 return NoOfFilesInArchive; /* error => exit! */
|
|
498 }
|
|
499 }
|
|
500 else {
|
|
501 debug_log("Error opening file.");
|
|
502 return NoOfFilesInArchive;
|
|
503 }
|
|
504 #endif
|
|
505
|
|
506 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
|
|
507 {
|
|
508 debug_log("Can't allocate memory for decompression!");
|
|
509 return NoOfFilesInArchive;
|
|
510 }
|
|
511
|
|
512 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
513 MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
|
|
514 #else
|
|
515 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
|
|
516 #endif
|
|
517 (*(DWORD*)list) = (DWORD)NULL; /* init file list */
|
|
518 /* do while file is not extracted and there's no error */
|
|
519 while (TRUE)
|
|
520 {
|
|
521 if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
|
|
522 { /* file within the RAR archive */
|
|
523 debug_log("Couldn't read next filename from archive (I/O error).");
|
|
524 break; /* error, file not found in */
|
|
525 } /* archive or I/O error */
|
|
526 if (BlockHead.HeadType==SUB_HEAD)
|
|
527 {
|
|
528 debug_log("Sorry, sub-headers not supported.");
|
|
529 break; /* error => exit */
|
|
530 }
|
|
531
|
|
532 if((void*)(*(DWORD*)list) == NULL) /* first entry */
|
|
533 {
|
|
534 tmp_List = malloc(sizeof(ArchiveList_struct));
|
|
535 tmp_List->next = NULL;
|
|
536
|
|
537 (*(DWORD*)list) = (DWORD)tmp_List;
|
|
538
|
|
539 } else /* add entry */
|
|
540 {
|
|
541 tmp_List->next = malloc(sizeof(ArchiveList_struct));
|
|
542 tmp_List = (ArchiveList_struct*) tmp_List->next;
|
|
543 tmp_List->next = NULL;
|
|
544 }
|
|
545
|
|
546 tmp_List->item.Name = malloc(NewLhd.NameSize + 1);
|
|
547 strcpy(tmp_List->item.Name, ArcFileName);
|
|
548 tmp_List->item.NameSize = NewLhd.NameSize;
|
|
549 tmp_List->item.PackSize = NewLhd.PackSize;
|
|
550 tmp_List->item.UnpSize = NewLhd.UnpSize;
|
|
551 tmp_List->item.HostOS = NewLhd.HostOS;
|
|
552 tmp_List->item.FileCRC = NewLhd.FileCRC;
|
|
553 tmp_List->item.FileTime = NewLhd.FileTime;
|
|
554 tmp_List->item.UnpVer = NewLhd.UnpVer;
|
|
555 tmp_List->item.Method = NewLhd.Method;
|
|
556 tmp_List->item.FileAttr = NewLhd.FileAttr;
|
|
557
|
|
558 NoOfFilesInArchive++; /* count files */
|
|
559
|
|
560 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
561 MemRARFile->offset = NextBlockPos;
|
|
562 #else
|
|
563 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
|
|
564 #endif
|
|
565
|
|
566 };
|
|
567
|
|
568 /* free memory, clear password and close archive */
|
|
569 memset(Password,0,sizeof(Password)); /* clear password */
|
|
570 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
571 if (ArcPtr!=NULL){
|
|
572 fclose(ArcPtr);
|
|
573 ArcPtr = NULL;
|
|
574 }
|
|
575 #endif
|
|
576
|
|
577 free(UnpMemory); /* free memory */
|
|
578 free(TempMemory);
|
|
579 free(CommMemory);
|
|
580 UnpMemory=NULL;
|
|
581 TempMemory=NULL;
|
|
582 CommMemory=NULL;
|
|
583
|
|
584 return NoOfFilesInArchive;
|
|
585 }
|
|
586
|
|
587
|
|
588
|
|
589 /* urarlib_freelist:
|
|
590 * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
|
|
591 * and Johannes Winkelmann who independently wrote a patch)
|
|
592 * free the memory of a ArchiveList_struct created by urarlib_list.
|
|
593 *
|
|
594 * input: *list pointer to an ArchiveList_struct
|
|
595 * output: -
|
|
596 */
|
|
597
|
|
598 void urarlib_freelist(ArchiveList_struct *list)
|
|
599 {
|
|
600 ArchiveList_struct* tmp = list;
|
|
601
|
|
602 while ( list ) {
|
|
603 tmp = list->next;
|
|
604 free( list->item.Name );
|
|
605 free( list );
|
|
606 list = tmp;
|
|
607 }
|
|
608 }
|
|
609
|
|
610
|
|
611 /* ------------------------------------------------------------------------ */
|
|
612
|
|
613
|
|
614
|
|
615
|
|
616
|
|
617
|
|
618
|
|
619
|
|
620
|
|
621
|
|
622
|
|
623
|
|
624
|
|
625
|
|
626
|
|
627
|
|
628
|
|
629 /****************************************************************************
|
|
630 ****************************************************************************
|
|
631 ****************************************************************************
|
|
632 ****************************************************************************
|
|
633 ******* *******
|
|
634 ******* *******
|
|
635 ******* *******
|
|
636 ******* B L O C K I / O *******
|
|
637 ******* *******
|
|
638 ******* *******
|
|
639 ******* *******
|
|
640 ****************************************************************************
|
|
641 ****************************************************************************
|
|
642 ****************************************************************************
|
|
643 ****************************************************************************/
|
|
644
|
|
645
|
|
646
|
|
647 #define GetHeaderByte(N) Header[N]
|
|
648
|
|
649 #define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
|
|
650
|
|
651 #define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
|
|
652 ((UDWORD)Header[N+2]<<16)+\
|
|
653 ((UDWORD)Header[N+3]<<24))
|
|
654
|
|
655
|
|
656 int ReadBlock(int BlockType)
|
|
657 {
|
|
658 struct NewFileHeader SaveFileHead;
|
|
659 int Size=0,ReadSubBlock=0;
|
|
660 static int LastBlock;
|
|
661 memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
|
|
662 if (BlockType & READSUBBLOCK)
|
|
663 ReadSubBlock=1;
|
|
664 BlockType &= 0xff;
|
|
665 {
|
|
666 while (1)
|
|
667 {
|
|
668 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
669 CurBlockPos=MemRARFile->offset; /* get offset of mem-file */
|
|
670 #else
|
|
671 CurBlockPos=ftell(ArcPtr);
|
|
672 #endif
|
|
673 Size=ReadHeader(FILE_HEAD);
|
|
674 if (Size!=0)
|
|
675 {
|
|
676 if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
|
|
677 return(0);
|
|
678 NextBlockPos=CurBlockPos+NewLhd.HeadSize;
|
|
679 if (NewLhd.Flags & LONG_BLOCK)
|
|
680 NextBlockPos+=NewLhd.PackSize;
|
|
681 if (NextBlockPos<=CurBlockPos)
|
|
682 return(0);
|
|
683 }
|
|
684
|
|
685 if (Size > 0 && BlockType!=SUB_HEAD)
|
|
686 LastBlock=BlockType;
|
|
687 if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
|
|
688 (NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
|
|
689 break;
|
|
690 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
691 MemRARFile->offset = NextBlockPos;
|
|
692 #else
|
|
693 tseek(ArcPtr, NextBlockPos, SEEK_SET);
|
|
694 #endif
|
|
695 }
|
|
696 }
|
|
697
|
|
698 BlockHead.HeadCRC=NewLhd.HeadCRC;
|
|
699 BlockHead.HeadType=NewLhd.HeadType;
|
|
700 BlockHead.Flags=NewLhd.Flags;
|
|
701 BlockHead.HeadSize=NewLhd.HeadSize;
|
|
702 BlockHead.DataSize=NewLhd.PackSize;
|
|
703
|
|
704 if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
|
|
705
|
|
706 if((FILE_HEAD == BlockType) && (Size>0))
|
|
707 {
|
|
708 NewLhd.NameSize=Min(NewLhd.NameSize,sizeof(ArcFileName)-1);
|
|
709 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
710 tread(MemRARFile, ArcFileName, NewLhd.NameSize);
|
|
711 #else
|
|
712 tread(ArcPtr,ArcFileName,NewLhd.NameSize);
|
|
713 #endif
|
|
714 ArcFileName[NewLhd.NameSize]=0;
|
|
715 #ifdef _DEBUG_LOG
|
|
716 if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
|
|
717 NewLhd.NameSize))
|
|
718 {
|
|
719 debug_log("file header broken");
|
|
720 }
|
|
721 #endif
|
|
722 Size+=NewLhd.NameSize;
|
|
723 } else
|
|
724 {
|
|
725 memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
|
|
726 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
727 MemRARFile->offset = CurBlockPos;
|
|
728 #else
|
|
729 tseek(ArcPtr,CurBlockPos,SEEK_SET);
|
|
730 #endif
|
|
731 }
|
|
732
|
|
733
|
|
734 return(Size);
|
|
735 }
|
|
736
|
|
737
|
|
738 int ReadHeader(int BlockType)
|
|
739 {
|
|
740 int Size = 0;
|
|
741 unsigned char Header[64];
|
|
742 switch(BlockType)
|
|
743 {
|
|
744 case MAIN_HEAD:
|
|
745 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
746 Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
|
|
747 #else
|
|
748 Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
|
|
749 #endif
|
|
750 NewMhd.HeadCRC=(unsigned short)GetHeaderWord(0);
|
|
751 NewMhd.HeadType=GetHeaderByte(2);
|
|
752 NewMhd.Flags=(unsigned short)GetHeaderWord(3);
|
|
753 NewMhd.HeadSize=(unsigned short)GetHeaderWord(5);
|
|
754 NewMhd.Reserved=(unsigned short)GetHeaderWord(7);
|
|
755 NewMhd.Reserved1=GetHeaderDword(9);
|
|
756 HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWMHD-2);
|
|
757 break;
|
|
758 case FILE_HEAD:
|
|
759 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
760 Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
|
|
761 #else
|
|
762 Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
|
|
763 #endif
|
|
764 NewLhd.HeadCRC=(unsigned short)GetHeaderWord(0);
|
|
765 NewLhd.HeadType=GetHeaderByte(2);
|
|
766 NewLhd.Flags=(unsigned short)GetHeaderWord(3);
|
|
767 NewLhd.HeadSize=(unsigned short)GetHeaderWord(5);
|
|
768 NewLhd.PackSize=GetHeaderDword(7);
|
|
769 NewLhd.UnpSize=GetHeaderDword(11);
|
|
770 NewLhd.HostOS=GetHeaderByte(15);
|
|
771 NewLhd.FileCRC=GetHeaderDword(16);
|
|
772 NewLhd.FileTime=GetHeaderDword(20);
|
|
773 NewLhd.UnpVer=GetHeaderByte(24);
|
|
774 NewLhd.Method=GetHeaderByte(25);
|
|
775 NewLhd.NameSize=(unsigned short)GetHeaderWord(26);
|
|
776 NewLhd.FileAttr=GetHeaderDword(28);
|
|
777 HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWLHD-2);
|
|
778 break;
|
|
779
|
|
780 #ifdef _DEBUG_LOG
|
|
781 case COMM_HEAD: /* log errors in case of debug */
|
|
782 debug_log("Comment headers not supported! "\
|
|
783 "Please create archives without comments.");
|
|
784 break;
|
|
785 case PROTECT_HEAD:
|
|
786 debug_log("Protected headers not supported!");
|
|
787 break;
|
|
788 case ALL_HEAD:
|
|
789 debug_log("ShortBlockHeader not supported!");
|
|
790 break;
|
|
791 default:
|
|
792 debug_log("Unknown//unsupported !");
|
|
793 #else
|
|
794 default: /* else do nothing */
|
|
795 break;
|
|
796 #endif
|
|
797 }
|
|
798 return(Size);
|
|
799 }
|
|
800
|
|
801 /* **************************************************************************
|
|
802 ****************************************************************************
|
|
803 ****************************************************************************
|
|
804 ************************************************************************** */
|
|
805
|
|
806
|
|
807
|
|
808
|
|
809
|
|
810
|
|
811
|
|
812
|
|
813
|
|
814
|
|
815
|
|
816
|
|
817
|
|
818
|
|
819
|
|
820
|
|
821
|
|
822 /* **************************************************************************
|
|
823 ****************************************************************************
|
|
824 ****************************************************************************
|
|
825 ****************************************************************************
|
|
826 ******* *******
|
|
827 ******* *******
|
|
828 ******* *******
|
|
829 ******* E X T R A C T L O O P *******
|
|
830 ******* *******
|
|
831 ******* *******
|
|
832 ******* *******
|
|
833 ****************************************************************************
|
|
834 ****************************************************************************
|
|
835 ****************************************************************************
|
|
836 ************************************************************************** */
|
|
837
|
|
838
|
|
839 int IsArchive(void)
|
|
840 {
|
|
841 #ifdef _DEBUG_LOG
|
|
842 int str_offs; /* used for debug-strings */
|
|
843 char DebugMsg[500]; /* used to compose debug msg */
|
|
844 #endif
|
|
845
|
|
846 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
847 if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD)
|
|
848 return(FALSE);
|
|
849 #else
|
|
850 if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
|
|
851 return(FALSE);
|
|
852 #endif
|
|
853 /* Old archive => error */
|
|
854 if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
|
|
855 MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
|
|
856 {
|
|
857 debug_log("Attention: format as OLD detected! Can't handel archive!");
|
|
858 }
|
|
859 else
|
|
860 /* original RAR v2.0 */
|
|
861 if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original */
|
|
862 MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
|
|
863 MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
|
|
864 MarkHead.Mark[6]==0x00) ||
|
|
865 /* "UniquE!" - header */
|
|
866 (MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' && /* "UniquE!" */
|
|
867 MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' && /* header */
|
|
868 MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
|
|
869 MarkHead.Mark[6]=='!'))
|
|
870
|
|
871 {
|
|
872 if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD)
|
|
873 return(FALSE);
|
|
874 } else
|
|
875 {
|
|
876
|
|
877 #ifdef _DEBUG_LOG
|
|
878 /* sorry for this ugly code, but older SunOS gcc compilers don't */
|
|
879 /* support white spaces within strings */
|
|
880 str_offs = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
|
|
881 str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
|
|
882 str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
|
|
883 str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
|
|
884
|
|
885 debug_log(DebugMsg);
|
|
886 #endif
|
|
887
|
|
888 }
|
|
889
|
|
890
|
|
891 MainHeadSize=SIZEOF_NEWMHD;
|
|
892
|
|
893 return(TRUE);
|
|
894 }
|
|
895
|
|
896
|
|
897 BOOL ExtrFile(void)
|
|
898 {
|
|
899 BOOL ReturnCode=TRUE;
|
|
900 FileFound=FALSE; /* no file found by default */
|
|
901
|
|
902 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
903 MemRARFile->offset = 0; /* start reading from offset 0 */
|
|
904 if (!IsArchive())
|
|
905 {
|
|
906 debug_log("Not a RAR file");
|
|
907 return FALSE; /* error => exit! */
|
|
908 }
|
|
909
|
|
910 #else
|
|
911 /* open and identify archive */
|
|
912 if ((ArcPtr=fopen(ArcName,READBINARY))!=NULL)
|
|
913 {
|
|
914 if (!IsArchive())
|
|
915 {
|
|
916 debug_log("Not a RAR file");
|
|
917 fclose(ArcPtr);
|
|
918 ArcPtr = NULL;
|
|
919 return FALSE; /* error => exit! */
|
|
920 }
|
|
921 } else
|
|
922 {
|
|
923 debug_log("Error opening file.");
|
|
924 return FALSE;
|
|
925 }
|
|
926 #endif
|
|
927
|
|
928
|
|
929 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
|
|
930 {
|
|
931 debug_log("Can't allocate memory for decompression!");
|
|
932 return FALSE;
|
|
933 }
|
|
934
|
|
935 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
936 MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
|
|
937 #else
|
|
938 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
|
|
939 #endif
|
|
940
|
|
941 /* do while file is not extracted and there's no error */
|
|
942 do
|
|
943 {
|
|
944
|
|
945 if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
|
|
946 { /* file within the RAR archive */
|
|
947 /*
|
|
948 *
|
|
949 * 21.11.2000 UnQ There's a problem with some linux distros when a file
|
|
950 * can not be found in an archive.
|
|
951 *
|
|
952 * debug_log("Couldn't read next filename from archive (I/O error).");
|
|
953 *
|
|
954 */
|
|
955 ReturnCode=FALSE;
|
|
956 break; /* error, file not found in */
|
|
957 } /* archive or I/O error */
|
|
958 if (BlockHead.HeadType==SUB_HEAD)
|
|
959 {
|
|
960 debug_log("Sorry, sub-headers not supported.");
|
|
961 ReturnCode=FALSE;
|
|
962 break; /* error => exit */
|
|
963 }
|
|
964
|
|
965
|
|
966 if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
|
|
967 /* *** file found! *** */
|
|
968 {
|
|
969 {
|
|
970 temp_output_buffer=malloc(NewLhd.UnpSize);/* allocate memory for the*/
|
|
971 }
|
|
972 *temp_output_buffer_offset=0; /* file. The default offset */
|
|
973 /* within the buffer is 0 */
|
|
974
|
|
975 if(temp_output_buffer == NULL)
|
|
976 {
|
|
977 debug_log("can't allocate memory for the file decompression");
|
|
978 ReturnCode=FALSE;
|
|
979 break; /* error, can't extract file! */
|
|
980 }
|
|
981
|
|
982
|
|
983 }
|
|
984
|
|
985 /* in case of a solid archive, we need to decompress any single file till
|
|
986 * we have found the one we are looking for. In case of normal archives
|
|
987 * (recommended!!), we skip the files until we are sure that it is the
|
|
988 * one we want.
|
|
989 */
|
|
990 if((NewMhd.Flags & 0x08) || FileFound)
|
|
991 {
|
|
992 if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
|
|
993 {
|
|
994 debug_log("unknown compression method");
|
|
995 ReturnCode=FALSE;
|
|
996 break; /* error, can't extract file! */
|
|
997 }
|
|
998
|
|
999 CurUnpRead=CurUnpWrite=0;
|
|
1000 if ((*Password!=0) && (NewLhd.Flags & LHD_PASSWORD))
|
|
1001 Encryption=NewLhd.UnpVer;
|
|
1002 else
|
|
1003 Encryption=0;
|
|
1004 if (Encryption) SetCryptKeys(Password);
|
|
1005
|
|
1006 UnpPackedSize=NewLhd.PackSize;
|
|
1007 DestUnpSize=NewLhd.UnpSize;
|
|
1008
|
|
1009 if (NewLhd.Method==0x30)
|
|
1010 {
|
|
1011 UnstoreFile();
|
|
1012 } else
|
|
1013 {
|
|
1014 Unpack(UnpMemory);
|
|
1015 }
|
|
1016
|
|
1017
|
|
1018
|
|
1019 #ifdef _DO_CRC32_CHECK /* calculate CRC32 */
|
|
1020 if((UBYTE*)temp_output_buffer != NULL)
|
|
1021 {
|
|
1022 if(NewLhd.FileCRC!=~CalcCRC32(0xFFFFFFFFL,
|
|
1023 (UBYTE*)temp_output_buffer,
|
|
1024 NewLhd.UnpSize))
|
|
1025 {
|
|
1026 debug_log("CRC32 error - file couldn't be decompressed correctly!");
|
|
1027 ReturnCode=FALSE;
|
|
1028 break; /* error, can't extract file! */
|
|
1029 }
|
|
1030 }
|
|
1031 #endif
|
|
1032
|
|
1033 }
|
|
1034
|
|
1035 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
1036 MemRARFile->offset = NextBlockPos;
|
|
1037 #else
|
|
1038 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
|
|
1039 #endif
|
|
1040 } while(stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */
|
|
1041
|
|
1042 /* free memory, clear password and close archive */
|
|
1043 free(UnpMemory);
|
|
1044 UnpMemory=NULL;
|
|
1045 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
1046 if (ArcPtr!=NULL){
|
|
1047 fclose(ArcPtr);
|
|
1048 ArcPtr = NULL;
|
|
1049 }
|
|
1050 #endif
|
|
1051
|
|
1052 return ReturnCode; /* file extracted successful! */
|
|
1053 }
|
|
1054
|
|
1055 /* **************************************************************************
|
|
1056 ****************************************************************************
|
|
1057 ****************************************************************************
|
|
1058 ************************************************************************** */
|
|
1059
|
|
1060
|
|
1061
|
|
1062
|
|
1063
|
|
1064
|
|
1065
|
|
1066
|
|
1067
|
|
1068
|
|
1069
|
|
1070
|
|
1071
|
|
1072
|
|
1073
|
|
1074
|
|
1075
|
|
1076
|
|
1077 /* **************************************************************************
|
|
1078 ****************************************************************************
|
|
1079 ****************************************************************************
|
|
1080 ****************************************************************************
|
|
1081 ******* *******
|
|
1082 ******* *******
|
|
1083 ******* *******
|
|
1084 ******* G L O B A L F U N C T I O N S *******
|
|
1085 ******* *******
|
|
1086 ******* *******
|
|
1087 ******* *******
|
|
1088 ****************************************************************************
|
|
1089 ****************************************************************************
|
|
1090 ****************************************************************************
|
|
1091 ************************************************************************** */
|
|
1092
|
|
1093
|
|
1094 int tread(void *stream,void *buf,unsigned len)
|
|
1095 {
|
|
1096 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
1097
|
|
1098 if(((MemRARFile->offset + len) > MemRARFile->size) || (len == 0))
|
|
1099 return 0;
|
|
1100
|
|
1101 memcpy(buf,
|
|
1102 (BYTE*)(((MemoryFile*)stream)->data)+((MemoryFile*)stream)->offset,
|
|
1103 len % ((((MemoryFile*)stream)->size) - 1));
|
|
1104
|
|
1105 MemRARFile->offset+=len; /* update read pointer */
|
|
1106 return len % ((((MemoryFile*)stream)->size) - 1);
|
|
1107 #else
|
|
1108 return(fread(buf,1,len,(FILE*)stream));
|
|
1109 #endif
|
|
1110 }
|
|
1111
|
|
1112
|
|
1113 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
1114 int tseek(void *stream,long offset,int fromwhere)
|
|
1115 {
|
|
1116 return(fseek((FILE*)stream,offset,fromwhere));
|
|
1117 }
|
|
1118 #endif
|
|
1119
|
|
1120
|
|
1121 char* strupper(char *Str)
|
|
1122 {
|
|
1123 char *ChPtr;
|
|
1124 for (ChPtr=Str;*ChPtr;ChPtr++)
|
|
1125 *ChPtr=(char)toupper(*ChPtr);
|
|
1126 return(Str);
|
|
1127 }
|
|
1128
|
|
1129
|
|
1130 int stricomp(char *Str1,char *Str2)
|
|
1131 /* compare strings without regard of '\' and '/' */
|
|
1132 {
|
|
1133 char S1[512],S2[512];
|
|
1134 char *chptr;
|
|
1135
|
|
1136 strncpy(S1,Str1,sizeof(S1));
|
|
1137 strncpy(S2,Str2,sizeof(S2));
|
|
1138
|
|
1139 while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash */
|
|
1140 {
|
|
1141 *chptr = '_';
|
|
1142 }
|
|
1143
|
|
1144 while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash */
|
|
1145 {
|
|
1146 *chptr = '_';
|
|
1147 }
|
|
1148
|
|
1149 while((chptr = strchr(S1, '/')) != NULL) /* ignore slash */
|
|
1150 {
|
|
1151 *chptr = '_';
|
|
1152 }
|
|
1153
|
|
1154 while((chptr = strchr(S2, '/')) != NULL) /* ignore slash */
|
|
1155 {
|
|
1156 *chptr = '_';
|
|
1157 }
|
|
1158
|
|
1159 return(strcmp(strupper(S1),strupper(S2)));
|
|
1160 }
|
|
1161
|
|
1162
|
|
1163 /* **************************************************************************
|
|
1164 ****************************************************************************
|
|
1165 ****************************************************************************
|
|
1166 ************************************************************************** */
|
|
1167
|
|
1168
|
|
1169
|
|
1170
|
|
1171
|
|
1172
|
|
1173
|
|
1174
|
|
1175
|
|
1176
|
|
1177
|
|
1178
|
|
1179
|
|
1180
|
|
1181
|
|
1182
|
|
1183
|
|
1184
|
|
1185 /* **************************************************************************
|
|
1186 ****************************************************************************
|
|
1187 ****************************************************************************
|
|
1188 ****************************************************************************
|
|
1189 ******* *******
|
|
1190 ******* *******
|
|
1191 ******* *******
|
|
1192 ******* U N P A C K C O D E *******
|
|
1193 ******* *******
|
|
1194 ******* *******
|
|
1195 ******* *******
|
|
1196 ****************************************************************************
|
|
1197 ****************************************************************************
|
|
1198 ****************************************************************************
|
|
1199 ************************************************************************** */
|
|
1200
|
|
1201
|
|
1202 /* *****************************
|
|
1203 * ** unpack stored RAR files **
|
|
1204 * *****************************/
|
|
1205
|
|
1206 BOOL UnstoreFile(void)
|
|
1207 {
|
|
1208 if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
|
|
1209 NewLhd.UnpSize))==-1)
|
|
1210 {
|
|
1211 debug_log("Read error of stored file!");
|
|
1212 return FALSE;
|
|
1213 }
|
|
1214 return TRUE;
|
|
1215 }
|
|
1216
|
|
1217
|
|
1218
|
|
1219
|
|
1220 /* ****************************************
|
|
1221 * ** RAR decompression code starts here **
|
|
1222 * ****************************************/
|
|
1223
|
|
1224 #define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
|
|
1225 #define DC 48
|
|
1226 #define RC 28
|
|
1227 #define BC 19
|
|
1228 #define MC 257
|
|
1229
|
|
1230 enum {CODE_HUFFMAN=0,CODE_LZ=1,CODE_LZ2=2,CODE_REPEATLZ=3,CODE_CACHELZ=4,
|
|
1231 CODE_STARTFILE=5,CODE_ENDFILE=6,CODE_STARTMM=8,CODE_ENDMM=7,
|
|
1232 CODE_MMDELTA=9};
|
|
1233
|
|
1234 struct AudioVariables
|
|
1235 {
|
|
1236 int K1,K2,K3,K4,K5;
|
|
1237 int D1,D2,D3,D4;
|
|
1238 int LastDelta;
|
|
1239 unsigned int Dif[11];
|
|
1240 unsigned int ByteCount;
|
|
1241 int LastChar;
|
|
1242 };
|
|
1243
|
|
1244
|
|
1245 #define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
|
|
1246 #define DC 48
|
|
1247 #define RC 28
|
|
1248 #define BC 19
|
|
1249 #define MC 257
|
|
1250
|
|
1251
|
|
1252 struct AudioVariables AudV[4];
|
|
1253
|
|
1254 #define GetBits() \
|
|
1255 BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
|
|
1256 ( (UWORD) InBuf[InAddr+1] << 8 ) | \
|
|
1257 ( InBuf[InAddr+2] ) ) \
|
|
1258 >> (8-InBit) ) & 0xffff;
|
|
1259
|
|
1260
|
|
1261 #define AddBits(Bits) \
|
|
1262 InAddr += ( InBit + (Bits) ) >> 3; \
|
|
1263 InBit = ( InBit + (Bits) ) & 7;
|
|
1264
|
|
1265 static unsigned char *UnpBuf;
|
|
1266 static unsigned int BitField;
|
|
1267 static unsigned int Number;
|
|
1268
|
|
1269 unsigned char InBuf[8192]; /* input read buffer */
|
|
1270
|
|
1271 unsigned char UnpOldTable[MC*4];
|
|
1272
|
|
1273 unsigned int InAddr,InBit,ReadTop;
|
|
1274
|
|
1275 unsigned int LastDist,LastLength;
|
|
1276 static unsigned int Length,Distance;
|
|
1277
|
|
1278 unsigned int OldDist[4],OldDistPtr;
|
|
1279
|
|
1280
|
|
1281 struct LitDecode
|
|
1282 {
|
|
1283 unsigned int MaxNum;
|
|
1284 unsigned int DecodeLen[16];
|
|
1285 unsigned int DecodePos[16];
|
|
1286 unsigned int DecodeNum[NC];
|
|
1287 } LD;
|
|
1288
|
|
1289 struct DistDecode
|
|
1290 {
|
|
1291 unsigned int MaxNum;
|
|
1292 unsigned int DecodeLen[16];
|
|
1293 unsigned int DecodePos[16];
|
|
1294 unsigned int DecodeNum[DC];
|
|
1295 } DD;
|
|
1296
|
|
1297 struct RepDecode
|
|
1298 {
|
|
1299 unsigned int MaxNum;
|
|
1300 unsigned int DecodeLen[16];
|
|
1301 unsigned int DecodePos[16];
|
|
1302 unsigned int DecodeNum[RC];
|
|
1303 } RD;
|
|
1304
|
|
1305 struct MultDecode
|
|
1306 {
|
|
1307 unsigned int MaxNum;
|
|
1308 unsigned int DecodeLen[16];
|
|
1309 unsigned int DecodePos[16];
|
|
1310 unsigned int DecodeNum[MC];
|
|
1311 } MD[4];
|
|
1312
|
|
1313 struct BitDecode
|
|
1314 {
|
|
1315 unsigned int MaxNum;
|
|
1316 unsigned int DecodeLen[16];
|
|
1317 unsigned int DecodePos[16];
|
|
1318 unsigned int DecodeNum[BC];
|
|
1319 } BD;
|
|
1320
|
|
1321 static struct MultDecode *MDPtr[4]={&MD[0],&MD[1],&MD[2],&MD[3]};
|
|
1322
|
|
1323 int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
|
|
1324
|
|
1325
|
|
1326 void Unpack(unsigned char *UnpAddr)
|
|
1327 /* *** 38.3% of all CPU time is spent within this function!!! */
|
|
1328 {
|
|
1329 static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
|
|
1330 40,48,56,64,80,96,112,128,160,192,224};
|
|
1331 static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
|
|
1332 3,3,3,4,4,4,4,5,5,5,5};
|
|
1333 static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
|
|
1334 512,768,1024,1536,2048,3072,4096,6144,8192,12288,
|
|
1335 16384,24576,32768U,49152U,65536,98304,131072,196608,
|
|
1336 262144,327680,393216,458752,524288,589824,655360,
|
|
1337 720896,786432,851968,917504,983040};
|
|
1338 static unsigned char DBits[]= {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,
|
|
1339 9,10,10,11,11,12,12,13,13,14,14,15,15,16,
|
|
1340 16,16,16,16,16,16,16,16,16,16,16,16,16};
|
|
1341 static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
|
|
1342 static unsigned char SDBits[]={2,2,3, 4, 5, 6, 6, 6};
|
|
1343 unsigned int Bits;
|
|
1344
|
|
1345
|
|
1346 UnpBuf=UnpAddr; /* UnpAddr is a pointer to the */
|
|
1347 UnpInitData(); /* unpack buffer */
|
|
1348 UnpReadBuf(1);
|
|
1349 if (!(NewLhd.Flags & LHD_SOLID))
|
|
1350 ReadTables();
|
|
1351 DestUnpSize--;
|
|
1352
|
|
1353 while (DestUnpSize>=0)
|
|
1354 {
|
|
1355 UnpPtr&=MAXWINMASK;
|
|
1356
|
|
1357 if (InAddr>sizeof(InBuf)-30)
|
|
1358 UnpReadBuf(0);
|
|
1359 if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
|
|
1360 {
|
|
1361
|
|
1362
|
|
1363 if (FileFound)
|
|
1364 {
|
|
1365
|
|
1366 if (UnpPtr<WrPtr)
|
|
1367 {
|
|
1368 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
|
|
1369 {
|
|
1370 debug_log("Fatal! Buffer overrun during decompression!");
|
|
1371 DestUnpSize=-1;
|
|
1372
|
|
1373 } else
|
|
1374 {
|
|
1375 /* copy extracted data to output buffer */
|
|
1376 memcpy(temp_output_buffer + *temp_output_buffer_offset,
|
|
1377 &UnpBuf[WrPtr], (0-WrPtr) & MAXWINMASK);
|
|
1378 /* update offset within buffer */
|
|
1379 *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
|
|
1380 /* copy extracted data to output buffer */
|
|
1381 memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
|
|
1382 UnpPtr);
|
|
1383 /* update offset within buffer */
|
|
1384 *temp_output_buffer_offset+=UnpPtr;
|
|
1385 }
|
|
1386 } else
|
|
1387 {
|
|
1388 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
|
|
1389 {
|
|
1390 debug_log("Fatal! Buffer overrun during decompression!");
|
|
1391 DestUnpSize=-1;
|
|
1392 } else
|
|
1393 {
|
|
1394 /* copy extracted data to output buffer */
|
|
1395 memcpy(temp_output_buffer + *temp_output_buffer_offset,
|
|
1396 &UnpBuf[WrPtr], UnpPtr-WrPtr);
|
|
1397 *temp_output_buffer_offset+=UnpPtr-WrPtr; /* update offset within buffer */
|
|
1398 }
|
|
1399
|
|
1400 }
|
|
1401 }
|
|
1402
|
|
1403 WrPtr=UnpPtr;
|
|
1404 }
|
|
1405
|
|
1406 if (UnpAudioBlock)
|
|
1407 {
|
|
1408 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
|
|
1409 if (Number==256)
|
|
1410 {
|
|
1411 ReadTables();
|
|
1412 continue;
|
|
1413 }
|
|
1414 UnpBuf[UnpPtr++]=DecodeAudio(Number);
|
|
1415 if (++CurChannel==UnpChannels)
|
|
1416 CurChannel=0;
|
|
1417 DestUnpSize--;
|
|
1418 continue;
|
|
1419 }
|
|
1420
|
|
1421 DecodeNumber((struct Decode *)&LD);
|
|
1422 if (Number<256)
|
|
1423 {
|
|
1424 UnpBuf[UnpPtr++]=(UBYTE)Number;
|
|
1425 DestUnpSize--;
|
|
1426 continue;
|
|
1427 }
|
|
1428 if (Number>269)
|
|
1429 {
|
|
1430 Length=LDecode[Number-=270]+3;
|
|
1431 if ((Bits=LBits[Number])>0)
|
|
1432 {
|
|
1433 GetBits();
|
|
1434 Length+=BitField>>(16-Bits);
|
|
1435 AddBits(Bits);
|
|
1436 }
|
|
1437
|
|
1438 DecodeNumber((struct Decode *)&DD);
|
|
1439 Distance=DDecode[Number]+1;
|
|
1440 if ((Bits=DBits[Number])>0)
|
|
1441 {
|
|
1442 GetBits();
|
|
1443 Distance+=BitField>>(16-Bits);
|
|
1444 AddBits(Bits);
|
|
1445 }
|
|
1446
|
|
1447 if (Distance>=0x40000L)
|
|
1448 Length++;
|
|
1449
|
|
1450 if (Distance>=0x2000)
|
|
1451 Length++;
|
|
1452
|
|
1453 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
|
|
1454 DestUnpSize-=(LastLength=Length);
|
|
1455 while (Length--)
|
|
1456 {
|
|
1457 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
|
|
1458 UnpPtr=(UnpPtr+1) & MAXWINMASK;
|
|
1459 }
|
|
1460
|
|
1461 continue;
|
|
1462 }
|
|
1463 if (Number==269)
|
|
1464 {
|
|
1465 ReadTables();
|
|
1466 continue;
|
|
1467 }
|
|
1468 if (Number==256)
|
|
1469 {
|
|
1470 Length=LastLength;
|
|
1471 Distance=LastDist;
|
|
1472 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
|
|
1473 DestUnpSize-=(LastLength=Length);
|
|
1474 while (Length--)
|
|
1475 {
|
|
1476 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
|
|
1477 UnpPtr=(UnpPtr+1) & MAXWINMASK;
|
|
1478 }
|
|
1479 continue;
|
|
1480 }
|
|
1481 if (Number<261)
|
|
1482 {
|
|
1483 Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
|
|
1484 DecodeNumber((struct Decode *)&RD);
|
|
1485 Length=LDecode[Number]+2;
|
|
1486 if ((Bits=LBits[Number])>0)
|
|
1487 {
|
|
1488 GetBits();
|
|
1489 Length+=BitField>>(16-Bits);
|
|
1490 AddBits(Bits);
|
|
1491 }
|
|
1492 if (Distance>=0x40000)
|
|
1493 Length++;
|
|
1494 if (Distance>=0x2000)
|
|
1495 Length++;
|
|
1496 if (Distance>=0x101)
|
|
1497 Length++;
|
|
1498 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
|
|
1499 DestUnpSize-=(LastLength=Length);
|
|
1500 while (Length--)
|
|
1501 {
|
|
1502 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
|
|
1503 UnpPtr=(UnpPtr+1) & MAXWINMASK;
|
|
1504 }
|
|
1505 continue;
|
|
1506 }
|
|
1507 if (Number<270)
|
|
1508 {
|
|
1509 Distance=SDDecode[Number-=261]+1;
|
|
1510 if ((Bits=SDBits[Number])>0)
|
|
1511 {
|
|
1512 GetBits();
|
|
1513 Distance+=BitField>>(16-Bits);
|
|
1514 AddBits(Bits);
|
|
1515 }
|
|
1516 Length=2;
|
|
1517 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
|
|
1518 DestUnpSize-=(LastLength=Length);
|
|
1519 while (Length--)
|
|
1520 {
|
|
1521 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
|
|
1522 UnpPtr=(UnpPtr+1) & MAXWINMASK;
|
|
1523 }
|
|
1524 continue;
|
|
1525 }
|
|
1526 }
|
|
1527 ReadLastTables();
|
|
1528
|
|
1529 if (FileFound) /* flush buffer */
|
|
1530 {
|
|
1531
|
|
1532 if (UnpPtr<WrPtr)
|
|
1533 {
|
|
1534 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
|
|
1535 {
|
|
1536 debug_log("Fatal! Buffer overrun during decompression!");
|
|
1537 DestUnpSize=-1;
|
|
1538 } else
|
|
1539 {
|
|
1540 /* copy extracted data to output buffer */
|
|
1541 memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
|
|
1542 (0-WrPtr) & MAXWINMASK);
|
|
1543 /* update offset within buffer */
|
|
1544 *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
|
|
1545 /* copy extracted data to output buffer */
|
|
1546 memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf, UnpPtr);
|
|
1547 /* update offset within buffer */
|
|
1548 *temp_output_buffer_offset+=UnpPtr;
|
|
1549 }
|
|
1550 } else
|
|
1551 {
|
|
1552 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
|
|
1553 {
|
|
1554 debug_log("Fatal! Buffer overrun during decompression!");
|
|
1555 DestUnpSize=-1;
|
|
1556 } else
|
|
1557 {
|
|
1558 /* copy extracted data to output buffer */
|
|
1559 memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
|
|
1560 UnpPtr-WrPtr);
|
|
1561 /* update offset within buffer */
|
|
1562 *temp_output_buffer_offset+=UnpPtr-WrPtr;
|
|
1563 }
|
|
1564 }
|
|
1565 }
|
|
1566
|
|
1567 WrPtr=UnpPtr;
|
|
1568 }
|
|
1569
|
|
1570
|
|
1571 unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
|
|
1572 {
|
|
1573 int RetCode=0;
|
|
1574 unsigned int I,ReadSize,TotalRead=0;
|
|
1575 unsigned char *ReadAddr;
|
|
1576 ReadAddr=Addr;
|
|
1577 while (Count > 0)
|
|
1578 {
|
|
1579 ReadSize=(unsigned int)((Count>(unsigned long)UnpPackedSize) ?
|
|
1580 UnpPackedSize : Count);
|
|
1581 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
|
|
1582 if(MemRARFile->data == NULL)
|
|
1583 return(0);
|
|
1584 RetCode=tread(MemRARFile, ReadAddr, ReadSize);
|
|
1585 #else
|
|
1586 if (ArcPtr==NULL)
|
|
1587 return(0);
|
|
1588 RetCode=tread(ArcPtr,ReadAddr,ReadSize);
|
|
1589 #endif
|
|
1590 CurUnpRead+=RetCode;
|
|
1591 ReadAddr+=RetCode;
|
|
1592 TotalRead+=RetCode;
|
|
1593 Count-=RetCode;
|
|
1594 UnpPackedSize-=RetCode;
|
|
1595 break;
|
|
1596 }
|
|
1597 if (RetCode!= -1)
|
|
1598 {
|
|
1599 RetCode=TotalRead;
|
|
1600 if (Encryption)
|
|
1601 {
|
|
1602 if (Encryption<20)
|
|
1603 {
|
|
1604 debug_log("Old Crypt() not supported!");
|
|
1605 }
|
|
1606 else
|
|
1607 {
|
|
1608 for (I=0;I<(unsigned int)RetCode;I+=16)
|
|
1609 DecryptBlock(&Addr[I]);
|
|
1610 }
|
|
1611 }
|
|
1612 }
|
|
1613 return(RetCode);
|
|
1614 }
|
|
1615
|
|
1616
|
|
1617 void UnpReadBuf(int FirstBuf)
|
|
1618 {
|
|
1619 int RetCode;
|
|
1620 if (FirstBuf)
|
|
1621 {
|
|
1622 ReadTop=UnpRead(InBuf,sizeof(InBuf));
|
|
1623 InAddr=0;
|
|
1624 }
|
|
1625 else
|
|
1626 {
|
|
1627 memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
|
|
1628 InAddr&=0x1f;
|
|
1629 RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
|
|
1630 if (RetCode>0)
|
|
1631 ReadTop=RetCode+32;
|
|
1632 else
|
|
1633 ReadTop=InAddr;
|
|
1634 }
|
|
1635 }
|
|
1636
|
|
1637
|
|
1638 void ReadTables(void)
|
|
1639 {
|
|
1640 UBYTE BitLength[BC];
|
|
1641 unsigned char Table[MC*4];
|
|
1642 int TableSize,N,I;
|
|
1643 if (InAddr>sizeof(InBuf)-25)
|
|
1644 UnpReadBuf(0);
|
|
1645 GetBits();
|
|
1646 UnpAudioBlock=(BitField & 0x8000);
|
|
1647
|
|
1648 if (!(BitField & 0x4000))
|
|
1649 memset(UnpOldTable,0,sizeof(UnpOldTable));
|
|
1650 AddBits(2);
|
|
1651
|
|
1652
|
|
1653 if (UnpAudioBlock)
|
|
1654 {
|
|
1655 UnpChannels=((BitField>>12) & 3)+1;
|
|
1656 if (CurChannel>=UnpChannels)
|
|
1657 CurChannel=0;
|
|
1658 AddBits(2);
|
|
1659 TableSize=MC*UnpChannels;
|
|
1660 }
|
|
1661 else
|
|
1662 TableSize=NC+DC+RC;
|
|
1663
|
|
1664
|
|
1665 for (I=0;I<BC;I++)
|
|
1666 {
|
|
1667 GetBits();
|
|
1668 BitLength[I]=(UBYTE)(BitField >> 12);
|
|
1669 AddBits(4);
|
|
1670 }
|
|
1671 MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
|
|
1672 I=0;
|
|
1673 while (I<TableSize)
|
|
1674 {
|
|
1675 if (InAddr>sizeof(InBuf)-5)
|
|
1676 UnpReadBuf(0);
|
|
1677 DecodeNumber((struct Decode *)&BD);
|
|
1678 if (Number<16)
|
8451
|
1679 {
|
|
1680 Table[I]=(Number+UnpOldTable[I]) & 0xf;
|
|
1681 I++;
|
|
1682 }
|
7446
|
1683 else
|
|
1684 if (Number==16)
|
|
1685 {
|
|
1686 GetBits();
|
|
1687 N=(BitField >> 14)+3;
|
|
1688 AddBits(2);
|
|
1689 while (N-- > 0 && I<TableSize)
|
|
1690 {
|
|
1691 Table[I]=Table[I-1];
|
|
1692 I++;
|
|
1693 }
|
|
1694 }
|
|
1695 else
|
|
1696 {
|
|
1697 if (Number==17)
|
|
1698 {
|
|
1699 GetBits();
|
|
1700 N=(BitField >> 13)+3;
|
|
1701 AddBits(3);
|
|
1702 }
|
|
1703 else
|
|
1704 {
|
|
1705 GetBits();
|
|
1706 N=(BitField >> 9)+11;
|
|
1707 AddBits(7);
|
|
1708 }
|
|
1709 while (N-- > 0 && I<TableSize)
|
|
1710 Table[I++]=0;
|
|
1711 }
|
|
1712 }
|
|
1713 if (UnpAudioBlock)
|
|
1714 for (I=0;I<UnpChannels;I++)
|
|
1715 MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
|
|
1716 else
|
|
1717 {
|
|
1718 MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
|
|
1719 MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
|
|
1720 MakeDecodeTables(&Table[NC+DC],(struct Decode *)&RD,RC);
|
|
1721 }
|
|
1722 memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
|
|
1723 }
|
|
1724
|
|
1725
|
|
1726 static void ReadLastTables(void)
|
|
1727 {
|
|
1728 if (ReadTop>=InAddr+5)
|
|
1729 {
|
|
1730 if (UnpAudioBlock)
|
|
1731 {
|
|
1732 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
|
|
1733 if (Number==256)
|
|
1734 ReadTables();
|
|
1735 }
|
|
1736 else
|
|
1737 {
|
|
1738 DecodeNumber((struct Decode *)&LD);
|
|
1739 if (Number==269)
|
|
1740 ReadTables();
|
|
1741 }
|
|
1742 }
|
|
1743 }
|
|
1744
|
|
1745
|
|
1746 static void MakeDecodeTables(unsigned char *LenTab,
|
|
1747 struct Decode *Dec,
|
|
1748 int Size)
|
|
1749 {
|
|
1750 int LenCount[16],TmpPos[16],I;
|
|
1751 long M,N;
|
|
1752 memset(LenCount,0,sizeof(LenCount));
|
|
1753 for (I=0;I<Size;I++)
|
|
1754 LenCount[LenTab[I] & 0xF]++;
|
|
1755
|
|
1756 LenCount[0]=0;
|
|
1757 for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
|
|
1758 {
|
|
1759 N=2*(N+LenCount[I]);
|
|
1760 M=N<<(15-I);
|
|
1761 if (M>0xFFFF)
|
|
1762 M=0xFFFF;
|
|
1763 Dec->DecodeLen[I]=(unsigned int)M;
|
|
1764 TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
|
|
1765 }
|
|
1766
|
|
1767 for (I=0;I<Size;I++)
|
|
1768 if (LenTab[I]!=0)
|
|
1769 Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
|
|
1770 Dec->MaxNum=Size;
|
|
1771 }
|
|
1772
|
|
1773
|
|
1774 static void DecodeNumber(struct Decode *Deco)
|
|
1775 /* *** 52.6% of all CPU time is spent within this function!!! */
|
|
1776 {
|
|
1777 unsigned int I;
|
|
1778 register unsigned int N;
|
|
1779 GetBits();
|
|
1780
|
|
1781 #ifdef _USE_ASM
|
|
1782
|
|
1783 #ifdef _WIN_32
|
|
1784 __asm {
|
|
1785
|
|
1786 xor eax, eax
|
|
1787 mov eax, BitField // N=BitField & 0xFFFE;
|
|
1788 and eax, 0xFFFFFFFE
|
|
1789 mov [N], eax
|
|
1790 mov edx, [Deco] // EAX=N, EDX=Deco
|
|
1791
|
|
1792 cmp eax, dword ptr[edx + 8*4 + 4]// if (N<Dec->DecodeLen[8])
|
|
1793 jae else_G
|
|
1794
|
|
1795 cmp eax, dword ptr[edx + 4*4 + 4]// if (N<Dec->DecodeLen[4])
|
|
1796 jae else_F
|
|
1797
|
|
1798
|
|
1799 cmp eax, dword ptr[edx + 2*4 + 4]// if (N<Dec->DecodeLen[2])
|
|
1800 jae else_C
|
|
1801
|
|
1802 cmp eax, dword ptr[edx + 1*4 + 4]// if (N<Dec->DecodeLen[1])
|
|
1803 jae else_1
|
|
1804 mov I, 1 // I=1;
|
|
1805 jmp next_1
|
|
1806 else_1: // else
|
|
1807 mov I, 2 // I=2;
|
|
1808 next_1:
|
|
1809
|
|
1810 jmp next_C
|
|
1811 else_C: // else
|
|
1812
|
|
1813 cmp eax, dword ptr[edx + 3*4 + 4]// if (N<Dec->DecodeLen[3])
|
|
1814 jae else_2
|
|
1815 mov I, 3 // I=3;
|
|
1816 jmp next_2
|
|
1817 else_2: // else
|
|
1818 mov I, 4 // I=4;
|
|
1819 next_2:
|
|
1820
|
|
1821 next_C: // else
|
|
1822
|
|
1823 jmp next_F
|
|
1824 else_F:
|
|
1825
|
|
1826
|
|
1827 cmp eax, dword ptr[edx + 6*4 + 4]// if (N<Dec->DecodeLen[6])
|
|
1828 jae else_E
|
|
1829
|
|
1830 cmp eax, dword ptr[edx + 5*4 + 4]// if (N<Dec->DecodeLen[5])
|
|
1831 jae else_3
|
|
1832 mov I, 5 // I=5;
|
|
1833 jmp next_3
|
|
1834 else_3: // else
|
|
1835 mov I, 6 // I=6;
|
|
1836 next_3:
|
|
1837
|
|
1838 jmp next_E
|
|
1839 else_E: // else
|
|
1840
|
|
1841 cmp eax, dword ptr[edx + 7*4 + 4]// if (N<Dec->DecodeLen[7])
|
|
1842 jae else_4
|
|
1843 mov I, 7 // I=7;
|
|
1844 jmp next_4
|
|
1845 else_4: // else
|
|
1846 mov I, 8 // I=8;
|
|
1847 next_4:
|
|
1848
|
|
1849 next_E:
|
|
1850
|
|
1851 next_F:
|
|
1852
|
|
1853 jmp next_G
|
|
1854 else_G:
|
|
1855
|
|
1856 cmp eax, dword ptr[edx + 12*4 + 4] // if (N<Dec->DecodeLen[12])
|
|
1857 jae else_D
|
|
1858
|
|
1859 cmp eax, dword ptr[edx + 10*4 + 4]// if (N<Dec->DecodeLen[10])
|
|
1860 jae else_B
|
|
1861
|
|
1862 cmp eax, dword ptr[edx + 9*4 + 4]// if (N<Dec->DecodeLen[9])
|
|
1863 jae else_5
|
|
1864 mov I, 9 // I=9;
|
|
1865 jmp next_5
|
|
1866 else_5: // else
|
|
1867 mov I, 10 // I=10;
|
|
1868 next_5:
|
|
1869
|
|
1870 jmp next_B
|
|
1871 else_B: // else
|
|
1872
|
|
1873 cmp eax, dword ptr[edx + 11*4 + 4]// if (N<Dec->DecodeLen[11])
|
|
1874 jae else_6
|
|
1875 mov I, 11 // I=11;
|
|
1876 jmp next_6
|
|
1877 else_6: // else
|
|
1878 mov I, 12 // I=12;
|
|
1879 next_6:
|
|
1880
|
|
1881 next_B:
|
|
1882
|
|
1883
|
|
1884 jmp next_D
|
|
1885 else_D: // else
|
|
1886
|
|
1887 cmp eax, dword ptr[edx + 14*4 + 4]// if (N<Dec->DecodeLen[14])
|
|
1888 jae else_A
|
|
1889
|
|
1890 cmp eax, dword ptr[edx + 13*4 + 4]// if (N<Dec->DecodeLen[13])
|
|
1891 jae else_7
|
|
1892 mov I, 13 // I=13;
|
|
1893 jmp next_7
|
|
1894 else_7: // else
|
|
1895 mov I, 14 // I=14;
|
|
1896 next_7:
|
|
1897
|
|
1898 jmp next_A
|
|
1899 else_A: // else
|
|
1900 mov I, 15 // I=15;
|
|
1901 next_A:
|
|
1902
|
|
1903 next_D:
|
|
1904 next_G:
|
|
1905 }
|
|
1906 #else
|
|
1907 __asm__ __volatile__ (
|
|
1908 "andl $0xFFFFFFFE, %%eax"
|
|
1909 " movl %%eax, %1"
|
|
1910 " cmpl 8*4(%%edx), %%eax /* 5379 */"
|
|
1911 " jae else_G"
|
|
1912 ""
|
|
1913 " cmpl 4*4(%%edx), %%eax"
|
|
1914 " jae else_F"
|
|
1915 ""
|
|
1916 " cmpl 2*4(%%edx), %%eax"
|
|
1917 " jae else_C"
|
|
1918 ""
|
|
1919 " cmpl 1*4(%%edx), %%eax"
|
|
1920 ""
|
|
1921 " jae else_1"
|
|
1922 " movl $1, %0"
|
|
1923 " jmp next_1"
|
|
1924 " else_1: "
|
|
1925 " movl $2, %0"
|
|
1926 " next_1:"
|
|
1927 " "
|
|
1928 " jmp next_C"
|
|
1929 " else_C: "
|
|
1930 ""
|
|
1931 " cmpl 3*4(%%edx), %%eax "
|
|
1932 " jae else_2"
|
|
1933 " movl $3, %0"
|
|
1934 " jmp next_2"
|
|
1935 " else_2: "
|
|
1936 " movl $4, %0"
|
|
1937 " next_2:"
|
|
1938 ""
|
|
1939 " next_C: "
|
|
1940 ""
|
|
1941 " jmp next_F"
|
|
1942 " else_F:"
|
|
1943 ""
|
|
1944 " cmpl 6*4(%%edx), %%eax"
|
|
1945 " jae else_E"
|
|
1946 ""
|
|
1947 " cmpl 5*4(%%edx), %%eax"
|
|
1948 " jae else_3"
|
|
1949 " movl $5, %0 "
|
|
1950 " jmp next_3"
|
|
1951 " else_3: "
|
|
1952 " movl $6, %0 "
|
|
1953 " next_3:"
|
|
1954 ""
|
|
1955 " jmp next_E"
|
|
1956 " else_E: "
|
|
1957 ""
|
|
1958 " cmpl 7*4(%%edx), %%eax"
|
|
1959 " jae else_4"
|
|
1960 " movl $7, %0 "
|
|
1961 " jmp next_4"
|
|
1962 " else_4: "
|
|
1963 " movl $8, %0 "
|
|
1964 " next_4:"
|
|
1965 ""
|
|
1966 " next_E:"
|
|
1967 ""
|
|
1968 " next_F:"
|
|
1969 ""
|
|
1970 " jmp next_G"
|
|
1971 " else_G:"
|
|
1972 ""
|
|
1973 " cmpl 12*4(%%edx), %%eax"
|
|
1974 " jae else_D"
|
|
1975 ""
|
|
1976 " cmpl 10*4(%%edx), %%eax"
|
|
1977 " jae else_B"
|
|
1978 ""
|
|
1979 " cmpl 9*4(%%edx), %%eax"
|
|
1980 " jae else_5"
|
|
1981 " movl $9, %0 "
|
|
1982 " jmp next_5"
|
|
1983 " else_5: "
|
|
1984 " movl $10, %0 "
|
|
1985 " next_5:"
|
|
1986 ""
|
|
1987 " jmp next_B"
|
|
1988 " else_B: "
|
|
1989 ""
|
|
1990 " cmpl 11*4(%%edx), %%eax"
|
|
1991 " "
|
|
1992 " jae else_6"
|
|
1993 " movl $11, %0 "
|
|
1994 " jmp next_6"
|
|
1995 " else_6: "
|
|
1996 " movl $12, %0 "
|
|
1997 " next_6:"
|
|
1998 ""
|
|
1999 " next_B:"
|
|
2000 " "
|
|
2001 " "
|
|
2002 " jmp next_D"
|
|
2003 " else_D: "
|
|
2004 ""
|
|
2005 " cmpl 14*4(%%edx), %%eax"
|
|
2006 " jae else_A"
|
|
2007 ""
|
|
2008 " cmpl 13*4(%%edx), %%eax"
|
|
2009 " jae else_7"
|
|
2010 " movl $13, %0"
|
|
2011 " jmp next_7"
|
|
2012 " else_7: "
|
|
2013 " movl $14, %0"
|
|
2014 " next_7:"
|
|
2015 ""
|
|
2016 " jmp next_A"
|
|
2017 " else_A: "
|
|
2018 " movl $15, %0 "
|
|
2019 " next_A:"
|
|
2020 " "
|
|
2021 " next_D: "
|
|
2022 " next_G:"
|
|
2023 : "=g" (I), "=r"(N)
|
|
2024 : "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
|
|
2025 : "memory"
|
|
2026 );
|
|
2027 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
|
|
2028
|
|
2029 #else
|
|
2030 N=BitField & 0xFFFE;
|
|
2031 if (N<Deco->DecodeLen[8]) {
|
|
2032 if (N<Deco->DecodeLen[4]) {
|
|
2033 if (N<Deco->DecodeLen[2]) {
|
|
2034 if (N<Deco->DecodeLen[1])
|
|
2035 I=1;
|
|
2036 else
|
|
2037 I=2;
|
|
2038 } else {
|
|
2039 if (N<Deco->DecodeLen[3])
|
|
2040 I=3;
|
|
2041 else
|
|
2042 I=4;
|
|
2043 }
|
|
2044 } else {
|
|
2045 if (N<Deco->DecodeLen[6]) {
|
|
2046 if (N<Deco->DecodeLen[5])
|
|
2047 I=5;
|
|
2048 else
|
|
2049 I=6;
|
|
2050 } else {
|
|
2051 if (N<Deco->DecodeLen[7])
|
|
2052 I=7;
|
|
2053 else
|
|
2054 I=8;
|
|
2055 }
|
|
2056 }
|
|
2057 } else {
|
|
2058 if (N<Deco->DecodeLen[12]) {
|
|
2059 if (N<Deco->DecodeLen[10]) {
|
|
2060 if (N<Deco->DecodeLen[9])
|
|
2061 I=9;
|
|
2062 else
|
|
2063 I=10;
|
|
2064 } else {
|
|
2065 if (N<Deco->DecodeLen[11])
|
|
2066 I=11;
|
|
2067 else
|
|
2068 I=12;
|
|
2069 }
|
|
2070 } else {
|
|
2071 if (N<Deco->DecodeLen[14]) {
|
|
2072 if (N<Deco->DecodeLen[13])
|
|
2073 I=13;
|
|
2074 else
|
|
2075 I=14;
|
|
2076
|
|
2077 } else {
|
|
2078 I=15;
|
|
2079 }
|
|
2080 }
|
|
2081
|
|
2082 }
|
|
2083 #endif
|
|
2084
|
|
2085 AddBits(I);
|
|
2086 if ((N=Deco->DecodePos[I]+((N-Deco->DecodeLen[I-1])>>(16-I)))>=Deco->MaxNum)
|
|
2087 N=0;
|
|
2088 Number=Deco->DecodeNum[N];
|
|
2089 }
|
|
2090
|
|
2091
|
|
2092 void UnpInitData()
|
|
2093 {
|
|
2094 InAddr=InBit=0;
|
|
2095 if (!(NewLhd.Flags & LHD_SOLID))
|
|
2096 {
|
|
2097 ChannelDelta=CurChannel=0;
|
|
2098
|
|
2099 #ifdef _USE_ASM
|
|
2100
|
|
2101 #ifdef _WIN_32 /* Win32 with VisualC */
|
|
2102
|
|
2103 __asm {
|
|
2104 push edi
|
|
2105 push eax
|
|
2106 push ecx
|
|
2107
|
|
2108 cld /* increment EDI and ESI */
|
|
2109 mov al, 0x00
|
|
2110 mov ecx, SIZE AudV
|
|
2111 mov edi, Offset AudV
|
|
2112 rep stosb /* clear memory */
|
|
2113
|
|
2114 mov ecx, SIZE OldDist
|
|
2115 mov edi, Offset OldDist
|
|
2116 rep stosb /* clear memory */
|
|
2117
|
|
2118 mov ecx, SIZE UnpOldTable
|
|
2119 mov edi, Offset UnpOldTable
|
|
2120 rep stosb /* clear memory */
|
|
2121
|
|
2122 pop ecx
|
|
2123 pop eax
|
|
2124 pop edi
|
|
2125
|
|
2126
|
|
2127 mov [OldDistPtr], 0
|
|
2128 mov [LastDist], 0
|
|
2129 mov [LastLength], 0
|
|
2130 mov [UnpPtr], 0
|
|
2131 mov [WrPtr], 0
|
|
2132 mov [OldDistPtr], 0
|
|
2133 mov [LastLength], 0
|
|
2134 mov [LastDist], 0
|
|
2135 mov [UnpPtr], 0
|
|
2136 mov [WrPtr], 0
|
|
2137
|
|
2138 }
|
|
2139 memset(UnpBuf,0,MAXWINSIZE);
|
|
2140
|
|
2141
|
|
2142 #else /* unix/linux on i386 cpus */
|
|
2143 __asm__ __volatile (
|
|
2144 " cld /* increment EDI and ESI */"
|
|
2145 " movb $0x00, %%al"
|
|
2146 " movl %0, %%ecx"
|
|
2147 " movl %1, %%edi"
|
|
2148 " rep "
|
|
2149 " stosb /* clear memory */"
|
|
2150 ""
|
|
2151 " movl %2, %%ecx"
|
|
2152 " mov %3, %%edi"
|
|
2153 " rep "
|
|
2154 " stosb /* clear memory */"
|
|
2155 ""
|
|
2156 " movl %4, %%ecx"
|
|
2157 " movl %5, %%edi"
|
|
2158 " rep "
|
|
2159 " stosb /* clear memory */"
|
|
2160 ""
|
|
2161 " movl $0, (OldDistPtr)"
|
|
2162 " movl $0, (LastDist)"
|
|
2163 " movl $0, (LastLength)"
|
|
2164 " movl $0, (UnpPtr)"
|
|
2165 " movl $0, (WrPtr)"
|
|
2166 " movl $0, (OldDistPtr)"
|
|
2167 " movl $0, (LastLength)"
|
|
2168 " movl $0, (LastDist)"
|
|
2169 " movl $0, (UnpPtr)"
|
|
2170 " movl $0, (WrPtr)"
|
|
2171 :
|
|
2172 : "m" ((long)sizeof(AudV)),
|
|
2173 "m" ((long)AudV),
|
|
2174 "m" ((long)sizeof(OldDist)),
|
|
2175 "m" ((long)OldDist),
|
|
2176 "m" ((long)sizeof(UnpOldTable)),
|
|
2177 "m" ((long)UnpOldTable)
|
|
2178 : "memory", "edi", "eax", "ecx"
|
|
2179 );
|
|
2180 memset(UnpBuf,0,MAXWINSIZE);
|
|
2181 #endif
|
|
2182
|
|
2183 #else /* unix/linux on non-i386 cpu */
|
|
2184 memset(AudV,0,sizeof(AudV));
|
|
2185 memset(OldDist,0,sizeof(OldDist));
|
|
2186 OldDistPtr=0;
|
|
2187 LastDist=LastLength=0;
|
|
2188 memset(UnpBuf,0,MAXWINSIZE);
|
|
2189 memset(UnpOldTable,0,sizeof(UnpOldTable));
|
|
2190 UnpPtr=WrPtr=0;
|
|
2191 #endif
|
|
2192
|
|
2193 }
|
|
2194 }
|
|
2195
|
|
2196
|
|
2197 UBYTE DecodeAudio(int Delta)
|
|
2198 {
|
|
2199 struct AudioVariables *V;
|
|
2200 unsigned int Ch;
|
|
2201 unsigned int NumMinDif,MinDif;
|
|
2202 int PCh,I;
|
|
2203
|
|
2204 V=&AudV[CurChannel];
|
|
2205 V->ByteCount++;
|
|
2206 V->D4=V->D3;
|
|
2207 V->D3=V->D2;
|
|
2208 V->D2=V->LastDelta-V->D1;
|
|
2209 V->D1=V->LastDelta;
|
|
2210 PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+
|
|
2211 V->K3*V->D3+V->K4*V->D4+V->K5*ChannelDelta;
|
|
2212 PCh=(PCh>>3) & 0xFF;
|
|
2213
|
|
2214 Ch=PCh-Delta;
|
|
2215
|
|
2216 I=((signed char)Delta)<<3;
|
|
2217
|
|
2218 V->Dif[0]+=abs(I);
|
|
2219 V->Dif[1]+=abs(I-V->D1);
|
|
2220 V->Dif[2]+=abs(I+V->D1);
|
|
2221 V->Dif[3]+=abs(I-V->D2);
|
|
2222 V->Dif[4]+=abs(I+V->D2);
|
|
2223 V->Dif[5]+=abs(I-V->D3);
|
|
2224 V->Dif[6]+=abs(I+V->D3);
|
|
2225 V->Dif[7]+=abs(I-V->D4);
|
|
2226 V->Dif[8]+=abs(I+V->D4);
|
|
2227 V->Dif[9]+=abs(I-ChannelDelta);
|
|
2228 V->Dif[10]+=abs(I+ChannelDelta);
|
|
2229
|
|
2230 ChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
|
|
2231 V->LastChar=Ch;
|
|
2232
|
|
2233 if ((V->ByteCount & 0x1F)==0)
|
|
2234 {
|
|
2235 MinDif=V->Dif[0];
|
|
2236 NumMinDif=0;
|
|
2237 V->Dif[0]=0;
|
|
2238 for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
|
|
2239 {
|
|
2240 if (V->Dif[I]<MinDif)
|
|
2241 {
|
|
2242 MinDif=V->Dif[I];
|
|
2243 NumMinDif=I;
|
|
2244 }
|
|
2245 V->Dif[I]=0;
|
|
2246 }
|
|
2247 switch(NumMinDif)
|
|
2248 {
|
|
2249 case 1:
|
|
2250 if (V->K1>=-16)
|
|
2251 V->K1--;
|
|
2252 break;
|
|
2253 case 2:
|
|
2254 if (V->K1<16)
|
|
2255 V->K1++;
|
|
2256 break;
|
|
2257 case 3:
|
|
2258 if (V->K2>=-16)
|
|
2259 V->K2--;
|
|
2260 break;
|
|
2261 case 4:
|
|
2262 if (V->K2<16)
|
|
2263 V->K2++;
|
|
2264 break;
|
|
2265 case 5:
|
|
2266 if (V->K3>=-16)
|
|
2267 V->K3--;
|
|
2268 break;
|
|
2269 case 6:
|
|
2270 if (V->K3<16)
|
|
2271 V->K3++;
|
|
2272 break;
|
|
2273 case 7:
|
|
2274 if (V->K4>=-16)
|
|
2275 V->K4--;
|
|
2276 break;
|
|
2277 case 8:
|
|
2278 if (V->K4<16)
|
|
2279 V->K4++;
|
|
2280 break;
|
|
2281 case 9:
|
|
2282 if (V->K5>=-16)
|
|
2283 V->K5--;
|
|
2284 break;
|
|
2285 case 10:
|
|
2286 if (V->K5<16)
|
|
2287 V->K5++;
|
|
2288 break;
|
|
2289 }
|
|
2290 }
|
|
2291 return((UBYTE)Ch);
|
|
2292 }
|
|
2293
|
|
2294
|
|
2295
|
|
2296
|
|
2297
|
|
2298
|
|
2299
|
|
2300 /* ***************************************************
|
|
2301 * ** CRCCrypt Code - decryption engine starts here **
|
|
2302 * ***************************************************/
|
|
2303
|
|
2304
|
|
2305 #define NROUNDS 32
|
|
2306
|
|
2307 #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
|
|
2308 #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
|
|
2309
|
|
2310 #define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
|
|
2311 ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
|
|
2312 ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
|
|
2313 ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
|
|
2314
|
|
2315
|
|
2316 UDWORD CRCTab[256];
|
|
2317
|
|
2318 UBYTE SubstTable[256];
|
|
2319 UBYTE InitSubstTable[256]={
|
|
2320 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
|
|
2321 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
|
|
2322 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
|
|
2323 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
|
|
2324 107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
|
|
2325 158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
|
|
2326 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
|
|
2327 164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
|
|
2328 207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
|
|
2329 122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
|
|
2330 131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
|
|
2331 224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
|
|
2332 118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
|
|
2333 161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
|
|
2334 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
|
|
2335 116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
|
|
2336 };
|
|
2337
|
|
2338 UDWORD Key[4];
|
|
2339
|
|
2340
|
|
2341 void EncryptBlock(UBYTE *Buf)
|
|
2342 {
|
|
2343 int I;
|
|
2344
|
|
2345 UDWORD A,B,C,D,T,TA,TB;
|
|
2346 #ifdef NON_INTEL_BYTE_ORDER
|
|
2347 A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
|
|
2348 ((UDWORD)Buf[3]<<24))^Key[0];
|
|
2349 B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
|
|
2350 ((UDWORD)Buf[7]<<24))^Key[1];
|
|
2351 C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
|
|
2352 ((UDWORD)Buf[11]<<24))^Key[2];
|
|
2353 D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
|
|
2354 ((UDWORD)Buf[15]<<24))^Key[3];
|
|
2355 #else
|
|
2356 UDWORD *BufPtr;
|
|
2357 BufPtr=(UDWORD *)Buf;
|
|
2358 A=BufPtr[0]^Key[0];
|
|
2359 B=BufPtr[1]^Key[1];
|
|
2360 C=BufPtr[2]^Key[2];
|
|
2361 D=BufPtr[3]^Key[3];
|
|
2362 #endif
|
|
2363 for(I=0;I<NROUNDS;I++)
|
|
2364 {
|
|
2365 T=((C+rol(D,11))^Key[I&3]);
|
|
2366 TA=A^substLong(T);
|
|
2367 T=((D^rol(C,17))+Key[I&3]);
|
|
2368 TB=B^substLong(T);
|
|
2369 A=C;
|
|
2370 B=D;
|
|
2371 C=TA;
|
|
2372 D=TB;
|
|
2373 }
|
|
2374 #ifdef NON_INTEL_BYTE_ORDER
|
|
2375 C^=Key[0];
|
|
2376 Buf[0]=(UBYTE)C;
|
|
2377 Buf[1]=(UBYTE)(C>>8);
|
|
2378 Buf[2]=(UBYTE)(C>>16);
|
|
2379 Buf[3]=(UBYTE)(C>>24);
|
|
2380 D^=Key[1];
|
|
2381 Buf[4]=(UBYTE)D;
|
|
2382 Buf[5]=(UBYTE)(D>>8);
|
|
2383 Buf[6]=(UBYTE)(D>>16);
|
|
2384 Buf[7]=(UBYTE)(D>>24);
|
|
2385 A^=Key[2];
|
|
2386 Buf[8]=(UBYTE)A;
|
|
2387 Buf[9]=(UBYTE)(A>>8);
|
|
2388 Buf[10]=(UBYTE)(A>>16);
|
|
2389 Buf[11]=(UBYTE)(A>>24);
|
|
2390 B^=Key[3];
|
|
2391 Buf[12]=(UBYTE)B;
|
|
2392 Buf[13]=(UBYTE)(B>>8);
|
|
2393 Buf[14]=(UBYTE)(B>>16);
|
|
2394 Buf[15]=(UBYTE)(B>>24);
|
|
2395 #else
|
|
2396 BufPtr[0]=C^Key[0];
|
|
2397 BufPtr[1]=D^Key[1];
|
|
2398 BufPtr[2]=A^Key[2];
|
|
2399 BufPtr[3]=B^Key[3];
|
|
2400 #endif
|
|
2401 UpdKeys(Buf);
|
|
2402 }
|
|
2403
|
|
2404
|
|
2405 void DecryptBlock(UBYTE *Buf)
|
|
2406 {
|
|
2407 int I;
|
|
2408 UBYTE InBuf[16];
|
|
2409 UDWORD A,B,C,D,T,TA,TB;
|
|
2410 #ifdef NON_INTEL_BYTE_ORDER
|
|
2411 A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
|
|
2412 ((UDWORD)Buf[3]<<24))^Key[0];
|
|
2413 B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
|
|
2414 ((UDWORD)Buf[7]<<24))^Key[1];
|
|
2415 C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
|
|
2416 ((UDWORD)Buf[11]<<24))^Key[2];
|
|
2417 D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
|
|
2418 ((UDWORD)Buf[15]<<24))^Key[3];
|
|
2419 #else
|
|
2420 UDWORD *BufPtr;
|
|
2421 BufPtr=(UDWORD *)Buf;
|
|
2422 A=BufPtr[0]^Key[0]; /* xxx may be this can be */
|
|
2423 B=BufPtr[1]^Key[1]; /* optimized in assembler */
|
|
2424 C=BufPtr[2]^Key[2];
|
|
2425 D=BufPtr[3]^Key[3];
|
|
2426 #endif
|
|
2427 memcpy(InBuf,Buf,sizeof(InBuf));
|
|
2428 for(I=NROUNDS-1;I>=0;I--)
|
|
2429 {
|
|
2430 T=((C+rol(D,11))^Key[I&3]);
|
|
2431 TA=A^substLong(T);
|
|
2432 T=((D^rol(C,17))+Key[I&3]);
|
|
2433 TB=B^substLong(T);
|
|
2434 A=C;
|
|
2435 B=D;
|
|
2436 C=TA;
|
|
2437 D=TB;
|
|
2438 }
|
|
2439 #ifdef NON_INTEL_BYTE_ORDER
|
|
2440 C^=Key[0];
|
|
2441 Buf[0]=(UBYTE)C;
|
|
2442 Buf[1]=(UBYTE)(C>>8);
|
|
2443 Buf[2]=(UBYTE)(C>>16);
|
|
2444 Buf[3]=(UBYTE)(C>>24);
|
|
2445 D^=Key[1];
|
|
2446 Buf[4]=(UBYTE)D;
|
|
2447 Buf[5]=(UBYTE)(D>>8);
|
|
2448 Buf[6]=(UBYTE)(D>>16);
|
|
2449 Buf[7]=(UBYTE)(D>>24);
|
|
2450 A^=Key[2];
|
|
2451 Buf[8]=(UBYTE)A;
|
|
2452 Buf[9]=(UBYTE)(A>>8);
|
|
2453 Buf[10]=(UBYTE)(A>>16);
|
|
2454 Buf[11]=(UBYTE)(A>>24);
|
|
2455 B^=Key[3];
|
|
2456 Buf[12]=(UBYTE)B;
|
|
2457 Buf[13]=(UBYTE)(B>>8);
|
|
2458 Buf[14]=(UBYTE)(B>>16);
|
|
2459 Buf[15]=(UBYTE)(B>>24);
|
|
2460 #else
|
|
2461 BufPtr[0]=C^Key[0];
|
|
2462 BufPtr[1]=D^Key[1];
|
|
2463 BufPtr[2]=A^Key[2];
|
|
2464 BufPtr[3]=B^Key[3];
|
|
2465 #endif
|
|
2466 UpdKeys(InBuf);
|
|
2467 }
|
|
2468
|
|
2469
|
|
2470 void UpdKeys(UBYTE *Buf)
|
|
2471 {
|
|
2472 int I;
|
|
2473 for (I=0;I<16;I+=4)
|
|
2474 {
|
|
2475 Key[0]^=CRCTab[Buf[I]]; /* xxx may be I'll rewrite this */
|
|
2476 Key[1]^=CRCTab[Buf[I+1]]; /* in asm for speedup */
|
|
2477 Key[2]^=CRCTab[Buf[I+2]];
|
|
2478 Key[3]^=CRCTab[Buf[I+3]];
|
|
2479 }
|
|
2480 }
|
|
2481
|
|
2482 void SetCryptKeys(char *Password)
|
|
2483 {
|
|
2484 unsigned int I,J,K,PswLength;
|
|
2485 unsigned char N1,N2;
|
|
2486 unsigned char Psw[256];
|
|
2487
|
|
2488 #if !defined _USE_ASM
|
|
2489 UBYTE Ch;
|
|
2490 #endif
|
|
2491
|
|
2492 SetOldKeys(Password);
|
|
2493
|
|
2494 Key[0]=0xD3A3B879L;
|
|
2495 Key[1]=0x3F6D12F7L;
|
|
2496 Key[2]=0x7515A235L;
|
|
2497 Key[3]=0xA4E7F123L;
|
|
2498 memset(Psw,0,sizeof(Psw));
|
|
2499 strcpy((char *)Psw,Password);
|
|
2500 PswLength=strlen(Password);
|
|
2501 memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
|
|
2502
|
|
2503 for (J=0;J<256;J++)
|
|
2504 for (I=0;I<PswLength;I+=2)
|
|
2505 {
|
|
2506 N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xFF];
|
|
2507 for (K=1, N1=(unsigned char)CRCTab[(Psw[I]-J)&0xFF];
|
|
2508 (N1!=N2) && (N1 < 256); /* I had to add "&& (N1 < 256)", */
|
|
2509 N1++, K++) /* because the system crashed with */
|
|
2510 { /* encrypted RARs */
|
|
2511 #ifdef _USE_ASM
|
|
2512
|
|
2513 #ifdef _WIN_32
|
|
2514 __asm {
|
|
2515
|
|
2516 mov ebx, Offset SubstTable
|
|
2517 mov edx, ebx
|
|
2518
|
|
2519 xor ecx, ecx // read SubstTable[N1]...
|
|
2520 mov cl, N1
|
|
2521 add ebx, ecx
|
|
2522 mov al, byte ptr[ebx]
|
|
2523
|
|
2524 mov cl, N1 // read SubstTable[(N1+I+K)&0xFF]...
|
|
2525 add ecx, I
|
|
2526 add ecx, K
|
|
2527 and ecx, 0xFF
|
|
2528 add edx, ecx
|
|
2529 mov ah, byte ptr[edx]
|
|
2530
|
|
2531 mov byte ptr[ebx], ah // and write back
|
|
2532 mov byte ptr[edx], al
|
|
2533
|
|
2534 }
|
|
2535 #else
|
|
2536 __asm__ __volatile__ (
|
|
2537 " xorl %%ecx, %%ecx"
|
|
2538 " movl %2, %%ecx /* ecx = N1 */"
|
|
2539 " mov %%ebx, %%edx"
|
|
2540 " addl %%ecx, %%ebx"
|
|
2541 ""
|
|
2542 " addl %0, %%ecx"
|
|
2543 " addl %1, %%ecx"
|
|
2544 " andl $0x000000FF, %%ecx"
|
|
2545 " addl %%ecx, %%edx"
|
|
2546 " "
|
|
2547 " movb (%%ebx), %%al"
|
|
2548 " movb (%%edx), %%ah"
|
|
2549 ""
|
|
2550 " movb %%ah, (%%ebx) /* and write back */"
|
|
2551 " movb %%al, (%%edx)"
|
|
2552 : : "g" ((long)I),
|
|
2553 "g" ((long)K),
|
|
2554 "g" ((long)N1),
|
|
2555 "ebx"((long)SubstTable)
|
|
2556 : "ecx", "edx"
|
|
2557
|
|
2558 );
|
|
2559 #endif
|
|
2560
|
|
2561 #else
|
|
2562 /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
|
|
2563 Ch=SubstTable[N1];
|
|
2564 SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
|
|
2565 SubstTable[(N1+I+K)&0xFF]=Ch;
|
|
2566 #endif
|
|
2567 }
|
|
2568 }
|
|
2569 for (I=0;I<PswLength;I+=16)
|
|
2570 EncryptBlock(&Psw[I]);
|
|
2571 }
|
|
2572
|
|
2573
|
|
2574 void SetOldKeys(char *Password)
|
|
2575 {
|
|
2576 UDWORD PswCRC;
|
|
2577 UBYTE Ch;
|
|
2578 PswCRC=CalcCRC32(0xFFFFFFFFL,(UBYTE*)Password,strlen(Password));
|
|
2579 OldKey[0]=(UWORD)PswCRC;
|
|
2580 OldKey[1]=(UWORD)(PswCRC>>16);
|
|
2581 OldKey[2]=OldKey[3]=0;
|
|
2582 PN1=PN2=PN3=0;
|
|
2583 while ((Ch=*Password)!=0)
|
|
2584 {
|
|
2585 PN1+=Ch;
|
|
2586 PN2^=Ch;
|
|
2587 PN3+=Ch;
|
|
2588 PN3=(UBYTE)rol(PN3,1);
|
|
2589 OldKey[2]^=((UWORD)(Ch^CRCTab[Ch]));
|
|
2590 OldKey[3]+=((UWORD)(Ch+(CRCTab[Ch]>>16)));
|
|
2591 Password++;
|
|
2592 }
|
|
2593 }
|
|
2594
|
|
2595 void InitCRC(void)
|
|
2596 {
|
|
2597 int I, J;
|
|
2598 UDWORD C;
|
|
2599 for (I=0;I<256;I++)
|
|
2600 {
|
|
2601 for (C=I,J=0;J<8;J++)
|
|
2602 C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
|
|
2603 CRCTab[I]=C;
|
|
2604 }
|
|
2605 }
|
|
2606
|
|
2607
|
|
2608 UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
|
|
2609 {
|
|
2610 unsigned int I;
|
|
2611 for (I=0; I<Size; I++)
|
|
2612 StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
|
|
2613 return(StartCRC);
|
|
2614 }
|
|
2615
|
|
2616
|
|
2617 /* **************************************************************************
|
|
2618 ****************************************************************************
|
|
2619 ****************************************************************************
|
|
2620 ************************************************************************** */
|
|
2621
|
|
2622
|
|
2623
|
|
2624
|
|
2625
|
|
2626
|
|
2627
|
|
2628
|
|
2629
|
|
2630
|
|
2631
|
|
2632
|
|
2633
|
|
2634
|
|
2635
|
|
2636
|
|
2637
|
|
2638
|
|
2639
|
|
2640
|
|
2641
|
|
2642
|
|
2643
|
|
2644
|
|
2645
|
|
2646 /* **************************************************************************
|
|
2647 ****************************************************************************
|
|
2648 ****************************************************************************
|
|
2649 ****************************************************************************
|
|
2650 ******* *******
|
|
2651 ******* *******
|
|
2652 ******* *******
|
|
2653 ******* D E B U G F U N C T I O N S *******
|
|
2654 ******* *******
|
|
2655 ******* *******
|
|
2656 ******* *******
|
|
2657 ****************************************************************************
|
|
2658 ****************************************************************************
|
|
2659 ****************************************************************************
|
|
2660 ************************************************************************** */
|
|
2661 #ifdef _DEBUG_LOG
|
|
2662
|
|
2663
|
|
2664 /* -- global stuff -------------------------------------------------------- */
|
|
2665 char log_file_name[256]; /* file name for the log file */
|
|
2666 DWORD debug_start_time; /* starttime of debug */
|
|
2667 BOOL debug_started = FALSE; /* debug_log writes only if */
|
|
2668 /* this is TRUE */
|
|
2669 /* ------------------------------------------------------------------------ */
|
|
2670
|
|
2671
|
|
2672 /* -- global functions ---------------------------------------------------- */
|
|
2673 void debug_init_proc(char *file_name)
|
|
2674 /* Create/Rewrite a log file */
|
|
2675 {
|
|
2676 FILE *fp;
|
|
2677 char date[] = __DATE__;
|
|
2678 char time[] = __TIME__;
|
|
2679
|
|
2680 debug_start_time = GetTickCount(); /* get start time */
|
|
2681 strcpy(log_file_name, file_name); /* save file name */
|
|
2682
|
|
2683 if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
|
|
2684 {
|
|
2685 debug_started = TRUE; /* enable debug */
|
|
2686 fprintf(fp, "Debug log of UniquE's RARFileLib\n"\
|
|
2687 "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
|
|
2688 fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time);
|
|
2689 fclose(fp);
|
|
2690 }
|
|
2691 }
|
|
2692
|
|
2693
|
|
2694 void debug_log_proc(char *text, char *sourcefile, int sourceline)
|
|
2695 /* add a line to the log file */
|
|
2696 {
|
|
2697 FILE *fp;
|
|
2698
|
|
2699 if(debug_started == FALSE) return; /* exit if not initialized */
|
|
2700
|
|
2701 if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile */
|
|
2702
|
|
2703 {
|
|
2704 fprintf(fp, " %8u ms (line %u in %s):\n - %s\n",
|
|
2705 (unsigned int)(GetTickCount() - debug_start_time),
|
|
2706 sourceline, sourcefile, text);
|
|
2707 fclose(fp);
|
|
2708 }
|
|
2709 }
|
|
2710
|
|
2711 /* ------------------------------------------------------------------------ */
|
|
2712 #endif
|
|
2713 /* **************************************************************************
|
|
2714 ****************************************************************************
|
|
2715 ****************************************************************************
|
|
2716 ************************************************************************** */
|
|
2717
|
|
2718
|
|
2719 /* end of file urarlib.c */
|