File Annotation

Not logged in
4e2933c620 2015-04-21        kinaba: private import win32.windows;
4e2933c620 2015-04-21        kinaba: private import std.string;
c2b7a98c21 2011-02-23        kinaba: private import std.file;
c2b7a98c21 2011-02-23        kinaba: private import std.c.stdio;
4e2933c620 2015-04-21        kinaba: private import std.string;
c2b7a98c21 2011-02-23        kinaba: private import etc.c.zlib;
c2b7a98c21 2011-02-23        kinaba: private import libbz2.bzlib;
c2b7a98c21 2011-02-23        kinaba: private import util;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: // Bga書庫のファイルヘッダ形式
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: align(1) struct BgaHeader
c2b7a98c21 2011-02-23        kinaba: {
c2b7a98c21 2011-02-23        kinaba: 	 int   checksum;        // type~fname のsigned charでの和
c2b7a98c21 2011-02-23        kinaba: 	char   method[4];       // "GZIP" または "BZ2\0"
c2b7a98c21 2011-02-23        kinaba: 	uint   compressed_size; // 圧縮後のデータサイズ( ヘッダは含まない )
c2b7a98c21 2011-02-23        kinaba: 	uint   original_size;   // 元のファイルサイズ
c2b7a98c21 2011-02-23        kinaba: 	ushort date;            // ファイルの更新日付( DOS形式 )
c2b7a98c21 2011-02-23        kinaba: 	ushort time;            // ファイルの更新時刻( DOS形式 )
c2b7a98c21 2011-02-23        kinaba: 	ubyte  attrib;          // ファイルの属性
c2b7a98c21 2011-02-23        kinaba: 	                        // ( 1:RO 2:Hid 4:Sys 8:Vol 16:Dir 32:Arc )
c2b7a98c21 2011-02-23        kinaba: 	ubyte  header_type;     // ヘッダの種類( 現在は常に 0 )
c2b7a98c21 2011-02-23        kinaba: 	ushort arc_type;        // アーカイブタイプ
c2b7a98c21 2011-02-23        kinaba: 	                        // 0:(ext==↓?非圧縮:圧縮) 1:圧縮 2:非圧縮
c2b7a98c21 2011-02-23        kinaba: 	                        //	.ARC, .ARJ, .BZ2, .BZA, .CAB, .GZ, .GZA, .LZH,
c2b7a98c21 2011-02-23        kinaba: 	                        //	.LZS, .PAK, .RAR, .TAZ, .TBZ, .TGZ, .Z, .ZIP, .ZOO
c2b7a98c21 2011-02-23        kinaba: 	ushort dir_name_len;    // ディレクトリ名の長さ
c2b7a98c21 2011-02-23        kinaba: 	ushort file_name_len;   // ファイル名の長さ
4e2933c620 2015-04-21        kinaba: 	string fname;           // dir_name_len + file_name_len ( no '\0' )
c2b7a98c21 2011-02-23        kinaba: }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: // エラー発生時に投げる例外
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: class BgaMelterError : Error
c2b7a98c21 2011-02-23        kinaba: {
c2b7a98c21 2011-02-23        kinaba: 	int errcode;
c2b7a98c21 2011-02-23        kinaba: 	this( int e ) { super("BgaMelterError"); errcode=e; }
c2b7a98c21 2011-02-23        kinaba: }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: enum
c2b7a98c21 2011-02-23        kinaba: {
c2b7a98c21 2011-02-23        kinaba: 	ERROR_FILE_OPEN=0x800D,//         ファイルを開けませんでした。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_MAKEDIRECTORY=0x8012,//     ディレクトリが作成できません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_CANNOT_WRITE=0x8013,//      書き込みエラーが生じました。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_HEADER_CRC=0x8016,//        書庫のヘッダのチェックサムが合っていません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_ARC_FILE_OPEN=0x8018,//     書庫を開く事が出来ません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_NOT_ARC_FILE=0x8019,//      書庫のファイル名が指定されていません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_CANNOT_READ=0x801A,//       ファイルの読み込み時にエラーが生じました。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_FILE_STYLE=0x801B,//        指定されたファイルは有効な書庫ではありません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_COMMAND_NAME=0x801C,//      コマンド指定が間違っています。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_MORE_HEAP_MEMORY=0x801D,//  作業用のためのヒープメモリが不足しています。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_ALREADY_RUNNING=0x801F,//   既に BGA32.DLL が動作中です。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_USER_CANCEL=0x8020,//       ユーザーによって処理を中断されました。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_TMP_OPEN=0x8025,//          作業ファイルが作成できません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_ARC_READ_ONLY=0x8027,//     書き込み専用属性の書庫に対する操作はできません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_NOT_FIND_ARC_FILE=0x8029,// 指定されたディレクトリには書庫がありませんでした。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_RESPONSE_READ=0x802A,//     レスポンスファイルの読み込み時にエラーが生じました。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_TMP_COPY=0x802C,//          作業ファイルの書庫への書き戻しができませんでした。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_NOT_FIND_FILE=0x8031,//     ファイルが見つかりません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_GET_ATTRIBUTES=0x8034,//    ファイル属性が取得できません。
c2b7a98c21 2011-02-23        kinaba: 	ERROR_GET_INFORMATION=0x8036,//   ファイル情報が取得できません。
c2b7a98c21 2011-02-23        kinaba: }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: // コールバック関数の返答用型
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: enum BgaAnswer
c2b7a98c21 2011-02-23        kinaba: {
c2b7a98c21 2011-02-23        kinaba: 	MeltIt, SkipIt, Abort
c2b7a98c21 2011-02-23        kinaba: }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: // Filep
c2b7a98c21 2011-02-23        kinaba: //   D言語らしからぬのですがzlibやlibbz2と簡単に連携する
c2b7a98c21 2011-02-23        kinaba: //   都合上std.c.stdio.FILE*でファイルを読み書きします。
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: extern(C)
c2b7a98c21 2011-02-23        kinaba: {
c2b7a98c21 2011-02-23        kinaba: 	// stdio.h
c2b7a98c21 2011-02-23        kinaba:     int fileno( FILE *fp ) { return fp._file; }
c2b7a98c21 2011-02-23        kinaba: 	// io.h
c2b7a98c21 2011-02-23        kinaba: 	int lseek( int fd, int offset, int mode );
c2b7a98c21 2011-02-23        kinaba: 	int dup( int fd );
c2b7a98c21 2011-02-23        kinaba: 	int close( int fd );
c2b7a98c21 2011-02-23        kinaba: }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: class Filep
c2b7a98c21 2011-02-23        kinaba: {
c2b7a98c21 2011-02-23        kinaba: 	private FILE* fp;
c2b7a98c21 2011-02-23        kinaba: 	private this( FILE* p ) { fp = p; }
c2b7a98c21 2011-02-23        kinaba: 
4e2933c620 2015-04-21        kinaba: 	static Filep open( string filename, bool read )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		FILE* fp = fopen( toStringz(filename), read?"rb":"wb" );
c2b7a98c21 2011-02-23        kinaba: 		return (fp ? new Filep(fp) : null);
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	int dup_han()
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		int fd = dup( fileno(fp) );
c2b7a98c21 2011-02-23        kinaba: 		lseek( fd, cur(), 0 );
c2b7a98c21 2011-02-23        kinaba: 		return fd;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	void[] read( int siz )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		char[] buf; buf.length = siz;
4e2933c620 2015-04-21        kinaba: 		int rsiz = fread( buf.ptr, 1, siz, fp );
c2b7a98c21 2011-02-23        kinaba: 		if( rsiz < 0 )
c2b7a98c21 2011-02-23        kinaba: 			throw new BgaMelterError(ERROR_FILE_OPEN);
c2b7a98c21 2011-02-23        kinaba: 		buf.length = rsiz;
c2b7a98c21 2011-02-23        kinaba: 		return buf;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	void write( void[] buf )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		while( buf.length > 0 )
c2b7a98c21 2011-02-23        kinaba: 		{
4e2933c620 2015-04-21        kinaba: 			int rsiz = fwrite( buf.ptr, 1, buf.length, fp );
c2b7a98c21 2011-02-23        kinaba: 			if( rsiz < 0 ) return;
4e2933c620 2015-04-21        kinaba: 			buf = buf[rsiz .. $];
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	int cur()
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		return ftell(fp);
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	void seek_to( int i )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		fseek( fp, i, std.c.stdio.SEEK_SET );
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	void close()
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		fclose(fp);
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	FILE* get_fp()
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		return fp;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: // メインクラス
c2b7a98c21 2011-02-23        kinaba: //----------------------------------------------------------------
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: class BgaMelter
c2b7a98c21 2011-02-23        kinaba: {
4e2933c620 2015-04-21        kinaba: 	alias BgaAnswer delegate(ref BgaHeader) FileHandler;
c2b7a98c21 2011-02-23        kinaba: 	alias BgaAnswer delegate(int, int)        ProgressHandler;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	private Filep fp = null;
c2b7a98c21 2011-02-23        kinaba: 
4e2933c620 2015-04-21        kinaba: 	this( string arc_name )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		fp = Filep.open( arc_name, true );
c2b7a98c21 2011-02-23        kinaba: 		if( fp is null )
c2b7a98c21 2011-02-23        kinaba: 			throw new BgaMelterError(ERROR_FILE_OPEN);
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	void close()
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		if( fp ) { fp.close(); fp = null; }
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	void start( FileHandler fh, ProgressHandler ph )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		try
c2b7a98c21 2011-02-23        kinaba: 		{
c2b7a98c21 2011-02-23        kinaba: 			// ヘッダを探す
c2b7a98c21 2011-02-23        kinaba: 			int hpos = find_header();
c2b7a98c21 2011-02-23        kinaba: 			if( hpos == -1 )
c2b7a98c21 2011-02-23        kinaba: 				throw new BgaMelterError(ERROR_NOT_ARC_FILE);
c2b7a98c21 2011-02-23        kinaba: 			fp.seek_to(hpos);
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			// ループ:
c2b7a98c21 2011-02-23        kinaba: 			// ヘッダ読みとり
c2b7a98c21 2011-02-23        kinaba: 			BgaHeader hdr;
c2b7a98c21 2011-02-23        kinaba: 			while( read_header(hdr) )
c2b7a98c21 2011-02-23        kinaba: 			{
c2b7a98c21 2011-02-23        kinaba: 				// 次のヘッダ位置を計算しておく
c2b7a98c21 2011-02-23        kinaba: 				uint nextpos = fp.cur() + hdr.compressed_size;
c2b7a98c21 2011-02-23        kinaba: 				try
c2b7a98c21 2011-02-23        kinaba: 				{
c2b7a98c21 2011-02-23        kinaba: 					// callback
c2b7a98c21 2011-02-23        kinaba: 					BgaAnswer a = fh(hdr);
c2b7a98c21 2011-02-23        kinaba: 					if( a == BgaAnswer.Abort )  return;
c2b7a98c21 2011-02-23        kinaba: 					if( a == BgaAnswer.SkipIt ) continue;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 					// 出力先ファイルを開く
c2b7a98c21 2011-02-23        kinaba: 					if( lastChar(hdr.fname)=='\\' )
c2b7a98c21 2011-02-23        kinaba: 					  { pathMake(hdr.fname); continue; }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 					Filep outf = Filep.open( pathMake(hdr.fname), false );
c2b7a98c21 2011-02-23        kinaba: 					if( outf is null )
c2b7a98c21 2011-02-23        kinaba: 						throw new BgaMelterError(ERROR_FILE_OPEN);
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 					// 解凍処理
c2b7a98c21 2011-02-23        kinaba: 					bool bContinue = true;
c2b7a98c21 2011-02-23        kinaba: 					if( !is_compressed(hdr) )
c2b7a98c21 2011-02-23        kinaba: 						bContinue = NcDec( hdr.original_size, outf, ph );
c2b7a98c21 2011-02-23        kinaba: 					else if( hdr.method == "GZIP" )
c2b7a98c21 2011-02-23        kinaba: 						bContinue = GzDec( hdr.compressed_size, hdr.original_size, outf, ph );
c2b7a98c21 2011-02-23        kinaba: 					else if( hdr.method == "BZ2\0" )
c2b7a98c21 2011-02-23        kinaba: 						bContinue = BzDec( hdr.original_size, outf, ph );
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 					// 閉じて属性設定
c2b7a98c21 2011-02-23        kinaba: 					outf.close();
c2b7a98c21 2011-02-23        kinaba: 					dosSetFTime( hdr.fname, hdr.date, hdr.time );
4e2933c620 2015-04-21        kinaba: 					SetFileAttributesA( toStringz(hdr.fname), hdr.attrib );
c2b7a98c21 2011-02-23        kinaba: 					if( !bContinue )
c2b7a98c21 2011-02-23        kinaba: 						return;
c2b7a98c21 2011-02-23        kinaba: 				}
c2b7a98c21 2011-02-23        kinaba: 				finally { fp.seek_to(nextpos); }
c2b7a98c21 2011-02-23        kinaba: 			}
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 		finally { close(); }
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	static int signed_char( char c )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		int cn = c;
c2b7a98c21 2011-02-23        kinaba: 		return (cn>=0x80 ? cn|0xffffff00 : cn);
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	private int find_header()
c2b7a98c21 2011-02-23        kinaba: 	{
4e2933c620 2015-04-21        kinaba: 		string dat = cast(string) fp.read(0x10000);
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		for( int i=0; i<dat.length-28; ++i )
c2b7a98c21 2011-02-23        kinaba: 		{
c2b7a98c21 2011-02-23        kinaba: 			if( dat[i+4]!='G' && dat[i+4]!='B' ) continue;
c2b7a98c21 2011-02-23        kinaba: 			if( dat[i+5]!='Z'                  ) continue;
c2b7a98c21 2011-02-23        kinaba: 			if( dat[i+6]!='I' && dat[i+6]!='2' ) continue;
c2b7a98c21 2011-02-23        kinaba: 			if( dat[i+7]!='P' && dat[i+7]!='\0') continue;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			 int checksum = dat[i+0]+(dat[i+1]<<8)+(dat[i+2]<<16)+(dat[i+3]<<24);
c2b7a98c21 2011-02-23        kinaba: 			uint fnlen    = dat[i+24]+(dat[i+25]<<8)+dat[i+26]+(dat[i+27]<<8);
c2b7a98c21 2011-02-23        kinaba: 			if( i+28+fnlen > dat.length )        continue;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			int sum = 0;
c2b7a98c21 2011-02-23        kinaba: 			for( int j=i+4; j!=i+28+fnlen; ++j )
c2b7a98c21 2011-02-23        kinaba: 				sum += signed_char(dat[j]);
c2b7a98c21 2011-02-23        kinaba: 			if( checksum == sum )
c2b7a98c21 2011-02-23        kinaba: 				return i;
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		return -1;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	private bool read_header( out BgaHeader hdr )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		// リトルエンディアンを仮定。ヘッダ読み込み
4e2933c620 2015-04-21        kinaba: 		string buf = cast(string) fp.read(28);
c2b7a98c21 2011-02-23        kinaba: 		if( buf.length < 28 ) return false;
c2b7a98c21 2011-02-23        kinaba: 		buf.length = BgaHeader.sizeof;
c2b7a98c21 2011-02-23        kinaba: 		hdr = (cast(BgaHeader[]) buf)[0];
c2b7a98c21 2011-02-23        kinaba: 		hdr.fname = "";
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// ファイル名
4e2933c620 2015-04-21        kinaba: 		hdr.fname = cast(string) fp.read(hdr.dir_name_len + hdr.file_name_len);
c2b7a98c21 2011-02-23        kinaba: 		if( hdr.fname.length < hdr.dir_name_len + hdr.file_name_len ) return false;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// チェックサム
c2b7a98c21 2011-02-23        kinaba: 		int sum = 0;
c2b7a98c21 2011-02-23        kinaba: 		for( int i=4; i!=28; ++i )    sum += signed_char(buf[i]);
c2b7a98c21 2011-02-23        kinaba: 		foreach( char c ; hdr.fname ) sum += signed_char(c);
c2b7a98c21 2011-02-23        kinaba: 		return (sum == hdr.checksum);
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
4e2933c620 2015-04-21        kinaba: 	private bool is_compressed( ref BgaHeader hdr ) // ref=just for optimization
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		// ヘッダから、ファイルが圧縮格納されているかどうかを判定
c2b7a98c21 2011-02-23        kinaba: 		if( hdr.arc_type==2 )
c2b7a98c21 2011-02-23        kinaba: 			return false;
c2b7a98c21 2011-02-23        kinaba: 		if( hdr.arc_type==0 && hdr.compressed_size==hdr.original_size )
c2b7a98c21 2011-02-23        kinaba: 		{
4e2933c620 2015-04-21        kinaba: 			int x = hdr.fname.lastIndexOf('.');
c2b7a98c21 2011-02-23        kinaba: 			if( x == -1 )
c2b7a98c21 2011-02-23        kinaba: 				return true;
4e2933c620 2015-04-21        kinaba: 			string ext = toLower(hdr.fname[x+1 .. $]);
c2b7a98c21 2011-02-23        kinaba: 			if( ext=="arc" || ext=="arj" || ext=="bz2" || ext=="bza"
c2b7a98c21 2011-02-23        kinaba: 			 || ext=="cab" || ext=="gz"  || ext=="gza" || ext=="lzh"
c2b7a98c21 2011-02-23        kinaba: 			 || ext=="lzs" || ext=="pak" || ext=="rar" || ext=="taz"
c2b7a98c21 2011-02-23        kinaba: 			 || ext=="tbz" || ext=="tgz" || ext=="z"   || ext=="zip"
c2b7a98c21 2011-02-23        kinaba: 			 || ext=="zoo" )
c2b7a98c21 2011-02-23        kinaba: 				return false;
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 		return true;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
4e2933c620 2015-04-21        kinaba: 	static string pathMake( string path )
c2b7a98c21 2011-02-23        kinaba: 	{
4e2933c620 2015-04-21        kinaba: 		char* ps = cast(char*)toStringz(path);
c2b7a98c21 2011-02-23        kinaba: 		for(char* p=ps;;)
c2b7a98c21 2011-02-23        kinaba: 		{
4e2933c620 2015-04-21        kinaba: 			for(; *p!=0&&*p!='\\'&&*p!='/'; p=CharNextA(p)) {}
c2b7a98c21 2011-02-23        kinaba: 			if( *p==0 )
c2b7a98c21 2011-02-23        kinaba: 				break;
4e2933c620 2015-04-21        kinaba: 			CreateDirectoryA( toStringz(ps[0..(p-ps)]), null );
c2b7a98c21 2011-02-23        kinaba: 			++p;
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 		return path;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	enum { BUFSIZ = 65536 }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	private bool NcDec( uint usiz, Filep outf, ProgressHandler ph )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		uint init_usiz = usiz;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// 非圧縮。コピーするだけ
c2b7a98c21 2011-02-23        kinaba: 		while( usiz )
c2b7a98c21 2011-02-23        kinaba: 		{
4e2933c620 2015-04-21        kinaba: 			string r = cast(string) fp.read( BUFSIZ<usiz?BUFSIZ:usiz );
c2b7a98c21 2011-02-23        kinaba: 			usiz -= r.length;
4e2933c620 2015-04-21        kinaba: 			outf.write(cast(char[])r);
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			// dlg
c2b7a98c21 2011-02-23        kinaba: 			if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// dlg
c2b7a98c21 2011-02-23        kinaba: 		if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
c2b7a98c21 2011-02-23        kinaba: 		return true;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	private bool GzDec( uint csiz, uint usiz, Filep outf, ProgressHandler ph )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		uint init_usiz = usiz;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// zlibで展開
c2b7a98c21 2011-02-23        kinaba: 		fp.read(10); csiz -= 10; // ヘッダ,フッタスキップ
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		ubyte[]  inbuf;  inbuf.length = 65536;
c2b7a98c21 2011-02-23        kinaba: 		ubyte[] outbuf; outbuf.length = 65536;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// zlib準備
c2b7a98c21 2011-02-23        kinaba: 		z_stream zs;
c2b7a98c21 2011-02-23        kinaba: 		zs.zalloc   = null;
c2b7a98c21 2011-02-23        kinaba: 		zs.zfree    = null;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// 出力バッファ
4e2933c620 2015-04-21        kinaba: 		zs.next_out  = outbuf.ptr;
c2b7a98c21 2011-02-23        kinaba: 		zs.avail_out = outbuf.length;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// 入力バッファ
c2b7a98c21 2011-02-23        kinaba: 		inbuf = cast(ubyte[]) fp.read( csiz<65536 ? csiz : 65536 );
c2b7a98c21 2011-02-23        kinaba: 		csiz       -= inbuf.length;
4e2933c620 2015-04-21        kinaba: 		zs.next_in  = inbuf.ptr;
c2b7a98c21 2011-02-23        kinaba: 		zs.avail_in = inbuf.length;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// スタート
c2b7a98c21 2011-02-23        kinaba: 		inflateInit2( &zs, -15 );
c2b7a98c21 2011-02-23        kinaba: 		try {
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// 書庫から入力し終わるまでループ
c2b7a98c21 2011-02-23        kinaba: 		int err = Z_OK;
c2b7a98c21 2011-02-23        kinaba: 		while( csiz&&usiz )
c2b7a98c21 2011-02-23        kinaba: 		{
c2b7a98c21 2011-02-23        kinaba: 			while( zs.avail_out > 0 )
c2b7a98c21 2011-02-23        kinaba: 			{
c2b7a98c21 2011-02-23        kinaba: 				err = etc.c.zlib.inflate( &zs, Z_PARTIAL_FLUSH );
c2b7a98c21 2011-02-23        kinaba: 				if( err!=Z_STREAM_END && err!=Z_OK )
c2b7a98c21 2011-02-23        kinaba: 					csiz=0;
c2b7a98c21 2011-02-23        kinaba: 				if( !csiz )
c2b7a98c21 2011-02-23        kinaba: 					break;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 				if( zs.avail_in<=0 )
c2b7a98c21 2011-02-23        kinaba: 				{
c2b7a98c21 2011-02-23        kinaba: 					inbuf = cast(ubyte[]) fp.read( csiz<65536 ? csiz : 65536 );
c2b7a98c21 2011-02-23        kinaba: 					csiz       -= inbuf.length;
4e2933c620 2015-04-21        kinaba: 					zs.next_in  = inbuf.ptr;
c2b7a98c21 2011-02-23        kinaba: 					zs.avail_in = inbuf.length;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 					if( inbuf.length==0 )
c2b7a98c21 2011-02-23        kinaba: 					{
c2b7a98c21 2011-02-23        kinaba: 						err  = Z_STREAM_END;
c2b7a98c21 2011-02-23        kinaba: 						csiz = 0;
c2b7a98c21 2011-02-23        kinaba: 						break;
c2b7a98c21 2011-02-23        kinaba: 					}
c2b7a98c21 2011-02-23        kinaba: 				}
c2b7a98c21 2011-02-23        kinaba: 			}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			int written = outbuf.length - zs.avail_out;
c2b7a98c21 2011-02-23        kinaba: 			if( usiz < written ) written = usiz;
c2b7a98c21 2011-02-23        kinaba: 			usiz -= written;
c2b7a98c21 2011-02-23        kinaba: 			outf.write( outbuf[0..written] );
4e2933c620 2015-04-21        kinaba: 			zs.next_out  = outbuf.ptr;
c2b7a98c21 2011-02-23        kinaba: 			zs.avail_out = outbuf.length;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			// dlg
c2b7a98c21 2011-02-23        kinaba: 			if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// 出力残しを無くす。
c2b7a98c21 2011-02-23        kinaba: 		while( err!=Z_STREAM_END&&usiz )
c2b7a98c21 2011-02-23        kinaba: 		{
c2b7a98c21 2011-02-23        kinaba: 			err = etc.c.zlib.inflate(&zs,Z_PARTIAL_FLUSH);
c2b7a98c21 2011-02-23        kinaba: 			if( err!=Z_STREAM_END && err!=Z_OK )
c2b7a98c21 2011-02-23        kinaba: 				break;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			int written = outbuf.length - zs.avail_out;
c2b7a98c21 2011-02-23        kinaba: 			if( usiz < written ) written = usiz;
c2b7a98c21 2011-02-23        kinaba: 			usiz -= written;
c2b7a98c21 2011-02-23        kinaba: 			outf.write( outbuf[0..written] );
4e2933c620 2015-04-21        kinaba: 			zs.next_out  = outbuf.ptr;
c2b7a98c21 2011-02-23        kinaba: 			zs.avail_out = outbuf.length;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 			// dlg
c2b7a98c21 2011-02-23        kinaba: 			if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
c2b7a98c21 2011-02-23        kinaba: 		}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// 終了
c2b7a98c21 2011-02-23        kinaba: 		} finally { inflateEnd(&zs); }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// dlg
c2b7a98c21 2011-02-23        kinaba: 		if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
c2b7a98c21 2011-02-23        kinaba: 		return true;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 	private bool BzDec( uint usiz, Filep outf, ProgressHandler ph )
c2b7a98c21 2011-02-23        kinaba: 	{
c2b7a98c21 2011-02-23        kinaba: 		uint init_usiz = usiz;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// libbz2で展開
c2b7a98c21 2011-02-23        kinaba: 		int err;
4e2933c620 2015-04-21        kinaba: 		BZFILE* b = BZ2_bzReadOpen( &err, fp.get_fp(), 0, 0, null, 0 );
c2b7a98c21 2011-02-23        kinaba: 		if( err!=BZ_OK || b is null )
c2b7a98c21 2011-02-23        kinaba: 			return true;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		try
c2b7a98c21 2011-02-23        kinaba: 		{
c2b7a98c21 2011-02-23        kinaba: 			char[] buf; buf.length = BUFSIZ;
c2b7a98c21 2011-02-23        kinaba: 			int len;
4e2933c620 2015-04-21        kinaba: 			while( 0<(len=BZ2_bzRead( &err, b, buf.ptr, BUFSIZ<usiz?BUFSIZ:usiz )) )
c2b7a98c21 2011-02-23        kinaba: 			{
c2b7a98c21 2011-02-23        kinaba: 				outf.write( buf[0..len] );
c2b7a98c21 2011-02-23        kinaba: 				usiz -= len;
c2b7a98c21 2011-02-23        kinaba: 				if( err != BZ_OK )
c2b7a98c21 2011-02-23        kinaba: 					break;
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 				// dlg
c2b7a98c21 2011-02-23        kinaba: 				if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
c2b7a98c21 2011-02-23        kinaba: 			}
c2b7a98c21 2011-02-23        kinaba: 		} finally { BZ2_bzReadClose( &err, b ); }
c2b7a98c21 2011-02-23        kinaba: 
c2b7a98c21 2011-02-23        kinaba: 		// dlg
c2b7a98c21 2011-02-23        kinaba: 		if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
c2b7a98c21 2011-02-23        kinaba: 		return true;
c2b7a98c21 2011-02-23        kinaba: 	}
c2b7a98c21 2011-02-23        kinaba: }