⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arjtool.cpp

📁 一个解压程序,只要设定了解压路径和解压文件的种类,就可以随意解压
💻 CPP
字号:

#include "stdafx.h"
#include "ArjTool.h"
#include "LzhDecoder2.h"

bool CArjTool::Check( const char* fname, unsigned long fsize )
{
	const unsigned char* hdr = CTool::common_buf;
	unsigned long siz = (fsize>XACR_BUFSIZE ? XACR_BUFSIZE : fsize);
//--------------------------------------------------------------------//

	return (-1!=FindHeader( hdr,siz ));
}

bool CArjTool::Extract( const char* fname,const char* ddir )
{
	// 彂屔僆乕僾儞
	if( !(arj = fopen( fname,"rb" )) )
		return false;
	// 僿僢僟扵偟
	unsigned long siz = fread( CTool::common_buf, 1, 50000, arj );
	int skps = FindHeader( CTool::common_buf, siz );
	if( -1==skps )
	{
		fclose( arj );
		return false;
	}
	fseek( arj,skps,SEEK_SET );
	if( !ReadHeader() ) // 堦屄撉傒幪偰
	{
		fclose( arj );
		return false;
	}

	// 奺奿擺僼傽僀儖傪張棟
	while( ReadHeader() )
	{
		char* name;
		char tmpname[MAX_PATH]=""; //by uemaa2.
		CLzhDecoder2 lzh;

		// 惓忢側僿僢僟偐偳偆偐専徹 & 弌椡愭僼傽僀儖嶌惉
		if( !IsValidFlags()	)
		{
		    fseek( arj,h_Compsize,SEEK_CUR );
			continue;
		}
		sprintf(tmpname, "%s\\%s", ueutil::GetExtractPath(),
			name=kiutil::pathMake(h_Filename)); // by uema2.
//		out = fopen( name=kiutil::pathMake(h_Filename),
//								(h_FileType&1)?"w":"wb" );
		strcpy(name, tmpname);
		out = fopen( name, (h_FileType&1)?"w":"wb" ); // by uema2.
		if( !out )
		{
		    fseek( arj,h_Compsize,SEEK_CUR );
			continue;
		}

		// 揥奐
		crc = 0xffffffff;
		switch( h_Method )
		{
		case 0:
			lzh.Decode( LH0,arj,h_Compsize,out,h_Origsize );
			break;
		case 1:
		case 2:
		case 3:
			lzh.Decode( ARJ,arj,h_Compsize,out,h_Origsize);
			break;
		case 4:
			Decode_f();
			break;
		}

		// 屻張棟
		fclose( out );

		kiutil::timeSet(name,(WORD)(h_TimeStamp>>16),(WORD)h_TimeStamp);

		//name傪t_name(TCHAR)偵 by uema2.
		TCHAR *t_name = (TCHAR*)LocalAlloc(LPTR, (strlen(name)+1)*sizeof(TCHAR));
		_MultiByteToWideChar(CP_ACP, 0, name, strlen(name)+1,
			t_name, strlen(name)+1);
//		SetFileAttributes( name,h_Attrib );
		SetFileAttributes( t_name,h_Attrib );
		LocalFree(t_name);
	}

    fclose( arj );
	return true;
}

/**********************************************************/

static BYTE fget_byte(FILE* f)
{
	return getc(f);//    error(M_CANTREAD, "");
}
static WORD fget_word(FILE* f)
{
	WORD b0=fget_byte(f);
	WORD b1=fget_byte(f);
	return (b1<<8)+b0;
}
#define fget_crc fget_longword
static DWORD fget_longword(FILE* f)
{
	DWORD b0=fget_byte(f);
	DWORD b1=fget_byte(f);
	DWORD b2=fget_byte(f);
	DWORD b3=fget_byte(f);
	return (b3<<24)+(b2<<16)+(b1<<8)+b0;
}

/**************************************************************/

////////////////////
#define ARJ_X_VERSION     3

#define BINARY_TYPE       0
#define TEXT_TYPE         1

#define COMMENT_MAX    2048
#define FIRST_HDR_SIZE   30
#define HEADERSIZE_MAX (FIRST_HDR_SIZE + 10 + ARJ_FNAME_MAX + COMMENT_MAX)

#define CRC_MASK 0xffffffff

#define HEADER_ID     0xEA60
#define HEADER_ID_HI    0xEA
#define HEADER_ID_LO    0x60
/////////////////////

size_t CArjTool::fread_crc(void* p,size_t n,FILE* f)
{
	n = fread(p,1,n,f);
	h_Origsize += n;
	UpdateCRC( (BYTE*)p,n );
	return n;
}

void CArjTool::fwrite_crc(BYTE* p,int n)
{
	UpdateCRC(p,n);
	if( h_FileType==TEXT_TYPE )
	{
		while( --n )
			putc(p[n],out);
	}
	else
		fwrite( p,1,n,out );
}

int CArjTool::FindHeader( const unsigned char* hdr, unsigned long siz )
{
	long last = ( siz-2-HEADERSIZE_MAX > 50000 ?
					50000 : siz-2-HEADERSIZE_MAX );

	for( long i=0; i<last; i++ )
	{
		// Flag
		if( hdr[i] != HEADER_ID_LO )
			continue;
		if( hdr[i+1] != HEADER_ID_HI )
			continue;
		// Header_size
		int hsiz = (hdr[i+2] + (hdr[i+3]<<8));
		if( hsiz > HEADERSIZE_MAX )
			continue;
		// Crc
		crc = CRC_MASK;
		UpdateCRC( hdr+(i+4),hsiz );
		DWORD hcrc = (hdr[i+4+hsiz+0]
				   + (hdr[i+4+hsiz+1]<<8)
				   + (hdr[i+4+hsiz+2]<<16)
				   + (hdr[i+4+hsiz+3]<<24));
		if( (crc^CRC_MASK) == hcrc )
			return i;
    }
    return -1;
}

bool CArjTool::ReadHeader()
{
	WORD header_id = fget_word(arj);
	if( header_id!=HEADER_ID )
		return false;

	h_Size = fget_word(arj);
    if( h_Size==0 )
		return false;
    if( h_Size>HEADERSIZE_MAX )
		return false;

	BYTE header[HEADERSIZE_MAX],*ph=header;
    crc = CRC_MASK;
    fread_crc( header,h_Size,arj );
	h_CRC = fget_crc(arj);
	if( (crc^CRC_MASK)!=h_CRC )
		return false;

	h_1stSize = *(ph++);
	h_ArjVer = *(ph++);
	h_ArjXVer = *(ph++);
	h_OS = *(ph++);
	h_Flags = *(ph++);
	h_Method = *(ph++);
	h_FileType = *(ph++);
	(ph++);
	h_TimeStamp = (ph[3]<<24)+(ph[2]<<16)+(ph[1]<<8)+ph[0];	ph+=4;
	h_Compsize = (ph[3]<<24)+(ph[2]<<16)+(ph[1]<<8)+ph[0];	ph+=4;
	h_Origsize = (ph[3]<<24)+(ph[2]<<16)+(ph[1]<<8)+ph[0];	ph+=4;
	h_FileCRC = (ph[3]<<24)+(ph[2]<<16)+(ph[1]<<8)+ph[0];	ph+=4;
	h_EntryPos = (ph[1]<<8)+ph[0];	ph+=2;
	h_Attrib = (ph[1]<<8)+ph[0];	ph+=2;;
	h_HostData = (ph[1]<<8)+ph[0];	ph+=2;;
	
//	lstrcpyn( h_Filename,(char*)&header[h_1stSize],ARJ_FNAME_MAX );
	strncpy( h_Filename,(char*)&header[h_1stSize],ARJ_FNAME_MAX ); //by uema2.
	if( h_OS != 0 )//MSDOS偠傖側偗傟偽ASCII埲奜捠偝側偄丅
	{
		char* pp=h_Filename;
		while(*pp)
			*(pp++)&=0x7f;
	}

	// 奼挘僿僢僟撉傒幪偰
	WORD extheadersize;
	while( extheadersize=fget_word(arj) )
		fseek( arj,extheadersize+4,SEEK_CUR );

	return true;
}

bool CArjTool::IsValidFlags()
{
	if( h_ArjXVer>ARJ_X_VERSION )
		return false;
	if( (h_Flags&0x01)!=0 )
		return false;
	if( h_Method<0 || h_Method>4 || (h_Method==4 && h_ArjVer==1) )
		return false;
	if( h_FileType!=BINARY_TYPE && h_FileType!=TEXT_TYPE )
		return false;
	return true;
}

/************************************************************************/

void CArjTool::init_getbits()
{
	bitbuf = 0;
	subbitbuf = 0;
	bitcount = 0;
	fillbuf(16);
}

void CArjTool::fillbuf(int n)
{
	bitbuf = (bitbuf<<n)&0xFFFF;
	while( n>bitcount )
	{
		bitbuf |= subbitbuf << (n -= bitcount);
		if( h_Compsize!=0 )
		{
			h_Compsize--;
			subbitbuf = (BYTE)getc(arj);
		}
		else
			subbitbuf = 0;
		bitcount = 8;
	}
	bitbuf |= subbitbuf >> (bitcount -= n);
}

#define CODE_BIT 16
#define ARJ_DICSIZE 26624
#define THRESHOLD    3
#define STRTP          9
#define STOPP         13
#define STRTL          0
#define STOPL          7

#define BFIL {getbuf|=bitbuf>>getlen;fillbuf(CODE_BIT-getlen);getlen=CODE_BIT;}
#define GETBIT(c) {if(getlen<=0)BFIL c=(getbuf&0x8000)!=0;getbuf<<=1;getlen--;}
#define BPUL(l) {getbuf<<=l;getlen-=l;}
#define GETBITS(c,l) {if(getlen<l)BFIL c=(WORD)getbuf>>(CODE_BIT-l);BPUL(l)}

short CArjTool::decode_ptr()
{
	short c,width,plus,pwr;

	plus = 0;
	pwr = 1 << (STRTP);
	for( width=(STRTP); width<(STOPP); width++ )
	{
		GETBIT(c);
		if( c==0 )
			break;
		plus += pwr;
		pwr <<= 1;
	}
	if( width!=0 )
		GETBITS(c, width);
	c += plus;
	return c;
}

short CArjTool::decode_len()
{
	short c,width,plus,pwr;

	plus = 0;
	pwr = 1 << (STRTL);
	for( width=(STRTL); width<(STOPL); width++ )
	{
		GETBIT(c);
		if( c==0 )
			break;
		plus += pwr;
		pwr <<= 1;
	}
	if( width!=0 )
		GETBITS(c, width);
	c += plus;
	return c;
}

void CArjTool::Decode_f()
{
	BYTE* text = new BYTE[ARJ_DICSIZE];

	init_getbits();
	getlen = getbuf = 0;

	short pos,i,j,c,r=0;
	DWORD count=0;
	while( count<h_Origsize )
	{
		c = decode_len();
		if( c==0 )
		{
			GETBITS(c, 8);
			text[r] = (BYTE)c;
			count++;
			if( ++r>=ARJ_DICSIZE )
			{
				r=0;
				fwrite_crc(text,ARJ_DICSIZE);
			}
		}
		else
		{
			j = c - 1 + THRESHOLD;
			count += j;
			pos = decode_ptr();
			if( (i=r-pos-1)<0 )
				i += ARJ_DICSIZE;
            while( j-->0 )
			{
				text[r] = text[i];
				if( ++r>=ARJ_DICSIZE )
				{
					r = 0;
					fwrite_crc(text,ARJ_DICSIZE);
				}
				if( ++i>=ARJ_DICSIZE )
					i = 0;
			}
		}
	}
	if( r!=0 )
		fwrite_crc(text,r);

	delete [] text;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -