//>> pP: CReport
//
bool CPreferences::m_bCreateReportFileOnClose;
void CPreferences::CreateReportFile(bool bForceSimpleFilename)
{
	CString strFileListPath;
	CString strFile;
	CString StrPath;

	StrPath.Format(L"%s", thePrefs.GetDefaultDirectory(EMULE_EXECUTEABLEDIR));

	// we can only use the explicit filename on NTFS drives...
	bool bNtfs;
	CString strRootPath(GetDefaultDirectory(EMULE_CONFIGDIR)+L"preferences.ini");
	BOOL bResult = PathStripToRoot(strRootPath.GetBuffer());
	strRootPath.ReleaseBuffer();
	if (!bResult)
		bNtfs = false;
	else
	{
		PathAddBackslash(strRootPath.GetBuffer());
		strRootPath.ReleaseBuffer();

		DWORD dwMaximumComponentLength = 0;
		DWORD dwFileSystemFlags = 0;
		TCHAR szFileSystemNameBuffer[128];
		if (!GetVolumeInformation(strRootPath, NULL, 0, NULL, &dwMaximumComponentLength, &dwFileSystemFlags, szFileSystemNameBuffer, 128))
			bNtfs = false;
		else
			bNtfs = (_tcscmp(szFileSystemNameBuffer, L"NTFS") == 0);
	}

	if (bNtfs && !bForceSimpleFilename)
	{
		strFile.Format(L"[%s] Stats - %s.txt", SZ_MODVERSION_NAME, CTime::GetCurrentTime().Format(L"%c"));
		strFile.Replace(L":", L"-"); // no ":" allowed in filenames
		strFile.Replace(L"/", L"."); // no "/" allowed in filenames // US date fix // r9f2
	}
	else
		strFile = L"report.txt";

	strFileListPath.Format(L"%s%s", StrPath, strFile);
	//
	CString strTmpFileListPath = strFileListPath;
	PathRenameExtension(strTmpFileListPath.GetBuffer(MAX_PATH), L".tmp");
	strTmpFileListPath.ReleaseBuffer();
	//
	CSafeBufferedFile file;
	CFileException fexp;
	//
	if (!file.Open(strTmpFileListPath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary | CFile::shareDenyWrite, &fexp))
	{
		CString strError;
		TCHAR szError[MAX_CFEXP_ERRORMSG];
		if (fexp.GetErrorMessage(szError, ARRSIZE(szError)))
		{
			strError += L" - ";
			strError += szError;
		}
		LogError(L"Failed to create Stats export - Errorcode: '%s'", strError);
		LogError(L"--> Path: '%s'", StrPath);
		LogError(L"--> File: '%s'", strFile);
		LogError(L"--> Using FallBack mode filename 'report.txt'");
		CreateReportFile(true);
		return;
	}
	// write Unicode byte-order mark 0xFEFF
	fputwc(0xFEFF, file.m_pStream);
	//
	// create create the report strings
	CString str2File = GetReportString(false); 
	CString str2Clip = GetReportString(true); //>> pP: CReport [phpbb tags]
	//
	try
	{
		file.printf(str2File); // write to disk
		str2File.Empty();
		//
		if (GetCommitFiles() >= 2 || (GetCommitFiles() >= 1 && !theApp.emuledlg->IsRunning()))
		{
			file.Flush(); // flush file stream buffers to disk buffers
			if (_commit(_fileno(file.m_pStream)) != 0) // commit disk buffers to disk
				AfxThrowFileException(CFileException::hardIO, GetLastError(), file.GetFileName());
		}
		file.Close();
		AddLogLine(true, L"CReport: A new report was created in '%s'", strFileListPath);

		theApp.CopyTextToClipboard(str2Clip); // copy to clipboard //>> pP: CReport [phpbb tags]
		str2Clip.Empty();

		CString strBakFileListPath = strFileListPath;
		PathRenameExtension(strBakFileListPath.GetBuffer(MAX_PATH), L".bak");
		strBakFileListPath.ReleaseBuffer();

		if (_taccess(strBakFileListPath, 0) == 0)
			CFile::Remove(strBakFileListPath);
		if (_taccess(strFileListPath, 0) == 0)
			CFile::Rename(strFileListPath, strBakFileListPath);
		CFile::Rename(strTmpFileListPath, strFileListPath);
	}
	catch(CFileException* e)
	{
		CString strError;
		TCHAR szError[MAX_CFEXP_ERRORMSG];
		if (e->GetErrorMessage(szError, ARRSIZE(szError)))
		{
			strError += L" - ";
			strError += szError;
		}
		LogError(L"Failed to write stats export - Error '%s'", strError);
		LogError(L"--> Path: '%s'", StrPath);
		LogError(L"--> File: '%s'", strFile);

		e->Delete();
		file.Abort();
		(void)_tremove(file.GetFilePath());
	}
}

CString CPreferences::GetReportString(bool b) // b=true -> export with phpbb tags 
{
	UINT   FoundSources = 0;
	UINT   ValidSources = 0;
	UINT   ActiveDownloads = 0;
	UINT   RunningDownloads = 0;
	UINT   AllDownloads = 0;
	UINT   NNS = 0;
	UINT   QF  = 0;
	UINT   UNK = 0;
	UINT   TM  = 0;
	UINT   Banned = 0;
	//
	time_t	sessionRunTime = ((GetTickCount() - theStats.starttime)/1000); // fix 47a
	//
	POSITION pos;
	pos=theApp.downloadqueue->GetFileHeadPosition();
	while (pos)
	{
		CPartFile* cur_file=theApp.downloadqueue->GetNextFile(pos);
		AllDownloads++;
		if (!cur_file->IsStopped())
		{
			ActiveDownloads++;
			//
			NNS		+= cur_file->GetSrcStatisticsValue(DS_NONEEDEDPARTS);
			QF		+= cur_file->GetSrcStatisticsValue(DS_REMOTEQUEUEFULL);
			UNK		+= cur_file->GetSrcStatisticsValue(DS_NONE);
			TM		+= cur_file->GetSrcStatisticsValue(DS_TOOMANYCONNS);
			Banned	+= cur_file->GetSrcStatisticsValue(DS_BANNED);
			//
			FoundSources	 += cur_file->GetSourceCount();
			ValidSources	 += cur_file->GetValidSourcesCount();
			RunningDownloads += cur_file->GetTransferringSrcCount();
		}
	}
	CString MyString = L"";

	//>> pP: CReport [phpbb tags]
	CString tagf = L"", tagb = L"";
	if (b)
	{
		tagf = L"[b][u]";   // leading tag 
		tagb = L"[/b][/u]"; // closing tag
	}
	//<< pP: CReport [phpbb tags]

	CString str;
	str.Format(L"%s", SZ_MODVERSION_NAME);

	// generate report
	MyString.Format(L"%s> Mod-Statistics report for:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> eMule v%s [%s]\r\n",theApp.m_strCurVersionLong, str);
	MyString.AppendFormat(L"|--> Created: %s\r\n", CTime::GetCurrentTime().Format(L"%c"));
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
/*	//>> evl: SysInfo
	CString strCpuSpeed;
	if (theApp.sysinfo->GetCPUSpeed()>1000)
		strCpuSpeed.Format(L"%.2f Ghz", (float)theApp.sysinfo->GetCPUSpeed()/1000.0f);
	else 
		strCpuSpeed.Format(L"%u Mhz", theApp.sysinfo->GetCPUSpeed());

	MyString.AppendFormat(L"%s> System Info:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> CPU    : %s (%s)\r\n", theApp.sysinfo->GetCPUNameString(), strCpuSpeed);
	MyString.AppendFormat(L"|--> Usage  : %3d%% (%3d%%)\r\n", GetCpuUsage(theApp.m_pszExeName), GetCpuUsage());
	MyString.AppendFormat(L"|--> Memory : %s\r\n", CastItoXBytes(theApp.sysinfo->GetTotalPhys()));
	MyString.AppendFormat(L"|--> Usage  : %s (%s)\r\n", CastItoXBytes((uint16)theApp.sysinfo->GetProcessMemoryUsage(), true), CastItoXBytes(theApp.sysinfo->GetGlobalMemoryUsage()));
	MyString.AppendFormat(L"|--> OS     : %s\r\n", theApp.sysinfo->GetOSType());
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//<< evl: SysInfo
*/	//
	MyString.AppendFormat(L"%s> eMule Settings:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> Linecapacities  u/d : %i/%i [kiB/s]\r\n", maxGraphUploadRate, maxGraphDownloadRate);
	MyString.AppendFormat(L"|--> Linelimits      u/d : %i/%i [kiB/s]\r\n", GetMaxUpload(), GetMaxDownload());
	MyString.AppendFormat(L"|--> Max. srcs per file  : %i\r\n", maxsourceperfile);
	MyString.AppendFormat(L"|--> Max. conns          : %i\r\n", maxconnections);
	MyString.AppendFormat(L"|--> Max. conns per 5 sec: %i\r\n", GetMaxConperFive());
	MyString.AppendFormat(L"|--> Max. halfopen conns.: %i\r\n", GetMaxHalfConnections());
	MyString.AppendFormat(L"|--> Uses standard ports : %s %s\r\n", (port == 4662 && udpport == 4672) ? L"yes" : L"no", /*thePrefs.GetUseRandomPorts() ? L"(random)" : */ L"(static)");
	MyString.AppendFormat(L"|--> UPnP activated      : %s\r\n", IsUPnPEnabled() ? L"yes" : L"no");
	MyString.AppendFormat(L"|--> Filebuffer size     : %.2f MiB\r\n", (float)m_iFileBufferSize / 1048576);
	MyString.AppendFormat(L"|--> Waiting Queuesize   : %i\r\n", m_iQueueSize);
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	MyString.AppendFormat(L"%s> Connectionstats:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> Networks connected  : ed2k %s, Kad %s\r\n", theApp.serverconnect->IsConnected() ? L"on" : L"off", Kademlia::CKademlia::IsConnected() ? L"on" : L"off");
	MyString.AppendFormat(L"|--> Peak connections    : %i\r\n", theApp.listensocket->GetPeakConnections());
	MyString.AppendFormat(L"|--> Average connections : %i\r\n", (int)theApp.listensocket->GetAverageConnections());
	MyString.AppendFormat(L"|--> Conn. limit reached : %i times\r\n", theApp.listensocket->GetMaxConnectionReached());
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	MyString.AppendFormat(L"%s> Transferstats:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> Session runtime     : %s\r\n",CastSecondsToLngHM(sessionRunTime));
	MyString.AppendFormat(L"|--> Uploaded data       : %s\r\n", CastItoXBytes(theStats.sessionSentBytes, false, false));
	MyString.AppendFormat(L"|--> Downloaded data     : %s\r\n", CastItoXBytes( theStats.sessionReceivedBytes, false, false ));
	//
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	if (theStats.sessionReceivedBytes<theStats.sessionSentBytes)
		MyString.AppendFormat(L"|--> u/d ratio           : %.2f : 1\r\n",theStats.sessionReceivedBytes>0?(float)theStats.sessionSentBytes/theStats.sessionReceivedBytes:0);
	else if (theStats.sessionReceivedBytes>theStats.sessionSentBytes)
		MyString.AppendFormat(L"|--> u/d ratio           : 1 : %.2f\r\n",theStats.sessionSentBytes>0?(float)theStats.sessionReceivedBytes/theStats.sessionSentBytes:0);
	else
		MyString.AppendFormat(L"|--> u/d ratio           : 1 : 1\r\n");
	//
	MyString.AppendFormat(L"|--> Avg. uploadrate     : %s\r\n", CastItoXBytes(theStats.GetAvgUploadRate(AVG_SESSION), true, true));
	MyString.AppendFormat(L"|--> Peak uploadrate     : %s\r\n", CastItoXBytes(theStats.maxUp, true, true));
	MyString.AppendFormat(L"|--> Avg. downloadrate   : %s\r\n", CastItoXBytes(theStats.GetAvgDownloadRate(AVG_SESSION), true, true));
	MyString.AppendFormat(L"|--> Peak downloadrate   : %s\r\n", CastItoXBytes(theStats.maxDown, true, true));
	MyString.AppendFormat(L"|--> Lost to corruption  : %s\r\n", CastItoXBytes(thePrefs.GetSesLostFromCorruption(), false, false));
	//
	float sup = (float)(theApp.uploadqueue->GetSuccessfullUpCount()+theApp.uploadqueue->GetUploadQueueLength());// successful up sessions
	float fup = (float)theApp.uploadqueue->GetFailedUpCount();													// failed up sessions
	float sdn = (float)(thePrefs.GetDownS_SuccessfulSessions()+RunningDownloads);								// successful dn sessions
	float fdn = (float)thePrefs.GetDownS_FailedSessions();														// failed dn sessions
	float upfailedpercent = 0.0f;
	float upsuccpercent   = 0.0f;
	float dnfailedpercent = 0.0f;
	float dnsuccpercent   = 0.0f;
	//
	if (sup+fup > 0.0f)
	{
		upfailedpercent = (fup) / ((sup+fup) / 100.0f);
		upsuccpercent   = (sup) / ((sup+fup) / 100.0f);
	}
	if (sdn+fdn > 0.0f)
	{
		dnfailedpercent = (fdn) / ((sdn+fdn) / 100.0f);
		dnsuccpercent   = (sdn) / ((sdn+fdn) / 100.0f);
	}
	//
	MyString.AppendFormat(L"|--> DL Sessions         : success %i (%.2f %%), failed %i (%.2f %%)\r\n", thePrefs.GetDownS_SuccessfulSessions(), dnsuccpercent, thePrefs.GetDownS_FailedSessions(), dnfailedpercent);
	MyString.AppendFormat(L"|--> UL Sessions         : success %i (%.2f %%), failed %i (%.2f %%)\r\n", theApp.uploadqueue->GetSuccessfullUpCount(), upsuccpercent, theApp.uploadqueue->GetFailedUpCount(), upfailedpercent);
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	MyString.AppendFormat(L"%s> Downloadqueue:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> Found sources       : %i\r\n", FoundSources);
	MyString.AppendFormat(L"|--> Valid sources       : %i\r\n", ValidSources);
	MyString.AppendFormat(L"|--> NoNeededParts       : %i\r\n", NNS);
	MyString.AppendFormat(L"|--> QueueFull           : %i\r\n", QF);
	MyString.AppendFormat(L"|--> Unknown             : %i\r\n", UNK);
	MyString.AppendFormat(L"|--> TooMany             : %i\r\n", TM);
	MyString.AppendFormat(L"|--> Banned (both-way)   : %i\r\n", Banned);
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	MyString.AppendFormat(L"%s> Uploadqueue:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> Waiting on queue    : %i\r\n", theApp.uploadqueue->GetWaitingUserCount());
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	MyString.AppendFormat(L"%s> ClientAnalyzer:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> Nickthieveries      : %u\r\n",	theApp.antileechlist->GetBadActionCounter(0));
	MyString.AppendFormat(L"|--> Modthieveries       : %u\r\n",	theApp.antileechlist->GetBadActionCounter(1));
	MyString.AppendFormat(L"|--> File fakes          : %u\r\n",	theApp.antileechlist->GetBadActionCounter(2));
	MyString.AppendFormat(L"|--> UDP-FNF fakes       : %u\r\n",	theApp.antileechlist->GetBadActionCounter(3));
	MyString.AppendFormat(L"|--> Fast asks           : %u\r\n",	theApp.antileechlist->GetBadActionCounter(4));
	MyString.AppendFormat(L"|--> Spams               : %u\r\n",	theApp.antileechlist->GetBadActionCounter(5));
	MyString.AppendFormat(L"|--> FastXS              : %u\r\n", theApp.antileechlist->GetBadActionCounter(6));
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	MyString.AppendFormat(L"%s> Filestats:%s\r\n", tagf, tagb); //>> pP: CReport [phpbb tags]
	MyString.AppendFormat(L"|--> Overall files       : %i\r\n", AllDownloads);
	MyString.AppendFormat(L"|--> Active files        : %i\r\n", ActiveDownloads);
	MyString.AppendFormat(L"|--> Running downloads   : %i\r\n", RunningDownloads);
	MyString.AppendFormat(L"|--> Running uploads     : %i\r\n", theApp.uploadqueue->GetUploadQueueLength());
	MyString.AppendFormat(L"|--> Finished files      : %i\r\n", GetDownSessionCompletedFiles());
	MyString.AppendFormat(L"|\r\n");  // new chapter
	//
	MyString.AppendFormat(L"| **** Modded  by unseen.evil ****\r\n");
	MyString.AppendFormat(L"| **** for www.specialmods.eu ****\r\n");
	//
	//>> pP: CReport [phpbb tags]
	if (b)
		return (L"[quote]" + MyString + L"[/quote]");
	//<< pP: CReport [phpbb tags]

	return MyString;
}
//<< pP: CReport