diff options
author | kmkaplan <kmkaplan@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-09-20 01:26:39 +0000 |
---|---|---|
committer | kmkaplan <kmkaplan@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-09-20 01:26:39 +0000 |
commit | 1637590528c8dc789fbab5456951f9d3b5627e1e (patch) | |
tree | 51101a267242722e34feeb460e75dd0139fbb436 | |
parent | f2066d42ae59c68f3c6632dda2a44fcc996ada37 (diff) | |
download | mpv-1637590528c8dc789fbab5456951f9d3b5627e1e.tar.bz2 mpv-1637590528c8dc789fbab5456951f9d3b5627e1e.tar.xz |
Automatic unrar of vobsub. Does not work with rar v3
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7447 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r-- | Makefile | 4 | ||||
-rwxr-xr-x | configure | 16 | ||||
-rw-r--r-- | unrarlib.c | 2716 | ||||
-rw-r--r-- | unrarlib.h | 200 | ||||
-rw-r--r-- | vobsub.c | 243 |
5 files changed, 3138 insertions, 41 deletions
@@ -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 @@ -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)."); + * +*/ + Return |