#include "StdAfx.h"
#include "updatemanager.h"
//#include "../RarLib/Rar.h"
//#include "RYLLoginDlg.h"
#include "../GlobalScript/Utility/CheckSum/Crc32Static.h"
#include "RYLLOGIN_DEFINITIONS.H"

#include "ZipArchive.h"

#include "Patch_Util.h"


//DWORD *CUpdateManager::m_dwZipTotalCount = NULL;
//DWORD *CUpdateManager::m_dwZipNowCount = NULL;

CGradientStatic *CUpdateManager::m_pInfoWnd = NULL;
CWnd			*CUpdateManager::m_pDisplayWnd = NULL;
BOOL			CUpdateManager::m_bUpdateLogin = FALSE;


CUpdateManager::CUpdateManager(void)
{
	m_bServerClosed = false;
	
	m_pDisplayState = NULL;
	
	m_nVersion = -1;

	m_bUpdateLogin = FALSE;

	m_pfProgressPercentage = NULL;
	m_pfFileProgressPercentage = NULL;

	m_bTerminate = false;
}

CUpdateManager::~CUpdateManager(void)
{

}



void CUpdateManager::Init()
{
	m_HTTPFile.Init();

	// 강제종료 플래그
	m_bTerminate = false;
}


//bool IsDirectoryExist( const char* szDirectoryName )
//{
//	DWORD dwAttr = ::GetFileAttributes( szDirectoryName );
//
//	
//	if( dwAttr == 0xFFFFFFFF )
//		return false;	// file not exists ?
//
//	if( dwAttr & FILE_ATTRIBUTE_DIRECTORY )
//		return true;
//
//	return false;	// exists but not a directory
//}

bool CUpdateManager::ProcessNoticeFiles()
{
	//////////////////////////////////////////////////////////////////////////
	// 공지사항 파일의 전송 및 압축해제

	CString strNoticeRoot;
	CString strNoticePath, strNoticeClientPath, strFilename;
	std::vector< int > vecNoticeVer;
	
	// 업데이트 버전을 근거로 공지사항 목록(받아할 파일이름 리스트) 생성
	strNoticeRoot = m_strServerPath + "/Notice";		// By Belldandy(2005.02.02)
	
	strNoticePath.Format( "%s/NoticeInfo.dat", strNoticeRoot );
	strNoticeClientPath.Format( "%s/NoticeInfo.dat", m_strRootPath );
	bool bRet = m_HTTPFile.TransferFile( strNoticePath, strNoticeClientPath, "NoticeInfo.dat" );
	
	FILE* fp = fopen( strNoticeClientPath, "r" );
	if( NULL == fp )
	{
		// NoticeInfo.dat 가 없을 경우,
		// 지금은 단순히 빠져나가는 식으로 처리하지만 추후엔 별도로 파일 목록을
		// FTP로 부터 긁어와 최근 파일을 얻는 식으로 처리도 생각해 볼 수 있겠지?
		AfxMessageBox( RYLLoginGetMessage( LOGIN_MSG_FAIL_TO_GET_NOTICEINFO ) );
		return false;
	}
	
	int nNoticeVersion = 0;
	bool bAddAfterAll = false;
	CString strTmp;
	while( !feof(fp) )
	{
		int nReadCount = fscanf( fp, "%d", &nNoticeVersion );

		// NoticeInfo.dat 말미 공백시 마지막 버전번호가 중복해 들어가는 문제 해결을 위해
		if( nReadCount < 1 )
		{
			break;
		}

		if( nNoticeVersion <= 0 )
		{
			// versioninfo.dat 파일이 깨진 경우
			AfxMessageBox( RYLLoginGetMessage( LOGIN_MSG_FAIL_TO_GET_NOTICEINFO ) );
			return false;
		}

		strTmp.Format( "%s/Notice/%d", m_strRootPath, nNoticeVersion );
		if( !IsDirectoryExist(strTmp) )
		{
			bAddAfterAll = true;
		}

		if( bAddAfterAll )
		{
			vecNoticeVer.push_back( nNoticeVersion );
		}
	}
	fclose( fp );
	DeleteFile( strNoticeClientPath );
	
	DWORD dwNoticeTotalSize = 0;
	int cDown;
	// notice 파일 전송
	for( cDown=0; cDown < vecNoticeVer.size(); cDown++ )
	{
		if( m_bTerminate )
		{
			// 강제종료
			return false;
		}

		strNoticePath.Format( "%s/%dNotice.zip", strNoticeRoot, vecNoticeVer[cDown] );
		strNoticeClientPath.Format( "%s/%dNotice.zip", m_strRootPath, vecNoticeVer[cDown] );
		strFilename.Format( "%dNotice.zip", vecNoticeVer[cDown] );
		
		m_HTTPFile.TransferFile( strNoticePath, strNoticeClientPath, strFilename );

		// notice 파일 전송에 5% 할당		
		*m_pfProgressPercentage = (cDown*5.0f) / vecNoticeVer.size();
		CRect rcUpdate;
		rcUpdate.left = 31;
		rcUpdate.top = 427;
		rcUpdate.right = 31 + 464;
		rcUpdate.bottom = 427 + 16;
		m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
	}
	
	// notice 파일 압축 해제
	CZipArchive zipArc;
	for( cDown = 0; cDown < vecNoticeVer.size(); ++cDown )
	{
		if( m_bTerminate )
		{
			for( cDown = 0; cDown < vecNoticeVer.size(); ++cDown )
			{
				strNoticeClientPath.Format( "%s/%dNotice.zip", m_strRootPath, vecNoticeVer[cDown] );
				DeleteFile( strNoticeClientPath );
			}
			// 강제종료
			return false;
		}
		
		strNoticeClientPath.Format( "%s/%dNotice.zip", m_strRootPath, vecNoticeVer[cDown] );
		
		try
		{
			zipArc.Open( strNoticeClientPath, CZipArchive::zipOpen );
		}
		catch(CException* e)
		{
			if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
			{
				CZipException* p = (CZipException*) e;

				//if( CZipException::badZipFile == p->m_iCause )
				{
					CString strTmp;
					strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
					AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
				}
			}
			
			e->Delete();
			exit(0);
		}

		for( int i = 0; i < zipArc.GetCount(); ++i )
		{
			CZipFileHeader zfh;
			zipArc.GetFileInfo( zfh, (WORD)i );

			try
			{
				zipArc.ExtractFile( (WORD)i, m_strRootPath+"\\Notice" );
			}
			catch(CException* e)
			{
				if( e->IsKindOf( RUNTIME_CLASS(CFileException) ) )
				{
					CFileException* p = (CFileException*) e;

					if( CFileException::accessDenied == p->m_cause )
					{
//						DWORD dwAttr = GetFileAttributes( p->m_strFileName );
//						if( dwAttr & FILE_ATTRIBUTE_SYSTEM )
//						{
//							dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
//							SetFileAttributes( p->m_strFileName, dwAttr );
//						}
//
//						if( dwAttr & FILE_ATTRIBUTE_HIDDEN )
//						{
//							dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
//							SetFileAttributes( p->m_strFileName, dwAttr );
//						}
//
//						if( dwAttr & FILE_ATTRIBUTE_READONLY )
//						{
//							dwAttr &= (~FILE_ATTRIBUTE_READONLY);
//							SetFileAttributes( p->m_strFileName, dwAttr );
//						}
//
//						DeleteFile( p->m_strFileName );
//						zipArc.ExtractFile( (WORD)i, m_strRootPath+"\\Notice" );
					}
				}

				e->Delete();
			}
		}
		
		zipArc.Close();
		
		DeleteFile( strNoticeClientPath );

		// notice 파일 압축 해제에 5% 할당
		*m_pfProgressPercentage =  (cDown*5.0f) / vecNoticeVer.size() + 5.0f;
		CRect rcUpdate;
		rcUpdate.left = 31;
		rcUpdate.top = 427;
		rcUpdate.right = 31 + 464;
		rcUpdate.bottom = 427 + 16;
		m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
	}

	return true;
}


bool CUpdateManager::LoadServerPatchInfo()
{
	m_pInfoWnd->SetWindowText( "Get Patchinfo" );
	m_pInfoWnd->Invalidate(FALSE);
	
	// PatchInfoV2.zip 파일 전송
#ifdef _NATION_JP_
	// 일본서버는 얻어온 서버주소 + "/FilePatch/" 가 패치 파일을 가져올 주소다
	// (공지주소 하드코딩을 서버에서 얻어온 주소 이용으로 바꿈)
	m_HTTPFile.TransferFile( m_strServerPath+"/FilePatch/PatchInfoV2.zip", m_strRootPath+"\\PatchInfoV2.zip", "PatchInfoV2.zip" );
#else
	m_HTTPFile.TransferFile( m_strServerPath+"/PatchInfoV2.zip", m_strRootPath+"\\PatchInfoV2.zip", "PatchInfoV2.zip" );
#endif

//	HANDLE hFile = CreateFile( m_strRootPath+"\\PatchInfo.zip",
//		GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
//		NULL, OPEN_EXISTING, 0, 0 );
//	if( INVALID_HANDLE_VALUE == hFile )
	if( false == IsFileExist( m_strRootPath+"\\PatchInfoV2.zip" ) )
	{
		// PatchInfo 파일을 받아올 수 없습니다
		AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_FAIL_TO_GET_PATCHINFO) );

		return false;
	}
	
	// 압축해제
	CZipArchive zipArc;
	try
	{
		zipArc.Open( m_strRootPath+"\\PatchInfoV2.zip", CZipArchive::zipOpen );
	}
	catch(CException* e)
	{
		if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
		{
			CZipException* p = (CZipException*) e;
			
			//if( CZipException::badZipFile == p->m_iCause )
			{
				CString strTmp;
				strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
				AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
			}
		}
		
		e->Delete();
		exit(0);
	}

	CString strTmp = m_strRootPath+"\\"+"PatchInfoV2";
	DWORD dwAttr = 0;
	dwAttr = GetFileAttributes( strTmp );
	if( 0xFFFFFFFF != dwAttr )
	{
		if( FILE_ATTRIBUTE_SYSTEM & dwAttr )
		{
			dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
			SetFileAttributes( strTmp, dwAttr );
		}
		
		if( FILE_ATTRIBUTE_HIDDEN & dwAttr )
		{
			dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
			SetFileAttributes( strTmp, dwAttr );
		}
		
		if( FILE_ATTRIBUTE_READONLY & dwAttr )
		{
			dwAttr &= (~FILE_ATTRIBUTE_READONLY);
			SetFileAttributes( strTmp, dwAttr );
		}
	}
	zipArc.ExtractFile( 0, m_strRootPath );
	zipArc.Close();
	
	// PatchInfoV2.zip 삭제
	DeleteFile( m_strRootPath+"\\PatchInfoV2.zip" );

	// PatchInfoV2 로드 후 삭제
	m_ServerFileInfoList.Reset();
	m_ServerFileInfoList.Load( m_strRootPath+"\\PatchInfoV2" );
	DeleteFile( m_strRootPath+"\\PatchInfoV2" );


	// 서버측 patchinfo 전송에 5%할당
	*m_pfProgressPercentage =  15.0f;
	CRect rcUpdate;
	rcUpdate.left = 31;
	rcUpdate.top = 427;
	rcUpdate.right = 31 + 464;
	rcUpdate.bottom = 427 + 16;
	m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );

	return true;
}


//bool CUpdateManager::LoadLocalPatchInfoCache()
//{
//	// 목록 캐시파일이 존재하는지 체크해 불러옴, 없으면 생성
//	HANDLE hFile = CreateFile( m_strRootPath+"\\PatchInfo.cache",
//		GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
//		NULL, OPEN_EXISTING, 0, 0 );
//	if( INVALID_HANDLE_VALUE != hFile )
//	{
//		CloseHandle(hFile);
//		
//		CZipArchive zipArc;
//		try
//		{
//			zipArc.Open( m_strRootPath+"\\PatchInfo.cache", CZipArchive::zipOpen );
//		}
//		catch(CException* e)
//		{
//			if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
//			{
//				CZipException* p = (CZipException*) e;
//				
//				//if( CZipException::badZipFile == p->m_iCause )
//				{
//					CString strTmp;
//					strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
//					AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
//				}
//			}
//			
//			e->Delete();
//			exit(0);
//		}
//
//		CString strTmp = m_strRootPath+"\\"+"PatchInfo.local";
//		DWORD dwAttr = 0;
//		dwAttr = GetFileAttributes( strTmp );
//		if( 0xFFFFFFFF != dwAttr )
//		{
//			if( FILE_ATTRIBUTE_SYSTEM & dwAttr )
//			{
//				dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
//				SetFileAttributes( strTmp, dwAttr );
//			}
//			
//			if( FILE_ATTRIBUTE_HIDDEN & dwAttr )
//			{
//				dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
//				SetFileAttributes( strTmp, dwAttr );
//			}
//			
//			if( FILE_ATTRIBUTE_READONLY & dwAttr )
//			{
//				dwAttr &= (~FILE_ATTRIBUTE_READONLY);
//				SetFileAttributes( strTmp, dwAttr );
//			}
//		}
//		zipArc.ExtractFile( 0, m_strRootPath );
//		zipArc.Close();
//		
//		if( false == m_LocalFileInfoList.Load( m_strRootPath+"\\PatchInfo.local" ) )
//		{
//			if( false == CreateFileInfoCache() )
//			{ 
//				return false;
//			}
//		}
//	}
//	else
//	{
//		if( false == CreateFileInfoCache() )
//		{
//			return false;
//		}
//	}
//	
//
//	// 로컬 파일명으로의 quickfind용 인덱스 맵
//	int nTotal = m_LocalFileInfoList.GetList().GetSize();
//	CString strProgress;
//	for( int i = 0; i < nTotal; ++i )
//	{
//		if( m_bTerminate )
//		{
//			// 강제종료
//			return false;
//		}
//
//		LocalFileInfoRecord &rLfir = m_LocalFileInfoList.GetList()[i];
//
//		m_mapLocalFileName2Index[ CString(rLfir.szFileName) ] = i;
//
//		if( !(i % 100) )
//		{
//			strProgress.Format( "[%d/%d] Building quick search index", i, nTotal );
//			m_pInfoWnd->SetWindowText( strProgress );
//			m_pInfoWnd->Invalidate( FALSE );
//			
//			*m_pfFileProgressPercentage = (100.0f*i) / nTotal;
//			CRect rect;
//			rect.left = 22;
//			rect.right = 536;
//			rect.top = 405;
//			rect.bottom = 440;
//			m_pDisplayWnd->InvalidateRect( rect, FALSE );
//		}
//	}
//
//
//	// 로컬측 patchinfo (생성+)로딩에 15%할당
//	*m_pfProgressPercentage =  30.0f;
//	CRect rcUpdate;
//	rcUpdate.left = 31;
//	rcUpdate.top = 427;
//	rcUpdate.right = 31 + 464;
//	rcUpdate.bottom = 427 + 16;
//	m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
//
//	return true;
//}


void CUpdateManager::AddToPkg2FileNameBucket( char* szPkgName, char* szFileName )
{
	std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;
	std::vector< char* > * pVec;

	it = m_mapPackageName2FileNameVectorPtr.find( szPkgName );
	
	if( m_mapPackageName2FileNameVectorPtr.end() == it )
	{
		pVec = new std::vector< char* >;
		pVec->push_back( szFileName );
		m_mapPackageName2FileNameVectorPtr[szPkgName] = pVec;
	}
	else
	{
		pVec = it->second;
		pVec->push_back( szFileName );
	}
}


bool CUpdateManager::CollectDownloadFileList( bool bFileCheckMode )
{
	// 서버측 파일정보 리스트와 로컬측 파일정보 리스트를 비교, 업데이트가 필요한
	// 파일의 목록을 얻어냄
	int i;

	int nTotal = m_ServerFileInfoList.GetList().size();

	CString strTmp;

	for( i = 0; i < nTotal; ++i )
	{
		if( m_bTerminate )
		{
			// 강제종료
			return false;
		}
		
		FilePatchInfoRecord &rServerRecord = m_ServerFileInfoList.GetList()[i];


		if( !(i% 100) )
		{
			strTmp.Format( "[%d/%d] Comparing %s", i, nTotal, rServerRecord.szFileName );
			m_pInfoWnd->SetWindowText( strTmp );
			m_pInfoWnd->Invalidate(FALSE);
		}


		if( bFileCheckMode )
		{
			// File check mode 일 경우 -> 파일이 존재하는지, 존재한다면 CRC/size 일치하는지 체크
			CString strTmp = m_strRootPath+"\\"+rServerRecord.szFileName;
			
			if( IsFileExist( strTmp ) )
			{
				DWORD dwSize, dwCRC32;

				dwSize = GetFileSize( strTmp );
				CCrc32Static::FileCrc32Assembly( strTmp, dwCRC32 );

				if( rServerRecord.dwCRC32 != dwCRC32 || rServerRecord.dwSize != dwSize )
				{
					AddToPkg2FileNameBucket( rServerRecord.szPackageFileName, rServerRecord.szFileName );
				}
			}
			else
			{
				// 파일이 존재하지 않을경우 -> 당근 서버에서 갖구와야지
				AddToPkg2FileNameBucket( rServerRecord.szPackageFileName, rServerRecord.szFileName );
			}

		}
		else
		{
			// Normal patch mode 일 경우 -> 버전필드와 클라이언트 버전 비교
			// 서버패치파일목록의 버전필드값이 클라이언트 버전값보다 큰 경우 -> 가져와야 할 대상
			if( rServerRecord.dwVersion > m_nVersion )
			{
				AddToPkg2FileNameBucket( rServerRecord.szPackageFileName, rServerRecord.szFileName );
			}
		}

		
		if( !(i% 100) )
		{
			// 서버/로컬측 파일정보 비교에 45% 할당
			*m_pfProgressPercentage = (45.0f*i)/nTotal + 15.0f;
			*m_pfFileProgressPercentage = (i*100.0f)/nTotal;
			CRect rcUpdate;
			rcUpdate.left = 31;
			rcUpdate.top = 408;
			rcUpdate.right = 494;
			rcUpdate.bottom = 442;
			m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
		}
	}

	return true;
}


bool CUpdateManager::DownloadUpdateFile(void)
{
	//////////////////////////////////////////////////////////////////////////
	//
	// 다운로드 해야 할 압축 파일들을 전송
	//

	char* szPackageFileName;

	int nTotal = m_mapPackageName2FileNameVectorPtr.size();
	int nCounter = 0;

	// package 파일 전송
	CString strTotalCount;
	std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;

	for( it = m_mapPackageName2FileNameVectorPtr.begin();
		 it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
	{
		if( m_bTerminate )
		{
		 // 강제종료
		 return false;
		}

		szPackageFileName = it->first.m_pStr;

		strTotalCount.Format( " [ Total %d / %d files ]", ++nCounter, m_mapPackageName2FileNameVectorPtr.size() );

#ifdef _NATION_JP_
		// 일본서버는 얻어온 서버주소 + "/FilePatch/" 가 패치 파일을 가져올 주소다
		// (공지주소 하드코딩을 서버에서 얻어온 주소 이용으로 바꿈)
		m_HTTPFile.TransferFile(
			m_strServerPath+"/FilePatch/"+szPackageFileName+".zip",
			m_strRootPath+"\\"+szPackageFileName+".zip", CString(szPackageFileName)+".zip"+strTotalCount );
#else
		m_HTTPFile.TransferFile(
			m_strServerPath+"/"+szPackageFileName+".zip",
			m_strRootPath+"\\"+szPackageFileName+".zip", CString(szPackageFileName)+".zip"+strTotalCount );
#endif
		
		// 패키지 파일 전송에 20% 할당
		*m_pfProgressPercentage = (20.0f*nCounter)/nTotal + 60.0f;
		CRect rcUpdate;
		rcUpdate.left = 31;
		rcUpdate.top = 427;
		rcUpdate.right = 31 + 464;
		rcUpdate.bottom = 427 + 16;
		m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
	}

	return true;
}


bool CUpdateManager::ExtractPatchFiles()
{
	// package 파일에서 필요한 파일 압축 해제
	// 로컬캐시의 CRC, size 항목 업데이트
	// 압축해제 끝난 package 파일 삭제

	std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;
	char* szPackageFileName;
	std::vector< char* > * pVec;

	int nTotal = 0, nCounter = 0;

	// 총 업데이트할 파일 갯수 합산
	for( it = m_mapPackageName2FileNameVectorPtr.begin();
	it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
	{
		pVec = it->second;
		nTotal += pVec->size();
	}



	CString strTmp;
	CZipArchive zipArc;

	for( it = m_mapPackageName2FileNameVectorPtr.begin();
	it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
	{
		if( m_bTerminate )
		{
			// 강제종료
			return false;
		}
		
		szPackageFileName = it->first.m_pStr;
		pVec = it->second;

		// package 파일 오픈
		try
		{
			zipArc.Open( m_strRootPath+"\\"+szPackageFileName+".zip", CZipArchive::zipOpen );
		}
		catch(CException* e)
		{
			if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
			{
				CZipException* p = (CZipException*) e;
				
				//if( CZipException::badZipFile == p->m_iCause )
				{
					CString strTmp;
					strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
					AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
				}
			}
			
			e->Delete();
			exit(0);
		}

		// 압축 해제
		for( int i = 0; i < pVec->size(); ++i )
		{
			int nIdx = zipArc.FindFile( (*pVec)[i], CZipArchive::ffNoCaseSens );
			if( -1 != nIdx )
			{
				++nCounter;
				
				strTmp.Format( "[%d/%d] Extracting %s\\%s", nCounter, nTotal, (*pVec)[i], (*pVec)[i] );
				m_pInfoWnd->SetWindowText( strTmp );
				m_pInfoWnd->Invalidate(FALSE);
				
				strTmp = m_strRootPath+"\\"+(*pVec)[i];
				DWORD dwAttr = 0;
				dwAttr = GetFileAttributes( strTmp );
				if( 0xFFFFFFFF != dwAttr )
				{
					if( FILE_ATTRIBUTE_SYSTEM & dwAttr )
					{
						dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
						SetFileAttributes( strTmp, dwAttr );
					}
					
					if( FILE_ATTRIBUTE_HIDDEN & dwAttr )
					{
						dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
						SetFileAttributes( strTmp, dwAttr );
					}
					
					if( FILE_ATTRIBUTE_READONLY & dwAttr )
					{
						dwAttr &= (~FILE_ATTRIBUTE_READONLY);
						SetFileAttributes( strTmp, dwAttr );
					}
				}
				
				zipArc.ExtractFile( nIdx, m_strRootPath );
				
				// 패치 파일 추출에 20% 할당
				*m_pfProgressPercentage = (20.0f*nCounter)/nTotal + 80.0f;
				CRect rcUpdate;
				rcUpdate.left = 31;
				rcUpdate.top = 427;
				rcUpdate.right = 31 + 464;
				rcUpdate.bottom = 427 + 16;
				m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
				
				// 런처 업데이트 체크
				if( 0 == stricmp( "Login.new", (*pVec)[i] ) )
				{
					m_bUpdateLogin = TRUE;
				}
			}
		}
		
		zipArc.Close();
		
		DeleteFile( m_strRootPath+"\\"+szPackageFileName+".zip" );
	}
		

	m_nVersion = m_ServerFileInfoList.GetVersion();
	return true;
}


bool CUpdateManager::CleanUp()
{
	std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;
	std::vector< char* > * pVec;
	
	// 총 업데이트할 파일 갯수 합산
	for( it = m_mapPackageName2FileNameVectorPtr.begin();
	it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
	{
		pVec = it->second;
		delete pVec;
	}

	m_mapPackageName2FileNameVectorPtr.clear();

	return true;
}


//bool CUpdateManager::SaveLocalCache()
//{
//	// cache 파일을 저장
//	m_LocalFileInfoList.Save( m_strRootPath+"\\PatchInfo.local" );
//
//	CZipArchive zipArc;
//
//	try
//	{
//		zipArc.Open( m_strRootPath+"\\PatchInfo.cache", CZipArchive::zipCreate );
//	}
//	catch(CException* e)
//	{
//		if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
//		{
//			CZipException* p = (CZipException*) e;
//			
//			//if( CZipException::badZipFile == p->m_iCause )
//			{
//				CString strTmp;
//				strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
//				AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
//			}
//		}
//		
//		e->Delete();
//		exit(0);
//	}
//	zipArc.AddNewFile( m_strRootPath+"\\PatchInfo.local", "PatchInfo.local" );
//	zipArc.Close();
//
//	DeleteFile( m_strRootPath+"\\PatchInfo.local" );
//
//	return true;
//}


//bool CUpdateManager::CreateFileInfoCache()
//{
//	long lTotalFileCount = GetFileCountInSubDir( m_strRootPath );
//
//	WIN32_FIND_DATA w32fd;
//	
//	HANDLE hFind = FindFirstFile( m_strRootPath+"\\*.*", &w32fd );
//	
//	if( INVALID_HANDLE_VALUE == hFind )
//	{
//		return false;
//	}
//	
//	CString strCurrentSubPath("");
//	CStringArray astrSubDirList;
//	CString strFullPathName;
//	CString strTmp;
//	int nCounter = 0;
//	while( 1 )
//	{
//		if( m_bTerminate )
//		{
//			// 강제종료
//			return false;
//		}
//		
//		if( 0 != stricmp( ".", w32fd.cFileName ) &&
//			0 != stricmp( "..", w32fd.cFileName ) )
//		{
//			if( w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
//			{
//				strTmp.Format( "%s%s", strCurrentSubPath, w32fd.cFileName );
//				astrSubDirList.Add( strTmp );
//			}
//			else
//			{
//				LocalFileInfoRecord lfir;
//				++nCounter;
//				
//				strcpy( lfir.szFileName, strCurrentSubPath+w32fd.cFileName );
//				strFullPathName = m_strRootPath+"\\"+strCurrentSubPath+w32fd.cFileName;
//
//				if( !(nCounter % 30) )
//				{
//					strTmp.Format( "[%d/%d] Checking %s", nCounter, lTotalFileCount, strFullPathName );
//					m_pInfoWnd->SetWindowText( strTmp );
//					m_pInfoWnd->InvalidateRect(NULL,FALSE);
//					
//					
//					// 로컬측 patchinfo 생성에 15%할당
//					*m_pfProgressPercentage = (nCounter*15.0f)/lTotalFileCount + 15.0f;
//					*m_pfFileProgressPercentage = (nCounter*100.0f)/lTotalFileCount;
//					CRect rcUpdate;
//					rcUpdate.left = 31;
//					rcUpdate.top = 408;
//					rcUpdate.right = 494;
//					rcUpdate.bottom = 442;
//					m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
//				}
//
//				
//				CCrc32Static::FileCrc32Assembly( strFullPathName, lfir.dwCRC32 );
//				HANDLE hFile = CreateFile( strFullPathName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
//					NULL, OPEN_EXISTING, 0, 0 );
//				lfir.dwSize = GetFileSize ( hFile, NULL );
//				CloseHandle( hFile );
//				
//				m_LocalFileInfoList.GetList().Add( lfir );
//			}
//		}
//		
//		if( 0 == FindNextFile( hFind, &w32fd ) )
//		{
//			FindClose( hFind );
//			
//			// sub dir queue 에 순서를 기다리고 있는 놈이 존재하면
//			if( astrSubDirList.GetSize() > 0 )
//			{
//				// 꺼내서 쓰고
//				strCurrentSubPath = astrSubDirList[0] + "\\";
//				astrSubDirList.RemoveAt(0);
//				hFind = FindFirstFile( m_strRootPath+"\\"+strCurrentSubPath+"*.*", &w32fd );
//			}
//			else
//			{
//				// 없음 루프 종료
//				break;
//			}
//		}
//	}
//
//	// 생성 직후 한번 저장해줌
//	return SaveLocalCache();
//}


long CUpdateManager::GetFileCountInSubDir( const char* szSubDirName )
{
	WIN32_FIND_DATA w32fd;
	CString strSubDirName( szSubDirName );
	
	CString strCurrentSubPath("");
	CStringArray astrSubDirList;
	int nCounter = 0;

	
	HANDLE hFind = FindFirstFile( strSubDirName+"\\*.*", &w32fd );
	
	if( INVALID_HANDLE_VALUE == hFind )
	{
		return false;
	}
	
	while( 1 )
	{
		if( 0 != stricmp( ".", w32fd.cFileName ) &&
			0 != stricmp( "..", w32fd.cFileName ) )
		{
			if( w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
			{
				CString strTmp;
				strTmp.Format( "%s%s", strCurrentSubPath, w32fd.cFileName );
				astrSubDirList.Add( strTmp );
			}
			else
			{
				++nCounter;
			}
		}
		
		if( 0 == FindNextFile( hFind, &w32fd ) )
		{
			FindClose( hFind );
			
			// sub dir queue 에 순서를 기다리고 있는 놈이 존재하면
			if( astrSubDirList.GetSize() > 0 )
			{
				// 꺼내서 쓰고
				strCurrentSubPath = astrSubDirList[0] + "\\";
				astrSubDirList.RemoveAt(0);
				hFind = FindFirstFile( strSubDirName+"\\"+strCurrentSubPath+"*.*", &w32fd );
			}
			else
			{
				// 없음 루프 종료
				break;
			}
		}
	}

	return nCounter;
}


// case-insensitive version
//UINT AFXAPI HashKey(CString& string)
//{
//    LPCTSTR key = (LPCTSTR) string;
//    UINT nHash = 0;
//
//	TCHAR tc;
//
//    while (*key)
//	{
//		if( TCHAR('A') <= *key && *key <= TCHAR('Z') )
//		{
//			tc = *key + ( TCHAR('a') - TCHAR('A') );
//		}
//		else
//		{
//			tc = *key;
//		}
//		
//        nHash = (nHash<<5) + nHash + tc;
//
//		+++key;
//	}
//
//    return nHash;
//}























//void CUpdateManager::ProgressReport(char *pFilename, int nCount)
//{
//	static int nUpdate = 0;
//	CString strInfo;
//	
//	if( strcmp( pFilename, "Login.new" ) == 0 )
//	{
//		m_bUpdateLogin = TRUE;
//	}
//	//if( ( nUpdate++ ) % 3 == 0 )
//	{
//		
//		strInfo.Format( " %d / %d Extract File = %d", nCount, *m_dwZipTotalCount, pFilename );
//		m_pInfoWnd->SetWindowText( strInfo );
//		m_pInfoWnd->Invalidate( FALSE );
//		
//		CRect rect;
//		rect.left = 22;
//		rect.right = 536;
//		rect.top = 405;
//		rect.bottom = 440;
//		
//		m_pDisplayWnd->InvalidateRect( rect, FALSE );
//	}
//}


//void CUpdateManager::LoadClientFileInfoCacheList()
//{
//	FILE* fp;
//	
//	CString strFileName = m_strRootPath + "\\PatchInfo.cache";
//	
//	fp = fopen( strFileName.GetBuffer(0), "rb" );
//	
//	if( NULL == fp )
//	{
//		return;
//	}
//	
//	int nFileNameLength;
//	//DWORD dwSize, dwCRC;
//	ClientFileInfo cfi;
//	char szFileName[1024];
//	
//	int nCount;
//	
//	fread( &nCount, sizeof(int), 1, fp );
//	
//	int nRealCount = 0;
//	while( !feof(fp) ) 
//	{
//		fread( &nFileNameLength, sizeof(int), 1, fp );
//		
//		fread( szFileName, nFileNameLength, 1, fp );
//		szFileName[nFileNameLength] = '\0';
//		
//		fread( &cfi, sizeof(ClientFileInfo), 1, fp );
//		
//		CString strKey = szFileName;
//		strKey.MakeLower();
//		
//		m_mapFileInfoCache[strKey] = cfi;
//		
//		++nRealCount;
//		
//		if( m_pInfoWnd )
//		{
//			CString strCacheCount;
//			strCacheCount.Format( "%s %d / %d", RYLLoginGetMessage(LOGIN_MSG_LOADING_PATCHINFO_CACHE), nRealCount, nCount );
//			m_pInfoWnd->SetWindowText( strCacheCount );
//		}
//	}
//	
//	fclose(fp);
//}
//
//
//void CUpdateManager::SaveClientFileInfoCacheList()
//{
//	FILE* fp;
//	
//	CString strPatchInfoFileName = m_strRootPath + "\\PatchInfo.cache";
//	
//	fp = fopen( strPatchInfoFileName.GetBuffer(0), "wb" );
//	
//	if( NULL == fp )
//	{
//		return;
//	}
//	
//	int nCount = m_mapFileInfoCache.GetCount();
//	
//	fwrite( &nCount, sizeof(int), 1, fp );
//	
//	int nFileNameLength;
//	ClientFileInfo cfi;
//	CString strFileName;
//	
//	POSITION iter;
//	
//	iter = m_mapFileInfoCache.GetStartPosition();
//	
//	while( NULL != iter )
//	{
//		m_mapFileInfoCache.GetNextAssoc( iter, strFileName, cfi );
//		
//		nFileNameLength = strFileName.GetLength();
//		
//		fwrite( &nFileNameLength, sizeof(int), 1, fp );
//		fwrite( strFileName.GetBuffer(0), nFileNameLength, 1, fp );
//		fwrite( &cfi, sizeof(ClientFileInfo), 1, fp );
//	}
//}
