summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rwxr-xr-xconfigure16
-rw-r--r--unrarlib.c2716
-rw-r--r--unrarlib.h200
-rw-r--r--vobsub.c243
5 files changed, 3138 insertions, 41 deletions
diff --git a/Makefile b/Makefile
index a0d3fad226..5475b51c9a 100644
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,10 @@ ifeq ($(GUI),yes)
PARTS += Gui
endif
+ifeq ($(UNRARLIB),yes)
+SRCS_COMMON += unrarlib.c
+endif
+
ifneq ($(W32_LIB),)
PARTS += loader loader/dshow
endif
diff --git a/configure b/configure
index 8905593f09..17ff00ce91 100755
--- a/configure
+++ b/configure
@@ -149,6 +149,7 @@ Optional features:
--disable-css Disable old-style libcss DVD support [autodetect]
--disable-cdparanoia Disable cdparanoia support [autodetect]
--enable-freetype Enable freetype2 font rendering support [disabled]
+ --disable-unrarlib Disable Unique RAR File Library [enabled]
Codecs:
--enable-gif enable gif89a output support [autodetect]
@@ -965,6 +966,7 @@ _sgiaudio=auto
_sunaudio=auto
_alsa=auto
_fastmemcpy=yes
+_unrarlib=yes
_win32=auto
_dshow=yes
_select=yes
@@ -1159,6 +1161,8 @@ for ac_option do
--disable-big-endian) _big_endian=no ;;
--enable-freetype) _freetype=yes ;;
--disable-freetype) _freetype=no ;;
+ --enable-unralib) _unrarlib=yes ;;
+ --disable-unrarlib) _unrarlib=no ;;
--enable-dga) _dga=auto ;; # as we don't know if it's 1 or 2
--enable-dga=*) _dga=`echo $ac_option | cut -d '=' -f 2` ;;
@@ -3960,6 +3964,13 @@ else
fi
echores "$_fastmemcpy"
+echocheck "UniquE RAR File Library"
+if test "$_unrarlib" = yes ; then
+ _def_unrarlib='#define USE_UNRARLIB 1'
+else
+ _def_unrarlib='#undef USE_UNRARLIB'
+fi
+echores "$_unrarlib"
echocheck "TV interface"
if test "$_tv" = yes ; then
@@ -4343,6 +4354,8 @@ VIDIX = $_vidix
OPENDIVX = $_opendivx
+UNRARLIB = $_unrarlib
+
PNG = $_mkf_png
JPEG = $_mkf_jpg
GIF = $_mkf_gif
@@ -4659,6 +4672,9 @@ $_def_live
/* Use 3dnow/mmxext/sse/mmx optimized fast memcpy() [maybe buggy... signal 4]*/
$_def_fastmemcpy
+/* Use unrarlib for Vobsubs */
+$_def_unrarlib
+
/* gui support, please do not edit this option */
$_def_gui
diff --git a/unrarlib.c b/unrarlib.c
new file mode 100644
index 0000000000..48bece58e0
--- /dev/null
+++ b/unrarlib.c
@@ -0,0 +1,2716 @@
+/* ***************************************************************************
+ **
+ ** This file is part of the UniquE RAR File Library.
+ **
+ ** Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
+ ** UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
+ **
+ ** The contents of this file are subject to the UniquE RAR File Library
+ ** License (the "unrarlib-license.txt"). You may not use this file except
+ ** in compliance with the License. You may obtain a copy of the License
+ ** at http://www.unrarlib.org/license.html.
+ ** Software distributed under the License is distributed on an "AS IS"
+ ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
+ **
+ ** Alternatively, the contents of this file may be used under the terms
+ ** of the GNU General Public License Version 2 or later (the "GPL"), in
+ ** which case the provisions of the GPL are applicable instead of those
+ ** above. If you wish to allow use of your version of this file only
+ ** under the terms of the GPL and not to allow others to use your version
+ ** of this file under the terms of the UniquE RAR File Library License,
+ ** indicate your decision by deleting the provisions above and replace
+ ** them with the notice and other provisions required by the GPL. If you
+ ** do not delete the provisions above, a recipient may use your version
+ ** of this file under the terms of the GPL or the UniquE RAR File Library
+ ** License.
+ **
+ ************************************************************************** */
+
+/* ***************************************************************************
+ **
+ ** UniquE RAR File Library
+ ** The free file lib for the demoscene
+ ** multi-OS version (Win32, Linux and SunOS)
+ **
+ *****************************************************************************
+ **
+ ** ==> Please configure the program in "unrarlib.h". <==
+ **
+ ** RAR decompression code:
+ ** (C) Eugene Roshal
+ ** Modifications to a FileLib:
+ ** (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
+ ** Linux port:
+ ** (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
+ **
+ ** The UniquE RAR File Library gives you the ability to access RAR archives
+ ** (any compression method supported in RAR v2.0 including Multimedia
+ ** Compression and encryption) directly from your program with ease an by
+ ** adding only 12kB (6kB UPX-compressed) additional code to your program.
+ ** Both solid and normal (recommended for fast random access to the files!)
+ ** archives are supported. This FileLib is made for the Demo scene, so it's
+ ** designed for easy use within your demos and intros.
+ ** Please read "licence.txt" to learn more about how you may use URARFileLib
+ ** in your productions.
+ **
+ *****************************************************************************
+ **
+ ** ==> see the "CHANGES" file to see what's new
+ **
+ ************************************************************************** */
+
+/* -- include files ------------------------------------------------------- */
+#include "unrarlib.h" /* include global configuration */
+/* ------------------------------------------------------------------------ */
+
+
+
+/* -- global stuff -------------------------------------------------------- */
+#ifdef _WIN_32
+
+#include <windows.h> /* WIN32 definitions */
+#include <stdio.h>
+#include <string.h>
+
+
+#define ENABLE_ACCESS
+
+#define HOST_OS WIN_32
+
+#define FM_NORMAL 0x00
+#define FM_RDONLY 0x01
+#define FM_HIDDEN 0x02
+#define FM_SYSTEM 0x04
+#define FM_LABEL 0x08
+#define FM_DIREC 0x10
+#define FM_ARCH 0x20
+
+#define PATHDIVIDER "\\"
+#define CPATHDIVIDER '\\'
+#define MASKALL "*.*"
+
+#define READBINARY "rb"
+#define READTEXT "rt"
+#define UPDATEBINARY "r+b"
+#define CREATEBINARY "w+b"
+#define CREATETEXT "w"
+#define APPENDTEXT "at"
+
+#endif
+
+#ifdef _UNIX
+
+#include <stdio.h> /* LINUX/UNIX definitions */
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define ENABLE_ACCESS
+
+#define HOST_OS UNIX
+
+#define FM_LABEL 0x0000
+#define FM_DIREC 0x4000
+
+#define PATHDIVIDER "/"
+#define CPATHDIVIDER '/'
+#define MASKALL "*.*"
+
+#define READBINARY "r"
+#define READTEXT "r"
+#define UPDATEBINARY "r+"
+#define CREATEBINARY "w+"
+#define CREATETEXT "w"
+#define APPENDTEXT "a"
+
+
+/* emulation of the windows API and data types */
+/* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
+
+typedef long DWORD;
+typedef short BOOL;
+#define TRUE 1
+#define FALSE 0
+
+
+#ifdef _DEBUG_LOG /* define macros for debugging */
+#include <unistd.h>
+#include <sys/time.h>
+
+DWORD GetTickCount()
+{
+ struct timeval tv;
+ gettimeofday( &tv, 0 );
+ return (tv.tv_usec / 1000);
+}
+#endif
+
+#endif
+
+
+
+
+
+#ifdef _DEBUG_LOG /* define macros for debugging */
+
+BOOL debug_log_first_start = TRUE;
+
+#define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
+#define debug_init(a); debug_init_proc(a);
+
+void debug_log_proc(char *text, char *sourcefile, int sourceline);
+void debug_init_proc(char *file_name);
+
+#else
+#define debug_log(a); /* no debug this time */
+#define debug_init(a); /* no debug this time */
+#endif
+
+
+
+
+
+#define MAXWINSIZE 0x100000
+#define MAXWINMASK (MAXWINSIZE-1)
+#define UNP_MEMORY MAXWINSIZE
+#define Min(x,y) (((x)<(y)) ? (x):(y))
+#define Max(x,y) (((x)>(y)) ? (x):(y))
+#define NM 260
+
+#define SIZEOF_MARKHEAD 7
+#define SIZEOF_OLDMHD 7
+#define SIZEOF_NEWMHD 13
+#define SIZEOF_OLDLHD 21
+#define SIZEOF_NEWLHD 32
+#define SIZEOF_SHORTBLOCKHEAD 7
+#define SIZEOF_LONGBLOCKHEAD 11
+#define SIZEOF_COMMHEAD 13
+#define SIZEOF_PROTECTHEAD 26
+
+
+#define PACK_VER 20 /* version of decompression code*/
+#define UNP_VER 20
+#define PROTECT_VER 20
+
+
+enum { M_DENYREAD,M_DENYWRITE,M_DENYNONE,M_DENYALL };
+enum { FILE_EMPTY,FILE_ADD,FILE_UPDATE,FILE_COPYOLD,FILE_COPYBLOCK };
+enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
+ OPEN_ERROR,USER_ERROR,MEMORY_ERROR,USER_BREAK=255,IMM_ABORT=0x8000 };
+enum { EN_LOCK=1,EN_VOL=2 };
+enum { SD_MEMORY=1,SD_FILES=2 };
+enum { NAMES_DONTCHANGE };
+enum { LOG_ARC=1,LOG_FILE=2 };
+enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
+enum { OLD_UNPACK,NEW_UNPACK };
+
+
+#define MHD_COMMENT 2
+#define MHD_LOCK 4
+#define MHD_PACK_COMMENT 16
+#define MHD_AV 32
+#define MHD_PROTECT 64
+
+#define LHD_SPLIT_BEFORE 1
+#define LHD_SPLIT_AFTER 2
+#define LHD_PASSWORD 4
+#define LHD_COMMENT 8
+#define LHD_SOLID 16
+
+#define LHD_WINDOWMASK 0x00e0
+#define LHD_WINDOW64 0
+#define LHD_WINDOW128 32
+#define LHD_WINDOW256 64
+#define LHD_WINDOW512 96
+#define LHD_WINDOW1024 128
+#define LHD_DIRECTORY 0x00e0
+
+#define LONG_BLOCK 0x8000
+#define READSUBBLOCK 0x8000
+
+enum { ALL_HEAD=0,MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,
+ COMM_HEAD=0x75,AV_HEAD=0x76,SUB_HEAD=0x77,PROTECT_HEAD=0x78};
+enum { EA_HEAD=0x100 };
+enum { MS_DOS=0,OS2=1,WIN_32=2,UNIX=3 };
+
+
+struct MarkHeader
+{
+ UBYTE Mark[7];
+};
+
+
+struct NewMainArchiveHeader
+{
+ UWORD HeadCRC;
+ UBYTE HeadType;
+ UWORD Flags;
+ UWORD HeadSize;
+ UWORD Reserved;
+ UDWORD Reserved1;
+};
+
+
+struct NewFileHeader
+{
+ UWORD HeadCRC;
+ UBYTE HeadType;
+ UWORD Flags;
+ UWORD HeadSize;
+ UDWORD PackSize;
+ UDWORD UnpSize;
+ UBYTE HostOS;
+ UDWORD FileCRC;
+ UDWORD FileTime;
+ UBYTE UnpVer;
+ UBYTE Method;
+ UWORD NameSize;
+ UDWORD FileAttr;
+};
+
+
+struct BlockHeader
+{
+ UWORD HeadCRC;
+ UBYTE HeadType;
+ UWORD Flags;
+ UWORD HeadSize;
+ UDWORD DataSize;
+};
+
+
+struct Decode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[2];
+};
+
+
+struct MarkHeader MarkHead;
+struct NewMainArchiveHeader NewMhd;
+struct NewFileHeader NewLhd;
+struct BlockHeader BlockHead;
+
+UBYTE *TempMemory; /* temporary unpack-buffer */
+char *CommMemory;
+
+
+UBYTE *UnpMemory;
+char ArgName[NM]; /* current file in rar archive */
+char ArcFileName[NM]; /* file to decompress */
+
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
+ MemoryFile *MemRARFile; /* pointer to RAR file in memory*/
+#else
+ char ArcName[255]; /* RAR archive name */
+ FILE *ArcPtr; /* input RAR file handler */
+#endif
+char Password[255]; /* password to decrypt files */
+
+unsigned char *temp_output_buffer; /* extract files to this pointer*/
+unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */
+
+BOOL FileFound; /* TRUE=use current extracted */
+ /* data FALSE=throw data away, */
+ /* wrong file */
+int MainHeadSize;
+long CurBlockPos,NextBlockPos;
+
+unsigned long CurUnpRead, CurUnpWrite;
+long UnpPackedSize;
+long DestUnpSize;
+
+UDWORD HeaderCRC;
+int Encryption;
+
+unsigned int UnpWrSize;
+unsigned char *UnpWrAddr;
+unsigned int UnpPtr,WrPtr;
+
+unsigned char PN1,PN2,PN3;
+unsigned short OldKey[4];
+
+
+
+/* function header definitions */
+int ReadHeader(int BlockType);
+BOOL ExtrFile(void);
+BOOL ListFile(void);
+int tread(void *stream,void *buf,unsigned len);
+int tseek(void *stream,long offset,int fromwhere);
+BOOL UnstoreFile(void);
+int IsArchive(void);
+int ReadBlock(int BlockType);
+unsigned int UnpRead(unsigned char *Addr,unsigned int Count);
+void UnpInitData(void);
+void Unpack(unsigned char *UnpAddr);
+UBYTE DecodeAudio(int Delta);
+static void DecodeNumber(struct Decode *Dec);
+void UpdKeys(UBYTE *Buf);
+void SetCryptKeys(char *Password);
+void SetOldKeys(char *Password);
+void DecryptBlock(unsigned char *Buf);
+void InitCRC(void);
+UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);
+void UnpReadBuf(int FirstBuf);
+void ReadTables(void);
+static void ReadLastTables(void);
+static void MakeDecodeTables(unsigned char *LenTab,
+ struct Decode *Dec,
+ int Size);
+int stricomp(char *Str1,char *Str2);
+/* ------------------------------------------------------------------------ */
+
+
+/* -- global functions ---------------------------------------------------- */
+
+int urarlib_get(void *output,
+ unsigned long *size,
+ char *filename,
+ void *rarfile,
+ char *libpassword)
+/* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
+ * does everything from allocating memory, decrypting and unpacking the file
+ * from the archive. TRUE is returned if the file could be successfully
+ * extracted, else a FALSE indicates a failure.
+ */
+{
+ BOOL retcode = FALSE;
+
+#ifdef _DEBUG_LOG
+ int str_offs; /* used for debug-strings */
+ char DebugMsg[500]; /* used to compose debug msg */
+
+ if(debug_log_first_start)
+ {
+ debug_log_first_start=FALSE; /* only create a new log file */
+ debug_init(_DEBUG_LOG_FILE); /* on startup */
+ }
+
+#endif
+
+ InitCRC(); /* init some vars */
+
+ strcpy(ArgName, filename); /* set file(s) to extract */
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile = rarfile; /* set pointer to mem-RAR file */
+#else
+ strcpy(ArcName, rarfile); /* set RAR file name */
+#endif
+ if(libpassword != NULL)
+ strcpy(Password, libpassword); /* init password */
+
+ temp_output_buffer = NULL;
+ temp_output_buffer_offset=size; /* set size of the temp buffer */
+
+#ifdef _DEBUG_LOG
+ sprintf(DebugMsg, "Extracting >%s< from >%s< (password is >%s<)...",
+ filename, (char*)rarfile, libpassword);
+ debug_log(DebugMsg);
+#endif
+
+ retcode = ExtrFile(); /* unpack file now! */
+
+ memset(Password,0,sizeof(Password)); /* clear password */
+
+#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ if (ArcPtr!=NULL){
+ fclose(ArcPtr);
+ ArcPtr = NULL;
+ }
+#endif
+
+ free(UnpMemory); /* free memory */
+ free(TempMemory);
+ free(CommMemory);
+ UnpMemory=NULL;
+ TempMemory=NULL;
+ CommMemory=NULL;
+
+
+ if(retcode == FALSE)
+ {
+ free(temp_output_buffer); /* free memory and return NULL */
+ temp_output_buffer=NULL;
+ *(DWORD*)output=0; /* pointer on errors */
+ *size=0;
+#ifdef _DEBUG_LOG
+
+
+ /* sorry for this ugly code, but older SunOS gcc compilers don't support */
+ /* white spaces within strings */
+ str_offs = sprintf(DebugMsg, "Error - couldn't extract ");
+ str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename);
+ str_offs += sprintf(DebugMsg + str_offs, " and allocated ");
+ str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size);
+ str_offs += sprintf(DebugMsg + str_offs, " of unused memory!");
+
+ } else
+ {
+ sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
+ }
+ debug_log(DebugMsg);
+#else
+ }
+#endif
+ *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
+ /* data */
+
+ return retcode;
+}
+
+
+int urarlib_list(void *rarfile, ArchiveList_struct *list)
+{
+ ArchiveList_struct *tmp_List = NULL;
+ int NoOfFilesInArchive = 0; /* number of files in archive */
+
+#ifdef _DEBUG_LOG
+ if(debug_log_first_start)
+ {
+ debug_log_first_start=FALSE; /* only create a new log file */
+ debug_init(_DEBUG_LOG_FILE); /* on startup */
+ }
+#endif
+
+ InitCRC(); /* init some vars */
+
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile = rarfile; /* assign pointer to RAR file */
+ MemRARFile->offset = 0;
+ if (!IsArchive())
+ {
+ debug_log("Not a RAR file");
+ return NoOfFilesInArchive; /* error => exit! */
+ }
+#else
+ /* open and identify archive */
+ if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL)
+ {
+ if (!IsArchive())
+ {
+ debug_log("Not a RAR file");
+ fclose(ArcPtr);
+ ArcPtr = NULL;
+ return NoOfFilesInArchive; /* error => exit! */
+ }
+ }
+ else {
+ debug_log("Error opening file.");
+ return NoOfFilesInArchive;
+ }
+#endif
+
+ if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
+ {
+ debug_log("Can't allocate memory for decompression!");
+ return NoOfFilesInArchive;
+ }
+
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
+#else
+ tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
+#endif
+ (*(DWORD*)list) = (DWORD)NULL; /* init file list */
+ /* do while file is not extracted and there's no error */
+ while (TRUE)
+ {
+ if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
+ { /* file within the RAR archive */
+ debug_log("Couldn't read next filename from archive (I/O error).");
+ break; /* error, file not found in */
+ } /* archive or I/O error */
+ if (BlockHead.HeadType==SUB_HEAD)
+ {
+ debug_log("Sorry, sub-headers not supported.");
+ break; /* error => exit */
+ }
+
+ if((void*)(*(DWORD*)list) == NULL) /* first entry */
+ {
+ tmp_List = malloc(sizeof(ArchiveList_struct));
+ tmp_List->next = NULL;
+
+ (*(DWORD*)list) = (DWORD)tmp_List;
+
+ } else /* add entry */
+ {
+ tmp_List->next = malloc(sizeof(ArchiveList_struct));
+ tmp_List = (ArchiveList_struct*) tmp_List->next;
+ tmp_List->next = NULL;
+ }
+
+ tmp_List->item.Name = malloc(NewLhd.NameSize + 1);
+ strcpy(tmp_List->item.Name, ArcFileName);
+ tmp_List->item.NameSize = NewLhd.NameSize;
+ tmp_List->item.PackSize = NewLhd.PackSize;
+ tmp_List->item.UnpSize = NewLhd.UnpSize;
+ tmp_List->item.HostOS = NewLhd.HostOS;
+ tmp_List->item.FileCRC = NewLhd.FileCRC;
+ tmp_List->item.FileTime = NewLhd.FileTime;
+ tmp_List->item.UnpVer = NewLhd.UnpVer;
+ tmp_List->item.Method = NewLhd.Method;
+ tmp_List->item.FileAttr = NewLhd.FileAttr;
+
+ NoOfFilesInArchive++; /* count files */
+
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile->offset = NextBlockPos;
+#else
+ if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
+#endif
+
+ };
+
+ /* free memory, clear password and close archive */
+ memset(Password,0,sizeof(Password)); /* clear password */
+#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ if (ArcPtr!=NULL){
+ fclose(ArcPtr);
+ ArcPtr = NULL;
+ }
+#endif
+
+ free(UnpMemory); /* free memory */
+ free(TempMemory);
+ free(CommMemory);
+ UnpMemory=NULL;
+ TempMemory=NULL;
+ CommMemory=NULL;
+
+ return NoOfFilesInArchive;
+}
+
+
+
+/* urarlib_freelist:
+ * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
+ * and Johannes Winkelmann who independently wrote a patch)
+ * free the memory of a ArchiveList_struct created by urarlib_list.
+ *
+ * input: *list pointer to an ArchiveList_struct
+ * output: -
+ */
+
+void urarlib_freelist(ArchiveList_struct *list)
+{
+ ArchiveList_struct* tmp = list;
+
+ while ( list ) {
+ tmp = list->next;
+ free( list->item.Name );
+ free( list );
+ list = tmp;
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ ******* *******
+ ******* *******
+ ******* *******
+ ******* B L O C K I / O *******
+ ******* *******
+ ******* *******
+ ******* *******
+ ****************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ ****************************************************************************/
+
+
+
+#define GetHeaderByte(N) Header[N]
+
+#define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
+
+#define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
+ ((UDWORD)Header[N+2]<<16)+\
+ ((UDWORD)Header[N+3]<<24))
+
+
+int ReadBlock(int BlockType)
+{
+ struct NewFileHeader SaveFileHead;
+ int Size=0,ReadSubBlock=0;
+ static int LastBlock;
+ memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
+ if (BlockType & READSUBBLOCK)
+ ReadSubBlock=1;
+ BlockType &= 0xff;
+ {
+ while (1)
+ {
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ CurBlockPos=MemRARFile->offset; /* get offset of mem-file */
+#else
+ CurBlockPos=ftell(ArcPtr);
+#endif
+ Size=ReadHeader(FILE_HEAD);
+ if (Size!=0)
+ {
+ if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
+ return(0);
+ NextBlockPos=CurBlockPos+NewLhd.HeadSize;
+ if (NewLhd.Flags & LONG_BLOCK)
+ NextBlockPos+=NewLhd.PackSize;
+ if (NextBlockPos<=CurBlockPos)
+ return(0);
+ }
+
+ if (Size > 0 && BlockType!=SUB_HEAD)
+ LastBlock=BlockType;
+ if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
+ (NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
+ break;
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile->offset = NextBlockPos;
+#else
+ tseek(ArcPtr, NextBlockPos, SEEK_SET);
+#endif
+ }
+ }
+
+ BlockHead.HeadCRC=NewLhd.HeadCRC;
+ BlockHead.HeadType=NewLhd.HeadType;
+ BlockHead.Flags=NewLhd.Flags;
+ BlockHead.HeadSize=NewLhd.HeadSize;
+ BlockHead.DataSize=NewLhd.PackSize;
+
+ if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
+
+ if((FILE_HEAD == BlockType) && (Size>0))
+ {
+ NewLhd.NameSize=Min(NewLhd.NameSize,sizeof(ArcFileName)-1);
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ tread(MemRARFile, ArcFileName, NewLhd.NameSize);
+#else
+ tread(ArcPtr,ArcFileName,NewLhd.NameSize);
+#endif
+ ArcFileName[NewLhd.NameSize]=0;
+#ifdef _DEBUG_LOG
+ if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
+ NewLhd.NameSize))
+ {
+ debug_log("file header broken");
+ }
+#endif
+ Size+=NewLhd.NameSize;
+ } else
+ {
+ memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile->offset = CurBlockPos;
+#else
+ tseek(ArcPtr,CurBlockPos,SEEK_SET);
+#endif
+ }
+
+
+ return(Size);
+}
+
+
+int ReadHeader(int BlockType)
+{
+ int Size = 0;
+ unsigned char Header[64];
+ switch(BlockType)
+ {
+ case MAIN_HEAD:
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
+#else
+ Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
+#endif
+ NewMhd.HeadCRC=(unsigned short)GetHeaderWord(0);
+ NewMhd.HeadType=GetHeaderByte(2);
+ NewMhd.Flags=(unsigned short)GetHeaderWord(3);
+ NewMhd.HeadSize=(unsigned short)GetHeaderWord(5);
+ NewMhd.Reserved=(unsigned short)GetHeaderWord(7);
+ NewMhd.Reserved1=GetHeaderDword(9);
+ HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWMHD-2);
+ break;
+ case FILE_HEAD:
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
+#else
+ Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
+#endif
+ NewLhd.HeadCRC=(unsigned short)GetHeaderWord(0);
+ NewLhd.HeadType=GetHeaderByte(2);
+ NewLhd.Flags=(unsigned short)GetHeaderWord(3);
+ NewLhd.HeadSize=(unsigned short)GetHeaderWord(5);
+ NewLhd.PackSize=GetHeaderDword(7);
+ NewLhd.UnpSize=GetHeaderDword(11);
+ NewLhd.HostOS=GetHeaderByte(15);
+ NewLhd.FileCRC=GetHeaderDword(16);
+ NewLhd.FileTime=GetHeaderDword(20);
+ NewLhd.UnpVer=GetHeaderByte(24);
+ NewLhd.Method=GetHeaderByte(25);
+ NewLhd.NameSize=(unsigned short)GetHeaderWord(26);
+ NewLhd.FileAttr=GetHeaderDword(28);
+ HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWLHD-2);
+ break;
+
+#ifdef _DEBUG_LOG
+ case COMM_HEAD: /* log errors in case of debug */
+ debug_log("Comment headers not supported! "\
+ "Please create archives without comments.");
+ break;
+ case PROTECT_HEAD:
+ debug_log("Protected headers not supported!");
+ break;
+ case ALL_HEAD:
+ debug_log("ShortBlockHeader not supported!");
+ break;
+ default:
+ debug_log("Unknown//unsupported !");
+#else
+ default: /* else do nothing */
+ break;
+#endif
+ }
+ return(Size);
+}
+
+/* **************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ ************************************************************************** */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* **************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ ******* *******
+ ******* *******
+ ******* *******
+ ******* E X T R A C T L O O P *******
+ ******* *******
+ ******* *******
+ ******* *******
+ ****************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ ************************************************************************** */
+
+
+int IsArchive(void)
+{
+#ifdef _DEBUG_LOG
+ int str_offs; /* used for debug-strings */
+ char DebugMsg[500]; /* used to compose debug msg */
+#endif
+
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD)
+ return(FALSE);
+#else
+ if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
+ return(FALSE);
+#endif
+ /* Old archive => error */
+ if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
+ MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
+ {
+ debug_log("Attention: format as OLD detected! Can't handel archive!");
+ }
+ else
+ /* original RAR v2.0 */
+ if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original */
+ MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
+ MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
+ MarkHead.Mark[6]==0x00) ||
+ /* "UniquE!" - header */
+ (MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' && /* "UniquE!" */
+ MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' && /* header */
+ MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
+ MarkHead.Mark[6]=='!'))
+
+ {
+ if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD)
+ return(FALSE);
+ } else
+ {
+
+#ifdef _DEBUG_LOG
+ /* sorry for this ugly code, but older SunOS gcc compilers don't */
+ /* support white spaces within strings */
+ str_offs = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
+ str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
+ str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
+ str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
+
+ debug_log(DebugMsg);
+#endif
+
+ }
+
+
+ MainHeadSize=SIZEOF_NEWMHD;
+
+ return(TRUE);
+}
+
+
+BOOL ExtrFile(void)
+{
+ BOOL ReturnCode=TRUE;
+ FileFound=FALSE; /* no file found by default */
+
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile->offset = 0; /* start reading from offset 0 */
+ if (!IsArchive())
+ {
+ debug_log("Not a RAR file");
+ return FALSE; /* error => exit! */
+ }
+
+#else
+ /* open and identify archive */
+ if ((ArcPtr=fopen(ArcName,READBINARY))!=NULL)
+ {
+ if (!IsArchive())
+ {
+ debug_log("Not a RAR file");
+ fclose(ArcPtr);
+ ArcPtr = NULL;
+ return FALSE; /* error => exit! */
+ }
+ } else
+ {
+ debug_log("Error opening file.");
+ return FALSE;
+ }
+#endif
+
+
+ if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
+ {
+ debug_log("Can't allocate memory for decompression!");
+ return FALSE;
+ }
+
+#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
+ MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
+#else
+ tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
+#endif
+
+ /* do while file is not extracted and there's no error */
+ do
+ {
+
+ if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
+ { /* file within the RAR archive */
+/*
+ *
+ * 21.11.2000 UnQ There's a problem with some linux distros when a file
+ * can not be found in an archive.
+ *
+ * debug_log("Couldn't read next filename from archive (I/O error).");
+ *
+*/
+ ReturnCode=FALSE;
+ break; /* error, file not found in */
+ } /* archive or I/O error */
+ if (BlockHead.HeadType==SUB_HEAD)
+ {
+ debug_log("Sorry, sub-headers not supported.");
+ ReturnCode=FALSE;
+ break; /* error => exit */
+ }
+
+
+ if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
+ /* *** file found! *** */
+ {
+ {
+ temp_output_buffer=malloc(NewLhd.UnpSize);/* allocate memory for the*/
+ }
+ *temp_output_buffer_offset=0; /* file. The default offset */
+ /* within the buffer is 0 */
+
+ if(temp_output_buffer == NULL)
+ {
+ debug_log("can't allocate memory for the file decompression");
+ ReturnCode=FALSE;
+ break; /* error, can't extract file! */
+ }
+
+
+ }
+
+ /* in case of a solid archive, we need to decompress any single file till
+ * we have found the one we are looking for. In case of normal archives
+ * (recommended!!), we skip the files until we