// epsAspInitDlg.cpp : implementation file
//

#include "stdafx.h"
#include "epsAspInit.h"
#include "epsAspInitDlg.h"
#include "resource.h"

#include "../common/eps1kDemo.h"
#include "../common/eps1kUtility.h"

#define DMEO_KEYFILE_1    0x1
#define DMEO_KEYFILE_2    0x2
#define DEMO_DIR_NAME     "ASP_DEMO"

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

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CEpsAspInitDlg dialog

CEpsAspInitDlg::CEpsAspInitDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CEpsAspInitDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CEpsAspInitDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CEpsAspInitDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CEpsAspInitDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CEpsAspInitDlg, CDialog)
	//{{AFX_MSG_MAP(CEpsAspInitDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CEpsAspInitDlg message handlers

BOOL CEpsAspInitDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	ZeroMemory(&m_sn,sizeof(char));
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CEpsAspInitDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CEpsAspInitDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CEpsAspInitDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

// Format the ePass error code to a string.
char* FormatErrMsg(EPAS_STATUS status)
{
    switch( status )
    {
        case FT_SUCCESS:
            return ("");
        case FT_CANNOT_OPEN_DRIVER:
            return ("Error : Can't open the driver.");
        case FT_INVALID_DRVR_VERSION:
            return ("Error : Driver version not supported.");
        case FT_INVALID_COMMAND:
            return ("Error : Invalid command sent to API.");
        case FT_ACCESS_DENIED:
            return ("Error : Access denied.");
        case FT_ALREADY_ZERO: 
            return ("Error : Counter already zero.");
        case FT_UNIT_NOT_FOUND:
            return ("Error : Device not found.");
        case FT_DEVICE_REMOVED:
            return ("Error : Device removed.");
        case FT_COMMUNICATIONS_ERROR: 
            return ("Error : Device communication error.");
        case FT_DIR_NOT_FOUND:
            return ("Error : Directory does not exist.");
        case FT_FILE_NOT_FOUND:
            return ("Error : File not found.");
        case FT_MEM_CORRUPT:
            return ("Error : Device memory is corrupted.");
        case FT_INTERNAL_HW_ERROR:
            return ("Error : Internal hardware error.");
        case FT_INVALID_RESP_SIZE:
            return ("Error : Invalid response received from the device.");
        case FT_PIN_EXPIRED: 
            return ("Error : PIN retry attempts has expired.");
        case FT_ALREADY_EXISTS: 
            return ("Error : Directory or file already exist.");
        case FT_NOT_ENOUGH_MEMORY: 
            return ("Error : Not enough memory to perform the operation.");
        case FT_INVALID_PARAMETER: 
            return ("Error : Invalid parameter sent to API.");
        case FT_INPUT_TOO_LONG: 
            return ("Error : Input data is too long.");
        case FT_INVALID_FILE_SELECTED: 
            return ("Error : Invalid file selected or operation.");
        case FT_DEVICE_IN_USE: 
            return ("Error : The device is currently in use.");
        case FT_INVALID_API_VERSION: 
            return ("Error : The version of this library is not supported.");
        case FT_TIME_OUT_ERROR: 
            return ("Error : Communication time-out.");
        case FT_ITEM_NOT_FOUND: 
            return ("Error : Item not found."); 
        case FT_COMMAND_ABORTED: 
            return ("Error : Communication error, command aborted.");
        case FT_INVALID_STATUS: 
            return ("Error : Invalid status.");
        default: 
            return ("Error : An unknown error occurred.");
    }
} // End of FormatErrMsg().

void CEpsAspInitDlg::OnOK() 
{
	CString strInfo;

	//////////////////////////////////////////////////////////////////////////
	// Get the necessary information to create the KEY files.

//	CString strUserName;
	CString strPassword;
	CString strCnfrmPswd;
	CString strTempUN;
	CString strTempPW;

//	GetDlgItemText(IDC_EDIT_USERNAME,strUserName);
	GetDlgItemText(IDC_EDIT_PSWD,strPassword);
	GetDlgItemText(IDC_EDIT_CNFRM_PSWD,strCnfrmPswd);

	if (lstrcmpi(strPassword,strCnfrmPswd) != 0)
	{
		AfxMessageBox("The password you input are not same.");
		return;
	}

	if (strPassword.IsEmpty() || strCnfrmPswd.IsEmpty())
	{
		AfxMessageBox("You must gave me enough information to create KEY file.");
		return;
	}


	//////////////////////////////////////////////////////////////////////////
	// Software-compute the MD5_HMAC and create context of key files.
	unsigned char pucKey1[16];
	unsigned char pucKey2[16];
	unsigned char pucDigest[16];

	MD5_HMAC(
		NULL,
		0,
		(unsigned char*)(LPCSTR)strPassword,
		strPassword.GetLength(),
		pucKey1,
		pucKey2,
		pucDigest
		);

	//////////////////////////////////////////////////////////////////////////
	// ePass operation.
	EPAS_STATUS epsRet;
	EPAS_HANDLE epsHandle;

	// Create context handle.
	epsRet = epas_CreateContext(
		&epsHandle,
		0,
		EPAS_API_VERSION);

	// Open device.
	if (FT_SUCCESS == epsRet)
	{
		epsRet = epas_OpenDevice(epsHandle,
			EPAS_OPEN_FIRST,
			NULL);
	}

	//add by Zhu Yangsheng 
	//date:2003/5/26
	//purpose:Get the token sn to insert user.txt
	unsigned long sn[2]={0,0};
	epsRet = epas_GetProperty(epsHandle,EPAS_PROP_SERNUM,0,sn,2*sizeof(unsigned long));
	//m_sn = {0,};
	sprintf(m_sn, "%08X%08X", sn[1], sn[0]);

	// Create a directory in ePass.
	// If the directory had exists, remove it first and re-create it.
	EPAS_DIRINFO di;
	ZeroMemory(&di,sizeof(EPAS_DIRINFO));
	if (FT_SUCCESS == epsRet)
	{
		epsRet = epas_CreateDir(epsHandle,
			EPAS_CREATE_AUTO_ID,
			(unsigned char*)DEMO_DIR_NAME,
			NULL,
			&di,
			sizeof(EPAS_DIRINFO));
	}

	if (FT_ALREADY_EXISTS == epsRet)
	{
		epsRet = epas_DeleteDir(epsHandle,
			EPAS_DIR_BY_NAME,
			0,
			(unsigned char*)DEMO_DIR_NAME);
		if (FT_SUCCESS == epsRet)
		{
			// Re-create.
			epsRet = epas_CreateDir(epsHandle,
				EPAS_CREATE_AUTO_ID,
				(unsigned char*)DEMO_DIR_NAME,
				NULL,
				&di,
				sizeof(EPAS_DIRINFO));
		}
	}

	// Create KEY files
	if (FT_SUCCESS == epsRet)
	{
		EPAS_FILEINFO fi;
		unsigned long ulWritten;

		ZeroMemory(&fi, sizeof(EPAS_FILEINFO));
		fi.ucFileType = EPAS_FILETYPE_KEY;
		fi.ulID = 0x1;
		fi.ulFileSize = 16;
		fi.ucReadAccess = EPAS_ACCESS_NONE;
		fi.ucCryptAccess = EPAS_ACCESS_USER;
		fi.ucWriteAccess = EPAS_ACCESS_ANYONE;

		epsRet = epas_CreateFile(epsHandle,
			0,
			&fi,
			sizeof(EPAS_FILEINFO));
		if (FT_SUCCESS == epsRet)
		{
			epsRet = epas_Write(epsHandle,
				0,							// Must set to ZERO
				0,							// Offset.
				pucKey1,
				16,
				&ulWritten);
		}

		if (FT_SUCCESS == epsRet)
		{
			fi.ulID = 0x2;
			epsRet = epas_CreateFile(epsHandle,
				0,
				&fi,
				sizeof(EPAS_FILEINFO));
		}

		if (FT_SUCCESS == epsRet)
		{
			epsRet = epas_Write(epsHandle,
				0,
				0,
				pucKey2,
				16,
				&ulWritten);
		}
	}

	if (FT_SUCCESS != epsRet)
	{
		strInfo.Format(
			"Initialize ePass failed.\n\n%s",
			FormatErrMsg(epsRet));
		AfxMessageBox(strInfo);

		// Remember remove the user data file "User.txt" if failed.
	//我将对文件的操作放到下面去操作了，所以我删除了这里的操作
	//	fUser.Remove("user.txt");
	}
	else
	{
		AfxMessageBox("OK! ePass now initialized!\n\nYou can use it to logon the demo ASP site.");
	}

	epsRet = epas_CloseDevice(epsHandle);
	epsRet = epas_DeleteContext(epsHandle);

		//////////////////////////////////////////////////////////////////////////
	// File operation.

	CStdioFile fUser;
	CFileException ex;

	// Create the file "user.txt" to write.

	if (!fUser.Open("user.txt",
			CFile::modeReadWrite |
			CFile::modeNoTruncate |
			CFile::modeCreate,
			&ex))
	{
		TCHAR szError[1024];
		ex.GetErrorMessage(szError, 1024);
		strInfo.Format("Couldn't open data file : %s",szError);
		AfxMessageBox(strInfo);
		return;
	}

	// First search whether the username had exists.
	BOOL bExists = FALSE;
	BOOL bRead = TRUE;
	while (bRead)
	{
		bRead = fUser.ReadString(strTempUN);
		if (bRead)
		{
			bRead = fUser.ReadString(strTempPW);
		}
		CString strUserName = m_sn;
		if (strTempUN == strUserName)
		{
			bExists = TRUE;
		}

	}

	if (!bExists)
	{
		fUser.WriteString(m_sn);
		//here we should write sn
		fUser.WriteString("\n");
		fUser.WriteString(strPassword);//,strPassword.GetLength());
		fUser.WriteString("\n");
	}
	else
	{
		AfxMessageBox("Sorry, the user had exists.",MB_OK | MB_ICONSTOP);
		fUser.Close();
		return;
	}


	fUser.Close();

	// Call the CDialog::OnOK() to close the window
	// and exit the demonstrator program.
	CDialog::OnOK();
}
