using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IndianHealthService.BMXNet.WinForm.Forms;
using IndianHealthService.BMXNet.Net;
using IndianHealthService.BMXNet.WinForm.Configuration;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Security.Principal;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace IndianHealthService.BMXNet.WinForm.Forms
{
public partial class VerifyCodeUpdateDialog : Form
{
///
/// Private variable that takes framework as parameter
///
private WinFramework _framework = null;
///
/// Login process, not sure if this is needed
///
private LoginProcess mylogin;
private RpmsConnectionSpec _connectionSpec = null;
///
/// The active ConnectionSpec being used to login. With care, the property can be changed or the instance can be modified during the AttemptingLogin and LoginAttempted events
/// with care.
///
public RpmsConnectionSpec ConnectionSpec
{
get { return _connectionSpec; }
set { _connectionSpec = value; }
}
private string _accessCode;
internal protected WinFramework Framework
{
get { return _framework; }
set { _framework = value; }
}
private bool isUpdateSuccessful;
public VerifyCodeUpdateDialog(WinFramework framework, RpmsConnectionSpec connspec, string accesscode)
{
this.Framework = framework;
this._accessCode = accesscode;
this.ConnectionSpec = connspec;
mylogin = new LoginProcess(framework);
InitializeComponent();
}
private bool _isSwitchServerModeEnabled = false;
public bool IsSwitchServerModeEnabled
{
get { return _isSwitchServerModeEnabled; }
set { _isSwitchServerModeEnabled = value; }
}
private void VerifyCodeUpdateDialog_Load(object sender, EventArgs e)
{
this.currentVerifyCodeEntry.Focus();
}
public void ShowView(IWin32Window anOwner)
{
this.ShowDialog(anOwner);
}
public VerifyCodeUpdateResult ShowVerifyChangeDialog(IWin32Window anOwner)
{
DialogResult dr = new DialogResult();
if (anOwner != null)
{
dr = this.ShowDialog(anOwner);
}
else
{
dr = this.ShowDialog();
}
VerifyCodeUpdateResult vr = new VerifyCodeUpdateResult();
vr.DialogResult = dr;
vr.WasVerifyCodeUpdatedSuccessfully = this.IsUpdateSuccessful;
return vr;
}
public IWin32Window UiOwner
{
get { return this.Owner; }
}
#region RpmsLoginView Members
public string Title
{
set { this.Text = value; }
}
public bool IsUpdateSuccessful
{
set { this.isUpdateSuccessful = value; }
get { return this.isUpdateSuccessful; }
}
public string CurrentVerifyCode
{
get { return this.currentVerifyCodeEntry.Text; }
}
public string AccessCode
{
set { this._accessCode = value; }
get { return this._accessCode; }
}
private string _updateMessage;
public string UpdateMessage
{
set { this._updateMessage = value; }
get { return this._updateMessage; }
}
public string NewVerifyCode
{
get { return this.NewVerifyCodeEntry.Text; }
}
public string RepeatNewVerifyCode
{
get { return this.RepeatVerifyCodeEntry.Text; }
}
public event EventHandler Ok;
public event EventHandler Cancel;
#endregion
public void CloseView()
{
this.Close();
}
private void okButton_Click(object sender, EventArgs e)
{
//make sure all fields were filled with values
if ((this.currentVerifyCodeEntry.Text.Length == 0) ||
(this.NewVerifyCodeEntry.Text.Length == 0) ||
(this.RepeatVerifyCodeEntry.Text.Length == 0) )
{
string message = "Please fill all blank fields";
string caption = "Verify Code Update";
MessageBoxButtons buttons = MessageBoxButtons.OK;
DialogResult result;
// Displays the MessageBox.
result = MessageBox.Show(message, caption, buttons);
}
else if (this.currentVerifyCodeEntry.Text.Contains("^") ||
this.NewVerifyCodeEntry.Text.Contains("^") ||
this.RepeatVerifyCodeEntry.Text.Contains("^"))
{
string message = "The character '^' is not allowed in any of the verify code entry fields.";
string caption = "Verify Code Update";
MessageBoxButtons buttons = MessageBoxButtons.OK;
DialogResult result;
//Display the MessageBox
result = MessageBox.Show(message, caption, buttons);
ResetVerifyCodeEntries();
}
else if (this.NewVerifyCodeEntry.Text != this.RepeatVerifyCodeEntry.Text)
{
string message = "Please key in the same verify code twice.";
string caption = "Verify Code Update";
MessageBoxButtons buttons = MessageBoxButtons.OK;
DialogResult result;
// Displays the MessageBox.
result = MessageBox.Show(message, caption, buttons);
}
else
{
//get all the values and ready to udpate
string currentVCode = this.currentVerifyCodeEntry.Text;
string newVCode = this.NewVerifyCodeEntry.Text;
string repeatVCode = this.RepeatVerifyCodeEntry.Text;
this.IsUpdateSuccessful = SendSecurityRequest(EncryptAccessVerifyCode(this.AccessCode,currentVCode,newVCode));
if (!this.IsUpdateSuccessful)
{
ResetVerifyCodeEntries();
}
}
}
private void cancelButton_Click(object sender, EventArgs e)
{
if (this.Cancel != null)
{
this.Cancel(this, new EventArgs());
}
}
public void ResetVerifyCodeEntries()
{
this.currentVerifyCodeEntry.Clear();
this.RepeatVerifyCodeEntry.Clear();
this.NewVerifyCodeEntry.Clear();
this.currentVerifyCodeEntry.Select();
}
public void ShowWait()
{
this.Cursor = Cursors.WaitCursor;
}
public void HideWait()
{
this.Cursor = Cursors.Default;
}
public String EncryptAccessVerifyCode(string anAccessCode, string aCurrentVerifyCode, string aNewVerifyCode)
{
BMXNetBroker broker = this.Framework.SocketBroker;
string accessVerifyPair = anAccessCode.ToUpper() + ";" + aNewVerifyCode.ToUpper() + ";" + aCurrentVerifyCode.ToUpper();
return broker.EncryptionProvider.Encrypt(accessVerifyPair);
}
private bool SendSecurityRequest(string encryptedAccessVerifyCode)
{
BMXNetSocketBroker broker = (BMXNetSocketBroker)this.Framework.SocketBroker;
string strReceive = "";
string cMSG;
string m_sWKID = "BMX";
string m_sWINH = "";
string m_sPRCH = "";
string m_sWISH = "";
string m_cHDR = broker.ADEBHDR(m_sWKID,m_sWINH,m_sPRCH,m_sWISH);
//open a TCP sockry
TcpClient mySocket = this.OpenConnectionCommon();
cMSG = broker.ADEBLDMsg(m_cHDR, "BMX CVC", encryptedAccessVerifyCode);
SendString(mySocket, cMSG, "");
strReceive = ReceiveString(mySocket);
//"2VERIFY CODE must be a mix of alpha and numerics."
//"3This code is the same as the current one."
//"4This has been used previously as the VERIFY CODE."
//"5VERIFY CODE must be different than the ACCESS CODE."
List rspMessages = new List(); // List of received messages
rspMessages.Add("Sorry that isn't the correct current code");
rspMessages.Add("Enter 8-20 characters mixed alphanumeric and punctuation (except '^', ';', ':').");
rspMessages.Add("VERIFY CODE must be a mix of alpha and numerics and punctuation."); // String element 2
rspMessages.Add("This code is the same as the current one."); // 3
rspMessages.Add("This has been used previously as the VERIFY CODE."); // 4
rspMessages.Add("VERIFY CODE must be different than the ACCESS CODE."); // 5
if (strReceive.StartsWith("M ERROR="))
{
string caption = "Verify Code Update";
MessageBoxButtons buttons = MessageBoxButtons.OK;
DialogResult result;
// Displays the MessageBox.
result = MessageBox.Show(strReceive, caption, buttons);
return false;
}
else
{
foreach (string errorMsg in rspMessages)
{
if (strReceive.Contains(errorMsg))
{
this.UpdateMessage = errorMsg;
string caption = "Verify Code Update";
MessageBoxButtons buttons = MessageBoxButtons.OK;
DialogResult result;
// Displays the MessageBox.
result = MessageBox.Show(errorMsg, caption, buttons);
return false;
}
}
//if the code runs here, it means the update is successful
if (strReceive.Contains("0"))
{
string message = "Verify code has been successfully updated. ";
MessageBoxButtons msgButtons = MessageBoxButtons.OK;
// Displays the MessageBox.
MessageBox.Show(message, "Verify Code Update", msgButtons);
return true;
}
else
{
this.UpdateMessage = strReceive;
string caption = "Verify Code Update";
MessageBoxButtons buttons = MessageBoxButtons.OK;
DialogResult result;
// Displays the MessageBox.
result = MessageBox.Show(strReceive, caption, buttons);
return false;
}
}
}
protected void SendString(TcpClient tcpClient, string cSendString, string cMult)
{
String encodedString = this.EncodeSendString(cSendString, cMult);
NetworkStream ns = tcpClient.GetStream();
ns.WriteTimeout = 20000;
byte[] sendBytes = Encoding.ASCII.GetBytes(encodedString);
ns.Write(sendBytes,0,sendBytes.Length);
return;
}
protected string EncodeSendString(String cSendString, String cMulti)
{
String encoded = null;
int nLen = cSendString.Length;
string sLen = nLen.ToString();
sLen = sLen.PadLeft(5, '0');
encoded = sLen + cSendString;
nLen += 15;
sLen = nLen.ToString();
sLen = sLen.PadLeft(5, '0');
encoded = "{BMX}" + sLen + encoded;
encoded = encoded + cMulti;
return encoded;
}
private string ReceiveString(TcpClient tcpClient)
{
NetworkStream ns = tcpClient.GetStream();
ns.ReadTimeout = 40000;
//TAE: This following is suspect. NetworkSTream Read and ReadTimeout provide
//the same behavior. Look at removing in the futuer. For now, this works.
int cyclePause = 25;
int cycles = 0;
DateTime start = DateTime.Now;
while (ns.DataAvailable == false)
{
if (cycles++ > 999)
break;
if ((DateTime.Now-start).TotalMilliseconds > 40000)
break;
Thread.Sleep(cyclePause);
}
if (!ns.DataAvailable)
{
this.Close();
throw new Exception("BMXNetBroker.ReceiveString timeout. Connection Closed.");
}
byte[] bReadBuffer = new byte[1024];
string sReadBuffer = "";
StringBuilder sbAll = new StringBuilder("", 1024);
int numberOfBytesRead = 0;
// Incoming message may be larger than the buffer size.
bool bFinished = false;
bool bStarted = false;
int lpBuf = 0;
string sError = "";
string sAppError = "";
do
{
numberOfBytesRead = ns.Read(bReadBuffer, 0, bReadBuffer.Length);
if ((numberOfBytesRead == 1)&&(bStarted == false))
{
//TAE: This following is suspect. If Read is blocking then this sleep is extra.
//This is rarely called
Thread.Sleep(15);
numberOfBytesRead += ns.Read(bReadBuffer,1, bReadBuffer.Length-1);
}
if (bStarted == false)
{
//Process error info at beginning of returned string
int nErrLen = bReadBuffer[0];
int nAppLen = bReadBuffer[bReadBuffer[0]+1];
if ((bReadBuffer[2] == 0)&&(bReadBuffer[3] == 0))
{ //special case: M error trap invoked in SND^XWBTCPC
lpBuf += 2;
}
sError = Encoding.ASCII.GetString(bReadBuffer, lpBuf + 1, nErrLen);
if (sError != "")
{
sAppError = Encoding.ASCII.GetString(bReadBuffer, lpBuf + 1 + nErrLen + 1, nAppLen);
throw new BMXNetException(sError);
}
sAppError = Encoding.ASCII.GetString(bReadBuffer, lpBuf+1+nErrLen+1, nAppLen);
lpBuf += (nErrLen + nAppLen + 2);
numberOfBytesRead -= (nErrLen + nAppLen + 2);
bStarted = true;
}
bFinished = FindChar(bReadBuffer, (char)4) > -1;
sReadBuffer = Encoding.ASCII.GetString(bReadBuffer, lpBuf, numberOfBytesRead);
lpBuf = 0;
if (bFinished)
{
sbAll.Append(sReadBuffer, 0, numberOfBytesRead -1);
}
else
{
sbAll.Append(sReadBuffer);
}
}
while(!bFinished);
String decodedReceiveString = sbAll.ToString();
return decodedReceiveString;
}
public static int FindChar(byte[] c, char y)
{
int n = 0;
int nRet = -1;
for (n = 0; n < c.Length; n++)
{
if (y == (char)c[n])
{
nRet = n;
break;
}
}
return nRet;
}
public static int FindChar(string s, char y)
{
int n = 0;
int nRet = -1;
foreach (char c in s)
{
if (y == c)
{
nRet = n;
break;
}
n++;
}
return nRet;
}
protected TcpClient OpenConnectionCommon()
{
try
{
TcpClient connector = null;
try
{
BMXNetSocketBroker broker = (BMXNetSocketBroker)this.Framework.SocketBroker;
BMXNetSocketConnectionSpec ConnectionSpec = broker.ConnectionSpec;
connector = new TcpClient();
connector.SendTimeout = ConnectionSpec.SendTimeout;
connector.ReceiveTimeout = ConnectionSpec.ReceiveTimeout;
connector.Connect(ConnectionSpec.Server, ConnectionSpec.Port);
}
catch (SocketException exSocket)
{
string s = exSocket.Message + exSocket.StackTrace;
throw new BMXNetException(s);
}
//Prepare & send the connect message
string cSend = "TCPconnect^" + "" + "^^";
int nLen = cSend.Length;
string sLen = nLen.ToString();
sLen = sLen.PadLeft(5, '0');
cSend = "{BMX}" + sLen + cSend;
NetworkStream ns = connector.GetStream();
byte[] sendBytes = Encoding.ASCII.GetBytes(cSend);
ns.Write(sendBytes,0,sendBytes.Length);
return connector;
}
catch (BMXNetException bmxEx)
{
throw bmxEx;
}
catch (Exception ex)
{
string s = ex.Message + ex.StackTrace;
throw new BMXNetException(s);
}
}//End OpenConnectionCommon
}
///
/// Class for passing result of AttemptChangeVerifyCode to calling routine
///
public class VerifyCodeUpdateResult
{
//Members
private DialogResult dr = new DialogResult();
private bool bVerifyCodeWasSucessfullyChanged;
//Properties
public DialogResult DialogResult
{
set { this.dr = value; }
get { return this.dr; }
}
public bool WasVerifyCodeUpdatedSuccessfully
{
set { this.bVerifyCodeWasSucessfullyChanged = value; }
get { return this.bVerifyCodeWasSucessfullyChanged; }
}
}
}