//>>> shadow2004::IP2Country [EastShare]

/*
the IP to country data is provided by http://ip-to-country.webhosting.info/

"IP2Country uses the IP-to-Country Database
 provided by WebHosting.Info (http://www.webhosting.info),
 available from http://ip-to-country.webhosting.info."

 */

// by Superlexx, based on IPFilter by Bouc7

#include "StdAfx.h"
#include <share.h>
#include "EMF/IP2Country.h"
#include "emule.h"
#include "otherfunctions.h"
#include <flag/resource.h>
#include "log.h"

//refresh list
#include "serverlist.h"
#include "clientlist.h"

//refresh server list ctrl
#include "emuledlg.h"
#include "serverwnd.h"
#include "serverlistctrl.h"
#include "downloadqueue.h" //>>> WiZaRd::IP2Country Addon: File Origin

//Start
//#include "kadcontactlistctrl.h"
#include "kademliawnd.h"
//End

#include "HttpDownloadDlg.h"
#include "ZipFile.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static int __cdecl CmpIP2CountryByAddr(const void* pvKey, const void* pvElement)
{
	UINT ip = *(UINT*)pvKey;
	const IPRange_Struct2* pIP2Country = *(IPRange_Struct2**)pvElement;

	if (ip < pIP2Country->IPstart)
		return -1;
	if (ip > pIP2Country->IPend)
		return 1;
	return 0;
}

static int __cdecl CmpIP2CountryByStartAddr(const void* p1, const void* p2)
{
	const IPRange_Struct2* rng1 = *(IPRange_Struct2**)p1;
	const IPRange_Struct2* rng2 = *(IPRange_Struct2**)p2;
	return CompareUnsigned(rng1->IPstart, rng2->IPstart);
}

void FirstCharCap(CString *pstrTarget)
{
	pstrTarget->TrimRight();//clean out the space at the end, prevent exception for index++
	if(!pstrTarget->IsEmpty())
	{
		pstrTarget->MakeLower();
		for (int iIdx = 0;;)
		{
			pstrTarget->SetAt(iIdx, pstrTarget->Mid(iIdx, 1).MakeUpper().GetAt(0));
			iIdx = pstrTarget->Find(_T(' '), iIdx) + 1;
			if (iIdx == 0)
				break;
		}
	}
}

CIP2Country::CIP2Country()
{
	m_bRunning = false;

	defaultIP2Country.IPstart = 0;
	defaultIP2Country.IPend = 0;
	defaultIP2Country.ShortCountryName = GetResString(IDS_IP2COUNTRY_NASHORT);
	defaultIP2Country.MidCountryName = GetResString(IDS_IP2COUNTRY_NASHORT);
	defaultIP2Country.LongCountryName = GetResString(IDS_IP2COUNTRY_NALONG);
	defaultIP2Country.FlagIndex = NO_FLAG;

	m_bEnableIP2Country = false;
	m_bEnableCountryFlag = false;
	_hCountryFlagDll = NULL; //>>> WiZaRd

	Load();

	theApp.QueueLogLineEx(LOG_WARNING, GetResString(IDS_IP2COUNTRY_MSG1));
	theApp.QueueLogLineEx(LOG_WARNING, GetResString(IDS_IP2COUNTRY_MSG2));
//	m_bRunning = true;
	m_bRunning = m_bEnableIP2Country && m_bEnableCountryFlag;
}

CIP2Country::~CIP2Country()
{
	m_bRunning = false;

	Unload();
}

void CIP2Country::Load()
{
	m_bEnableCountryFlag = LoadCountryFlagLib();//flag lib first, so ip range can map to flag
//>>> WiZaRd::AddonDirectory
	//move file from config to addon dir
	if(!::PathFileExists(GetDefaultFilePath()) && ::PathFileExists(thePrefs.GetMuleDirectory(EMULE_CONFIGDIR) + DFLT_IP2COUNTRY_FILENAME))
		::MoveFile(thePrefs.GetMuleDirectory(EMULE_CONFIGDIR) + DFLT_IP2COUNTRY_FILENAME, GetDefaultFilePath());
//<<< WiZaRd::AddonDirectory
	if(m_bEnableCountryFlag)
		m_bEnableIP2Country = LoadFromFile();
	else
		m_bEnableIP2Country = false;

	if(!m_bEnableIP2Country || !m_bEnableCountryFlag)
		Unload();
	else //if(m_bRunning)  //not necessary to reset twice :)
		Reset();

	if(m_bEnableIP2Country && m_bEnableCountryFlag)
		theApp.QueueLogLineEx(LOG_SUCCESS, GetResString(IDS_IP2COUNTRY_LOADED));
}

void CIP2Country::Unload()
{
	m_bEnableIP2Country = false;
	m_bEnableCountryFlag = false;

	RemoveAllIPs();
	RemoveAllFlags();

	if(m_bRunning)
	{
		Reset();
		theApp.QueueDebugLogLineEx(LOG_WARNING, GetResString(IDS_IP2COUNTRY_UNLOADED));
	}
}

void CIP2Country::Reset()
{
	theApp.serverlist->ResetIP2Country();
	theApp.clientlist->ResetIP2Country();
	theApp.downloadqueue->ResetIP2Country(); //>>> WiZaRd::IP2Country Addon: File Origin
	theApp.emuledlg->kademliawnd->ResetIP2Country();	
}

void CIP2Country::Refresh()
{
//WiZaRd::Remark: 
//I doubt this is needed at all... usually icons will appear/disappear after some 
//seconds anyway
	theApp.emuledlg->serverwnd->serverlistctrl.RefreshAllServer();
	theApp.emuledlg->kademliawnd->RedrawWindow();//KTS à modifier quand list
}

bool CIP2Country::LoadFromFile()
{
	CString ip2countryCSVfile = GetDefaultFilePath();
	DWORD startMesure = GetTickCount();
	TCHAR szBuffer[1024];
	int	lenBuf = ARRSIZE(szBuffer);
	bool bRet = true;
	FILE* readFile = _tfsopen(ip2countryCSVfile, _T("r"), _SH_DENYWR);
	try
	{
		if (readFile != NULL) 
		{
			int iCount = 0;
			int iLine = 0;
			int iDuplicate = 0;
			int iMerged = 0;
			bool error = false;
			while (!feof(readFile)) 
			{
				error = false;
				if (_fgetts(szBuffer, lenBuf, readFile)==0) 
					break;
				CString sbuffer = szBuffer;
				++iLine;
				/*
					http://ip-to-country.webhosting.info/node/view/54

					This is a sample of how the CSV file is structured:

					"0033996344","0033996351","GB","GBR","UNITED KINGDOM"
					"0050331648","0083886079","US","USA","UNITED STATES"
					"0094585424","0094585439","SE","SWE","SWEDEN"

					FIELD  			DATA TYPE		  	FIELD DESCRIPTION
					IP_FROM 		NUMERICAL (DOUBLE) 	Beginning of IP address range.
					IP_TO			NUMERICAL (DOUBLE) 	Ending of IP address range.
					COUNTRY_CODE2 	CHAR(2)				Two-character country code based on ISO 3166.
					COUNTRY_CODE3 	CHAR(3)				Three-character country code based on ISO 3166.
					COUNTRY_NAME 	VARCHAR(50) 		Country name based on ISO 3166
				*/
				// we assume that the ip-to-country.csv is valid and doesn't cause any troubles
				// get & process IP range
				sbuffer.Remove(L'"'); // get rid of the " signs

				CString tempStr[5];
				int curPos = 0;
				for(int forCount = 0; forCount < 5; ++forCount)
				{
					tempStr[forCount] = sbuffer.Tokenize(_T(","), curPos);
					if(tempStr[forCount].IsEmpty()) 
					{
						if(forCount == 0 || forCount == 1) 
						{
							error = true; //no empty ip field
							break;
						}
						//no need to throw an exception, keep reading in next line
						//throw CString(_T("error line in"));
					}
				}
				if(error)
				{
					theApp.QueueDebugLogLineEx(LOG_ERROR, GetResString(IDS_IP2COUNTRY_ERROR1), iCount+1);
					theApp.QueueDebugLogLineEx(LOG_ERROR, _T("%s %s"), GetResString(IDS_IP2COUNTRY_ERROR2), ip2countryCSVfile);
					continue;
				}
				//tempStr[4] is full country name, capitalize country name from rayita
				FirstCharCap(&tempStr[4]);

				++iCount;
//>>> WiZaRd::VS2005compatible
				AddIPRange((UINT)_tstol(tempStr[0]), (UINT)_tstol(tempStr[1]), tempStr[2], tempStr[3], tempStr[4]);
//				AddIPRange(_tstoi(tempStr[0]),_tstoi(tempStr[1]), tempStr[2], tempStr[3], tempStr[4]);
//<<< WiZaRd::VS2005compatible
			}
			fclose(readFile);

			// sort the IP2Country list by IP range start addresses
			qsort(m_iplist.GetData(), m_iplist.GetCount(), sizeof(m_iplist[0]), CmpIP2CountryByStartAddr);
			if (m_iplist.GetCount() >= 2)
			{
				IPRange_Struct2* pPrv = m_iplist[0];
				int i = 1;
				while (i < m_iplist.GetCount())
				{
					IPRange_Struct2* pCur = m_iplist[i];
					if (   pCur->IPstart >= pPrv->IPstart && pCur->IPstart <= pPrv->IPend	 // overlapping
						|| pCur->IPstart == pPrv->IPend+1 && &pCur->ShortCountryName == &pPrv->ShortCountryName) // adjacent
					{
						if (pCur->IPstart != pPrv->IPstart || pCur->IPend != pPrv->IPend) // don't merge identical entries
						{
							//TODO: not yet handled, overlapping entries with different 'level'
							if (pCur->IPend > pPrv->IPend)
								pPrv->IPend = pCur->IPend;
							//pPrv->desc += _T("; ") + pCur->desc; // this may create a very very long description string...
							++iMerged;
						}
						else
						{
							// if we have identical entries, use the lowest 'level'
							/*if (pCur->level < pPrv->level)
								pPrv->level = pCur->level;
							*/
							++iDuplicate;
						}
						delete pCur;
						m_iplist.RemoveAt(i);
						continue;
					}
					pPrv = pCur;
					++i;
				}
			}

			if (thePrefs.GetVerbose())
			{
				theApp.QueueDebugLogLineEx(LOG_SUCCESS, GetResString(IDS_IP2COUNTRY_LOADED2), ip2countryCSVfile, CastSecondsToHM((::GetTickCount()-startMesure)/1000));
				theApp.QueueDebugLogLineEx(LOG_SUCCESS, GetResString(IDS_IP2COUNTRY_INFO), iLine, iCount, iDuplicate, iMerged);
			}
		}
		else
		{
			theApp.QueueDebugLogLineEx(LOG_WARNING, _T("%s %s"), GetResString(IDS_IP2COUNTRY_ERROR3), ip2countryCSVfile);
			bRet = false;
//			RemoveAllIPs();
//			return false;
		}
	}
	catch(...)
	{
		theApp.QueueDebugLogLineEx(LOG_ERROR, _T("%s %s"), GetErrorMessage(GetLastError()), ip2countryCSVfile);
		bRet = false;
//		RemoveAllIPs();
//		return false;
	}
	return bRet;
//	return true;
}

bool CIP2Country::LoadCountryFlagLib()
{
	CString ip2countryCountryFlag;
	bool bRet = true;
	try
	{
		ASSERT( CountryIDtoFlagIndex.GetCount() == 0);
		CountryIDtoFlagIndex.RemoveAll();		
		//shouldn't contain images either...
		ASSERT( CountryFlagImageList.GetSafeHandle() == NULL || CountryFlagImageList.GetImageCount() == 0);
		
		//WiZaRd - remark:
		//>= would be sufficient if the devs had chosen to use consistent defines... (see otherfunctions.h)
		//but that way Win98/ME are BIGGER than XP while Vista is smaller... that is also the reason why we tried to load the 32bit .dll in those lower OS
		_hCountryFlagDll = NULL; //just to be sure
		//detect windows version

// Contrib - W2K 24bit icon dlls Fix
/*
		if(IsRunning32BitOS())  //>>> shadow2004::IP2Country Vista-Fix?
		{
			//it's XP, we can use beautiful 32bits flags with alpha channel :)
			ip2countryCountryFlag = thePrefs.GetMuleDirectory(EMULE_ADDONDIR)+_T("countryflag32.dll");	//>>> shadow2004::AddonDirectory	
			_hCountryFlagDll = LoadLibrary(ip2countryCountryFlag); //>>> WiZaRd
		}		
		//WiZaRd: Fail safe - if 32bit not possible proceed with 24bit
		if (_hCountryFlagDll == NULL)  //>>> WiZaRd
		//else
		{
			//oh~ it's not XP, but we still can load the 24bits flags
			ip2countryCountryFlag = thePrefs.GetMuleDirectory(EMULE_ADDONDIR)+_T("countryflag.dll");	//>>> shadow2004::AddonDirectory
			_hCountryFlagDll = LoadLibrary(ip2countryCountryFlag); 
		}
*/
// Xman - from Xtreme + AddOn dir

		if(thePrefs.GetWindowsVersion() == _WINVER_XP_ || thePrefs.GetWindowsVersion() == _WINVER_2003_ || thePrefs.GetWindowsVersion() == _WINVER_VISTA_){
			//it's XP, we can use beautiful 32bits flags with alpha channel :)
			ip2countryCountryFlag = thePrefs.GetMuleDirectory(EMULE_ADDONDIR)+_T("countryflag32.dll");
		}
		else{
			//oh~ it's not XP, but we still can load the 24bits flags
			ip2countryCountryFlag = thePrefs.GetMuleDirectory(EMULE_ADDONDIR)+_T("countryflag.dll");
		}

		_hCountryFlagDll = LoadLibrary(ip2countryCountryFlag);
// <-------- W2K 24bit icon dlls Fix

		if (_hCountryFlagDll == NULL) 
			throw CString(GetResString(IDS_IP2COUNTRY_ERROR4));

		const uint16 resIDs[] = 
		{
			IDI_COUNTRY_FLAG_NOFLAG,		//first res in image list should be N/A
			IDI_COUNTRY_FLAG_AD,			//101
			IDI_COUNTRY_FLAG_AE,			//102
			IDI_COUNTRY_FLAG_AF,			//103
			IDI_COUNTRY_FLAG_AG,			//104
			IDI_COUNTRY_FLAG_AI,			//105
			IDI_COUNTRY_FLAG_AL,			//106
			IDI_COUNTRY_FLAG_AM,			//107
			IDI_COUNTRY_FLAG_AN,			//108
			IDI_COUNTRY_FLAG_AO,			//109
			IDI_COUNTRY_FLAG_AR,			//110
			IDI_COUNTRY_FLAG_AS,			//111
			IDI_COUNTRY_FLAG_AT,			//112
			IDI_COUNTRY_FLAG_AU,			//113
			IDI_COUNTRY_FLAG_AW,			//114
			IDI_COUNTRY_FLAG_AZ,			//115
			IDI_COUNTRY_FLAG_BA,			//116
			IDI_COUNTRY_FLAG_BB,			//117
			IDI_COUNTRY_FLAG_BD,			//118
			IDI_COUNTRY_FLAG_BE,			//119
			IDI_COUNTRY_FLAG_BF,			//120
			IDI_COUNTRY_FLAG_BG,			//121
			IDI_COUNTRY_FLAG_BH,			//122
			IDI_COUNTRY_FLAG_BI,			//123
			IDI_COUNTRY_FLAG_BJ,			//124
			IDI_COUNTRY_FLAG_BM,			//125
			IDI_COUNTRY_FLAG_BN,			//126
			IDI_COUNTRY_FLAG_BO,			//127
			IDI_COUNTRY_FLAG_BR,			//128
			IDI_COUNTRY_FLAG_BS,			//129
			IDI_COUNTRY_FLAG_BT,			//130
			IDI_COUNTRY_FLAG_BW,			//131
			IDI_COUNTRY_FLAG_BY,			//132
			IDI_COUNTRY_FLAG_BZ,			//133
			IDI_COUNTRY_FLAG_CA,			//134
			IDI_COUNTRY_FLAG_CC,			//135
			IDI_COUNTRY_FLAG_CD,			//136
			IDI_COUNTRY_FLAG_CF,			//137
			IDI_COUNTRY_FLAG_CG,			//138
			IDI_COUNTRY_FLAG_CH,			//139
			IDI_COUNTRY_FLAG_CI,			//140
			IDI_COUNTRY_FLAG_CK,			//141
			IDI_COUNTRY_FLAG_CL,			//142
			IDI_COUNTRY_FLAG_CM,			//143
			IDI_COUNTRY_FLAG_CN,			//144
			IDI_COUNTRY_FLAG_CO,			//145
			IDI_COUNTRY_FLAG_CR,			//146
			IDI_COUNTRY_FLAG_CU,			//147
			IDI_COUNTRY_FLAG_CV,			//148
			IDI_COUNTRY_FLAG_CX,			//149
			IDI_COUNTRY_FLAG_CY,			//150
			IDI_COUNTRY_FLAG_CZ,			//151
			IDI_COUNTRY_FLAG_DE,			//152
			IDI_COUNTRY_FLAG_DJ,			//153
			IDI_COUNTRY_FLAG_DK,			//154
			IDI_COUNTRY_FLAG_DM,			//155
			IDI_COUNTRY_FLAG_DO,			//156
			IDI_COUNTRY_FLAG_DZ,			//157
			IDI_COUNTRY_FLAG_EC,			//158
			IDI_COUNTRY_FLAG_EE,			//159
			IDI_COUNTRY_FLAG_EG,			//160
			IDI_COUNTRY_FLAG_EH,			//161
			IDI_COUNTRY_FLAG_ER,			//162
			IDI_COUNTRY_FLAG_ES,			//163
			IDI_COUNTRY_FLAG_ET,			//164
			IDI_COUNTRY_FLAG_FI,			//165
			IDI_COUNTRY_FLAG_FJ,			//166
			IDI_COUNTRY_FLAG_FK,			//167
			IDI_COUNTRY_FLAG_FM,			//168
			IDI_COUNTRY_FLAG_FO,			//169
			IDI_COUNTRY_FLAG_FR,			//170
			IDI_COUNTRY_FLAG_GA,			//171
			IDI_COUNTRY_FLAG_GB,			//172
			IDI_COUNTRY_FLAG_GD,			//173
			IDI_COUNTRY_FLAG_GE,			//174
			IDI_COUNTRY_FLAG_GG,			//175
			IDI_COUNTRY_FLAG_GH,			//176
			IDI_COUNTRY_FLAG_GI,			//177
			IDI_COUNTRY_FLAG_GK,			//178
			IDI_COUNTRY_FLAG_GL,			//179
			IDI_COUNTRY_FLAG_GM,			//180
			IDI_COUNTRY_FLAG_GN,			//181
			IDI_COUNTRY_FLAG_GP,			//182
			IDI_COUNTRY_FLAG_GQ,			//183
			IDI_COUNTRY_FLAG_GR,			//184
			IDI_COUNTRY_FLAG_GS,			//185
			IDI_COUNTRY_FLAG_GT,			//186
			IDI_COUNTRY_FLAG_GU,			//187
			IDI_COUNTRY_FLAG_GW,			//188
			IDI_COUNTRY_FLAG_GY,			//189
			IDI_COUNTRY_FLAG_HK,			//190
			IDI_COUNTRY_FLAG_HN,			//191
			IDI_COUNTRY_FLAG_HR,			//192
			IDI_COUNTRY_FLAG_HT,			//193
			IDI_COUNTRY_FLAG_HU,			//194
			IDI_COUNTRY_FLAG_ID,			//195
			IDI_COUNTRY_FLAG_IE,			//196
			IDI_COUNTRY_FLAG_IL,			//197
			IDI_COUNTRY_FLAG_IM,			//198
			IDI_COUNTRY_FLAG_IN,			//199
			IDI_COUNTRY_FLAG_IO,			//200
			IDI_COUNTRY_FLAG_IQ,			//201
			IDI_COUNTRY_FLAG_IR,			//202
			IDI_COUNTRY_FLAG_IS,			//203
			IDI_COUNTRY_FLAG_IT,			//204
			IDI_COUNTRY_FLAG_JE,			//205
			IDI_COUNTRY_FLAG_JM,			//206
			IDI_COUNTRY_FLAG_JO,			//207
			IDI_COUNTRY_FLAG_JP,			//208
			IDI_COUNTRY_FLAG_KE,			//209
			IDI_COUNTRY_FLAG_KG,			//210
			IDI_COUNTRY_FLAG_KH,			//211
			IDI_COUNTRY_FLAG_KI,			//212
			IDI_COUNTRY_FLAG_KM,			//213
			IDI_COUNTRY_FLAG_KN,			//214
			IDI_COUNTRY_FLAG_KP,			//215
			IDI_COUNTRY_FLAG_KR,			//216
			IDI_COUNTRY_FLAG_KW,			//217
			IDI_COUNTRY_FLAG_KY,			//218
			IDI_COUNTRY_FLAG_KZ,			//219
			IDI_COUNTRY_FLAG_LA,			//220
			IDI_COUNTRY_FLAG_LB,			//221
			IDI_COUNTRY_FLAG_LC,			//222
			IDI_COUNTRY_FLAG_LI,			//223
			IDI_COUNTRY_FLAG_LK,			//224
			IDI_COUNTRY_FLAG_LR,			//225
			IDI_COUNTRY_FLAG_LS,			//226
			IDI_COUNTRY_FLAG_LT,			//227
			IDI_COUNTRY_FLAG_LU,			//228
			IDI_COUNTRY_FLAG_LV,			//229
			IDI_COUNTRY_FLAG_LY,			//230
			IDI_COUNTRY_FLAG_MA,			//231
			IDI_COUNTRY_FLAG_MC,			//232
			IDI_COUNTRY_FLAG_MD,			//233
			IDI_COUNTRY_FLAG_MG,			//234
			IDI_COUNTRY_FLAG_MH,			//235
			IDI_COUNTRY_FLAG_MK,			//236
			IDI_COUNTRY_FLAG_ML,			//237
			IDI_COUNTRY_FLAG_MM,			//238
			IDI_COUNTRY_FLAG_MN,			//239
			IDI_COUNTRY_FLAG_MO,			//240
			IDI_COUNTRY_FLAG_MP,			//241
			IDI_COUNTRY_FLAG_MQ,			//242
			IDI_COUNTRY_FLAG_MR,			//243
			IDI_COUNTRY_FLAG_MS,			//244
			IDI_COUNTRY_FLAG_MT,			//245
			IDI_COUNTRY_FLAG_MU,			//246
			IDI_COUNTRY_FLAG_MV,			//247
			IDI_COUNTRY_FLAG_MW,			//248
			IDI_COUNTRY_FLAG_MX,			//249
			IDI_COUNTRY_FLAG_MY,			//250
			IDI_COUNTRY_FLAG_MZ,			//251
			IDI_COUNTRY_FLAG_NA,			//252
			IDI_COUNTRY_FLAG_NC,			//253
			IDI_COUNTRY_FLAG_NE,			//254
			IDI_COUNTRY_FLAG_NF,			//255
			IDI_COUNTRY_FLAG_NG,			//256
			IDI_COUNTRY_FLAG_NI,			//257
			IDI_COUNTRY_FLAG_NL,			//258
			IDI_COUNTRY_FLAG_NO,			//259
			IDI_COUNTRY_FLAG_NP,			//260
			IDI_COUNTRY_FLAG_NR,			//261
			IDI_COUNTRY_FLAG_NU,			//262
			IDI_COUNTRY_FLAG_NZ,			//263
			IDI_COUNTRY_FLAG_OM,			//264
			IDI_COUNTRY_FLAG_PA,			//265
			IDI_COUNTRY_FLAG_PC,			//266
			IDI_COUNTRY_FLAG_PE,			//267
			IDI_COUNTRY_FLAG_PF,			//268
			IDI_COUNTRY_FLAG_PG,			//269
			IDI_COUNTRY_FLAG_PH,			//270
			IDI_COUNTRY_FLAG_PK,			//271
			IDI_COUNTRY_FLAG_PL,			//272
			IDI_COUNTRY_FLAG_PM,			//273
			IDI_COUNTRY_FLAG_PN,			//274
			IDI_COUNTRY_FLAG_PR,			//275
			IDI_COUNTRY_FLAG_PS,			//276
			IDI_COUNTRY_FLAG_PT,			//277
			IDI_COUNTRY_FLAG_PW,			//278
			IDI_COUNTRY_FLAG_PY,			//279
			IDI_COUNTRY_FLAG_QA,			//280
			IDI_COUNTRY_FLAG_RO,			//281
			IDI_COUNTRY_FLAG_RU,			//282
			IDI_COUNTRY_FLAG_RW,			//283
			IDI_COUNTRY_FLAG_SA,			//284
			IDI_COUNTRY_FLAG_SB,			//285
			IDI_COUNTRY_FLAG_SC,			//286
			IDI_COUNTRY_FLAG_SD,			//287
			IDI_COUNTRY_FLAG_SE,			//288
			IDI_COUNTRY_FLAG_SG,			//289
			IDI_COUNTRY_FLAG_SH,			//290
			IDI_COUNTRY_FLAG_SI,			//291
			IDI_COUNTRY_FLAG_SK,			//292
			IDI_COUNTRY_FLAG_SL,			//293
			IDI_COUNTRY_FLAG_SM,			//294
			IDI_COUNTRY_FLAG_SN,			//295
			IDI_COUNTRY_FLAG_SO,			//296
			IDI_COUNTRY_FLAG_SR,			//297
			IDI_COUNTRY_FLAG_ST,			//298
			IDI_COUNTRY_FLAG_SU,			//299
			IDI_COUNTRY_FLAG_SV,			//300
			IDI_COUNTRY_FLAG_SY,			//301
			IDI_COUNTRY_FLAG_SZ,			//302
			IDI_COUNTRY_FLAG_TC,			//303
			IDI_COUNTRY_FLAG_TD,			//304
			IDI_COUNTRY_FLAG_TF,			//305
			IDI_COUNTRY_FLAG_TG,			//306
			IDI_COUNTRY_FLAG_TH,			//307
			IDI_COUNTRY_FLAG_TJ,			//308
			IDI_COUNTRY_FLAG_TK,			//309
			IDI_COUNTRY_FLAG_TL,			//310
			IDI_COUNTRY_FLAG_TM,			//311
			IDI_COUNTRY_FLAG_TN,			//312
			IDI_COUNTRY_FLAG_TO,			//313
			IDI_COUNTRY_FLAG_TR,			//314
			IDI_COUNTRY_FLAG_TT,			//315
			IDI_COUNTRY_FLAG_TV,			//316
			IDI_COUNTRY_FLAG_TW,			//317
			IDI_COUNTRY_FLAG_TZ,			//318
			IDI_COUNTRY_FLAG_UA,			//319
			IDI_COUNTRY_FLAG_UG,			//320
			IDI_COUNTRY_FLAG_UM,			//321
			IDI_COUNTRY_FLAG_US,			//322
			IDI_COUNTRY_FLAG_UY,			//323
			IDI_COUNTRY_FLAG_UZ,			//324
			IDI_COUNTRY_FLAG_VA,			//325
			IDI_COUNTRY_FLAG_VC,			//326
			IDI_COUNTRY_FLAG_VE,			//327
			IDI_COUNTRY_FLAG_VG,			//328
			IDI_COUNTRY_FLAG_VI,			//329
			IDI_COUNTRY_FLAG_VN,			//330
			IDI_COUNTRY_FLAG_VU,			//331
			IDI_COUNTRY_FLAG_WF,			//332
			IDI_COUNTRY_FLAG_WS,			//333
			IDI_COUNTRY_FLAG_YE,			//334
			IDI_COUNTRY_FLAG_YU,			//335
			IDI_COUNTRY_FLAG_ZA,			//336
			IDI_COUNTRY_FLAG_ZM,			//337
			IDI_COUNTRY_FLAG_ZW,			//338
			IDI_COUNTRY_FLAG_UK,			//340
			IDI_COUNTRY_FLAG_CS,			//341
			//IDI_COUNTRY_FLAG_NOFLAG		//342
			IDI_COUNTRY_FLAG_TP,			//343
			IDI_COUNTRY_FLAG_AX,			//346
			IDI_COUNTRY_FLAG_ME,			//345
			IDI_COUNTRY_FLAG_RS,			//344
			IDI_COUNTRY_FLAG_FR,
			IDI_COUNTRY_FLAG_FR,
			IDI_COUNTRY_FLAG_FR,
			IDI_COUNTRY_FLAG_NOFLAG,
		};

		CString strIDs[] = 
		{
			L"N/A",			//first res in image list should be N/A
			L"AD",			//101
			L"AE",			//102
			L"AF",			//103
			L"AG",			//104
			L"AI",			//105
			L"AL",			//106
			L"AM",			//107
			L"AN",			//108
			L"AO",			//109
			L"AR",			//110
			L"AS",			//111
			L"AT",			//112
			L"AU",			//113
			L"AW",			//114
			L"AZ",			//115
			L"BA",			//116
			L"BB",			//117
			L"BD",			//118
			L"BE",			//119
			L"BF",			//120
			L"BG",			//121
			L"BH",			//122
			L"BI",			//123
			L"BJ",			//124
			L"BM",			//125
			L"BN",			//126
			L"BO",			//127
			L"BR",			//128
			L"BS",			//129
			L"BT",			//130
			L"BW",			//131
			L"BY",			//132
			L"BZ",			//133
			L"CA",			//134
			L"CC",			//135
			L"CD",			//136
			L"CF",			//137
			L"CG",			//138
			L"CH",			//139
			L"CI",			//140
			L"CK",			//141
			L"CL",			//142
			L"CM",			//143
			L"CN",			//144
			L"CO",			//145
			L"CR",			//146
			L"CU",			//147
			L"CV",			//148
			L"CX",			//149
			L"CY",			//150
			L"CZ",			//151
			L"DE",			//152
			L"DJ",			//153
			L"DK",			//154
			L"DM",			//155
			L"DO",			//156
			L"DZ",			//157
			L"EC",			//158
			L"EE",			//159
			L"EG",			//160
			L"EH",			//161
			L"ER",			//162
			L"ES",			//163
			L"ET",			//164
			L"FI",			//165
			L"FJ",			//166
			L"FK",			//167
			L"FM",			//168
			L"FO",			//169
			L"FR",			//170
			L"GA",			//171
			L"GB",			//172
			L"GD",			//173
			L"GE",			//174
			L"GG",			//175
			L"GH",			//176
			L"GI",			//177
			L"GK",			//178
			L"GL",			//179
			L"GM",			//180
			L"GN",			//181
			L"GP",			//182
			L"GQ",			//183
			L"GR",			//184
			L"GS",			//185
			L"GT",			//186
			L"GU",			//187
			L"GW",			//188
			L"GY",			//189
			L"HK",			//190
			L"HN",			//191
			L"HR",			//192
			L"HT",			//193
			L"HU",			//194
			L"ID",			//195
			L"IE",			//196
			L"IL",			//197
			L"IM",			//198
			L"IN",			//199
			L"IO",			//200
			L"IQ",			//201
			L"IR",			//202
			L"IS",			//203
			L"IT",			//204
			L"JE",			//205
			L"JM",			//206
			L"JO",			//207
			L"JP",			//208
			L"KE",			//209
			L"KG",			//210
			L"KH",			//211
			L"KI",			//212
			L"KM",			//213
			L"KN",			//214
			L"KP",			//215
			L"KR",			//216
			L"KW",			//217
			L"KY",			//218
			L"KZ",			//219
			L"LA",			//220
			L"LB",			//221
			L"LC",			//222
			L"LI",			//223
			L"LK",			//224
			L"LR",			//225
			L"LS",			//226
			L"LT",			//227
			L"LU",			//228
			L"LV",			//229
			L"LY",			//230
			L"MA",			//231
			L"MC",			//232
			L"MD",			//233
			L"MG",			//234
			L"MH",			//235
			L"MK",			//236
			L"ML",			//237
			L"MM",			//238
			L"MN",			//239
			L"MO",			//240
			L"MP",			//241
			L"MQ",			//242
			L"MR",			//243
			L"MS",			//244
			L"MT",			//245
			L"MU",			//246
			L"MV",			//247
			L"MW",			//248
			L"MX",			//249
			L"MY",			//250
			L"MZ",			//251
			L"NA",			//252
			L"NC",			//253
			L"NE",			//254
			L"NF",			//255
			L"NG",			//256
			L"NI",			//257
			L"NL",			//258
			L"NO",			//259
			L"NP",			//260
			L"NR",			//261
			L"NU",			//262
			L"NZ",			//263
			L"OM",			//264
			L"PA",			//265
			L"PC",			//266
			L"PE",			//267
			L"PF",			//268
			L"PG",			//269
			L"PH",			//270
			L"PK",			//271
			L"PL",			//272
			L"PM",			//273
			L"PN",			//274
			L"PR",			//275
			L"PS",			//276
			L"PT",			//277
			L"PW",			//278
			L"PY",			//279
			L"QA",			//280
			L"RO",			//281
			L"RU",			//282
			L"RW",			//283
			L"SA",			//284
			L"SB",			//285
			L"SC",			//286
			L"SD",			//287
			L"SE",			//288
			L"SG",			//289
			L"SH",			//290
			L"SI",			//291
			L"SK",			//292
			L"SL",			//293
			L"SM",			//294
			L"SN",			//295
			L"SO",			//296
			L"SR",			//297
			L"ST",			//298
			L"SU",			//299
			L"SV",			//300
			L"SY",			//301
			L"SZ",			//302
			L"TC",			//303
			L"TD",			//304
			L"TF",			//305
			L"TG",			//306
			L"TH",			//307
			L"TJ",			//308
			L"TK",			//309
			L"TL",			//310
			L"TM",			//311
			L"TN",			//312
			L"TO",			//313
			L"TR",			//314
			L"TT",			//315
			L"TV",			//316
			L"TW",			//317
			L"TZ",			//318
			L"UA",			//319
			L"UG",			//320
			L"UM",			//321
			L"US",			//322
			L"UY",			//323
			L"UZ",			//324
			L"VA",			//325
			L"VC",			//326
			L"VE",			//327
			L"VG",			//328
			L"VI",			//329
			L"VN",			//330
			L"VU",			//331
			L"WF",			//332
			L"WS",			//333
			L"YE",			//334
			L"YU",			//335
			L"ZA",			//336
			L"ZM",			//337
			L"ZW",			//338
			L"UK",			//340
			L"CS",			//341
			//L"N/A"		//342
			L"TP",			//343
			L"AX",			//346
			L"ME",			//345
			L"RS",			//344
			L"YT",			//IDI_COUNTRY_FLAG_FR
			L"GF",			//IDI_COUNTRY_FLAG_FR
			L"RE",			//IDI_COUNTRY_FLAG_FR
			L"AQ",			//IDI_COUNTRY_FLAG_NOFLAG
		};

		CountryFlagImageList.DeleteImageList();
		CountryFlagImageList.Create(18, 16, theApp.m_iDfltImageListColorFlags|ILC_MASK, 0, 1);
		CountryFlagImageList.SetBkColor(CLR_NONE);

//>>> FiX for IP2Country and other custom lists [Rapid Mule]
		HICON iconHandle = NULL; 
		int iconIndex = -1;
//<<< FiX for IP2Country and other custom lists [Rapid Mule]
		for(int i = 0; i != _countof(resIDs); ++i)
		{
//>>> FiX for IP2Country and other custom lists [Rapid Mule]
			iconHandle = (HICON)::LoadImage(_hCountryFlagDll, MAKEINTRESOURCE(resIDs[i]), IMAGE_ICON, 18, 16, LR_DEFAULTCOLOR);
			if(iconHandle) 
//<<< FiX for IP2Country and other custom lists [Rapid Mule]
			{
//>>> FiX for IP2Country and other custom lists [Rapid Mule]
				iconIndex = CountryFlagImageList.Add(iconHandle);
				if(iconIndex != -1)
					CountryIDtoFlagIndex.SetAt(strIDs[i], (uint16)iconIndex);
				::DestroyIcon(iconHandle);
//				CountryIDtoFlagIndex.SetAt(strIDs[i], (uint16)CountryFlagImageList.GetImageCount());
//				CountryFlagImageList.Add(iconHandle);
//>>> FiX for IP2Country and other custom lists [Rapid Mule]
			}
			else
				theApp.QueueDebugLogLineEx(LOG_WARNING, GetResString(IDS_IP2COUNTRY_ERROR5), resIDs[i]);
		}
		theApp.QueueDebugLogLineEx(LOG_SUCCESS, GetResString(IDS_IP2COUNTRY_FLAGLOAD));
	}
	catch(CString error)
	{
		theApp.QueueDebugLogLineEx(LOG_ERROR, L"IP2COUNTRY: error %s in %s", error, ip2countryCountryFlag);
		bRet = false;
//		RemoveAllFlags();	//unload will be called on failure!
	}
	catch(...)
	{
		theApp.QueueDebugLogLineEx(LOG_ERROR, L"IP2COUNTRY: error %s in %s", GetErrorMessage(GetLastError()), ip2countryCountryFlag);
		bRet = false;
//		RemoveAllFlags();	//unload will be called on failure!
	}

	//free lib
	if(_hCountryFlagDll != NULL) 
		FreeLibrary(_hCountryFlagDll);

	return bRet;
}

void CIP2Country::RemoveAllIPs()
{
	for (int i = 0; i < m_iplist.GetCount(); ++i)
		delete m_iplist[i];
	m_iplist.RemoveAll();

	if(m_bRunning)
		theApp.QueueDebugLogLineEx(LOG_WARNING, GetResString(IDS_IP2COUNTRY_FILELOAD));
}

void CIP2Country::RemoveAllFlags()
{
	//destroy all images
	CountryFlagImageList.DeleteImageList();

	//also clean out the map table
	CountryIDtoFlagIndex.RemoveAll();

	if(m_bRunning)
		theApp.QueueDebugLogLineEx(LOG_WARNING, GetResString(IDS_IP2COUNTRY_FLAGUNLD));
}

void CIP2Country::AddIPRange(UINT IPfrom,UINT IPto, CString& shortCountryName, CString& midCountryName, CString& longCountryName)
{
	IPRange_Struct2* newRange = new IPRange_Struct2();
	newRange->IPstart = IPfrom;
	newRange->IPend = IPto;
	newRange->ShortCountryName = shortCountryName;
	newRange->MidCountryName = midCountryName;
	newRange->LongCountryName = longCountryName;

	if(m_bEnableCountryFlag)
	{
		const CRBMap<CString, uint16>::CPair* pair = CountryIDtoFlagIndex.Lookup(shortCountryName);
		if(pair != NULL)
			newRange->FlagIndex = pair->m_value;
		else
			newRange->FlagIndex = NO_FLAG;
	}
	else
	{
		//this value is useless if the country flag havn't been load up, should be safe I think ...
		//newRange->FlagIndex = NO_FLAG;
	}
	m_iplist.Add(newRange);
}

struct IPRange_Struct2* CIP2Country::GetCountryFromIP(UINT ClientIP)
{
	if(m_bEnableIP2Country == false || ClientIP == 0)
		return &defaultIP2Country;
	if(m_iplist.IsEmpty())
	{
		theApp.QueueDebugLogLineEx(LOG_ERROR, L"CIP2Country::GetCountryFromIP iplist doesn't exist");
		return &defaultIP2Country;
	}
	ClientIP = htonl(ClientIP);
	IPRange_Struct2** ppFound = (IPRange_Struct2**)bsearch(&ClientIP, m_iplist.GetData(), m_iplist.GetCount(), sizeof(m_iplist[0]), CmpIP2CountryByAddr);
	if (ppFound)
		return *ppFound;

	return &defaultIP2Country;
}

CString CIP2Country::GetCountryNameFromRef(IPRange_Struct2* m_structCountry, bool longName)
{
	if(m_bEnableIP2Country)
	{
		if(longName)
			return m_structCountry->LongCountryName;
		switch(thePrefs.GetIP2CountryNameMode()){
			case IP2CountryName_SHORT:
				return m_structCountry->ShortCountryName;
			case IP2CountryName_MID:
				return m_structCountry->MidCountryName;
			case IP2CountryName_LONG:
				return m_structCountry->LongCountryName;
		}
	}
	else if(longName)
		return GetResString(IDS_DISABLED);	
	return _T("");
}
bool CIP2Country::ShowCountryFlag() const
{
	return 
		//user wanna see flag,
		(thePrefs.IsIP2CountryShowFlag()
		//flag have been loaded
		&& m_bEnableCountryFlag
		//ip table have been loaded
		&& m_bEnableIP2Country);
}

void CIP2Country::UpdateIP2CountryURL()
{   
	CString sbuffer;
	CString strURL = thePrefs.GetIP2CountryUpdateVerURL(); //Version URL to keep it separated

	TCHAR szTempFilePath[_MAX_PATH];
//>>> shadow2004::AddonDirectory
	_tmakepathlimit(szTempFilePath, NULL, thePrefs.GetMuleDirectory(EMULE_ADDONDIR), DFLT_IP2COUNTRY_FILENAME, _T("tmp"));
//	_tmakepathlimit(szTempFilePath, NULL, thePrefs.GetConfigDir(), DFLT_IP2COUNTRY_FILENAME, _T("tmp"));
//<<< shadow2004::AddonDirectory
	FILE* readFile= _tfsopen(szTempFilePath, _T("r"), _SH_DENYWR);

	CHttpDownloadDlg dlgDownload;
	dlgDownload.m_strTitle = GetResString(IDS_IP2COUNTRY_DWNFILE);
	dlgDownload.m_sURLToDownload = strURL;
	dlgDownload.m_sFileToDownloadInto = szTempFilePath;
	if (dlgDownload.DoModal() != IDOK)
	{
		_tremove(szTempFilePath);
		AddLogLine(true, GetResString(IDS_LOG_ERRDWN), strURL);
		return;
	}
	readFile = _tfsopen(szTempFilePath, _T("r"), _SH_DENYWR);

	char buffer[9]; //Versionformat: Ymmdd -> 20040101
	int lenBuf = 9;
	fgets(buffer,lenBuf,readFile);
	sbuffer = buffer;
	sbuffer = sbuffer.Trim();
	fclose(readFile);
	_tremove(szTempFilePath);

    // Compare the Version numbers
	if ((thePrefs.GetIP2CountryVersion()< (UINT) _tstoi(sbuffer)) || !PathFileExists(GetDefaultFilePath())) {
		
		CString IP2CountryURL = thePrefs.GetIP2CountryUpdateURL();
		
//>>> shadow2004::AddonDirectory
		_tmakepathlimit(szTempFilePath, NULL, thePrefs.GetMuleDirectory(EMULE_ADDONDIR), DFLT_IP2COUNTRY_FILENAME, _T("tmp"));
		//_tmakepathlimit(szTempFilePath, NULL, thePrefs.GetConfigDir(), DFLT_IP2COUNTRY_FILENAME, _T("tmp"));
//<<< shadow2004::AddonDirectory

		CHttpDownloadDlg dlgDownload;
		dlgDownload.m_strTitle = GetResString(IDS_IP2COUNTRY_DWNFILE);
		dlgDownload.m_sURLToDownload = IP2CountryURL;
		dlgDownload.m_sFileToDownloadInto = szTempFilePath;
		if (dlgDownload.DoModal() != IDOK)
		{
			_tremove(szTempFilePath);
			LogError(LOG_STATUSBAR, GetResString(IDS_IP2COUNTRY_ERROR6));
			return;
		}
        
		bool bIsZipFile = false;
		bool bUnzipped = false;
		CZIPFile zip;
		if (zip.Open(szTempFilePath))
		{
			bIsZipFile = true;

			CZIPFile::File* zfile = zip.GetFile(DFLT_IP2COUNTRY_FILENAME); // It has to be a zip-file which includes a file called: ip-to-country.csv
			if (zfile)
			{
				TCHAR szTempUnzipFilePath[MAX_PATH];
//>>> shadow2004::AddonDirectory
				_tmakepathlimit(szTempUnzipFilePath, NULL, thePrefs.GetMuleDirectory(EMULE_ADDONDIR), DFLT_IP2COUNTRY_FILENAME, _T(".unzip.tmp"));
				//_tmakepathlimit(szTempUnzipFilePath, NULL, thePrefs.GetConfigDir(), DFLT_IP2COUNTRY_FILENAME, _T(".unzip.tmp"));
//<<< shadow2004::AddonDirectory
				if (zfile->Extract(szTempUnzipFilePath))
				{
					zip.Close();
					zfile = NULL;

					if (_tremove(GetDefaultFilePath()) != 0)
						TRACE("*** Error: Failed to remove default IP to Country file \"%s\" - %s\n", GetDefaultFilePath(), _tcserror(errno));
					if (_trename(szTempUnzipFilePath, GetDefaultFilePath()) != 0)
						TRACE("*** Error: Failed to rename uncompressed IP to Country file \"%s\" to default IP to Country file \"%s\" - %s\n", szTempUnzipFilePath, GetDefaultFilePath(), _tcserror(errno));
					if (_tremove(szTempFilePath) != 0)
						TRACE("*** Error: Failed to remove temporary IP to Country file \"%s\" - %s\n", szTempFilePath, _tcserror(errno));
					bUnzipped = true;
				}
				else
					LogError(LOG_STATUSBAR, GetResString(IDS_IP2COUNTRY_ERROR7), szTempFilePath);
			}
			else
				LogError(LOG_STATUSBAR, GetResString(IDS_IP2COUNTRY_ERROR8), szTempFilePath); //File not found inside the zip-file

			zip.Close();
		}
        
		if (!bIsZipFile && !bUnzipped)
		{
			_tremove(GetDefaultFilePath());
			_trename(szTempFilePath, GetDefaultFilePath());
		}

		if(bIsZipFile && !bUnzipped)
			return;

		theApp.ip2country->Unload();
		AddLogLine(false,GetResString(IDS_IP2COUNTRY_UPUNLOAD));
		theApp.ip2country->Load();
		AddLogLine(false,GetResString(IDS_IP2COUNTRY_UPLOAD));

		thePrefs.SetIP2CountryVersion(_tstoi(sbuffer)); //Commander - Added: Update version number
		thePrefs.Save();
	}
}

CString CIP2Country::GetDefaultFilePath() const
{
//>>> shadow2004::AddonDirectory
	return thePrefs.GetMuleDirectory(EMULE_ADDONDIR) + DFLT_IP2COUNTRY_FILENAME;
//	return thePrefs.GetConfigDir() + DFLT_IP2COUNTRY_FILENAME;
//<<< shadow2004::AddonDirectory
}
//<<< shadow2004::IP2Country [EastShare]