File Annotation

Not logged in
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: #include "stdafx.h"
5128eecc9f 2011-02-23        kinaba: #include "LzhTool.h"
5128eecc9f 2011-02-23        kinaba: #include "LzhDecoder2.h"
5128eecc9f 2011-02-23        kinaba: #include "kiutil.h"
5128eecc9f 2011-02-23        kinaba: #include "kilib/kilib.h"
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: bool CLzhTool::crcinit;
5128eecc9f 2011-02-23        kinaba: unsigned short CLzhTool::crctable[256];
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: bool CLzhTool::Extract( const char* aname, const char* dll, kiPath& dll_rel_path )
5128eecc9f 2011-02-23        kinaba: {
5128eecc9f 2011-02-23        kinaba: 	// 先頭の方を読み込み
5128eecc9f 2011-02-23        kinaba: 	FILE* fp = fopen( aname,"rb" );
5128eecc9f 2011-02-23        kinaba: 	if( !fp )
5128eecc9f 2011-02-23        kinaba: 		return false;
36ad977839 2017-05-30        kinaba: 	const int maxHeaderOffset = 1<<20; // 1MB
36ad977839 2017-05-30        kinaba: 	unsigned char* buff = new unsigned char[maxHeaderOffset];
36ad977839 2017-05-30        kinaba: 	DWORD siz = fread( buff, 1, maxHeaderOffset, fp );
5128eecc9f 2011-02-23        kinaba: 	fclose( fp );
5128eecc9f 2011-02-23        kinaba: 	// ヘッダを探す
5128eecc9f 2011-02-23        kinaba: 	int ps = FindHeader( aname,buff,siz );
5128eecc9f 2011-02-23        kinaba: 	// 書庫を開く
5128eecc9f 2011-02-23        kinaba: 	if( ps==-1 || !(lzh = fopen( aname,"rb" )) )
5128eecc9f 2011-02-23        kinaba: 	{
5128eecc9f 2011-02-23        kinaba: 		delete [] buff;
5128eecc9f 2011-02-23        kinaba: 		return false;
5128eecc9f 2011-02-23        kinaba: 	}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	fseek( lzh,ps,SEEK_SET );
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	// 格納ファイル毎に処理
5128eecc9f 2011-02-23        kinaba: 	while( ReadHeader( buff ) )
5128eecc9f 2011-02-23        kinaba: 	{
5128eecc9f 2011-02-23        kinaba: 		long base = ftell( lzh );
5128eecc9f 2011-02-23        kinaba: 		char* name;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 		if( h_FileName[0]!='!' && h_FileName[0]!='$' && h_FileName[0]!='%' )
5128eecc9f 2011-02-23        kinaba: 			if( out=fopen( name=kiutil::pathMake(h_FileName),"wb" ) )
5128eecc9f 2011-02-23        kinaba: 			{
5128eecc9f 2011-02-23        kinaba: 				if( 0==strcmpi( kiPath::name(name), dll ) ) // DLLの位置を記憶
5128eecc9f 2011-02-23        kinaba: 					dll_rel_path = name;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 				// デコード
5128eecc9f 2011-02-23        kinaba: 				CLzhDecoder2 dec;
5128eecc9f 2011-02-23        kinaba: 				lzh_method mhd = UNKNOWN;
5128eecc9f 2011-02-23        kinaba: 					 if( 0==strcmp(h_Method,"-lh0-") )mhd=LH0;
5128eecc9f 2011-02-23        kinaba: 				else if( 0==strcmp(h_Method,"-lh5-") )mhd=LH5;
5128eecc9f 2011-02-23        kinaba: 				else if( 0==strcmp(h_Method,"-lh6-") )mhd=LH6;
5128eecc9f 2011-02-23        kinaba: 				else if( 0==strcmp(h_Method,"-lh7-") )mhd=LH7;
5128eecc9f 2011-02-23        kinaba: 				dec.Decode( mhd, lzh, h_CompSize, out, h_OrigSize );
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 				// 属性など設定
5128eecc9f 2011-02-23        kinaba: 				fclose( out );
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 				SetFileAttributes( name,h_Attrib );
5128eecc9f 2011-02-23        kinaba: 				if( h_Level<2 )
5128eecc9f 2011-02-23        kinaba: 					kiutil::timeSet( name, (WORD)(h_Update>>16),(WORD)h_Update );
5128eecc9f 2011-02-23        kinaba: 				else
5128eecc9f 2011-02-23        kinaba: 					kiutil::timeSet( name, h_Update );
5128eecc9f 2011-02-23        kinaba: 			}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 		fseek( lzh, base+h_CompSize, SEEK_SET );
5128eecc9f 2011-02-23        kinaba: 	}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	delete [] buff;
5128eecc9f 2011-02-23        kinaba:     fclose( lzh );
5128eecc9f 2011-02-23        kinaba: 	return true;
5128eecc9f 2011-02-23        kinaba: }
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: int CLzhTool::FindHeader( const char* fname, const BYTE* hdr, DWORD siz )
5128eecc9f 2011-02-23        kinaba: {
5128eecc9f 2011-02-23        kinaba: 	bool bopen = false;
5128eecc9f 2011-02-23        kinaba: 	BYTE* temp;
5128eecc9f 2011-02-23        kinaba: 	int ans=-1;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	for( DWORD i=0; i<siz-20; i++ )
5128eecc9f 2011-02-23        kinaba: 	{
5128eecc9f 2011-02-23        kinaba: 		if( hdr[i+2]=='-' && hdr[i+3]=='l' &&
5128eecc9f 2011-02-23        kinaba: 		   (hdr[i+4]=='h' || hdr[i+4]=='z') )
5128eecc9f 2011-02-23        kinaba: 		{
5128eecc9f 2011-02-23        kinaba: 			if( !bopen )
5128eecc9f 2011-02-23        kinaba: 				if( !(lzh=fopen( fname,"rb" )) )
5128eecc9f 2011-02-23        kinaba: 					return -1;
5128eecc9f 2011-02-23        kinaba: 				else
5128eecc9f 2011-02-23        kinaba: 					bopen=true, temp = new BYTE[65536];
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 			fseek( lzh,i,SEEK_SET );
5128eecc9f 2011-02-23        kinaba: 			if( ReadHeader(temp) )
5128eecc9f 2011-02-23        kinaba: 				{ans=(signed)i;break;}
5128eecc9f 2011-02-23        kinaba: 		}
5128eecc9f 2011-02-23        kinaba: 	}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	if( bopen )
5128eecc9f 2011-02-23        kinaba: 		{delete [] temp;fclose( lzh );}
5128eecc9f 2011-02-23        kinaba: 	return ans;
5128eecc9f 2011-02-23        kinaba: }
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: bool CLzhTool::ReadHeader( unsigned char* buf )
5128eecc9f 2011-02-23        kinaba: {
5128eecc9f 2011-02-23        kinaba: // 初期化
5128eecc9f 2011-02-23        kinaba: 	*h_FileName=0;
5128eecc9f 2011-02-23        kinaba: 	sum=0,crc=0;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: // だいたい共通な部分
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: //  0- 1: [0]=header_size [1]=check_sum (h0)
5128eecc9f 2011-02-23        kinaba: //        [0]=bas_hdr_siz [1]=check_sum (h1)
5128eecc9f 2011-02-23        kinaba: //        [WORD] = all_header_size      (h2)
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: //  2- 6: method
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: //  7-10: [DWORD]=compressed_size (h0/h2)
5128eecc9f 2011-02-23        kinaba: //        [DWORD]=offset_to_next_hdr (h1)
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: // 11-14: [DWORD]=original_size
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: // 15-18: [ftime]=update_date_time
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: //    19: attribute (h0)
5128eecc9f 2011-02-23        kinaba: //        0x20      (h1/h2)
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: //    20: header_level
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: 	if( 21!=fread_crc(buf,21) )
5128eecc9f 2011-02-23        kinaba: 		return false;
5128eecc9f 2011-02-23        kinaba: 	sum-=(buf[0]+buf[1]);
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	if( (h_Level=buf[20])>2 ) // LV3以上未対応
5128eecc9f 2011-02-23        kinaba: 		return false;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	BYTE bshdr = (h_Level==2)?26:buf[0]+2;
5128eecc9f 2011-02-23        kinaba: 	if( bshdr<21 || buf[0]==0 )
5128eecc9f 2011-02-23        kinaba: 		return false;
5128eecc9f 2011-02-23        kinaba: 	BYTE hdrsum= buf[1];
5128eecc9f 2011-02-23        kinaba: 	for( int i=0; i!=5; i++ )
5128eecc9f 2011-02-23        kinaba: 		h_Method[i]=(char)buf[2+i];h_Method[5]=0;
5128eecc9f 2011-02-23        kinaba: 	h_CompSize = (buf[ 7])+(buf[ 8]<<8)+(buf[ 9]<<16)+(buf[10]<<24);
5128eecc9f 2011-02-23        kinaba: 	h_OrigSize = (buf[11])+(buf[12]<<8)+(buf[13]<<16)+(buf[14]<<24);
5128eecc9f 2011-02-23        kinaba: 	h_Update   = (buf[15])+(buf[16]<<8)+(buf[17]<<16)+(buf[18]<<24);
5128eecc9f 2011-02-23        kinaba: 	h_Attrib   =  buf[19];
5128eecc9f 2011-02-23        kinaba: 	if( h_Method[0]!='-' || h_Method[1]!='l' )
5128eecc9f 2011-02-23        kinaba: 		return false;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: // レベル共通じゃない基本ヘッダ部分
5128eecc9f 2011-02-23        kinaba: // <h0>
5128eecc9f 2011-02-23        kinaba: //     21: file_name_length
5128eecc9f 2011-02-23        kinaba: //  22- n: file_name ( with path info )
5128eecc9f 2011-02-23        kinaba: //   WORD: crc16_of_file
5128eecc9f 2011-02-23        kinaba: //       : and some extension part
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: // <h1>
5128eecc9f 2011-02-23        kinaba: //     21: file_name_length
5128eecc9f 2011-02-23        kinaba: //  22- n: file_name ( with no path info )
5128eecc9f 2011-02-23        kinaba: //   WORD: crc16_of_file
5128eecc9f 2011-02-23        kinaba: //   BYTE: os_flag
5128eecc9f 2011-02-23        kinaba: //       : and some extension part
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: // <h2>
5128eecc9f 2011-02-23        kinaba: //   WORD: crc16_of_file
5128eecc9f 2011-02-23        kinaba: //   BYTE: os_flag
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: //
5128eecc9f 2011-02-23        kinaba: 	if( (bshdr-21)!=fread_crc(buf+21,(bshdr-21)) )
5128eecc9f 2011-02-23        kinaba: 		return false;
5128eecc9f 2011-02-23        kinaba: 	if( h_Level!=2 )
5128eecc9f 2011-02-23        kinaba: 	{
5128eecc9f 2011-02-23        kinaba: 		if( sum!=hdrsum || 21+1+buf[21]+2>bshdr )
5128eecc9f 2011-02-23        kinaba: 			return false;
5128eecc9f 2011-02-23        kinaba: 		memcpy( h_FileName,buf+22,buf[21] );
5128eecc9f 2011-02-23        kinaba: 		h_FileName[buf[21]]=0;
5128eecc9f 2011-02-23        kinaba: 	}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: // 拡張ヘッダ( h1/h2 )
5128eecc9f 2011-02-23        kinaba: //  repeating of such blocks.
5128eecc9f 2011-02-23        kinaba: //------------------------------------------------------
5128eecc9f 2011-02-23        kinaba: //  WORD: size_of_this_block ( if 0 then end_of_header )
5128eecc9f 2011-02-23        kinaba: //  BYTE: type_flag
5128eecc9f 2011-02-23        kinaba: //      : data ( (blocksize-3) bytes )
5128eecc9f 2011-02-23        kinaba: //------------------------------------------------------
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	char PathName[MAX_PATH*2]={0};
5128eecc9f 2011-02-23        kinaba: 	if( h_Level!=0 )
5128eecc9f 2011-02-23        kinaba: 	{
5128eecc9f 2011-02-23        kinaba: 		DWORD hdrcrc=0xffffffff;
5128eecc9f 2011-02-23        kinaba: 		WORD tmpcrc;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 		// ここでループって拡張ヘッダ読み込み
5128eecc9f 2011-02-23        kinaba: 		WORD ehs;
5128eecc9f 2011-02-23        kinaba: 		ehs = ((buf[bshdr-2])|(buf[bshdr-1]<<8));
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 		while( ehs>2 )
5128eecc9f 2011-02-23        kinaba: 		{
5128eecc9f 2011-02-23        kinaba: 			tmpcrc=crc;//CRC自身を読み込んだときに直すため
5128eecc9f 2011-02-23        kinaba: 			if( ehs!=fread_crc(buf,ehs) )
5128eecc9f 2011-02-23        kinaba: 				return false;
5128eecc9f 2011-02-23        kinaba: 			if( h_Level==1 )
5128eecc9f 2011-02-23        kinaba: 				h_CompSize-=ehs;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 			switch( *buf )
5128eecc9f 2011-02-23        kinaba: 			{
5128eecc9f 2011-02-23        kinaba: 			case 0x00://共通
5128eecc9f 2011-02-23        kinaba: 				if( ehs>=5 && hdrcrc==0xffffffff )
5128eecc9f 2011-02-23        kinaba: 				{
5128eecc9f 2011-02-23        kinaba: 					hdrcrc=((buf[1])|(buf[2]<<8));
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 					crc=tmpcrc;
5128eecc9f 2011-02-23        kinaba: 					buf[1]=buf[2]=0;
5128eecc9f 2011-02-23        kinaba: 					UpdateCRC(buf,ehs);
5128eecc9f 2011-02-23        kinaba: 				}
5128eecc9f 2011-02-23        kinaba: 				break;
5128eecc9f 2011-02-23        kinaba: 			case 0x01://ファイル名
5128eecc9f 2011-02-23        kinaba: 				memcpy(h_FileName,buf+1,ehs-3>MAX_PATH?MAX_PATH:ehs-3);
5128eecc9f 2011-02-23        kinaba: 				h_FileName[ehs-3>MAX_PATH?MAX_PATH:ehs-3]=0;
5128eecc9f 2011-02-23        kinaba: 				break;
5128eecc9f 2011-02-23        kinaba: 			case 0x02://パス名
5128eecc9f 2011-02-23        kinaba: 				memcpy(PathName,buf+1,ehs-3>MAX_PATH?MAX_PATH:ehs-3);
5128eecc9f 2011-02-23        kinaba: 				PathName[ehs-3>MAX_PATH?MAX_PATH:ehs-3]=0;
5128eecc9f 2011-02-23        kinaba: 				break;
5128eecc9f 2011-02-23        kinaba: 			case 0xff://新属性
5128eecc9f 2011-02-23        kinaba: 				break;
5128eecc9f 2011-02-23        kinaba: 			case 0x40://属性(DOS依存)
5128eecc9f 2011-02-23        kinaba: 				if( ehs>=5 )
5128eecc9f 2011-02-23        kinaba: 					h_Attrib=((buf[1])|(buf[2]<<8));
5128eecc9f 2011-02-23        kinaba: 				break;
5128eecc9f 2011-02-23        kinaba: 			case 0x41://タイムスタンプ(UNLHA32.DLL)
5128eecc9f 2011-02-23        kinaba: 				//は、なんだかうまくいかないので無視する。
5128eecc9f 2011-02-23        kinaba: 				break;
5128eecc9f 2011-02-23        kinaba: 			}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 			ehs = ((buf[ehs-2])|(buf[ehs-1]<<8));
5128eecc9f 2011-02-23        kinaba: 		}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 		if( hdrcrc!=0xffffffff && crc!=hdrcrc )
5128eecc9f 2011-02-23        kinaba: 			return false;
5128eecc9f 2011-02-23        kinaba: 	}
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: 	// ff -> \\ 変換
5128eecc9f 2011-02-23        kinaba: 	char* x;
5128eecc9f 2011-02-23        kinaba: 	for( x=h_FileName; *x!=0; x=CharNext(x) )
5128eecc9f 2011-02-23        kinaba: 		if( (BYTE)*x==0xff )
5128eecc9f 2011-02-23        kinaba: 			*x='\\';
5128eecc9f 2011-02-23        kinaba: 	for( x=PathName; *x!=0; x=CharNext(x) )
5128eecc9f 2011-02-23        kinaba: 		if( (BYTE)*x==0xff )
5128eecc9f 2011-02-23        kinaba: 			*x='\\';
5128eecc9f 2011-02-23        kinaba: 	strcat( PathName,h_FileName );
5128eecc9f 2011-02-23        kinaba: 	strcpy( h_FileName,PathName );
5128eecc9f 2011-02-23        kinaba: 	return true;
5128eecc9f 2011-02-23        kinaba: 
5128eecc9f 2011-02-23        kinaba: // lha header MEMO
5128eecc9f 2011-02-23        kinaba: // (h0/h1)
5128eecc9f 2011-02-23        kinaba: //   1 byte 目は、「1byte目自身を除いた基本ヘッダのサイズ」
5128eecc9f 2011-02-23        kinaba: //   チェックサムは、「1,2byte目自身を除いた基本ヘッダの合計」
5128eecc9f 2011-02-23        kinaba: // (h1)
5128eecc9f 2011-02-23        kinaba: //   offset_to_next_hdr は、基本ヘッダ末端から次のヘッダへの距離
5128eecc9f 2011-02-23        kinaba: // (h1/h2)
5128eecc9f 2011-02-23        kinaba: //   crcは自分自身は0000として他全部から算出
5128eecc9f 2011-02-23        kinaba: }