v0.60
This commit is contained in:
parent
d20061a62a
commit
87f99873d9
8 changed files with 208 additions and 130 deletions
2
Makefile
2
Makefile
|
@ -12,7 +12,7 @@ all:
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "TARGET_SYSTEM is one of"
|
@echo "TARGET_SYSTEM is one of"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " posix : POSIX system (FreeBSD/linux/OSX/sparc)"
|
@echo " posix : POSIX system (FreeBSD/linux/OSX/sparc/Win32)"
|
||||||
@echo " posix-utf8 : POSIX with utf8 filesystem(e.g. OSX)"
|
@echo " posix-utf8 : POSIX with utf8 filesystem(e.g. OSX)"
|
||||||
@echo " linux-utf8 : LINUX with utf8 filesystem(without -liconv option)"
|
@echo " linux-utf8 : LINUX with utf8 filesystem(without -liconv option)"
|
||||||
@echo " posix-noiconv : POSIX without libiconv (Windows(MINGW32,CYGWIN) or EUC-KR file system)"
|
@echo " posix-noiconv : POSIX without libiconv (Windows(MINGW32,CYGWIN) or EUC-KR file system)"
|
||||||
|
|
180
UnAlz.cpp
180
UnAlz.cpp
|
@ -1,4 +1,3 @@
|
||||||
//#include "stdafx.h"
|
|
||||||
#include "zlib/zlib.h"
|
#include "zlib/zlib.h"
|
||||||
#include "bzip2/bzlib.h"
|
#include "bzip2/bzlib.h"
|
||||||
#include "UnAlz.h"
|
#include "UnAlz.h"
|
||||||
|
@ -8,13 +7,11 @@
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
# include <sys/utime.h>
|
# include <sys/utime.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
# include <utime.h>
|
# include <utime.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// mkdir
|
// mkdir
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
|
@ -35,52 +32,39 @@
|
||||||
# include <errno.h> // iconv.h 때문에 필요
|
# include <errno.h> // iconv.h 때문에 필요
|
||||||
#endif
|
#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) )
|
#ifdef _WIN32 // string conversion
|
||||||
|
# include <atlbase.h>
|
||||||
|
# include <atlconv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32 // safe string 처리
|
||||||
|
# include "strsafe.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// ENDIAN 처리
|
||||||
|
#ifdef _WIN32 // (L)
|
||||||
|
# define swapint64(a) (UINT64) ( (((a)&0x00000000000000FFL) << 56) | (((a)&0x000000000000FF00L) << 40) | (((a)&0x0000000000FF0000L) << 24) | (((a)&0x00000000FF000000L) << 8) | (((a)&0x000000FF00000000L) >> 8) | (((a)&0x0000FF0000000000L) >> 24) | (((a)&0x00FF000000000000L) >> 40) | (((a)&0xFF00000000000000L) >> 56) )
|
||||||
|
#else // (LL)
|
||||||
|
# define swapint64(a) (UINT64) ( (((a)&0x00000000000000FFLL) << 56) | (((a)&0x000000000000FF00LL) << 40) | (((a)&0x0000000000FF0000LL) << 24) | (((a)&0x00000000FF000000LL) << 8) | (((a)&0x000000FF00000000LL) >> 8) | (((a)&0x0000FF0000000000LL) >> 24) | (((a)&0x00FF000000000000LL) >> 40) | (((a)&0xFF00000000000000LL) >> 56) )
|
||||||
|
#endif
|
||||||
#define swapint32(a) ((((a)&0xff)<<24)+(((a>>8)&0xff)<<16)+(((a>>16)&0xff)<<8)+(((a>>24)&0xff)))
|
#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))
|
#define swapint16(a) (((a)&0xff)<<8)+(((a>>8)&0xff))
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
typedef UINT16 (*_unalz_le16toh)(UINT16 a);
|
||||||
//// byte-order : little to host ////
|
typedef UINT32 (*_unalz_le32toh)(UINT32 a);
|
||||||
////////////////////////////////////////////////////////////////////////////
|
typedef UINT64 (*_unalz_le64toh)(UINT64 a);
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__) // little to little
|
static _unalz_le16toh unalz_le16toh=NULL;
|
||||||
inline UINT16 unalz_le16toh(UINT16 a){return a;}
|
static _unalz_le32toh unalz_le32toh=NULL;
|
||||||
inline UINT32 unalz_le32toh(UINT32 a){return a;}
|
static _unalz_le64toh unalz_le64toh=NULL;
|
||||||
inline UINT64 unalz_le64toh(UINT64 a){return a;}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
|
||||||
# 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
|
|
||||||
|
|
||||||
|
static UINT16 le16tole(UINT16 a){return a;}
|
||||||
|
static UINT32 le32tole(UINT32 a){return a;}
|
||||||
|
static UINT64 le64tole(UINT64 a){return a;}
|
||||||
|
static UINT16 le16tobe(UINT16 a){return swapint16(a);}
|
||||||
|
static UINT32 le32tobe(UINT32 a){return swapint32(a);}
|
||||||
|
static UINT64 le64tobe(UINT64 a){return swapint64(a);}
|
||||||
|
|
||||||
|
|
||||||
#ifndef MAX_PATH
|
#ifndef MAX_PATH
|
||||||
|
@ -108,6 +92,44 @@ static time_t dosTime2TimeT(UINT32 dostime) // from INFO-ZIP src
|
||||||
return mktime(&t);
|
return mktime(&t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL IsBigEndian(void)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
short a;
|
||||||
|
char b[2];
|
||||||
|
} endian;
|
||||||
|
|
||||||
|
endian.a = 0x0102;
|
||||||
|
if(endian.b[0] == 0x02) return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 안전한 strcpy
|
||||||
|
static void safe_strcpy(char* dst, const char* src, size_t dst_size)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
lstrcpynA(dst, src, dst_size);
|
||||||
|
#else
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void safe_strcat(char* dst, const char* src, size_t dst_size)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
StringCchCatExA(dst, dst_size, src, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
|
||||||
|
//lstrcatA(dst, src); // not safe!!
|
||||||
|
#else
|
||||||
|
strlcat(dst, src, dst_size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define safe_sprintf StringCbPrintfA
|
||||||
|
#else
|
||||||
|
# define safe_sprintf snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// error string table <- CUnAlz::ERR 의 번역
|
// error string table <- CUnAlz::ERR 의 번역
|
||||||
static const char* errorstrtable[]=
|
static const char* errorstrtable[]=
|
||||||
|
@ -148,7 +170,6 @@ static const char* errorstrtable[]=
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ctor
|
/// ctor
|
||||||
/// @date 2004-03-06 오후 11:19:49
|
/// @date 2004-03-06 오후 11:19:49
|
||||||
|
@ -173,13 +194,30 @@ CUnAlz::CUnAlz()
|
||||||
#ifdef _UNALZ_ICONV
|
#ifdef _UNALZ_ICONV
|
||||||
|
|
||||||
#ifdef _UNALZ_UTF8
|
#ifdef _UNALZ_UTF8
|
||||||
strcpy(m_szToCodepage, "UTF-8") ; // 기본적으로 utf-8
|
safe_strcpy(m_szToCodepage, "UTF-8",UNALZ_LEN_CODEPAGE) ; // 기본적으로 utf-8
|
||||||
#else
|
#else
|
||||||
strcpy(m_szToCodepage, "CP949") ; // 기본적으로 CP949
|
safe_strcpy(m_szToCodepage, "CP949",UNALZ_LEN_CODEPAGE) ; // 기본적으로 CP949
|
||||||
#endif // _UNALZ_UTF8
|
#endif // _UNALZ_UTF8
|
||||||
|
|
||||||
strcpy(m_szFromCodepage, "CP949"); // alz 는 949 만 지원
|
safe_strcpy(m_szFromCodepage, "CP949",UNALZ_LEN_CODEPAGE); // alz 는 949 만 지원
|
||||||
#endif // _UNALZ_ICONV
|
#endif // _UNALZ_ICONV
|
||||||
|
|
||||||
|
// check endian
|
||||||
|
if(unalz_le16toh==NULL)
|
||||||
|
{
|
||||||
|
if(IsBigEndian())
|
||||||
|
{
|
||||||
|
unalz_le16toh = le16tobe;
|
||||||
|
unalz_le32toh = le32tobe;
|
||||||
|
unalz_le64toh = le64tobe;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unalz_le16toh = le16tole;
|
||||||
|
unalz_le32toh = le32tole;
|
||||||
|
unalz_le64toh = le64tole;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -209,8 +247,6 @@ void CUnAlz::SetCallback(_UnAlzCallback* pFunc, void* param)
|
||||||
/// @return
|
/// @return
|
||||||
/// @date 2004-03-06 오후 11:03:59
|
/// @date 2004-03-06 오후 11:03:59
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#include <atlbase.h>
|
|
||||||
#include <atlconv.h>
|
|
||||||
BOOL CUnAlz::Open(LPCWSTR szPathName)
|
BOOL CUnAlz::Open(LPCWSTR szPathName)
|
||||||
{
|
{
|
||||||
USES_CONVERSION;
|
USES_CONVERSION;
|
||||||
|
@ -327,7 +363,6 @@ CUnAlz::SIGNATURE CUnAlz::ReadSignature()
|
||||||
UINT32 dwSig;
|
UINT32 dwSig;
|
||||||
if(FRead(&dwSig, sizeof(dwSig))==FALSE)
|
if(FRead(&dwSig, sizeof(dwSig))==FALSE)
|
||||||
{
|
{
|
||||||
//int pos = ftell(m_fp);
|
|
||||||
if(FEof())
|
if(FEof())
|
||||||
return SIG_EOF;
|
return SIG_EOF;
|
||||||
m_nErr = ERR_CANT_READ_SIG;
|
m_nErr = ERR_CANT_READ_SIG;
|
||||||
|
@ -351,7 +386,6 @@ BOOL CUnAlz::ReadAlzFileHeader()
|
||||||
m_nErr = ERR_CANT_READ_FILE;
|
m_nErr = ERR_CANT_READ_FILE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,7 +608,6 @@ BOOL CUnAlz::ReadCentralDirectoryStructure()
|
||||||
FRead(header.fileComment, 1, header.head.fileCommentLength, m_fp);
|
FRead(header.fileComment, 1, header.head.fileCommentLength, m_fp);
|
||||||
header.fileComment[header.head.fileCommentLength] = NULL;
|
header.fileComment[header.head.fileCommentLength] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -690,13 +723,13 @@ BOOL CUnAlz::ExtractCurrentFile(const char* szDestPathName, const char* szDestFi
|
||||||
}
|
}
|
||||||
|
|
||||||
// 경로명
|
// 경로명
|
||||||
strcpy(szDestPathFileName, szDestPathName);
|
safe_strcpy(szDestPathFileName, szDestPathName, MAX_PATH);
|
||||||
if(szDestPathFileName[strlen(szDestPathFileName)]!=PATHSEPC)
|
if(szDestPathFileName[strlen(szDestPathFileName)]!=PATHSEPC)
|
||||||
strcat(szDestPathFileName, PATHSEP);
|
safe_strcat(szDestPathFileName, PATHSEP, MAX_PATH);
|
||||||
|
|
||||||
// 파일명
|
// 파일명
|
||||||
if(szDestFileName) strcat(szDestPathFileName, szDestFileName);
|
if(szDestFileName) safe_strcat(szDestPathFileName, szDestFileName, MAX_PATH);
|
||||||
else strcat(szDestPathFileName, m_posCur->fileName);
|
else safe_strcat(szDestPathFileName, m_posCur->fileName, MAX_PATH);
|
||||||
|
|
||||||
// ../../ 형식의 보안 버그 확인
|
// ../../ 형식의 보안 버그 확인
|
||||||
if( strstr(szDestPathFileName, "../")||
|
if( strstr(szDestPathFileName, "../")||
|
||||||
|
@ -707,8 +740,6 @@ BOOL CUnAlz::ExtractCurrentFile(const char* szDestPathName, const char* szDestFi
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
{
|
{
|
||||||
char* p = szDestPathFileName; // 경로 delimiter 바꾸기
|
char* p = szDestPathFileName; // 경로 delimiter 바꾸기
|
||||||
|
@ -938,13 +969,15 @@ BOOL CUnAlz::DigPath(const char* szPathName)
|
||||||
if(strlen(path)==0)
|
if(strlen(path)==0)
|
||||||
{
|
{
|
||||||
if(szPathName[0]=='/') // is absolute path ?
|
if(szPathName[0]=='/') // is absolute path ?
|
||||||
strcpy(path,"/");
|
safe_strcpy(path,"/", MAX_PATH);
|
||||||
strcat(path, token);
|
else if(szPathName[0]=='\\' && szPathName[1]=='\\') // network drive ?
|
||||||
|
safe_strcpy(path,"\\\\", MAX_PATH);
|
||||||
|
safe_strcat(path, token, MAX_PATH);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcat(path, PATHSEP);
|
safe_strcat(path, PATHSEP,MAX_PATH);
|
||||||
strcat(path, token);
|
safe_strcat(path, token,MAX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsFolder(path)==FALSE)
|
if(IsFolder(path)==FALSE)
|
||||||
|
@ -1464,7 +1497,9 @@ BOOL CUnAlz::FOpen(const char* szPathName)
|
||||||
m_bIsEOF = FALSE;
|
m_bIsEOF = FALSE;
|
||||||
for(i=0;i<MAX_FILES;i++) // aa.alz 파일명을 가지고 aa.a00 aa.a01 aa.a02 .. 만들기
|
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);
|
if(i>0)
|
||||||
|
safe_sprintf(temp+nLen-3, 4, "%c%02d", (i-1)/100+'a', (i-1)%100);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
m_files[i].fp = CreateFileA(temp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
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;
|
if(m_files[i].fp==INVALID_HANDLE_VALUE) break;
|
||||||
|
@ -1689,7 +1724,6 @@ BOOL CUnAlz::chkValidPassword()
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// from CZipArchive
|
// from CZipArchive
|
||||||
// Copyright (C) 2000 - 2004 Tadeusz Dracz
|
// Copyright (C) 2000 - 2004 Tadeusz Dracz
|
||||||
|
@ -1756,7 +1790,6 @@ UINT32 CUnAlz::CryptCRC32(UINT32 l, CHAR c)
|
||||||
const ULONG *CRC_TABLE = get_crc_table();
|
const ULONG *CRC_TABLE = get_crc_table();
|
||||||
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
|
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1877,8 +1910,21 @@ void CUnAlz::DecryptingData(int nSize, BYTE* data)
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
UINT32 CUnAlz::CRC32(UINT32 l, BYTE c)
|
UINT32 CUnAlz::CRC32(UINT32 l, BYTE c)
|
||||||
{
|
{
|
||||||
const ULONG *CRC_TABLE = get_crc_table();
|
const unsigned long *CRC_TABLE = get_crc_table();
|
||||||
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
|
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CUnAlz::SetPassword(char *passwd)
|
||||||
|
{
|
||||||
|
if(strlen(passwd) == 0) return;
|
||||||
|
safe_strcpy(m_szPasswd, passwd, UNALZ_LEN_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _UNALZ_ICONV
|
||||||
|
void CUnAlz::SetDestCodepage(const char* szToCodepage)
|
||||||
|
{
|
||||||
|
safe_strcpy(m_szToCodepage, szToCodepage, UNALZ_LEN_CODEPAGE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
74
UnAlz.h
74
UnAlz.h
|
@ -1,12 +1,41 @@
|
||||||
/*
|
/*
|
||||||
|
UNALZ : read and extract module for ALZ format.
|
||||||
|
|
||||||
COPYRIGHT(C) 2004-2006 hardkoder@gmail , http://www.kipple.pe.kr
|
LICENSE (zlib License)
|
||||||
|
Copyright (C) 2004-2005 hardkoder@gmail , http://www.kipple.pe.kr
|
||||||
|
|
||||||
저작권 정보 : ( BSD License )
|
This software is provided 'as-is', without any express or implied
|
||||||
- 이 소스는 자유로이 사용/수정/재배포 가능합니다.
|
warranty. In no event will the authors be held liable for any damages
|
||||||
- 단, 당신이 만들었다고 주장하거나 거짓말하면 안됨.
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
이 소프트웨어는 어떠한 명시적 또는 묵시적 보증도 없이 "있는 그대로" 제공됩니다. 그
|
||||||
|
어떤 경우에도 작성자는 이 소프트웨어의 사용으로 인한 손해에 대해 책임을 지지 않습니다.
|
||||||
|
|
||||||
|
다음 제한 규정을 준수하는 경우에 한하여 상업적인 응용 프로그램을 포함하는 모든 용도로 이 소프트웨어를
|
||||||
|
사용하고 자유롭게 수정 및 재배포할 수 있는 권한이 누구에게나 부여됩니다.
|
||||||
|
|
||||||
|
1. 이 소프트웨어의 출처를 잘못 표시하거나 원래 소프트웨어를 자신이 작성했다고 주장해서는 안 됩니다. 제품에
|
||||||
|
이 소프트웨어를 사용하는 경우 요구 사항은 아니지만 제품 설명서에 인정 조항을 넣어 주시면 감사하겠습니다.
|
||||||
|
2. 수정된 소스 버전은 반드시 명확하게 표시되어야 하며 원래 소프트웨어로 오인되도록 잘못 표시해서는 안 됩니다.
|
||||||
|
3. 모든 소스 배포 시 이 공지를 삭제하거나 수정할 수 없습니다.
|
||||||
|
|
||||||
|
=============================================================================================================
|
||||||
|
|
||||||
|
권장사항 :
|
||||||
- 소스의 오류를 찾았거나, 문제점을 수정하였을 경우 이에 대한 내용을 알려주면 정말 고마울껄..
|
- 소스의 오류를 찾았거나, 문제점을 수정하였을 경우 이에 대한 내용을 알려주면 정말 고마울껄..
|
||||||
- 자신의 프로그램에 이 소스를 사용하였을 경우 원 저작자에게 알려주면 원 저작자가 고마워 할껄..
|
- 자신의 프로그램에 이 소스를 사용하였을 경우 나한테 메일한통 때려주면 내가 고마워 할껄..
|
||||||
|
|
||||||
소스 설명 :
|
소스 설명 :
|
||||||
- .ALZ 의 압축을 해제하기 위한 모듈.
|
- .ALZ 의 압축을 해제하기 위한 모듈.
|
||||||
|
@ -49,7 +78,7 @@
|
||||||
- 암호걸린 파일과 안걸린 파일 섞였을때 처리
|
- 암호걸린 파일과 안걸린 파일 섞였을때 처리
|
||||||
- 파일의 뒷부분이 잘려서 손상된 파일도 멀쩡한 부분까지는 압축을 풀도록 수정
|
- 파일의 뒷부분이 잘려서 손상된 파일도 멀쩡한 부분까지는 압축을 풀도록 수정
|
||||||
- unalz 0.31
|
- unalz 0.31
|
||||||
2005/01/08 - 암호 잘못 입력시 한번 체크후 두번째는 정상 암호를 입력해서 풀지 못하게 되던 버그 수정
|
2005/01/08 - 암호 잘못 입력시 한번 체크후 두번째는 정상 암호를 입력해도 풀지 못하게 되던 버그 수정
|
||||||
2005/02/05 - 압축 해제후 deflate 의 파일 CRC 확인 기능 추가
|
2005/02/05 - 압축 해제후 deflate 의 파일 CRC 확인 기능 추가
|
||||||
2005/03/07 - bzip2, raw 파일에 대한 파일 CRC 확인 기능 추가
|
2005/03/07 - bzip2, raw 파일에 대한 파일 CRC 확인 기능 추가
|
||||||
2005/03/13 - ALZ 파일이 아닐경우 에러 코드(ERR_NOT_ALZ_FILE) 추가
|
2005/03/13 - ALZ 파일이 아닐경우 에러 코드(ERR_NOT_ALZ_FILE) 추가
|
||||||
|
@ -75,6 +104,9 @@
|
||||||
- unalz 0.53
|
- unalz 0.53
|
||||||
2006/03/10 - .. 폴더 관련 보안 문제 수정 (by vuln@secunia )
|
2006/03/10 - .. 폴더 관련 보안 문제 수정 (by vuln@secunia )
|
||||||
- unalz 0.55
|
- unalz 0.55
|
||||||
|
2006/04/23 - 엔디안 처리를 런타임에 하도록 수정
|
||||||
|
2006/12/31 - strcpy/strcat/sprintf 와 같은 버퍼 오버플로우 가능성이 있는 함수 제거 (by liam.joo@gmail)
|
||||||
|
- unalz 0.60
|
||||||
|
|
||||||
기능 :
|
기능 :
|
||||||
- alz 파일의 압축 해제 (deflate/변형 bzip2/raw)
|
- alz 파일의 압축 해제 (deflate/변형 bzip2/raw)
|
||||||
|
@ -142,9 +174,6 @@ using namespace std;
|
||||||
#ifndef LONG
|
#ifndef LONG
|
||||||
typedef long LONG;
|
typedef long LONG;
|
||||||
#endif
|
#endif
|
||||||
#ifndef ULONG
|
|
||||||
typedef unsigned long ULONG; // same as DWORD? i don't know.
|
|
||||||
#endif
|
|
||||||
#ifndef BOOL
|
#ifndef BOOL
|
||||||
# ifndef BOOL_DEFINED // 이미 BOOL 이 DEFINE 되어 있으면 BOOL_DEFINED 를 define 해서 컴파일 에러를 막을 수 있다.
|
# ifndef BOOL_DEFINED // 이미 BOOL 이 DEFINE 되어 있으면 BOOL_DEFINED 를 define 해서 컴파일 에러를 막을 수 있다.
|
||||||
typedef int BOOL;
|
typedef int BOOL;
|
||||||
|
@ -181,7 +210,7 @@ namespace UNALZ
|
||||||
# pragma pack(1)
|
# pragma pack(1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char UNALZ_VERSION[] = "CUnAlz0.55";
|
static const char UNALZ_VERSION[] = "CUnAlz0.60";
|
||||||
static const char UNALZ_COPYRIGHT[] = "Copyright(C) 2004-2006 by hardkoder@gmail ( http://www.kipple.pe.kr ) ";
|
static const char UNALZ_COPYRIGHT[] = "Copyright(C) 2004-2006 by hardkoder@gmail ( http://www.kipple.pe.kr ) ";
|
||||||
|
|
||||||
enum {ENCR_HEADER_LEN=12}; // xf86
|
enum {ENCR_HEADER_LEN=12}; // xf86
|
||||||
|
@ -256,15 +285,6 @@ struct _SLocalFileHeaderHead ///<
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
struct _SDataDescriptor
|
|
||||||
{
|
|
||||||
UINT32 crc32;
|
|
||||||
UINT32 compressed;
|
|
||||||
UINT32 uncompressed;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct SLocalFileHeader
|
struct SLocalFileHeader
|
||||||
{
|
{
|
||||||
SLocalFileHeader() { memset(this, 0, sizeof(*this)); }
|
SLocalFileHeader() { memset(this, 0, sizeof(*this)); }
|
||||||
|
@ -281,7 +301,6 @@ struct SLocalFileHeader
|
||||||
|
|
||||||
CHAR* fileName;
|
CHAR* fileName;
|
||||||
BYTE* extraField;
|
BYTE* extraField;
|
||||||
// _SDataDescriptor dataDescriptor;
|
|
||||||
INT64 dwFileDataPos; ///< file data 가 저장된 위치..
|
INT64 dwFileDataPos; ///< file data 가 저장된 위치..
|
||||||
|
|
||||||
BYTE encChk[ENCR_HEADER_LEN]; // xf86
|
BYTE encChk[ENCR_HEADER_LEN]; // xf86
|
||||||
|
@ -360,7 +379,7 @@ struct SEndOfCentralDirectoryRecord
|
||||||
|
|
||||||
|
|
||||||
///< PROGRESS CALLBACK FUNCTION - 압축 해제 진행 상황을 알고 싶으면 이걸 쓰면 된다.
|
///< PROGRESS CALLBACK FUNCTION - 압축 해제 진행 상황을 알고 싶으면 이걸 쓰면 된다.
|
||||||
typedef void (_UnAlzCallback)(const char* szMessage, INT64 nCurrent, INT64 nRange, void* param, BOOL* bHalt);
|
typedef void (_UnAlzCallback)(const char* szFileName, INT64 nCurrent, INT64 nRange, void* param, BOOL* bHalt);
|
||||||
|
|
||||||
|
|
||||||
class CUnAlz
|
class CUnAlz
|
||||||
|
@ -377,12 +396,12 @@ public:
|
||||||
void SetCallback(_UnAlzCallback* pFunc, void* param=NULL);
|
void SetCallback(_UnAlzCallback* pFunc, void* param=NULL);
|
||||||
void SetPipeMode(BOOL bPipeMode) {m_bPipeMode=bPipeMode;}
|
void SetPipeMode(BOOL bPipeMode) {m_bPipeMode=bPipeMode;}
|
||||||
|
|
||||||
void setPassword(char *passwd) { if(strlen(passwd) == 0) return; strcpy(m_szPasswd, passwd); }; // xf86
|
void SetPassword(char *passwd); // xf86
|
||||||
BOOL chkValidPassword(); // xf86
|
BOOL chkValidPassword(); // xf86
|
||||||
BOOL IsEncrypted() { return m_bIsEncrypted; };
|
BOOL IsEncrypted() { return m_bIsEncrypted; };
|
||||||
|
|
||||||
#ifdef _UNALZ_ICONV
|
#ifdef _UNALZ_ICONV
|
||||||
void SetDestCodepage(const char* szToCodepage) { strcpy(m_szToCodepage, szToCodepage); }
|
void SetDestCodepage(const char* szToCodepage);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public : ///< WIN32 전용 ( UNICODE 처리용 )
|
public : ///< WIN32 전용 ( UNICODE 처리용 )
|
||||||
|
@ -534,7 +553,8 @@ private : //
|
||||||
|
|
||||||
BOOL m_bIsEncrypted; // xf86
|
BOOL m_bIsEncrypted; // xf86
|
||||||
BOOL m_bIsDataDescr;
|
BOOL m_bIsDataDescr;
|
||||||
char m_szPasswd[512];
|
#define UNALZ_LEN_PASSWORD 512
|
||||||
|
char m_szPasswd[UNALZ_LEN_PASSWORD];
|
||||||
BOOL m_bPipeMode; ///< pipemode - 메시지 출력없이 stdout 으로만 출력
|
BOOL m_bPipeMode; ///< pipemode - 메시지 출력없이 stdout 으로만 출력
|
||||||
|
|
||||||
private :
|
private :
|
||||||
|
@ -568,8 +588,10 @@ private :
|
||||||
BOOL m_bHalt;
|
BOOL m_bHalt;
|
||||||
|
|
||||||
#ifdef _UNALZ_ICONV
|
#ifdef _UNALZ_ICONV
|
||||||
char m_szToCodepage[256]; ///< codepage
|
|
||||||
char m_szFromCodepage[256]; ///< "CP949"
|
#define UNALZ_LEN_CODEPAGE 256
|
||||||
|
char m_szToCodepage[UNALZ_LEN_CODEPAGE]; ///< codepage
|
||||||
|
char m_szFromCodepage[UNALZ_LEN_CODEPAGE]; ///< "CP949"
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,7 +279,6 @@ Int32 BZ2_decompress ( DState* s )
|
||||||
GET_UCHAR(BZ_X_BLKHDR_1, uc);
|
GET_UCHAR(BZ_X_BLKHDR_1, uc);
|
||||||
|
|
||||||
// [ALZ] - º¯ÇüµÈ Çì´õ
|
// [ALZ] - º¯ÇüµÈ Çì´õ
|
||||||
|
|
||||||
if (uc != 'D')
|
if (uc != 'D')
|
||||||
RETURN(BZ_DATA_ERROR_MAGIC);
|
RETURN(BZ_DATA_ERROR_MAGIC);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "UnAlzUtils.h"
|
#include "UnAlzUtils.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32 // safe string ó¸®
|
||||||
|
# include "strsafe.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define I64FORM(x) "%"#x"I64d"
|
# define I64FORM(x) "%"#x"I64d"
|
||||||
|
@ -11,6 +14,8 @@
|
||||||
# define U64FORM(x) "%"#x"llu"
|
# define U64FORM(x) "%"#x"llu"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define LEN_ATTR 6
|
||||||
|
|
||||||
time_t dosTime2TimeT(UINT32 dostime) // from INFO-ZIP src
|
time_t dosTime2TimeT(UINT32 dostime) // from INFO-ZIP src
|
||||||
{
|
{
|
||||||
struct tm t;
|
struct tm t;
|
||||||
|
@ -24,6 +29,16 @@ time_t dosTime2TimeT(UINT32 dostime) // from INFO-ZIP src
|
||||||
return mktime(&t);
|
return mktime(&t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void safe_strcat(char* dst, const char* src, size_t dst_size)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
StringCchCatExA(dst, dst_size, src, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
|
||||||
|
//lstrcatA(dst, src); // not safe!!
|
||||||
|
#else
|
||||||
|
strlcat(dst, src, dst_size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// fileAttribute 를 스트링으로 바꿔준다.
|
/// fileAttribute 를 스트링으로 바꿔준다.
|
||||||
/// @param buf - 5byte 이상
|
/// @param buf - 5byte 이상
|
||||||
|
@ -31,29 +46,29 @@ time_t dosTime2TimeT(UINT32 dostime) // from INFO-ZIP src
|
||||||
/// @return
|
/// @return
|
||||||
/// @date 2005-06-23 오후 10:12:35
|
/// @date 2005-06-23 오후 10:12:35
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
void FileAttr2Str(char* buf, BYTE fileAttribute)
|
void FileAttr2Str(char szAttr[LEN_ATTR], BYTE fileAttribute)
|
||||||
{
|
{
|
||||||
buf[0] = 0;
|
szAttr[0] = 0;
|
||||||
|
|
||||||
if(fileAttribute&ALZ_FILEATTR_FILE)
|
if(fileAttribute&ALZ_FILEATTR_FILE)
|
||||||
strcat(buf, "A");
|
safe_strcat(szAttr, "A", LEN_ATTR);
|
||||||
else
|
else
|
||||||
strcat(buf, "_");
|
safe_strcat(szAttr, "_", LEN_ATTR);
|
||||||
|
|
||||||
if(fileAttribute&ALZ_FILEATTR_DIRECTORY)
|
if(fileAttribute&ALZ_FILEATTR_DIRECTORY)
|
||||||
strcat(buf, "D");
|
safe_strcat(szAttr, "D", LEN_ATTR);
|
||||||
else
|
else
|
||||||
strcat(buf, "_");
|
safe_strcat(szAttr, "_", LEN_ATTR);
|
||||||
|
|
||||||
if(fileAttribute&ALZ_FILEATTR_READONLY)
|
if(fileAttribute&ALZ_FILEATTR_READONLY)
|
||||||
strcat(buf, "R");
|
safe_strcat(szAttr, "R", LEN_ATTR);
|
||||||
else
|
else
|
||||||
strcat(buf, "_");
|
safe_strcat(szAttr, "_", LEN_ATTR);
|
||||||
|
|
||||||
if(fileAttribute&ALZ_FILEATTR_HIDDEN)
|
if(fileAttribute&ALZ_FILEATTR_HIDDEN)
|
||||||
strcat(buf, "H");
|
safe_strcat(szAttr, "H", LEN_ATTR);
|
||||||
else
|
else
|
||||||
strcat(buf, "_");
|
safe_strcat(szAttr, "_", LEN_ATTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +87,7 @@ int ListAlz(CUnAlz* pUnAlz, const char* src)
|
||||||
|
|
||||||
// char szDate[64];
|
// char szDate[64];
|
||||||
char szTime[64];
|
char szTime[64];
|
||||||
char szAttr[6];
|
char szAttr[LEN_ATTR];
|
||||||
UINT64 totalUnCompressedSize = 0;
|
UINT64 totalUnCompressedSize = 0;
|
||||||
UINT64 totalCompressedSize = 0;
|
UINT64 totalCompressedSize = 0;
|
||||||
unsigned fileNum = 0;
|
unsigned fileNum = 0;
|
||||||
|
|
|
@ -1444,8 +1444,13 @@ BZFILE * bzopen_or_bzdopen
|
||||||
}
|
}
|
||||||
mode++;
|
mode++;
|
||||||
}
|
}
|
||||||
|
#ifndef __OpenBSD__
|
||||||
strcat(mode2, writing ? "w" : "r" );
|
strcat(mode2, writing ? "w" : "r" );
|
||||||
strcat(mode2,"b"); /* binary mode */
|
strcat(mode2,"b"); /* binary mode */
|
||||||
|
#else // by liam.joo@gmail 2006/12
|
||||||
|
strlcat(mode2, writing ? "w" : "r", sizeof(mode2) );
|
||||||
|
strlcat(mode2,"b",sizeof(mode2));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (open_mode==0) {
|
if (open_mode==0) {
|
||||||
if (path==NULL || strcmp(path,"")==0) {
|
if (path==NULL || strcmp(path,"")==0) {
|
||||||
|
|
31
main.cpp
31
main.cpp
|
@ -28,7 +28,8 @@ void Copyright()
|
||||||
// printf("unalz v0.52 (2005/07/27) \n");
|
// printf("unalz v0.52 (2005/07/27) \n");
|
||||||
// printf("unalz v0.53 (2005/10/15) \n");
|
// printf("unalz v0.53 (2005/10/15) \n");
|
||||||
// printf("unalz v0.54 (2005/11/21) \n");
|
// printf("unalz v0.54 (2005/11/21) \n");
|
||||||
printf("unalz v0.55 (2006/03/10) \n");
|
// printf("unalz v0.55 (2006/03/10) \n");
|
||||||
|
printf("unalz v0.60 (2006/12/31) \n");
|
||||||
printf("Copyright(C) 2004-2006 by hardkoder@gmail (http://www.kipple.pe.kr) \n");
|
printf("Copyright(C) 2004-2006 by hardkoder@gmail (http://www.kipple.pe.kr) \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,25 +82,26 @@ void Usage()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void UnAlzCallback(const char* szMessage, INT64 nCurrent, INT64 nRange, void* param, BOOL* bHalt)
|
void UnAlzCallback(const char* szFileName, INT64 nCurrent, INT64 nRange, void* param, BOOL* bHalt)
|
||||||
{
|
{
|
||||||
if(g_bPipeMode) return; // slient
|
if(g_bPipeMode) return; // slient
|
||||||
|
|
||||||
|
#define MSG_BUF_LEN 1024
|
||||||
// progress
|
// progress
|
||||||
static char szFileName[1024]={0};
|
static char szMessage[MSG_BUF_LEN]={0};
|
||||||
INT64 percent;
|
|
||||||
static INT64 nPrevPercent = -1;
|
static INT64 nPrevPercent = -1;
|
||||||
|
INT64 percent;
|
||||||
|
|
||||||
// 파일명 출력..
|
// 파일명 출력..
|
||||||
if(szMessage)
|
if(szMessage)
|
||||||
{
|
{
|
||||||
printf("\n");
|
printf("\n");
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
sprintf(szFileName, "unalziiiing : %s (%I64dbytes) ", szMessage, nRange);
|
_snprintf(szMessage, MSG_BUF_LEN, "unalziiiing : %s (%I64dbytes) ", szFileName, nRange);
|
||||||
#else
|
#else
|
||||||
sprintf(szFileName, "unalziiiing : %s (%lldbytes) ", szMessage, nRange);
|
snprintf(szMessage, MSG_BUF_LEN, "unalziiiing : %s (%lldbytes) ", szFileName, nRange);
|
||||||
#endif
|
#endif
|
||||||
printf("%s", szFileName);
|
printf("%s", szMessage);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
nPrevPercent = -1;
|
nPrevPercent = -1;
|
||||||
return;
|
return;
|
||||||
|
@ -113,17 +115,6 @@ void UnAlzCallback(const char* szMessage, INT64 nCurrent, INT64 nRange, void* pa
|
||||||
printf(".");
|
printf(".");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
/*
|
|
||||||
char buf[1024];
|
|
||||||
#ifdef _WIN32
|
|
||||||
sprintf(buf, "\r%s %I64d/%I64d (%I64d%%)", szFileName, nCurrent, nRange, percent);
|
|
||||||
#else
|
|
||||||
// sprintf(buf, "\r%s %d/%d (%d%%)", szMessage, (int)nCurrent, (int)nRange, (int)percent); // int64 를 출력할라면 어찌해야 되는지?
|
|
||||||
sprintf(buf, "\r%s %lld/%lld (%lld%%)", szFileName, nCurrent, Range, percent);
|
|
||||||
#endif
|
|
||||||
puts(buf);
|
|
||||||
fflush(stdout);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -277,14 +268,14 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if(password) // command line 으로 암호가 지정되었을 경우.
|
if(password) // command line 으로 암호가 지정되었을 경우.
|
||||||
{
|
{
|
||||||
unalz.setPassword(password);
|
unalz.SetPassword(password);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char pwd[256];
|
char pwd[256];
|
||||||
printf("Enter Password : ");
|
printf("Enter Password : ");
|
||||||
fgets(pwd,256,stdin);
|
fgets(pwd,256,stdin);
|
||||||
unalz.setPassword(pwd);
|
unalz.SetPassword(pwd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
|
|
||||||
|
|
||||||
unalz v0.5
|
unalz v0.60
|
||||||
|
|
||||||
Copyright(C) 2004-2005 by hardkoder (http://www.kipple.pe.kr)
|
Copyright(C) 2004-2006 by hardkoder (http://www.kipple.pe.kr)
|
||||||
|
|
||||||
|
|
||||||
- 최초 작성일 : v0.20 - 2004/10/22
|
- 최초 작성일 : v0.20 - 2004/10/22
|
||||||
|
|
||||||
|
|
||||||
- 라이선스
|
- 라이선스
|
||||||
. 자유로이 변형/배포 가능 (BSD-license)
|
. 자유로이 변형/배포 가능 (zlib-license)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue