unalz/UnAlz.cpp
2020-05-05 20:22:39 +02:00

1793 lines
47 KiB
C++
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//#include "stdafx.h"
#include "zlib/zlib.h"
#include "bzip2/bzlib.h"
#include "UnAlz.h"
// mkdir
#ifdef _WIN32
# include <direct.h>
#else
# include <sys/stat.h>
#endif
#ifdef _UNALZ_ICONV // code page support
# include <iconv.h>
#endif
#ifdef __linux__ // __BYTE_ORDER °¡Á®¿À±â
# include <errno.h> // iconv.h ¶§¹®¿¡ ÇÊ¿ä
#endif
#define swapint64(Data) (INT64) ( (((Data)&0x00000000000000FFLL) << 56) | (((Data)&0x000000000000FF00LL) << 40) | (((Data)&0x0000000000FF0000LL) << 24) | (((Data)&0x00000000FF000000LL) << 8) | (((Data)&0x000000FF00000000LL) >> 8) | (((Data)&0x0000FF0000000000LL) >> 24) | (((Data)&0x00FF000000000000LL) >> 40) | (((Data)&0xFF00000000000000LL) >> 56) )
#define swapint32(a) ((((a)&0xff)<<24)+(((a>>8)&0xff)<<16)+(((a>>16)&0xff)<<8)+(((a>>24)&0xff)))
#define swapint16(a) (((a)&0xff)<<8)+(((a>>8)&0xff))
////////////////////////////////////////////////////////////////////////////
//// byte-order : little to host ////
////////////////////////////////////////////////////////////////////////////
#if defined(_WIN32) ||defined(__CYGWIN__) // little to little
inline UINT16 unalz_le16toh(UINT16 a){return a;}
inline UINT32 unalz_le32toh(UINT32 a){return a;}
inline UINT64 unalz_le64toh(UINT64 a){return a;}
#endif
#ifdef __FreeBSD__
# include <sys/endian.h>
inline UINT16 unalz_le16toh(UINT16 a){return le16toh(a);}
inline UINT32 unalz_le32toh(UINT32 a){return le32toh(a);}
inline UINT64 unalz_le64toh(UINT64 a){return le64toh(a);}
#endif
#ifdef __APPLE__
# include <machine/byte_order.h>
inline UINT16 unalz_le16toh(UINT16 a){return NXSwapShort(a);}
inline UINT32 unalz_le32toh(UINT32 a){return NXSwapLong(a);}
inline UINT64 unalz_le64toh(UINT64 a){return NXSwapLongLong(a);}
#endif
#ifdef __linux__
# include <endian.h>
# if __BYTE_ORDER == __BIG_ENDIAN
inline UINT16 unalz_le16toh(UINT16 a){return swapint16(a);}
inline UINT32 unalz_le32toh(UINT32 a){return swapint32(a);}
inline UINT64 unalz_le64toh(UINT64 a){return swapint64(a);}
# else // __LITTLE_ENDIAN
inline UINT16 unalz_le16toh(UINT16 a){return (a);}
inline UINT32 unalz_le32toh(UINT32 a){return (a);}
inline UINT64 unalz_le64toh(UINT64 a){return (a);}
# endif
//# include <asm/byteorder.h>
// inline UINT16 unalz_le16toh(UINT16 a){return le16_to_cpu(a);}
// inline UINT32 unalz_le32toh(UINT32 a){return le32_to_cpu(a);}
// inline UINT64 unalz_le64toh(UINT64 a){return le64_to_cpu(a);}
#endif
#ifndef MAX_PATH
# define MAX_PATH 260
#endif
#ifdef _WIN32
# define PATHSEP "\\"
# define PATHSEPC '\\'
#else
# define PATHSEP "/"
# define PATHSEPC '/'
#endif
// error string table <- CUnAlz::ERR ÀÇ ¹ø¿ª
static const char* errorstrtable[]=
{
"no error", // ERR_NOERR
"can't open file", // ERR_CANT_OPEN_FILE
"corrupted file", // ERR_CORRUPTED_FILE
"not alz file", // ERR_NOT_ALZ_FILE
"can't read signature", // ERR_CANT_READ_SIG
"can't read file", // ERR_CANT_READ_FILE
"error at read header", // ERR_AT_READ_HEADER
"invalid filename length", // ERR_INVALID_FILENAME_LENGTH
"invalid extrafield length", // ERR_INVALID_EXTRAFIELD_LENGTH,
"can't read central directory structure head", // ERR_CANT_READ_CENTRAL_DIRECTORY_STRUCTURE_HEAD,
"invalid filename size", // ERR_INVALID_FILENAME_SIZE,
"invalid extrafield size", // ERR_INVALID_EXTRAFIELD_SIZE,
"invalid filecomment size", // ERR_INVALID_FILECOMMENT_SIZE,
"cant' read header", // ERR_CANT_READ_HEADER,
"memory allocation failed", // ERR_MEM_ALLOC_FAILED,
"file read error", // ERR_FILE_READ_ERROR,
"inflate failed", // ERR_INFLATE_FAILED,
"bzip2 decompress failed", // ERR_BZIP2_FAILED,
"invalid file CRC", // ERR_INVALID_FILE_CRC
"unknown compression method", // ERR_UNKNOWN_COMPRESSION_METHOD
"iconv-can't open iconv", // ERR_ICONV_CANT_OPEN,
"iconv-invalid multisequence of characters", // ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS,
"iconv-incomplete multibyte sequence", // ERR_ICONV_INCOMPLETE_MULTIBYTE_SEQUENCE,
"iconv-not enough space of buffer to convert", // ERR_ICONV_NOT_ENOUGH_SPACE_OF_BUFFER_TO_CONVERT,
"iconv-etc", // ERR_ICONV_ETC,
"password was not set", // ERR_PASSWD_NOT_SET,
"invalid password", // ERR_INVALID_PASSWD,
"user aborted",
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ctor
/// @date 2004-03-06 ¿ÀÈÄ 11:19:49
////////////////////////////////////////////////////////////////////////////////////////////////////
CUnAlz::CUnAlz()
{
memset(m_files, 0, sizeof(m_files));
m_nErr = ERR_NOERR;
m_posCur = (FileList::iterator)NULL;
m_pFuncCallBack = NULL;
m_pCallbackParam = NULL;
m_bHalt = FALSE;
m_nFileCount = 0;
m_nCurFile = -1;
m_nVirtualFilePos = 0;
m_nCurFilePos = 0;
m_bIsEOF = FALSE;
m_bIsEncrypted = FALSE;
m_bIsDataDescr = FALSE;
#ifdef _UNALZ_ICONV
#ifdef _UNALZ_UTF8
strcpy(m_szToCodepage, "UTF-8") ; // ±âº»ÀûÀ¸·Î utf-8
#else
strcpy(m_szToCodepage, "CP949") ; // ±âº»ÀûÀ¸·Î CP949
#endif // _UNALZ_UTF8
strcpy(m_szFromCodepage, "CP949"); // alz ´Â 949 ¸¸ Áö¿ø
#endif // _UNALZ_ICONV
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// dtor
/// @date 2004-03-06 ¿ÀÈÄ 11:19:52
////////////////////////////////////////////////////////////////////////////////////////////////////
CUnAlz::~CUnAlz()
{
Close();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// progress callback func setting
/// @date 2004-03-01 ¿ÀÀü 6:02:05
////////////////////////////////////////////////////////////////////////////////////////////////////
void CUnAlz::SetCallback(_UnAlzCallback* pFunc, void* param)
{
m_pFuncCallBack = pFunc;
m_pCallbackParam = param;
}
#ifdef _WIN32
#if !defined(__GNUWIN32__) && !defined(__GNUC__)
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÆÄÀÏ ¿­±â
/// @param szPathName
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:03:59
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <atlbase.h>
#include <atlconv.h>
BOOL CUnAlz::Open(LPCWSTR szPathName)
{
USES_CONVERSION;
return Open(W2A(szPathName));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ´ë»ó ÆÄÀÏ ¼¼ÆÃÇϱâ.
/// @param szFileName
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:06:20
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::SetCurrentFile(LPCWSTR szFileName)
{
USES_CONVERSION;
return SetCurrentFile(W2A(szFileName));
}
BOOL CUnAlz::IsFolder(LPCWSTR szPathName)
{
UINT32 dwRet;
dwRet = GetFileAttributesW(szPathName);
if(dwRet==0xffffffff) return FALSE;
if(dwRet & FILE_ATTRIBUTE_DIRECTORY) return TRUE;
return FALSE;
}
#endif // __GNUWIN32__
#endif // _WIN32
BOOL CUnAlz::Open(const char* szPathName)
{
if(FOpen(szPathName)==FALSE)
{
m_nErr = ERR_CANT_OPEN_FILE;
return FALSE;
}
BOOL bValidAlzHeader = FALSE;
// file ºÐ¼®½ÃÀÛ..
for(;;)
{
SIGNATURE sig;
BOOL ret;
if(FEof()) break;
//int pos = ftell(m_fp);
sig = ReadSignature();
if(sig==SIG_EOF)
{
break;
}
if(sig==SIG_ERROR)
{
if(bValidAlzHeader)
m_nErr = ERR_CORRUPTED_FILE; // ¼Õ»óµÈ ÆÄÀÏ
else
m_nErr = ERR_NOT_ALZ_FILE; // alz ÆÄÀÏÀÌ ¾Æ´Ï´Ù.
return FALSE; // ±úÁø ÆÄÀÏ..
}
if(sig==SIG_ALZ_FILE_HEADER)
{
ret = ReadAlzFileHeader();
bValidAlzHeader = TRUE; // alz ÆÄÀÏÀº ¸Â´Ù.
}
else if(sig==SIG_LOCAL_FILE_HEADER) ret = ReadLocalFileheader();
else if(sig==SIG_CENTRAL_DIRECTORY_STRUCTURE) ret = ReadCentralDirectoryStructure();
else if(sig==SIG_ENDOF_CENTRAL_DIRECTORY_RECORD) ret = ReadEndofCentralDirectoryRecord();
else
{
// ¹Ì±¸ÇöµÈ signature ? ±úÁø ÆÄÀÏ ?
ASSERT(0);
m_nErr = ERR_CORRUPTED_FILE;
return FALSE;
}
if(ret==FALSE)
{
return FALSE;
}
if(FEof()) break;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÆÄÀÏ ´Ý±â..
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:04:21
////////////////////////////////////////////////////////////////////////////////////////////////////
void CUnAlz::Close()
{
FClose();
// ¸ñ·Ï ³¯¸®±â..
FileList::iterator i;
for(i=m_fileList.begin(); i<m_fileList.end(); i++)
{
i->Clear();
}
m_posCur = (FileList::iterator)NULL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// FILE ³»ÀÇ SIGNATURE Àбâ
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:04:47
////////////////////////////////////////////////////////////////////////////////////////////////////
CUnAlz::SIGNATURE CUnAlz::ReadSignature()
{
UINT32 dwSig;
if(FRead(&dwSig, sizeof(dwSig))==FALSE)
{
//int pos = ftell(m_fp);
if(FEof())
return SIG_EOF;
m_nErr = ERR_CANT_READ_SIG;
return SIG_ERROR;
}
return (SIGNATURE)unalz_le32toh(dwSig); // little to host;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ALZ HEADER SIGNATURE Àбâ
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:05:11
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::ReadAlzFileHeader()
{
SAlzHeader header;
if(FRead(&header, sizeof(header))==FALSE)
{
ASSERT(0);
m_nErr = ERR_CANT_READ_FILE;
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// °¢°¢ÀÇ ÆÄÀÏ Çì´õ Àбâ
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:05:18
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::ReadLocalFileheader()
{
SLocalFileHeader zipHeader;
int ret;
ret = FRead(&(zipHeader.head), sizeof(zipHeader.head));
if(ret==FALSE)
{
m_nErr = ERR_AT_READ_HEADER;
return FALSE;
}
// ALZ È®Àå..
if( (zipHeader.head.fileDescriptor & (SHORT)1) != 0){
m_bIsEncrypted = TRUE; // Çϳª¶óµµ ¾ÏÈ£ °É·ÈÀ¸¸é ¼¼ÆÃÇÑ´Ù.
}
if( (zipHeader.head.fileDescriptor & (SHORT)8) != 0){
m_bIsDataDescr = TRUE;
}
int byteLen = zipHeader.head.fileDescriptor/0x10;
if(byteLen)
{
FRead(&(zipHeader.compressionMethod), sizeof(zipHeader.compressionMethod));
FRead(&(zipHeader.unknown), sizeof(zipHeader.unknown));
FRead(&(zipHeader.fileCRC), sizeof(zipHeader.fileCRC));
// FRead(&(zipHeader.passwordCRC), sizeof(zipHeader.passwordCRC));
FRead(&(zipHeader.compressedSize), byteLen);
FRead(&(zipHeader.uncompressedSize), byteLen); // ¾ÐÃà »çÀÌÁî°¡ ¾ø´Ù.
}
// little to system
zipHeader.head.fileNameLength = unalz_le16toh(zipHeader.head.fileNameLength);
zipHeader.compressedSize = unalz_le64toh(zipHeader.compressedSize);
zipHeader.uncompressedSize = unalz_le64toh(zipHeader.uncompressedSize);
// FILE NAME
zipHeader.fileName = (char*)malloc(zipHeader.head.fileNameLength+sizeof(char));
if(zipHeader.fileName==NULL)
{
m_nErr = ERR_INVALID_FILENAME_LENGTH;
return FALSE;
}
FRead(zipHeader.fileName, zipHeader.head.fileNameLength);
zipHeader.fileName[zipHeader.head.fileNameLength] = (CHAR)NULL;
#ifdef _UNALZ_ICONV // codepage convert
if(strlen(m_szToCodepage))
{
#define ICONV_BUF_SIZE (260*6) // utf8 Àº ÃÖ´ë 6byte
size_t ileft, oleft;
iconv_t cd;
size_t iconv_result;
size_t size;
char inbuf[ICONV_BUF_SIZE];
char outbuf[ICONV_BUF_SIZE];
#if defined(__FreeBSD__) || defined(__CYGWIN__)
const char *inptr = inbuf;
#else
char *inptr = inbuf;
#endif
char *outptr = outbuf;
size = strlen(zipHeader.fileName)+1;
strncpy(inbuf, zipHeader.fileName, size);
ileft = size;
oleft = sizeof(outbuf);
cd = iconv_open(m_szToCodepage, m_szFromCodepage); // º¸Åë "CP949" ¿¡¼­ "UTF-8" ·Î
iconv(cd, NULL, NULL, NULL, NULL);
if( cd == (iconv_t)(-1))
{
m_nErr = ERR_ICONV_CANT_OPEN; // printf("Converting Error : Cannot open iconv");
return FALSE;
}
else
{
iconv_result = iconv(cd, &inptr, &ileft, &outptr, &oleft);
if(iconv_result== (size_t)(-1)) // iconv ½ÇÆÐ..
{
if (errno == EILSEQ)
m_nErr = ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS; // printf("Invalid Multibyte Sequence of Characters");
else if (errno == EINVAL)
m_nErr = ERR_ICONV_INCOMPLETE_MULTIBYTE_SEQUENCE; //printf("Incomplete multibyte sequence");
else if (errno != E2BIG)
m_nErr = ERR_ICONV_NOT_ENOUGH_SPACE_OF_BUFFER_TO_CONVERT; // printf("Not enough space of buffer to convert");
else
m_nErr = ERR_ICONV_ETC;
iconv_close(cd);
return FALSE;
}
else
{
outbuf[ICONV_BUF_SIZE-oleft] = 0;
if(zipHeader.fileName) free(zipHeader.fileName);
zipHeader.fileName = strdup(outbuf);
if (zipHeader.fileName == NULL)
{
m_nErr = ERR_ICONV_ETC;
iconv_close(cd);
return FALSE;
}
// printf("\n Converted File Name : %s", outbuf);
}
iconv_close(cd);
}
}
#endif
/*
// EXTRA FIELD LENGTH
if(zipHeader.head.extraFieldLength)
{
zipHeader.extraField = (BYTE*)malloc(zipHeader.head.extraFieldLength);
if(zipHeader.extraField==NULL)
{
m_nErr = ERR_INVALID_EXTRAFIELD_LENGTH;
return FALSE;
}
FRead(zipHeader.extraField, 1, zipHeader.head.extraFieldLength);
}
*/
if(IsEncryptedFile(zipHeader.head.fileDescriptor))
FRead(zipHeader.encChk, ENCR_HEADER_LEN); // xf86
// SKIP FILE DATA
zipHeader.dwFileDataPos = FTell(); // data ÀÇ À§Ä¡ ÀúÀåÇϱâ..
FSeek(FTell()+zipHeader.compressedSize);
// DATA DESCRIPTOR
/*
if(zipHeader.head.generalPurposeBitFlag.bit1)
{
FRead(zipHeader.extraField, 1, sizeof(zipHeader.extraField),);
}
*/
#ifdef _DEBUG
printf("NAME:%s COMPRESSED SIZE:%d UNCOMPRESSED SIZE:%d COMP METHOD:%d\n",
zipHeader.fileName,
zipHeader.compressedSize,
zipHeader.uncompressedSize,
zipHeader.compressionMethod
);
#endif
// ÆÄÀÏÀ» ¸ñ·Ï¿¡ Ãß°¡ÇÑ´Ù..
m_fileList.push_back(zipHeader);
return TRUE;
}
BOOL CUnAlz::ReadCentralDirectoryStructure()
{
SCentralDirectoryStructure header;
if(FRead(&header, sizeof(header.head))==FALSE)
{
m_nErr = ERR_CANT_READ_CENTRAL_DIRECTORY_STRUCTURE_HEAD;
return FALSE;
}
/*
// read file name
if(header.head.fileNameLength)
{
header.fileName = (char*)malloc(header.head.fileNameLength+1);
if(header.fileName==NULL)
{
m_nErr = ERR_INVALID_FILENAME_SIZE;
return FALSE;
}
FRead(header.fileName, 1, header.head.fileNameLength, m_fp);
header.fileName[header.head.fileNameLength] = NULL;
}
// extra field;
if(header.head.extraFieldLength)
{
header.extraField = (BYTE*)malloc(header.head.extraFieldLength);
if(header.extraField==NULL)
{
m_nErr = ERR_INVALID_EXTRAFIELD_SIZE;
return FALSE;
}
FRead(header.extraField, 1, header.head.extraFieldLength, m_fp);
}
// file comment;
if(header.head.fileCommentLength)
{
header.fileComment = (char*)malloc(header.head.fileCommentLength+1);
if(header.fileComment==NULL)
{
m_nErr = ERR_INVALID_FILECOMMENT_SIZE;
return FALSE;
}
FRead(header.fileComment, 1, header.head.fileCommentLength, m_fp);
header.fileComment[header.head.fileCommentLength] = NULL;
}
*/
return TRUE;
}
BOOL CUnAlz::ReadEndofCentralDirectoryRecord()
{
/*
SEndOfCentralDirectoryRecord header;
if(FRead(&header, sizeof(header.head), 1, m_fp)!=1)
{
m_nErr = ERR_CANT_READ_HEADER;
return FALSE;
}
if(header.head.zipFileCommentLength)
{
header.fileComment = (char*)malloc(header.head.zipFileCommentLength+1);
if(header.fileComment==NULL)
{
m_nErr = ERR_INVALID_FILECOMMENT_SIZE;
return FALSE;
}
FRead(header.fileComment, 1, header.head.zipFileCommentLength, m_fp);
header.fileComment[header.head.zipFileCommentLength] = NULL;
}
*/
return TRUE;
}
BOOL CUnAlz::SetCurrentFile(const char* szFileName)
{
FileList::iterator i;
// ¼øÂ÷ÀûÀ¸·Î ã´Â´Ù.
for(i=m_fileList.begin(); i<m_fileList.end(); i++)
{
#ifdef _WIN32
if(stricmp(i->fileName, szFileName)==0)
#else
if(strcmp(i->fileName, szFileName)==0)
#endif
{
m_posCur = i;
return TRUE;
}
}
m_posCur = (FileList::iterator)NULL;
return FALSE;
}
void CUnAlz::SetCurrentFile(FileList::iterator newPos)
{
m_posCur = newPos;
}
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ¹öÆÛ¿¡ ¾ÐÃà Ç®±â. ¹öÆÛ´Â ´ç±Ù ÃæºÐÇÑ Å©±â°¡ ÁغñµÇ¾î ÀÖ¾î¾ß ÇÑ´Ù.
/// @param pDestBuf
/// @return
/// @date 2004-03-07 ¿ÀÀü 12:26:13
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::ExtractCurrentFileToBuf(BYTE* pDestBuf, int nBufSize)
{
SExtractDest dest;
dest.nType = ET_MEM;
dest.buf = pDestBuf;
dest.bufpos = 0;
dest.bufsize = nBufSize;
return ExtractTo(&dest);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÇöÀç ÆÄÀÏ (SetCurrentFile·Î Áö)À» ´ë»ó °æ·Î¿¡ ´ë»ó ÆÄÀϷΠǬ´Ù.
/// @param szDestPathName - ´ë»ó °æ·Î
/// @param szDestFileName - ´ë»ó ÆÄÀϸí, NULL ÀÌ¸é ¿ø·¡ ÆÄÀÏ¸í »ç¿ë
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:06:59
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::ExtractCurrentFile(const char* szDestPathName, const char* szDestFileName)
{
if(m_posCur==(FileList::iterator)NULL) {ASSERT(0); return FALSE;}
BOOL ret=FALSE;
SExtractDest dest;
char szDestPathFileName[MAX_PATH];
if(chkValidPassword() == FALSE)
{
return FALSE;
}
// °æ·Î¸í
strcpy(szDestPathFileName, szDestPathName);
if(szDestPathFileName[strlen(szDestPathFileName)]!=PATHSEPC)
strcat(szDestPathFileName, PATHSEP);
// ÆÄÀϸí
if(szDestFileName) strcat(szDestPathFileName, szDestFileName);
else strcat(szDestPathFileName, m_posCur->fileName);
#ifndef _WIN32
{
char* p = szDestPathFileName; // °æ·Î delimiter ¹Ù²Ù±â
while(*p)
{
if(*p=='\\') *p='/';
p++;
}
}
#endif
// ¾ÐÃàÇ® ´ë»ó ( ÆÄÀÏ )
dest.nType = ET_FILE;
dest.fp = fopen(szDestPathFileName, "wb");
if(dest.fp==NULL)
{
DigPath(szDestPathFileName); // °æ·Î¸í¿¡ / °¡ ÀÖÀ» °æ¿ì..
dest.fp = fopen(szDestPathFileName, "wb");
}
#ifdef _WIN32
if(dest.fp==NULL)
{
ASSERT(0);
if(m_pFuncCallBack)
{
CHAR buf[1024];
sprintf(buf, "ÆÄÀÏ ¿­±â ½ÇÆÐ : %s", szDestPathFileName);
m_pFuncCallBack(buf, 0,0,m_pCallbackParam, NULL);
}
return FALSE;
}
#endif
// CALLBACK ¼¼ÆÃ
if(m_pFuncCallBack) m_pFuncCallBack(m_posCur->fileName, 0,m_posCur->uncompressedSize,m_pCallbackParam, NULL);
ret = ExtractTo(&dest);
if(dest.fp!=NULL)fclose(dest.fp);
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ´ë»ó¿¡ ¾ÐÃà Ç®±â..
/// @param dest
/// @return
/// @date 2004-03-07 ¿ÀÀü 12:44:36
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::ExtractTo(SExtractDest* dest)
{
BOOL ret = FALSE;
// ¾ÐÃà ¹æ¹ý¿¡ µû¶ó¼­ ¾ÐÃà Ç®±â
if(m_posCur->compressionMethod==COMP_NOCOMP)
{
ret = ExtractRawfile(dest, *m_posCur);
}
else if(m_posCur->compressionMethod==COMP_BZIP2)
{
ret = ExtractBzip2(dest, *m_posCur); // bzip2
}
else if(m_posCur->compressionMethod==COMP_DEFLATE)
{
ret = ExtractDeflate2(dest, *m_posCur); // deflate
}
else // COMP_UNKNOWN
{
// alzip 5.6 ºÎÅÍ Ãß°¡µÈ Æ÷¸Ë(5.5 ¿¡¼­´Â Ç®Áö ¸øÇÑ´Ù. ¿µ¹® 5.51 Àº Ǭ´Ù )
// ÇÏÁö¸¸ ¾î¶² ¹öÀü¿¡¼­ ÀÌ Æ÷¸ËÀ» ¸¸µé¾î ³»´ÂÁö Á¤È®È÷ ¾Ë ¼ö ¾ø´Ù.
m_nErr = ERR_UNKNOWN_COMPRESSION_METHOD;
ASSERT(0);
ret = FALSE;
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// DEFLATE ·Î Ç®±â - Å×½ºÆ®¿ë ÇÔ¼ö. ¸ðµç ÆÄÀÏÀ» ÇѲ¨¹ø¿¡ Àо Ǭ´Ù. ½ÇÁ¦ »ç¿ë ¾ÈÇÔ.
/// @param fp - ´ë»ó ÆÄÀÏ
/// @param file - ¼Ò½º ÆÄÀÏ Á¤º¸
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:09:17
////////////////////////////////////////////////////////////////////////////////////////////////////
/*
BOOL CUnAlz::ExtractDeflate(FILE* fp, SLocalFileHeader& file)
{
z_stream stream;
BYTE* pInBuf=NULL;
BYTE* pOutBuf=NULL;
int nInBufSize = file.compressedSize;
int nOutBufSize = file.uncompressedSize;
int err;
int flush=Z_SYNC_FLUSH;
BOOL ret = FALSE;
memset(&stream, 0, sizeof(stream));
pInBuf = (BYTE*)malloc(nInBufSize);
if(pInBuf==NULL)
{
m_nErr = ERR_MEM_ALLOC_FAILED;
goto END;
}
pOutBuf = (BYTE*)malloc(nOutBufSize);
if(pOutBuf==NULL)
{
m_nErr = ERR_MEM_ALLOC_FAILED;
goto END;
}
// Çѹø¿¡ Àо
fseek(m_fp, file.dwFileDataPos, SEEK_SET);
if(FRead(pInBuf, nInBufSize, 1, m_fp)!=1)
{
m_nErr = ERR_FILE_READ_ERROR;
goto END;
}
// ÃʱâÈ­..
inflateInit2(&stream, -MAX_WBITS);
stream.next_out = pOutBuf;
stream.avail_out = nOutBufSize;
stream.next_in = pInBuf;
stream.avail_in = nInBufSize;
err = inflate(&stream, flush);
if(err!=Z_OK && err!=Z_STREAM_END )
{
m_nErr = ERR_INFLATE_FAILED;
goto END;
}
fwrite(pOutBuf, 1, nOutBufSize, fp);
ret = TRUE;
END :
inflateEnd(&stream);
if(pInBuf) free(pInBuf);
if(pOutBuf) free(pOutBuf);
return ret;
}
*/
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ´ë»ó Æú´õ¿¡ ÇöÀç ¾ÐÃàÆÄÀÏÀ» ÀüºÎ Ç®±â
/// @param szDestPathName - ´ë»ó °æ·Î
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:09:49
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::ExtractAll(const char* szDestPathName)
{
FileList::iterator i;
for(i=m_fileList.begin(); i<m_fileList.end(); i++)
{
m_posCur = i;
if(ExtractCurrentFile(szDestPathName)==FALSE) return FALSE;
if(m_bHalt)
break; // ¸ØÃß±â..
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ´ë»ó °æ·Î Æıâ - ¾ÐÃà ÆÄÀÏ ³»¿¡ Æú´õ Á¤º¸°¡ ÀÖÀ» °æ¿ì, ´ÙÁß Æú´õ¸¦ ÆÇ´Ù(dig)
/// @param szPathName
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:10:12
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::DigPath(const char* szPathName)
{
char* dup = strdup(szPathName);
char seps[] = "/\\";
char *token;
char path[MAX_PATH] = {0};
char* last;
// °æ·Î¸¸ »Ì±â.
last = dup + strlen(dup);
while(last!=dup)
{
if(*last=='/' || *last=='\\')
{
*last = (char)NULL;
break;
}
last --;
}
token = strtok( dup, seps );
while( token != NULL )
{
if(strlen(path)==0)
strcpy(path, token);
else
{
strcat(path, PATHSEP);
strcat(path, token);
}
if(IsFolder(path)==FALSE)
#ifdef _WIN32
_mkdir(path);
#else
mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
#endif
token = strtok( NULL, seps );
}
free(dup);
if(IsFolder(szPathName)) return TRUE;
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Á¦´ë·ÎµÈ Æú´õ Àΰ¡?
/// @param szPathName
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:03:26
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::IsFolder(const CHAR* szPathName)
{
#ifdef _WIN32
UINT32 dwRet;
dwRet = GetFileAttributesA(szPathName);
if(dwRet==0xffffffff) return FALSE;
if(dwRet & FILE_ATTRIBUTE_DIRECTORY) return TRUE;
return FALSE;
#else
struct stat buf;
int result;
result = stat(szPathName, &buf);
if(result!=0) return FALSE;
//printf("isfolder:%s, %d,%d,%d\n", szPathName, buf.st_mode, S_IFDIR, buf.st_mode & S_IFDIR);
if(buf.st_mode & S_IFDIR) return TRUE;
return FALSE;
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ¾ÐÃàÀ» Ç® ´ë»ó¿¡ ¾ÐÃàÀ» Ǭ´Ù.
/// @param dest - ´ë»ó OBJECT
/// @param buf - Ç®¸° µ¥ÀÌŸ
/// @param nSize - µ¥ÀÌŸÀÇ Å©±â
/// @return ¾´ ¹ÙÀÌÆ®¼ö. ¿¡·¯½Ã -1 ¸®ÅÏ
/// @date 2004-03-07 ¿ÀÀü 12:37:41
////////////////////////////////////////////////////////////////////////////////////////////////////
int CUnAlz::WriteToDest(SExtractDest* dest, BYTE* buf, int nSize)
{
if(dest->nType==ET_FILE)
{
return fwrite(buf, 1, nSize, dest->fp);
}
else if(dest->nType==ET_MEM)
{
if(dest->buf==NULL) return nSize; // ´ë»óÀÌ NULL ÀÌ´Ù... ¾ÐÃàǪ´Â ½Ã´¿¸¸ ÇÑ´Ù..
if(dest->bufpos+nSize >dest->bufsize) // ¿¡·¯.. ¹öÆÛ°¡ ³ÑÃÆ´Ù.
{
ASSERT(0);
return -1;
}
// memcpy
memcpy(dest->buf + dest->bufpos, buf, nSize);
dest->bufpos += nSize;
return nSize;
}
else
{
ASSERT(0);
}
return -1;
}
/* ½ÇÆÐÇÑ ¹æ¹ý.. °í»ýÇÑ°Ô ¾Æ±î¿ö¼­ ¸øÁö¿ò.
#define ALZDLZ_HEADER_SIZE 4 // alz ÆÄÀÏÀÇ bzip2 Çì´õ Å©±â
#define BZIP2_HEADER_SIZE 10 // bzip ÆÄÀÏÀÇ Çì´õ Å©±â
#define BZIP2_CRC_SIZE 4 // bzip2 ÀÇ crc
#define BZIP2_TAIL_SIZE 10 // ´ëÃæ 4+5 Á¤µµ.?
BYTE bzip2Header[BZIP2_HEADER_SIZE] = {0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59};
BOOL CUnAlz::ExtractBzip2_bak(FILE* fp, SLocalFileHeader& file)
{
bz_stream stream;
BYTE* pInBuf=NULL;
BYTE* pOutBuf=NULL;
int nInBufSize = file.compressedSize;
int nOutBufSize = file.uncompressedSize;
//int err;
int flush=Z_SYNC_FLUSH;
BOOL ret = FALSE;
UINT32 crc = 0xffffffff;
//BYTE temp[100];
memset(&stream, 0, sizeof(stream));
pInBuf = (BYTE*)malloc(nInBufSize + BZIP2_HEADER_SIZE + BZIP2_CRC_SIZE - ALZDLZ_HEADER_SIZE + BZIP2_TAIL_SIZE);
if(pInBuf==NULL)
{
m_nErr = ERR_MEM_ALLOC_FAILED;
goto END;
}
pOutBuf = (BYTE*)malloc(nOutBufSize);
if(pOutBuf==NULL)
{
m_nErr = ERR_MEM_ALLOC_FAILED;
goto END;
}
// ALZ ÀÇ BZIP Çì´õ ("DLZ.") ½ºÅµÇϱâ.
fseek(m_fp, ALZDLZ_HEADER_SIZE, SEEK_CUR);
// BZIP2 Çì´õ »ðÀÔ
memcpy(pInBuf, bzip2Header, BZIP2_HEADER_SIZE);
// BZIP2 CRC
memcpy(pInBuf+BZIP2_HEADER_SIZE, &(crc), BZIP2_CRC_SIZE);
// ÁøÂ¥ ¾ÐÃàµÈ µ¥ÀÌŸ¸¦ Çѹø¿¡ Àо
fseek(m_fp, file.dwFileDataPos+ALZDLZ_HEADER_SIZE, SEEK_SET);
if(FRead(pInBuf+BZIP2_HEADER_SIZE+BZIP2_CRC_SIZE, nInBufSize-ALZDLZ_HEADER_SIZE, 1, m_fp)!=1)
{
m_nErr = ERR_FILE_READ_ERROR;
goto END;
}
// ÃʱâÈ­..
stream.bzalloc = NULL;
stream.bzfree = NULL;
stream.opaque = NULL;
ret = BZ2_bzDecompressInit ( &stream, 3,0 );
if (ret != BZ_OK) goto END;
//memcpy(temp, pInBuf, 100);
stream.next_in = (char*)pInBuf;
stream.next_out = (char*)pOutBuf;
stream.avail_in = nInBufSize+BZIP2_HEADER_SIZE+BZIP2_CRC_SIZE+BZIP2_TAIL_SIZE;
stream.avail_out = nOutBufSize;
ret = BZ2_bzDecompress ( &stream );
// BZ_DATA_ERROR °¡ ¸®Å쵃 ¼ö ÀÖ´Ù..
//if (ret == BZ_OK) goto END;
//if (ret != BZ_STREAM_END) goto END;
BZ2_bzDecompressEnd(&stream);
fwrite(pOutBuf, 1, nOutBufSize, fp);
ret = TRUE;
END :
if(pInBuf) free(pInBuf);
if(pOutBuf) free(pOutBuf);
if(ret==FALSE) BZ2_bzDecompressEnd(&stream);
return ret;
}
*/
////////////////////////////////////////////////////////////////////////////////////////////////////
/// RAW ·Î ¾ÐÃàµÈ ÆÄÀÏ Ç®±â
/// @param fp - ´ë»ó ÆÄÀÏ
/// @param file - ¼Ò½º ÆÄÀÏ
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:10:53
////////////////////////////////////////////////////////////////////////////////////////////////////
#define BUF_LEN (4096*2)
BOOL CUnAlz::ExtractRawfile(SExtractDest* dest, SLocalFileHeader& file)
{
BOOL ret = FALSE;
BYTE buf[BUF_LEN];
INT64 read;
INT64 sizeToRead;
INT64 bufLen = BUF_LEN;
INT64 nWritten = 0;
BOOL bHalt = FALSE;
BOOL bIsEncrypted = IsEncryptedFile(); // ¾ÏÈ£°É¸° ÆÄÀÏÀΰ¡?
UINT32 dwCRC32= 0;
// À§Ä¡ Àâ°í.
FSeek(file.dwFileDataPos);
sizeToRead = file.compressedSize; // ÀÐÀ» Å©±â.
m_nErr = ERR_NOERR;
while(sizeToRead)
{
read = min(sizeToRead, bufLen);
if(FRead(buf, (int)read)==FALSE)
{
break;
}
if(bIsEncrypted)
DecryptingData((int)read, buf); // xf86
dwCRC32 = crc32(dwCRC32, buf, (UINT)(read));
WriteToDest(dest, buf, (int)read);
//fwrite(buf, read, 1, fp);
sizeToRead -= read;
nWritten+=read;
// progress callback
if(m_pFuncCallBack)
{
m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
if(bHalt)
{
break;
}
}
}
m_bHalt = bHalt;
if(m_nErr==ERR_NOERR) // ¼º°øÀûÀ¸·Î ¾ÐÃàÀ» Ç®¾ú´Ù.. CRC °Ë»çÇϱâ..
{
if(file.fileCRC==dwCRC32)
{
ret = TRUE;
}
else
{
m_nErr = ERR_INVALID_FILE_CRC;
}
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// BZIP2 ¾ÐÃà Ç®±â..
/// @param fp_w - ´ë»ó ÆÄÀÏ
/// @param file - ¼Ò½º ÆÄÀÏ Á¤º¸
/// @return
/// @date 2004-03-01 ¿ÀÀü 5:47:36
////////////////////////////////////////////////////////////////////////////////////////////////////
#define BZIP2_EXTRACT_BUF_SIZE 0x2000
BOOL CUnAlz::ExtractBzip2(SExtractDest* dest, SLocalFileHeader& file)
{
BZFILE *bzfp = NULL;
int smallMode = 0;
int verbosity = 1;
int bzerr;
INT64 len;
BYTE buff[BZIP2_EXTRACT_BUF_SIZE];
INT64 nWritten = 0;
BOOL bHalt = FALSE;
UINT32 dwCRC32= 0;
BOOL ret = FALSE;
FSeek(file.dwFileDataPos);
bzfp = BZ2_bzReadOpen(&bzerr,this,verbosity,smallMode,0,0);
if(bzfp==NULL){ASSERT(0); return FALSE;}
m_nErr = ERR_NOERR;
while((len=BZ2_bzread(bzfp,buff,BZIP2_EXTRACT_BUF_SIZE))>0)
{
WriteToDest(dest, (BYTE*)buff, (int)len);
//fwrite(buff,1,len,fp_w);
dwCRC32 = crc32(dwCRC32,buff, (UINT)(len));
nWritten+=len;
// progress callback
if(m_pFuncCallBack)
{
m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
if(bHalt)
{
break;
}
}
}
if(len<0) // ¿¡·¯ »óȲ..
{
m_nErr = ERR_INFLATE_FAILED;
}
BZ2_bzReadClose( &bzerr, bzfp);
m_bHalt = bHalt;
if(m_nErr==ERR_NOERR) // ¼º°øÀûÀ¸·Î ¾ÐÃàÀ» Ç®¾ú´Ù.. CRC °Ë»çÇϱâ..
{
if(file.fileCRC==dwCRC32)
{
ret = TRUE;
}
else
{
m_nErr = ERR_INVALID_FILE_CRC;
}
}
/*
// FILE* ¸¦ »ç¿ëÇÒ°æ¿ì »ç¿ëÇÏ´ø ÄÚµå. - ¸ÖƼ º¼·ý Áö¿ø ¾ÈÇÔ..
BZFILE *bzfp = NULL;
int smallMode = 0;
int verbosity = 1;
int bzerr;
int len;
char buff[BZIP2_EXTRACT_BUF_SIZE];
INT64 nWritten = 0;
BOOL bHalt = FALSE;
FSeek(file.dwFileDataPos, SEEK_SET);
bzfp = BZ2_bzReadOpen(&bzerr,m_fp,verbosity,smallMode,0,0);
while((len=BZ2_bzread(bzfp,buff,BZIP2_EXTRACT_BUF_SIZE))>0)
{
WriteToDest(dest, (BYTE*)buff, len);
//fwrite(buff,1,len,fp_w);
nWritten+=len;
// progress callback
if(m_pFuncCallBack)
{
m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
if(bHalt)
{
break;
}
}
}
BZ2_bzReadClose( &bzerr, bzfp);
m_bHalt = bHalt;
*/
return ret;
}
#ifndef UNZ_BUFSIZE
#define UNZ_BUFSIZE 0x1000 // (16384)
#endif
#define IN_BUF_SIZE UNZ_BUFSIZE
#define OUT_BUF_SIZE 0x1000 //IN_BUF_SIZE
////////////////////////////////////////////////////////////////////////////////////////////////////
/// deflate ·Î ¾ÐÃà Ç®±â. ExtractDeflate() ¿Í ´Þ¸® Á¶±Ý¾¿ Àо Ǭ´Ù.
/// @param fp
/// @param file
/// @return
/// @date 2004-03-06 ¿ÀÈÄ 11:11:36
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::ExtractDeflate2(SExtractDest* dest, SLocalFileHeader& file)
{
z_stream stream;
BYTE pInBuf[IN_BUF_SIZE];
BYTE pOutBuf[OUT_BUF_SIZE];
int nInBufSize = IN_BUF_SIZE;
int nOutBufSize = OUT_BUF_SIZE;
int err;
int flush=Z_SYNC_FLUSH;
BOOL ret = FALSE;
INT64 nRestReadCompressed;
UINT32 dwCRC32= 0;
INT64 rest_read_uncompressed;
UINT iRead = 0;
INT64 nWritten = 0;
BOOL bHalt = FALSE;
BOOL bIsEncrypted = IsEncryptedFile(); // ¾ÏÈ£°É¸° ÆÄÀÏÀΰ¡?
memset(&stream, 0, sizeof(stream));
FSeek(file.dwFileDataPos);
inflateInit2(&stream, -MAX_WBITS);
nRestReadCompressed = file.compressedSize;
rest_read_uncompressed = file.uncompressedSize;
// Ãâ·Â ºÎºÐ.
stream.next_out = pOutBuf;
stream.avail_out = OUT_BUF_SIZE;
m_nErr = ERR_NOERR;
while(stream.avail_out>0)
{
if(stream.avail_in==0 && nRestReadCompressed>0)
{
UINT uReadThis = UNZ_BUFSIZE;
if (nRestReadCompressed<(int)uReadThis)
uReadThis = (UINT)nRestReadCompressed; // ÀÐÀ» Å©±â.
if (uReadThis == 0)
break; // ÁßÁö
if(FRead(pInBuf, uReadThis)==FALSE)
{
m_nErr = ERR_CANT_READ_FILE;
goto END;
}
if(bIsEncrypted)
DecryptingData(uReadThis, pInBuf); // xf86
// dwCRC32 = crc32(dwCRC32,pInBuf, (UINT)(uReadThis));
nRestReadCompressed -= uReadThis;
stream.next_in = pInBuf;
stream.avail_in = uReadThis;
}
UINT uTotalOutBefore,uTotalOutAfter;
const BYTE *bufBefore;
UINT uOutThis;
int flush=Z_SYNC_FLUSH;
uTotalOutBefore = stream.total_out;
bufBefore = stream.next_out;
err=inflate(&stream,flush);
uTotalOutAfter = stream.total_out;
uOutThis = uTotalOutAfter-uTotalOutBefore;
dwCRC32 = crc32(dwCRC32,bufBefore, (UINT)(uOutThis));
rest_read_uncompressed -= uOutThis;
iRead += (UINT)(uTotalOutAfter - uTotalOutBefore);
WriteToDest(dest, pOutBuf, uOutThis);
//fwrite(pOutBuf, uOutThis, 1, fp); // file ¿¡ ¾²±â.
stream.next_out = pOutBuf;
stream.avail_out = OUT_BUF_SIZE;
nWritten+=uOutThis;
// progress callback
if(m_pFuncCallBack)
{
m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
if(bHalt)
{
m_nErr = ERR_USER_ABORTED;
break;
}
}
if (err==Z_STREAM_END)
break;
//if(iRead==0) break; // UNZ_EOF;
if (err!=Z_OK)
{
m_nErr = ERR_INFLATE_FAILED;
goto END;
}
}
m_bHalt = bHalt;
if(m_nErr==ERR_NOERR) // ¼º°øÀûÀ¸·Î ¾ÐÃàÀ» Ç®¾ú´Ù.. CRC °Ë»çÇϱâ..
{
if(file.fileCRC==dwCRC32)
{
ret = TRUE;
}
else
{
m_nErr = ERR_INVALID_FILE_CRC;
}
}
END :
inflateEnd(&stream);
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÆÄÀÏ ¿­±â
/// @param szPathName
/// @return
/// @date 2004-10-02 ¿ÀÈÄ 11:47:14
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::FOpen(const char* szPathName)
{
char* temp = strdup(szPathName); // ÆÄÀÏ¸í º¹»ç..
int i;
int nLen = strlen(szPathName);
UINT64 nFileSizeLow;
UINT32 dwFileSizeHigh;
m_nFileCount = 0;
m_nCurFile = 0;
m_nVirtualFilePos = 0;
m_nCurFilePos = 0;
m_bIsEOF = FALSE;
for(i=0;i<MAX_FILES;i++) // aa.alz ÆÄÀϸíÀ» °¡Áö°í aa.a00 aa.a01 aa.a02 .. ¸¸µé±â
{
if(i>0) sprintf(temp+nLen-3, "%c%02d", (i-1)/100+'a', (i-1)%100);
#ifdef _WIN32
m_files[i].fp = CreateFileA(temp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(m_files[i].fp==INVALID_HANDLE_VALUE) break;
nFileSizeLow = GetFileSize(m_files[i].fp, (DWORD*)&dwFileSizeHigh);
#else
m_files[i].fp = fopen(temp, "rb");
if(m_files[i].fp==NULL) break;
dwFileSizeHigh=0;
fseek(m_files[i].fp,0,SEEK_END);
nFileSizeLow=ftell(m_files[i].fp);
fseek(m_files[i].fp,0,SEEK_SET);
#endif
m_nFileCount++;
m_files[i].nFileSize = ((INT64)nFileSizeLow) + (((INT64)dwFileSizeHigh)<<32);
if(i==0) m_files[i].nMultivolHeaderSize = 0;
else m_files[i].nMultivolHeaderSize = MULTIVOL_HEAD_SIZE;
m_files[i].nMultivolTailSize = MULTIVOL_TAIL_SIZE;
}
free(temp);
if(m_nFileCount==0) return FALSE;
m_files[m_nFileCount-1].nMultivolTailSize = 0; // ¸¶Áö¸· ÆÄÀÏÀº ²Ã¶ûÁö°¡ ¾ø´Ù..
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÆÄÀÏ ´Ý±â
/// @return
/// @date 2004-10-02 ¿ÀÈÄ 11:48:53
////////////////////////////////////////////////////////////////////////////////////////////////////
void CUnAlz::FClose()
{
int i;
#ifdef _WIN32
for(i=0;i<m_nFileCount;i++) CloseHandle(m_files[i].fp);
#else
for(i=0;i<m_nFileCount;i++) fclose(m_files[i].fp);
#endif
memset(m_files, 0, sizeof(m_files));
m_nFileCount = 0;
m_nCurFile = -1;
m_nVirtualFilePos = 0;
m_nCurFilePos = 0;
m_bIsEOF = FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÆÄÀÏÀÇ ³¡Àΰ¡?
/// @return
/// @date 2004-10-02 ¿ÀÈÄ 11:48:21
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::FEof()
{
return m_bIsEOF;
/*
if(m_fp==NULL){ASSERT(0); return TRUE;}
if(feof(m_fp)) return TRUE;
return FALSE;
*/
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÇöÀç ÆÄÀÏ À§Ä¡
/// @return
/// @date 2004-10-02 ¿ÀÈÄ 11:50:50
////////////////////////////////////////////////////////////////////////////////////////////////////
INT64 CUnAlz::FTell()
{
return m_nVirtualFilePos; // return ftell(m_fp);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÆÄÀÏ À§Ä¡ ¼¼ÆÃ
/// @param offset
/// @param origin
/// @return
/// @date 2004-10-02 ¿ÀÈÄ 11:51:53
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::FSeek(INT64 offset)
{
m_nVirtualFilePos = offset;
int i;
INT64 remain=offset;
LONG remainHigh;
m_bIsEOF = FALSE;
for(i=0;i<m_nFileCount;i++) // ¾Õ¿¡¼­ ·çÇÁ¸¦ µ¹¸é¼­ À§Ä¡ ¼±Á¤Çϱâ..
{
if(remain<=m_files[i].nFileSize-m_files[i].nMultivolHeaderSize-m_files[i].nMultivolTailSize)
{
m_nCurFile = i;
m_nCurFilePos = remain+m_files[i].nMultivolHeaderSize; // ¹°¸®Àû À§Ä¡.
remainHigh = (LONG)((m_nCurFilePos>>32)&0xffffffff);
#ifdef _WIN32
SetFilePointer(m_files[i].fp, LONG(m_nCurFilePos), &remainHigh, FILE_BEGIN);
#else
fseek(m_files[i].fp, m_nCurFilePos, SEEK_SET);
#endif
return TRUE;
}
remain -= (m_files[i].nFileSize-m_files[i].nMultivolHeaderSize-m_files[i].nMultivolTailSize);
}
// ½ÇÆÐ..?
ASSERT(0);
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ÆÄÀÏ Àбâ
/// @param buffer
/// @param size
/// @param count
/// @return
/// @date 2004-10-02 ¿ÀÈÄ 11:44:05
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::FRead(void* buffer, UINT32 nBytesToRead, int* pTotRead )
{
BOOL ret;
UINT32 nNumOfBytesRead;
INT64 dwRemain;
UINT32 dwRead;
UINT32 dwTotRead;
dwRemain = nBytesToRead;
dwTotRead = 0;
if(pTotRead) *pTotRead=0;
while(dwRemain)
{
dwRead = (UINT32)min(dwRemain, (m_files[m_nCurFile].nFileSize-m_nCurFilePos-m_files[m_nCurFile].nMultivolTailSize));
if(dwRead==0) {
m_bIsEOF = TRUE;return FALSE;
}
#ifdef _WIN32
ret = ReadFile(m_files[m_nCurFile].fp, ((BYTE*)buffer)+dwTotRead, dwRead, (DWORD*)&nNumOfBytesRead, NULL);
if(ret==FALSE && GetLastError()==ERROR_HANDLE_EOF)
{
m_bIsEOF = TRUE;return FALSE;
}
#else
nNumOfBytesRead = fread(((BYTE*)buffer)+dwTotRead, 1,dwRead ,m_files[m_nCurFile].fp);
if(nNumOfBytesRead<=0)
{
m_bIsEOF = TRUE;return FALSE;
}
ret=TRUE;
#endif
if(dwRead!=nNumOfBytesRead) // ¹ß»ýÇÏ¸é ¾ÈµÈ´Ù..
{
ASSERT(0); return FALSE;
}
m_nVirtualFilePos += nNumOfBytesRead; // virtual ÆÄÀÏ À§Ä¡..
m_nCurFilePos+=nNumOfBytesRead; // ¹°¸®Àû ÆÄÀÏ À§Ä¡.
dwRemain-=nNumOfBytesRead;
dwTotRead+=nNumOfBytesRead;
if(pTotRead) *pTotRead=dwTotRead;
if(m_nCurFilePos==m_files[m_nCurFile].nFileSize-m_files[m_nCurFile].nMultivolTailSize) // overflow
{
m_nCurFile++;
#ifdef _WIN32
if(m_files[m_nCurFile].fp==INVALID_HANDLE_VALUE)
#else
if(m_files[m_nCurFile].fp==NULL)
#endif
{
m_bIsEOF = TRUE;
if(dwRemain==0) return TRUE; // ¿ÏÀüÈ÷ ³¡±îÁö Àоú´Ù..
return FALSE;
}
m_nCurFilePos = m_files[m_nCurFile].nMultivolHeaderSize; // header skip
#ifdef _WIN32
SetFilePointer(m_files[m_nCurFile].fp, (int)m_nCurFilePos, NULL, FILE_BEGIN);
#else
fseek(m_files[m_nCurFile].fp, m_nCurFilePos, SEEK_SET);
#endif
}
else
if(m_nCurFilePos>m_files[m_nCurFile].nFileSize-m_files[m_nCurFile].nMultivolTailSize) ASSERT(0);
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// error code ¸¦ ½ºÆ®¸µÀ¸·Î ¹Ù²ã ÁØ´Ù.
/// @param nERR
/// @return
/// @date 2004-10-24 ¿ÀÈÄ 3:28:39
////////////////////////////////////////////////////////////////////////////////////////////////////
const char* CUnAlz::LastErrToStr(ERR nERR)
{
if(nERR>= sizeof(errorstrtable)/sizeof(errorstrtable[0])) {ASSERT(0); return NULL; }
return errorstrtable[nERR];
}
// by xf86
BOOL CUnAlz::chkValidPassword()
{
if(IsEncryptedFile()==FALSE) {return TRUE;}
if (getPasswordLen() == 0){
m_nErr = ERR_PASSWD_NOT_SET;
return FALSE;
}
InitCryptKeys(m_szPasswd);
if(CryptCheck(m_posCur->encChk) == FALSE){
m_nErr = ERR_INVALID_PASSWD;
return FALSE;
}
return TRUE;
}
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
// from CZipArchive
// Copyright (C) 2000 - 2004 Tadeusz Dracz
//
// http://www.artpol-software.com
//
// it's under GPL.
////////////////////////////////////////////////////////////////////////////////////////////////////
void CUnAlz::CryptDecodeBuffer(UINT32 uCount, CHAR *buf)
{
if (IsEncrypted())
for (UINT32 i = 0; i < uCount; i++)
CryptDecode(buf[i]);
}
void CUnAlz::CryptInitKeys()
{
m_keys[0] = 305419896L;
m_keys[1] = 591751049L;
m_keys[2] = 878082192L;
for (int i = 0; i < strlen(m_szPasswd); i++)
CryptUpdateKeys(m_szPasswd[i]);
}
void CUnAlz::CryptUpdateKeys(CHAR c)
{
m_keys[0] = CryptCRC32(m_keys[0], c);
m_keys[1] += m_keys[0] & 0xff;
m_keys[1] = m_keys[1] * 134775813L + 1;
c = CHAR(m_keys[1] >> 24);
m_keys[2] = CryptCRC32(m_keys[2], c);
}
BOOL CUnAlz::CryptCheck(CHAR *buf)
{
CHAR b = 0;
for (int i = 0; i < ENCR_HEADER_LEN; i++)
{
b = buf[i];
CryptDecode((CHAR&)b);
}
if (IsDataDescr()) // Data descriptor present
return CHAR(m_posCur->head.fileTimeDate >> 8) == b;
else
return CHAR(m_posCur->maybeCRC >> 24) == b;
}
CHAR CUnAlz::CryptDecryptCHAR()
{
int temp = (m_keys[2] & 0xffff) | 2;
return (CHAR)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
void CUnAlz::CryptDecode(CHAR &c)
{
c ^= CryptDecryptCHAR();
CryptUpdateKeys(c);
}
UINT32 CUnAlz::CryptCRC32(UINT32 l, CHAR c)
{
const ULONG *CRC_TABLE = get_crc_table();
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
}
*/
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ¾ÏÈ£°É¸° ÆÄÀÏÀÎÁö ¿©ºÎ
/// @param fileDescriptor
/// @return
/// @date 2004-11-27 ¿ÀÈÄ 11:25:32
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::IsEncryptedFile(BYTE fileDescriptor)
{
return fileDescriptor&0x01;
}
BOOL CUnAlz::IsEncryptedFile()
{
return m_posCur->head.fileDescriptor&0x01;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ¾ÏÈ£·Î Å° ÃʱâÈ­
/// @param szPassword
/// @return
/// @date 2004-11-27 ¿ÀÈÄ 11:04:01
////////////////////////////////////////////////////////////////////////////////////////////////////
void CUnAlz::InitCryptKeys(const CHAR* szPassword)
{
m_key[0] = 305419896;
m_key[1] = 591751049;
m_key[2] = 878082192;
int i;
for(i=0;i<(int)strlen(szPassword);i++)
{
UpdateKeys(szPassword[i]);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// µ¥ÀÌŸ·Î Å° ¾÷µ¥ÀÌÆ®Çϱâ
/// @param c
/// @return
/// @date 2004-11-27 ¿ÀÈÄ 11:04:09
////////////////////////////////////////////////////////////////////////////////////////////////////
void CUnAlz::UpdateKeys(BYTE c)
{
m_key[0] = CRC32(m_key[0], c);
m_key[1] = m_key[1]+(m_key[0]&0x000000ff);
m_key[1] = m_key[1]*134775813+1;
m_key[2] = CRC32(m_key[2],m_key[1]>>24);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// ¾ÏÈ£°¡ ¸Â´ÂÁö Çì´õ üũÇϱâ
/// @param buf
/// @return
/// @date 2004-11-27 ¿ÀÈÄ 11:04:24
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::CryptCheck(const BYTE* buf)
{
int i;
BYTE c;
BYTE temp[ENCR_HEADER_LEN];
memcpy(temp, buf, ENCR_HEADER_LEN); // Àӽà º¹»ç.
for(i=0;i<ENCR_HEADER_LEN;i++)
{
c = temp[i] ^ DecryptByte();
UpdateKeys(c);
temp[i] = c;
}
if (IsDataDescr()) // Data descriptor present
return (m_posCur->head.fileTimeDate >> 8) == c;
else
return ( ((m_posCur->fileCRC)>>24) ) == c; // ÆÄÀÏ crc ÀÇ ÃÖ»óÀ§ byte
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Å°¿¡¼­ µ¥ÀÌŸ ÃßÃâ
/// @return
/// @date 2004-11-27 ¿ÀÈÄ 11:05:36
////////////////////////////////////////////////////////////////////////////////////////////////////
BYTE CUnAlz::DecryptByte()
{
UINT16 temp;
temp = m_key[2] | 2;
return (temp * (temp^1))>>8;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// µ¥ÀÌŸ ¾ÐÃà Ç®±â
/// @param nSize
/// @param data
/// @return
/// @date 2004-11-27 ¿ÀÈÄ 11:03:30
////////////////////////////////////////////////////////////////////////////////////////////////////
void CUnAlz::DecryptingData(int nSize, BYTE* data)
{
BYTE* p = data;
BYTE temp;
while(nSize)
{
temp = *p ^ DecryptByte();
UpdateKeys(temp);
*p = temp;
nSize--;
p++;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// CRC Å×À̺í ÂüÁ¶
/// @param l
/// @param c
/// @return
/// @date 2004-11-27 ¿ÀÈÄ 11:14:16
////////////////////////////////////////////////////////////////////////////////////////////////////
UINT32 CUnAlz::CRC32(UINT32 l, BYTE c)
{
const ULONG *CRC_TABLE = get_crc_table();
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
}