~ubuntu-branches/ubuntu/hoary/clamav/hoary-backports

« back to all changes in this revision

Viewing changes to libclamav/unrarlib.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Gran
  • Date: 2004-06-21 22:26:45 UTC
  • Revision ID: james.westby@ubuntu.com-20040621222645-jvaxzuttrjz6kh8t
Tags: upstream-0.73
ImportĀ upstreamĀ versionĀ 0.73

Show diffs side-by-side

added added

removed removed

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