📄 unrarlib.c
字号:
/* *************************************************************************** ** ** 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) ** ** Modified for use with MPlayer, detailed CVS changelog at ** http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/ ** $Id: unrarlib.c,v 1.7 2005/04/15 18:48:03 diego Exp $ ** ** 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 20enum { 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 0x8000enum { 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;static UBYTE *TempMemory = NULL; /* temporary unpack-buffer */static char *CommMemory = NULL;static UBYTE *UnpMemory = NULL;static char* ArgName = NULL; /* current file in rar archive */static char* ArcFileName = NULL; /* file to decompress */#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */ static MemoryFile *MemRARFile; /* pointer to RAR file in memory*/#else static char* ArcName = NULL; /* RAR archive name */ static FILE *ArcPtr; /* input RAR file handler */#endifstatic char *Password = NULL; /* password to decrypt files */static unsigned char *temp_output_buffer; /* extract files to this pointer*/static unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */static BOOL FileFound; /* TRUE=use current extracted */ /* data FALSE=throw data away, */ /* wrong file */static int MainHeadSize;static long CurBlockPos,NextBlockPos;static unsigned long CurUnpRead, CurUnpWrite;static long UnpPackedSize;static long DestUnpSize;static UDWORD HeaderCRC;static int Encryption;//static unsigned int UnpWrSize;//static unsigned char *UnpWrAddr;static unsigned int UnpPtr,WrPtr;static unsigned char PN1,PN2,PN3;static unsigned short OldKey[4];/* function header definitions */static int ReadHeader(int BlockType);static BOOL ExtrFile(void);//BOOL ListFile(void);static int tread(void *stream,void *buf,unsigned len);static int tseek(void *stream,long offset,int fromwhere);static BOOL UnstoreFile(void);static int IsArchive(void);static int ReadBlock(int BlockType);static unsigned int UnpRead(unsigned char *Addr,unsigned int Count);static void UnpInitData(void);static void Unpack(unsigned char *UnpAddr);static UBYTE DecodeAudio(int Delta);static void DecodeNumber(struct Decode *Dec);static void UpdKeys(UBYTE *Buf);static void SetCryptKeys(char *Password);static void SetOldKeys(char *Password);static void DecryptBlock(unsigned char *Buf);static void InitCRC(void);static UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);static void UnpReadBuf(int FirstBuf);static void ReadTables(void);static void ReadLastTables(void);static void MakeDecodeTables(unsigned char *LenTab, struct Decode *Dec, int Size);static int my_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 */ if(ArgName) free(ArgName); ArgName = strdup(filename); /* set file(s) to extract */#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION MemRARFile = rarfile; /* set pointer to mem-RAR file */#else if(ArcName) free(ArcName); ArcName = strdup(rarfile); /* set RAR file name */#endif if(Password) free(Password); if(libpassword != NULL) Password = strdup(libpassword); /* init password */ else Password = strdup(""); 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 if(UnpMemory) free(UnpMemory); /* free memory */ if(TempMemory) free(TempMemory); if(CommMemory) free(CommMemory); UnpMemory=NULL; TempMemory=NULL; CommMemory=NULL; if(retcode == FALSE) { if(temp_output_buffer) /* free memory and return NULL */ free(temp_output_buffer); 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -