#include "stdafx.h"
#include "SecurityPasswordDlg.h"
#include <math.h>
//#include <aplBaseLib.h>
//#include "SecurityPasswordDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CChangePasswordDlg dialog


CSecurityPasswordDlg::CSecurityPasswordDlg(CaplAPI *api, CSecuritySettings* pSecurity, CWnd* pParent /*=NULL*/)
: CaplTranslateDialog(CSecurityPasswordDlg::IDD, pParent)
{
	ASSERT(api);
	m_api = api;

	ASSERT(pSecurity);
	m_pSecurity = pSecurity;
}


CSecurityPasswordDlg::~CSecurityPasswordDlg()
{
}

void CSecurityPasswordDlg::DoDataExchange(CDataExchange* pDX)
{
	CaplTranslateDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CChangePasswordDlg)
	DDX_Control(pDX, IDOK, m_ok_btn);
	DDX_Control(pDX, IDCANCEL, m_cancel_btn);

	DDX_Control(pDX, IDC_UPPER_CHECK, m_acSymbolsCheck[CSecuritySettings::ECT_UPPER]);
	DDX_Control(pDX, IDC_LOWER_CHECK, m_acSymbolsCheck[CSecuritySettings::ECT_LOWER]);
	DDX_Control(pDX, IDC_DIGIT_CHECK, m_acSymbolsCheck[CSecuritySettings::ECT_DIGIT]);
	DDX_Control(pDX, IDC_SPECIAL_CHECK, m_acSymbolsCheck[CSecuritySettings::ECT_SPECIAL]);

	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CSecurityPasswordDlg, CaplTranslateDialog)
	//{{AFX_MSG_MAP(CChangePasswordDlg)
	//}}AFX_MSG_MAP
	ON_EN_CHANGE(IDC_MIN_SIZE, &CSecurityPasswordDlg::OnEnChangeMinSize)
	ON_COMMAND_RANGE(IDC_UPPER_CHECK, IDC_SPECIAL_CHECK, &CSecurityPasswordDlg::OnBnClickedSymbolTypeCheck)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChangePasswordDlg message handlers

void CSecurityPasswordDlg::OnOK() 
{
	m_pSecurity->SaveToOptions();

	CaplTranslateDialog::OnOK();
}

BOOL CSecurityPasswordDlg::OnInitDialog() 
{
//	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	CaplTranslateDialog::OnInitDialog();

	m_cancel_btn.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));
	m_cancel_btn.SetFlat(FALSE);
	m_ok_btn.SetIcon(GetAplStdIco16(APLSTDICO_OK));
	m_ok_btn.SetFlat(FALSE);

	// Надежность пароля
	SetDlgItemText(IDC_SECURITY_LEVEL, m_pSecurity->GetPasswordSecurityStr());

	SetDlgItemInt(IDC_MIN_SIZE, m_pSecurity->m_iMinSize);
	for (int i = 0; i < CSecuritySettings::ECT_COUNT; ++i)
		m_acSymbolsCheck[i].SetCheck(m_pSecurity->m_aiSymbolTypes[i]);

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

CString CSecuritySettings::GetPasswordSecurityStr() const
{
	const ESecurityType& eSecurType = GetPasswordSecurity();

	// Надежность пароля
	switch(eSecurType)
	{
	case EST_LOW:
		{
			return APL_T("Низкая");
		}
	case EST_NORMAL:
		{
			return APL_T("Нормальная");
		}
	case EST_HARD:
		{
			return APL_T("Высокая");
		}
	}

	return APL_T("Не определена");
}

// Получить уровень надежности пароля
CSecuritySettings::ESecurityType CSecuritySettings::GetPasswordSecurity() const
{
	if (m_iMinSize == 0 || (!m_aiSymbolTypes[ECT_DIGIT] && !m_aiSymbolTypes[ECT_UPPER] && !m_aiSymbolTypes[ECT_LOWER] && !m_aiSymbolTypes[ECT_SPECIAL]))
		return EST_COUNT;

	double iSymbolVariantCount = 0;
	if (m_aiSymbolTypes[ECT_DIGIT])
		iSymbolVariantCount += DIGITS_COUNT;
	if (m_aiSymbolTypes[ECT_LOWER])
		iSymbolVariantCount += LOWER_COUNT;
	if (m_aiSymbolTypes[ECT_UPPER])
		iSymbolVariantCount += UPPER_COUNT;
	if (m_aiSymbolTypes[ECT_SPECIAL])
		iSymbolVariantCount += SPECIAL_COUNT;

	double iPasswordVariantCount = pow(iSymbolVariantCount, m_iMinSize);
	if (iPasswordVariantCount < PWD_BRUTE_FORCE_NORMAL_COUNT)
		return EST_LOW;
	else if (iPasswordVariantCount < PWD_BRUTE_FORCE_HARD_COUNT)
		return EST_NORMAL;
	else
		return EST_HARD;

	return EST_COUNT;
} 

void CSecurityPasswordDlg::OnEnChangeMinSize()
{
	m_pSecurity->m_iMinSize = GetDlgItemInt(IDC_MIN_SIZE);
	SetDlgItemText(IDC_SECURITY_LEVEL, m_pSecurity->GetPasswordSecurityStr());
}

void CSecurityPasswordDlg::OnBnClickedSymbolTypeCheck(UINT id)
{
	CSecuritySettings::ECharType eType = CSecuritySettings::ECharType(id - IDC_UPPER_CHECK);
	if(m_acSymbolsCheck[eType].GetCheck()>0) 
	{
		m_pSecurity->m_aiSymbolTypes[eType] = true;
	}
	else
	{
		m_pSecurity->m_aiSymbolTypes[eType] = false;
	}

	SetDlgItemText(IDC_SECURITY_LEVEL, m_pSecurity->GetPasswordSecurityStr());
}

CSecuritySettings::CSecuritySettings(CaplAPI *api)
{
	ASSERT(api);
	m_api = api;

	m_iMinSize = PWD_MINIMAL_SIZE;
	m_aiSymbolTypes[ECT_UPPER] = true;
	m_aiSymbolTypes[ECT_LOWER] = true;
	m_aiSymbolTypes[ECT_DIGIT] = true;
	m_aiSymbolTypes[ECT_SPECIAL] = false;
}

// Проверить пароль на удовлетворение параметрам сложности
bool CSecuritySettings::CheckPassword(const CString& sPassword) const
{
	const int iPwdLen =	sPassword.GetLength();
	if (m_iMinSize > iPwdLen)
		return false;

	// Проверка символов
	if (!m_aiSymbolTypes[ECT_DIGIT] && !m_aiSymbolTypes[ECT_UPPER] && !m_aiSymbolTypes[ECT_LOWER] && !m_aiSymbolTypes[ECT_SPECIAL])
		return true;

	bool abCurSymbolTypes[ECT_COUNT] = {false, false, false, false};
	for (int i = 0; i < iPwdLen; ++i)
	{
		wchar_t wCh = sPassword[i];
		if (iswdigit(wCh))
			abCurSymbolTypes[ECT_DIGIT] = true;
		else if (iswupper(wCh))
			abCurSymbolTypes[ECT_UPPER] = true;
		else if (iswlower(wCh))
			abCurSymbolTypes[ECT_LOWER] = true;
		else if (iswpunct(wCh))
			abCurSymbolTypes[ECT_SPECIAL] = true;
	}

	for (int i = 0; i < ECT_COUNT; ++i)
	{
		if (m_aiSymbolTypes[i] && !abCurSymbolTypes[i])
			return false;
	}

	return true;
}

void CSecuritySettings::ReadFromOptions()
{
	CaplOptionsManager& m_options_mgr = m_api->m_options_mgr;

	m_options_mgr.GetOptionValueBN(APL_NO_T("Параметры паролей\\Минимальное число символов"), m_iMinSize);
	m_options_mgr.GetOptionValueBN(APL_NO_T("Параметры паролей\\Символы\\Заглавные буквы"), m_aiSymbolTypes[ECT_UPPER]);
	m_options_mgr.GetOptionValueBN(APL_NO_T("Параметры паролей\\Символы\\Строчные буквы"), m_aiSymbolTypes[ECT_LOWER]);
	m_options_mgr.GetOptionValueBN(APL_NO_T("Параметры паролей\\Символы\\Цифры"), m_aiSymbolTypes[ECT_DIGIT]);
	m_options_mgr.GetOptionValueBN(APL_NO_T("Параметры паролей\\Символы\\Специальные символы"), m_aiSymbolTypes[ECT_SPECIAL]);

}

void CSecuritySettings::SaveToOptions()
{
	CaplOptionsManager& m_options_mgr = m_api->m_options_mgr;

	m_options_mgr.CreateOption(APL_NO_T("Параметры паролей\\Минимальное число символов"), m_iMinSize);
	m_options_mgr.CreateOption(APL_NO_T("Параметры паролей\\Символы\\Заглавные буквы"), m_aiSymbolTypes[ECT_UPPER]);
	m_options_mgr.CreateOption(APL_NO_T("Параметры паролей\\Символы\\Строчные буквы"), m_aiSymbolTypes[ECT_LOWER]);
	m_options_mgr.CreateOption(APL_NO_T("Параметры паролей\\Символы\\Цифры"), m_aiSymbolTypes[ECT_DIGIT]);
	m_options_mgr.CreateOption(APL_NO_T("Параметры паролей\\Символы\\Специальные символы"), m_aiSymbolTypes[ECT_SPECIAL]);
}

CString CSecuritySettings::GetPasswordInfo() const
{
	CString sInfo;
	sInfo.Format(APL_T("%i и более символов,"), m_iMinSize);
	if (m_aiSymbolTypes[ECT_UPPER])
		sInfo += APL_T("заглавные буквы,");
	if (m_aiSymbolTypes[ECT_LOWER])
		sInfo += APL_T("строчные буквы,");
	if (m_aiSymbolTypes[ECT_DIGIT])
		sInfo += APL_T("цифры,");
	if (m_aiSymbolTypes[ECT_SPECIAL])
		sInfo += APL_T("специальные символы,");

	if (!sInfo.IsEmpty())
		sInfo.SetAt(sInfo.GetLength() - 1, _T('.'));

	return sInfo;
};