(1) Smart card reader support, (2) Tag added to User DB table, (3) Graphs : Y-label fixed, two significant digits, ver. 2.18.893

This commit is contained in:
Milan Hanajik 2018-05-14 17:11:15 +02:00
parent 86601e1ba1
commit 875caf0e28
44 changed files with 2550 additions and 261 deletions

2
.gitignore vendored
View File

@ -4,6 +4,8 @@ DeviceTest/bin/
DeviceTest/obj/ DeviceTest/obj/
Dirichlet.Numerics/bin Dirichlet.Numerics/bin
Dirichlet.Numerics/obj Dirichlet.Numerics/obj
GemCard/bin
GemCard/obj
GraphLib/bin GraphLib/bin
GraphLib/obj GraphLib/obj
MonitoringDB/bin MonitoringDB/bin

View File

@ -119,6 +119,7 @@
<DependentUpon>Strings.resx</DependentUpon> <DependentUpon>Strings.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Units.cs" /> <Compile Include="Units.cs" />
<Compile Include="Utils.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Resources\Strings.cs.resx" /> <EmbeddedResource Include="Resources\Strings.cs.resx" />

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.18.891.0")] [assembly: AssemblyVersion("2.18.893.0")]
[assembly: AssemblyFileVersion("2.18.891.0")] [assembly: AssemblyFileVersion("2.18.893.0")]

69
Config/Utils.cs Normal file
View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Config
{
public static class Utils
{
public static string SignificantDigitsToFmt(double value, int sigDigits)
{
if (sigDigits == 5)
{
if (value >= 9999.5 || value < -9999.5) return "F0";
else if (value >= 999.95 || value < -999.95) return "F1";
else if (value >= 99.995 || value < -99.995) return "F2";
else if (value >= 9.9995 || value < -9.9995) return "F3";
else if (value >= 0.99995 || value < -0.99995) return "F4";
else if (value >= 0.099995 || value < -0.099995) return "F5";
else if (value >= 0.0099995 || value < -0.0099995) return "F6";
else if (value >= 0.00099995 || value < -0.00099995) return "F7";
else if (value >= 0.000099995 || value < -0.000099995) return "F8";
else return "F9";
}
else if (sigDigits == 4)
{
if (value >= 999.5 || value < -999.5) return "F0";
else if (value >= 99.95 || value < -99.95) return "F1";
else if (value >= 9.995 || value < -9.995) return "F2";
else if (value >= 0.9995 || value < -0.9995) return "F3";
else if (value >= 0.09995 || value < -0.09995) return "F4";
else if (value >= 0.009995 || value < -0.009995) return "F5";
else if (value >= 0.0009995 || value < -0.0009995) return "F6";
else if (value >= 0.00009995 || value < -0.00009995) return "F7";
else return "F8";
}
else if (sigDigits == 3)
{
if (value >= 99.5 || value < -99.5) return "F0";
else if (value >= 9.95 || value < -9.95) return "F1";
else if (value >= 0.995 || value < -0.995) return "F2";
else if (value >= 0.0995 || value < -0.0995) return "F3";
else if (value >= 0.00995 || value < -0.00995) return "F4";
else if (value >= 0.000995 || value < -0.000995) return "F5";
else if (value >= 0.0000995 || value < -0.0000995) return "F6";
else return "F7";
}
else if (sigDigits == 2)
{
if (value >= 9.5 || value < -9.5) return "F0";
else if (value >= 0.95 || value < -0.95) return "F1";
else if (value >= 0.095 || value < -0.095) return "F2";
else if (value >= 0.0095 || value < -0.0095) return "F3";
else if (value >= 0.00095 || value < -0.00095) return "F4";
else if (value >= 0.000095 || value < -0.000095) return "F5";
else return "F6";
}
else /// if (sigDigits == 1)
{
if (value >= 0.95 || value < -0.95) return "F0";
else if (value >= 0.095 || value < -0.095) return "F1";
else if (value >= 0.0095 || value < -0.0095) return "F2";
else if (value >= 0.00095 || value < -0.00095) return "F3";
else if (value >= 0.000095 || value < -0.000095) return "F4";
else return "F5";
}
}
}
}

94
GemCard/APDUCommand.cs Normal file
View File

@ -0,0 +1,94 @@
using System;
using System.Text;
namespace GemCard
{
/// <summary>
/// This class represents a command APDU
/// </summary>
public class APDUCommand
{
/// <summary>
/// Minimun size of an APDU command in bytes
/// </summary>
public const int APDU_MIN_LENGTH = 4;
public byte Class; /// Class byte
public byte Ins; /// Instruction byte
public byte P1; /// Parameter P1 byte
public byte P2; /// Parameter P2 byte
public byte[] Data; /// Data to send to the card if any, null if no data to send
public byte Le; /// Number of data expected, 0 if none
/// <summary>
/// Constructor
/// </summary>
/// <param name="bCla">Class byte</param>
/// <param name="bIns">Instruction byte</param>
/// <param name="bP1">Parameter P1 byte</param>
/// <param name="bP2">Parameter P2 byte</param>
/// <param name="baData">Data to send to the card if any, null if no data to send</param>
/// <param name="bLe">Number of data expected, 0 if none</param>
public APDUCommand(byte bCla, byte bIns, byte bP1, byte bP2, byte[] baData, byte bLe)
{
this.Class = bCla;
this.Ins = bIns;
this.P1 = bP1;
this.P2 = bP2;
this.Data = baData;
this.Le = bLe;
}
/// <summary>
/// Update the current APDU with selected parameters
/// </summary>
/// <param name="apduParam">APDU parameters</param>
public void Update(APDUParam apduParam)
{
if (apduParam.UseData) Data = apduParam.Data;
if (apduParam.UseLe) Le = apduParam.Le;
if (apduParam.UseP1) P1 = apduParam.P1;
if (apduParam.UseP2) P2 = apduParam.P2;
if (apduParam.UseChannel) Class += apduParam.Channel;
}
/// <summary>
/// Overrides the ToString method to format to a string the APDUCommand object
/// </summary>
/// <returns></returns>
public override string ToString()
{
string strData = null;
byte bLc = 0;
byte bP3 = Le;
if (Data != null)
{
StringBuilder sData = new StringBuilder(Data.Length * 2);
for (int nI = 0; nI < Data.Length; nI++)
{
sData.AppendFormat("{0:X02}", Data[nI]);
}
strData = "Data=" + sData.ToString();
bLc = (byte) Data.Length;
bP3 = bLc;
}
//string strApdu = string.Format("Class={0:X02} Ins={1:X02} P1={2:X02} P2={3:X02} Le={4:X02} Lc={5:X02} ",
//m_bCla, m_bIns, m_bP1, m_bP2, m_bLe, bLc);
StringBuilder strApdu = new StringBuilder();
strApdu.AppendFormat("Class={0:X02} Ins={1:X02} P1={2:X02} P2={3:X02} P3={4:X02} ",
Class, Ins, P1, P2, bP3);
if (Data != null)
{
strApdu.Append(strData);
}
return strApdu.ToString();
}
}
}

147
GemCard/APDUParam.cs Normal file
View File

@ -0,0 +1,147 @@
using System;
namespace GemCard
{
/// <summary>
/// This class is used to update a set of parameters of an APDUCommand object
/// </summary>
public class APDUParam
{
byte bClass;
byte bChannel;
byte bP2;
byte bP1;
byte[] baData;
short nLe;
bool fUseP1;
bool fUseP2;
bool fChannel;
bool fData;
bool fClass;
bool fLe;
/// <summary>
/// Resets the current instance, all flags are set to false
/// </summary>
public void Reset()
{
bClass = 0;
bChannel = 0;
bP2 = 0;
bP1 = 0;
baData = null;
nLe = -1;
fUseP1 = false;
fUseP2 = false;
fChannel = false;
fData = false;
fClass = false;
fLe = false;
}
#region Constructors
public APDUParam()
{
Reset();
}
/// <summary>
/// Copy constructor (used for cloning)
/// </summary>
/// <param name="param"></param>
public APDUParam(APDUParam param)
{
// Copy field
if (param.baData != null)
{
param.baData.CopyTo(baData, 0);
}
this.bClass = param.bClass;
this.bChannel = param.bChannel;
this.bP1 = param.bP1;
this.bP2 = param.bP2;
this.nLe = param.nLe;
// Copy flags field
this.fChannel = param.fChannel;
this.fClass = param.fClass;
this.fData = param.fData;
this.fLe = param.fLe;
this.fUseP1 = param.fUseP1;
this.fUseP2 = param.fUseP2;
}
public APDUParam(byte bClass, byte bP1, byte bP2, byte[] baData, short nLe)
{
this.Class = bClass;
this.P1 = bP1;
this.P2 = bP2;
this.Data = baData;
this.Le = (byte)nLe;
}
#endregion
/// <summary>
/// Clones the current APDUParam instance
/// </summary>
/// <returns></returns>
public APDUParam Clone()
{
return new APDUParam(this);
}
#region Properties
public bool UseClass { get { return fClass; } }
public bool UseChannel { get { return fChannel; } }
public bool UseLe { get { return fLe; } }
public bool UseData { get { return fData; } }
public bool UseP1 { get { return fUseP1; } }
public bool UseP2 { get { return fUseP2; } }
public byte P1
{
get { return bP1; }
set { bP1 = value; fUseP1 = true; }
}
public byte P2
{
get { return bP2; }
set { bP2 = value; fUseP2 = true; }
}
public byte[] Data
{
get { return baData; }
set { baData = value; fData = true; }
}
public byte Le
{
get { return (byte)nLe; }
set { nLe = value; fLe = true; }
}
public byte Channel
{
get { return bChannel; }
set { bChannel = value; fChannel = true; }
}
public byte Class
{
get { return bClass; }
set { bClass = value; fClass = true; }
}
#endregion
}
}

74
GemCard/APDUResponse.cs Normal file
View File

@ -0,0 +1,74 @@
using System;
using System.Text;
namespace GemCard
{
/// <summary>
/// This class represents the APDU response sent by the card
/// </summary>
public class APDUResponse
{
/// <summary>
/// Status bytes length
/// </summary>
public const int SW_LENGTH = 2;
/// <summary>
/// Response data. Contains the data sent by the card minus the 2 status bytes (SW1, SW2)
/// null if no data were sent by the card
/// </summary>
public byte[] Data;
public byte SW1;
public byte SW2;
/// <summary>
/// Status get property
/// </summary>
public ushort Status
{
get { return (ushort)(((short)SW1 << 8) + (short)SW2); }
}
/// <summary>
/// Constructor from the byte data sent back by the card
/// </summary>
/// <param name="baData">Buffer of data from the card</param>
public APDUResponse(byte[] baData)
{
if (baData.Length > SW_LENGTH)
{
Data = new byte[baData.Length - SW_LENGTH];
for (int nI = 0; nI < baData.Length - SW_LENGTH; nI++)
{
this.Data[nI] = baData[nI];
}
}
this.SW1 = baData[baData.Length - 2];
this.SW2 = baData[baData.Length - 1];
}
/// <summary>
/// Overrides the ToString method to format to a string the APDUResponse object
/// </summary>
/// <returns></returns>
public override string ToString()
{
if (Data != null)
{
StringBuilder sData = new StringBuilder(Data.Length * 2);
for (int nI = 0; nI < Data.Length; nI++)
{
sData.AppendFormat("{0:X02}", Data[nI]);
}
return sData.ToString();
}
else
{
return string.Empty;
}
}
}
}

58
GemCard/AssemblyInfo.cs Normal file
View File

@ -0,0 +1,58 @@
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

162
GemCard/CardBase.cs Normal file
View File

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace GemCard
{
/// <summary>
/// Values for AttrId of SCardGetAttrib
/// </summary>
public class SCARD_ATTR_VALUE
{
private const uint
SCARD_CLASS_COMMUNICATIONS = 2,
SCARD_CLASS_PROTOCOL = 3,
SCARD_CLASS_MECHANICAL = 6,
SCARD_CLASS_VENDOR_DEFINED = 7,
SCARD_CLASS_IFD_PROTOCOL = 8,
SCARD_CLASS_ICC_STATE = 9,
SCARD_CLASS_SYSTEM = 0x7fff;
private static UInt32 SCardAttrValue(UInt32 attrClass, UInt32 val)
{
return (attrClass << 16) | val;
}
public static UInt32 CHANNEL_ID { get { return SCardAttrValue(SCARD_CLASS_COMMUNICATIONS, 0x0110); } }
public static UInt32 CHARACTERISTICS { get { return SCardAttrValue(SCARD_CLASS_MECHANICAL, 0x0150); } }
public static UInt32 CURRENT_PROTOCOL_TYPE { get { return SCardAttrValue(SCARD_CLASS_IFD_PROTOCOL, 0x0201); } }
public static UInt32 DEVICE_UNIT { get { return SCardAttrValue(SCARD_CLASS_SYSTEM, 0x0001); } }
public static UInt32 DEVICE_FRIENDLY_NAME { get { return SCardAttrValue(SCARD_CLASS_SYSTEM, 0x0003); } }
public UInt32 DEVICE_SYSTEM_NAME { get { return SCardAttrValue(SCARD_CLASS_SYSTEM, 0x0004); } }
public static UInt32 ICC_PRESENCE { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0300); } }
public static UInt32 ICC_INTERFACE_STATUS { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0301); } }
public static UInt32 ATR_STRING { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0303); } }
public static UInt32 ICC_TYPE_PER_ATR { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0304); } }
public static UInt32 PROTOCOL_TYPES { get { return SCardAttrValue(SCARD_CLASS_PROTOCOL, 0x0120); } }
public static UInt32 VENDOR_NAME { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0100); } }
public static UInt32 VENDOR_IFD_TYPE { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0101); } }
public static UInt32 VENDOR_IFD_VERSION { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0102); } }
public static UInt32 VENDOR_IFD_SERIAL_NO { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0103); } }
}
/// <summary>
/// Abstract class that adds a basic event management to the ICard interface.
/// </summary>
abstract public class CardBase : ICard
{
protected const uint INFINITE = 0xFFFFFFFF;
protected const uint WAIT_TIME = 250;
protected bool m_bRunCardDetection = true;
protected Thread m_thread = null;
/// <summary>
/// Event handler for the card insertion
/// </summary>
public event EventHandler<CardInsertedEventArgs> OnCardInserted = null;
/// <summary>
/// Event handler for the card removal
/// </summary>
public event EventHandler<CardRemovedEventArgs> OnCardRemoved = null;
~CardBase()
{
// Stop any eventual card detection thread
StopCardEvents();
}
#region Abstract method that implement the ICard interface
abstract public string[] ListReaders();
abstract public void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols);
abstract public void Disconnect(DISCONNECT Disposition);
abstract public APDUResponse Transmit(APDUCommand ApduCmd);
abstract public void BeginTransaction();
abstract public void EndTransaction(DISCONNECT Disposition);
abstract public byte[] GetAttribute(UInt32 AttribId);
#endregion
/// <summary>
/// This method should start a thread that checks for card insertion or removal
/// </summary>
/// <param name="Reader"></param>
public void StartCardEvents(string Reader)
{
if (m_thread == null)
{
m_bRunCardDetection = true;
m_thread = new Thread(new ParameterizedThreadStart(RunCardDetection));
m_thread.Start(Reader);
}
}
/// <summary>
/// Stops the card events thread
/// </summary>
public void StopCardEvents()
{
if (m_thread != null)
{
int
nTimeOut = 10,
nCount = 0;
bool m_bStop = false;
m_bRunCardDetection = false;
do
{
if (nCount > nTimeOut)
{
m_thread.Abort();
break;
}
if (m_thread.ThreadState == ThreadState.Aborted)
m_bStop = true;
if (m_thread.ThreadState == ThreadState.Stopped)
m_bStop = true;
Thread.Sleep(200);
++nCount; // Manage time out
}
while (!m_bStop);
m_thread = null;
}
}
/// <summary>
/// This function must implement a card detection mechanism.
///
/// When card insertion is detected, it must call the method CardInserted()
/// When card removal is detected, it must call the method CardRemoved()
///
/// </summary>
/// <param name="Reader">Name of the reader to scan for card event</param>
abstract protected void RunCardDetection(object Reader);
#region Event methods
protected void CardInserted(object sender, CardInsertedEventArgs args)
{
if (OnCardInserted != null) OnCardInserted(sender, args);
}
protected void CardRemoved(object sender, CardRemovedEventArgs args)
{
if (OnCardRemoved != null) OnCardRemoved(sender, args);
}
#endregion
}
}

173
GemCard/CardCOM.cs Normal file
View File

@ -0,0 +1,173 @@
using System;
using System.Runtime.InteropServices;
using SCARDSSPLib;
using GemCardExLib;
namespace GemCard
{
/// <summary>
/// Implements the ICard interface using the SCard COM objects from Microsoft and SCardDatabaseEx object
/// for the ListReaders function.
/// </summary>
public class CardCOM : CardBase
{
private ISCard m_itfCard = null;
/// <summary>
/// Default constructor
/// </summary>
public CardCOM()
{
// Create the SCard object
m_itfCard = new CSCardClass();
}
#region ICard Members
/// <summary>
/// Wraps the PCSC function
/// LONG SCardListReaders(SCARDCONTEXT hContext,
/// LPCTSTR mszGroups,
/// LPTSTR mszReaders,
/// LPDWORD pcchReaders
/// );
/// </summary>
/// <returns>A string array of the readers</returns>
public override string[] ListReaders()
{
ISCardDatabaseEx itfCardBase = new SCardDatabaseEx();
return (string[]) itfCardBase.ListReaders();
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardConnect(
/// IN SCARDCONTEXT hContext,
/// IN LPCTSTR szReader,
/// IN DWORD dwShareMode,
/// IN DWORD dwPreferredProtocols,
/// OUT LPSCARDHANDLE phCard,
/// OUT LPDWORD pdwActiveProtocol
/// );
/// </summary>
/// <param name="Reader"></param>
/// <param name="ShareMode"></param>
/// <param name="PreferredProtocols"></param>
public override void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols)
{
// Calls AttachReader to connect to the card
m_itfCard.AttachByReader(Reader, (SCARD_SHARE_MODES) ShareMode, (SCARD_PROTOCOLS) PreferredProtocols);
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardDisconnect(
/// IN SCARDHANDLE hCard,
/// IN DWORD dwDisposition
/// );
/// </summary>
/// <param name="Disposition"></param>
public override void Disconnect(DISCONNECT Disposition)
{
// Off the connection with the card
m_itfCard.Detach((SCARD_DISPOSITIONS) Disposition);
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardTransmit(
/// SCARDHANDLE hCard,
/// LPCSCARD_I0_REQUEST pioSendPci,
/// LPCBYTE pbSendBuffer,
/// DWORD cbSendLength,
/// LPSCARD_IO_REQUEST pioRecvPci,
/// LPBYTE pbRecvBuffer,
/// LPDWORD pcbRecvLength
/// );
/// </summary>
/// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param>
/// <returns>An APDUResponse object with the response from the card</returns>
public override APDUResponse Transmit(APDUCommand ApduCmd)
{
CSCardCmd itfCmd = new CSCardCmdClass();
CByteBuffer itfData = new CByteBufferClass();
int nLe = ApduCmd.Le;
if (ApduCmd.Data == null)
{
itfData.SetSize(0);
}
else
{
int nWrite = 0;
itfData.SetSize(ApduCmd.Data.Length);
itfData.Write(ref ApduCmd.Data[0], ApduCmd.Data.Length, ref nWrite);
}
// Build the APDU command
itfCmd.BuildCmd(ApduCmd.Class, ApduCmd.Ins, ApduCmd.P1, ApduCmd.P2, itfData, ref nLe);
// Send the command
m_itfCard.Transaction(ref itfCmd);
// Analyse the response
int nRead = 0;
byte[] pbResp = new byte[itfCmd.ApduReplyLength];
itfCmd.ApduReply.Read(ref pbResp[0], itfCmd.ApduReplyLength, ref nRead);
return new APDUResponse(pbResp);
}
/// <summary>
/// Wraps the PSCS function
/// LONG SCardBeginTransaction(
/// SCARDHANDLE hCard
// );
/// This function is not supported in the COM implementation
/// </summary>
public override void BeginTransaction()
{
throw new NotImplementedException("BeginTransaction is not supported in the COM implementation");
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardEndTransaction(
/// SCARDHANDLE hCard,
/// DWORD dwDisposition
/// );
/// This function is not supported in the COM implementation
/// </summary>
/// <param name="Disposition">A value from DISCONNECT enum</param>
public override void EndTransaction(DISCONNECT Disposition)
{
throw new NotImplementedException("EndTransaction is not supported in the COM implementation");
}
/// <summary>
/// Gets the attributes of the card
/// </summary>
/// <param name="AttribId">Identifier for the Attribute to get</param>
/// <returns>Attribute content</returns>
public override byte[] GetAttribute(UInt32 AttribId)
{
throw new NotImplementedException();
}
#endregion
/// <summary>
/// This function must implement a card detection mechanism.
///
/// When card insertion is detected, it must call the method CardInserted()
/// When card removal is detected, it must call the method CardRemoved()
///
/// </summary>
protected override void RunCardDetection(object Reader)
{
throw new Exception("The method or operation is not implemented.");
}
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace GemCard
{
public class CardInsertedEventArgs : EventArgs
{
public CardInsertedEventArgs() { }
}
}

620
GemCard/CardNative.cs Normal file
View File

@ -0,0 +1,620 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace GemCard
{
/// <summary>
/// CARD_STATE enumeration, used by the PC/SC function SCardGetStatusChanged
/// </summary>
enum CARD_STATE
{
UNAWARE = 0x00000000,
IGNORE = 0x00000001,
CHANGED = 0x00000002,
UNKNOWN = 0x00000004,
UNAVAILABLE = 0x00000008,
EMPTY = 0x00000010,
PRESENT = 0x00000020,
ATRMATCH = 0x00000040,
EXCLUSIVE = 0x00000080,
INUSE = 0x00000100,
MUTE = 0x00000200,
UNPOWERED = 0x00000400
}
/// <summary>
/// Wraps the SCARD_IO_STRUCTURE
///
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct SCard_IO_Request
{
public UInt32 m_dwProtocol;
public UInt32 m_cbPciLength;
}
/// <summary>
/// Wraps theSCARD_READERSTATE structure of PC/SC
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SCard_ReaderState
{
public string m_szReader;
public IntPtr m_pvUserData;
public UInt32 m_dwCurrentState;
public UInt32 m_dwEventState;
public UInt32 m_cbAtr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public byte[] m_rgbAtr;
}
/// <summary>
/// Implementation of ICard using native (P/Invoke) interoperability for PC/SC
/// </summary>
public class CardNative : CardBase
{
private UInt32 m_hContext = 0;
private UInt32 m_hCard = 0;
private UInt32 m_nProtocol = (uint) PROTOCOL.T0;
private int m_nLastError = 0;
#region PCSC_FUNCTIONS
/// <summary>
/// Native SCardGetStatusChanged from winscard.dll
/// </summary>
/// <param name="hContext"></param>
/// <param name="dwTimeout"></param>
/// <param name="rgReaderStates"></param>
/// <param name="cReaders"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError = true)]
internal static extern int SCardGetStatusChange(UInt32 hContext,
UInt32 dwTimeout,
[In,Out] SCard_ReaderState[] rgReaderStates,
UInt32 cReaders);
/// <summary>
/// Native SCardListReaders function from winscard.dll
/// </summary>
/// <param name="hContext"></param>
/// <param name="mszGroups"></param>
/// <param name="mszReaders"></param>
/// <param name="pcchReaders"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError=true)]
internal static extern int SCardListReaders(UInt32 hContext,
[MarshalAs(UnmanagedType.LPTStr)] string mszGroups,
IntPtr mszReaders,
out UInt32 pcchReaders);
/// <summary>
/// Native SCardEstablishContext function from winscard.dll
/// </summary>
/// <param name="dwScope"></param>
/// <param name="pvReserved1"></param>
/// <param name="pvReserved2"></param>
/// <param name="phContext"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError=true)]
internal static extern int SCardEstablishContext(UInt32 dwScope,
IntPtr pvReserved1,
IntPtr pvReserved2,
IntPtr phContext);
/// <summary>
/// Native SCardReleaseContext function from winscard.dll
/// </summary>
/// <param name="hContext"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError=true)]
internal static extern int SCardReleaseContext(UInt32 hContext);
/// <summary>
/// Native SCardConnect function from winscard.dll
/// </summary>
/// <param name="hContext"></param>
/// <param name="szReader"></param>
/// <param name="dwShareMode"></param>
/// <param name="dwPreferredProtocols"></param>
/// <param name="phCard"></param>
/// <param name="pdwActiveProtocol"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError=true, CharSet=CharSet.Auto)]
internal static extern int SCardConnect(UInt32 hContext,
[MarshalAs(UnmanagedType.LPTStr)] string szReader,
UInt32 dwShareMode,
UInt32 dwPreferredProtocols,
IntPtr phCard,
IntPtr pdwActiveProtocol);
/// <summary>
/// Native SCardDisconnect function from winscard.dll
/// </summary>
/// <param name="hCard"></param>
/// <param name="dwDisposition"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError=true)]
internal static extern int SCardDisconnect(UInt32 hCard,
UInt32 dwDisposition);
/// <summary>
/// Native SCardTransmit function from winscard.dll
/// </summary>
/// <param name="hCard"></param>
/// <param name="pioSendPci"></param>
/// <param name="pbSendBuffer"></param>
/// <param name="cbSendLength"></param>
/// <param name="pioRecvPci"></param>
/// <param name="pbRecvBuffer"></param>
/// <param name="pcbRecvLength"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError=true)]
internal static extern int SCardTransmit(UInt32 hCard,
[In] ref SCard_IO_Request pioSendPci,
byte[] pbSendBuffer,
UInt32 cbSendLength,
IntPtr pioRecvPci,
[Out] byte[] pbRecvBuffer,
out UInt32 pcbRecvLength
);
/// <summary>
/// Native SCardBeginTransaction function of winscard.dll
/// </summary>
/// <param name="hContext"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError = true)]
internal static extern int SCardBeginTransaction(UInt32 hContext);
/// <summary>
/// Native SCardEndTransaction function of winscard.dll
/// </summary>
/// <param name="hContext"></param>
/// <returns></returns>
[DllImport("winscard.dll", SetLastError = true)]
internal static extern int SCardEndTransaction(UInt32 hContext, UInt32 dwDisposition);
[DllImport("winscard.dll", SetLastError = true)]
internal static extern int SCardGetAttrib(UInt32 hCard,
UInt32 dwAttribId,
[Out] byte[] pbAttr,
out UInt32 pcbAttrLen);
#endregion
/// <summary>
/// Default constructor
/// </summary>
public CardNative()
{
}
/// <summary>
/// Object destruction
/// </summary>
~CardNative()
{
Disconnect(DISCONNECT.Unpower);
ReleaseContext();
}
#region ICard Members
/// <summary>
/// Wraps the PCSC function
/// LONG SCardListReaders(SCARDCONTEXT hContext,
/// LPCTSTR mszGroups,
/// LPTSTR mszReaders,
/// LPDWORD pcchReaders
/// );
/// </summary>
/// <returns>A string array of the readers</returns>
public override string[] ListReaders()
{
EstablishContext(SCOPE.User);
string[] sListReaders = null;
UInt32 pchReaders = 0;
IntPtr szListReaders = IntPtr.Zero;
m_nLastError = SCardListReaders(m_hContext, null, szListReaders, out pchReaders);
if (m_nLastError == 0)
{
szListReaders = Marshal.AllocHGlobal((int) pchReaders);
m_nLastError = SCardListReaders(m_hContext, null, szListReaders, out pchReaders);
if (m_nLastError == 0)
{
char[] caReadersData = new char[pchReaders];
int nbReaders = 0;
for (int nI = 0; nI < pchReaders; nI++)
{
caReadersData[nI] = (char) Marshal.ReadByte(szListReaders, nI);
if (caReadersData[nI] == 0)
nbReaders++;
}
// Remove last 0
--nbReaders;
if (nbReaders != 0)
{
sListReaders = new string[nbReaders];
char[] caReader = new char[pchReaders];
int nIdx = 0;
int nIdy = 0;
int nIdz = 0;
// Get the nJ string from the multi-string
while(nIdx < pchReaders - 1)
{
caReader[nIdy] = caReadersData[nIdx];
if (caReader[nIdy] == 0)
{
sListReaders[nIdz] = new string(caReader, 0, nIdy);
++nIdz;
nIdy = 0;
caReader = new char[pchReaders];
}
else
++nIdy;
++nIdx;
}
}
}
Marshal.FreeHGlobal(szListReaders);
}
ReleaseContext();
return sListReaders;
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardEstablishContext(
/// IN DWORD dwScope,
/// IN LPCVOID pvReserved1,
/// IN LPCVOID pvReserved2,
/// OUT LPSCARDCONTEXT phContext
/// );
/// </summary>
/// <param name="Scope"></param>
public void EstablishContext(SCOPE Scope)
{
IntPtr hContext = Marshal.AllocHGlobal(Marshal.SizeOf(m_hContext));
m_nLastError = SCardEstablishContext((uint) Scope, IntPtr.Zero, IntPtr.Zero, hContext);
if (m_nLastError != 0)
{
string msg = "SCardEstablishContext error: " + m_nLastError;
Marshal.FreeHGlobal(hContext);
throw new Exception(msg);
}
m_hContext = (uint) Marshal.ReadInt32(hContext);
Marshal.FreeHGlobal(hContext);
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardReleaseContext(
/// IN SCARDCONTEXT hContext
/// );
/// </summary>
public void ReleaseContext()
{
if (m_hContext != 0)
{
m_nLastError = SCardReleaseContext(m_hContext);
if (m_nLastError != 0)
{
string msg = "SCardReleaseContext error: " + m_nLastError;
throw new Exception(msg);
}
m_hContext = 0;
}
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardConnect(
/// IN SCARDCONTEXT hContext,
/// IN LPCTSTR szReader,
/// IN DWORD dwShareMode,
/// IN DWORD dwPreferredProtocols,
/// OUT LPSCARDHANDLE phCard,
/// OUT LPDWORD pdwActiveProtocol
/// );
/// </summary>
/// <param name="Reader"></param>
/// <param name="ShareMode"></param>
/// <param name="PreferredProtocols"></param>
public override void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols)
{
EstablishContext(SCOPE.User);
IntPtr hCard = Marshal.AllocHGlobal(Marshal.SizeOf(m_hCard));
IntPtr pProtocol = Marshal.AllocHGlobal(Marshal.SizeOf(m_nProtocol));
m_nLastError = SCardConnect(m_hContext,
Reader,
(uint) ShareMode,
(uint) PreferredProtocols,
hCard,
pProtocol);
if (m_nLastError != 0)
{
string msg = "SCardConnect error: " + m_nLastError;
Marshal.FreeHGlobal(hCard);
Marshal.FreeHGlobal(pProtocol);
throw new Exception(msg);
}
m_hCard = (uint) Marshal.ReadInt32(hCard);
m_nProtocol = (uint) Marshal.ReadInt32(pProtocol);
Marshal.FreeHGlobal(hCard);
Marshal.FreeHGlobal(pProtocol);
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardDisconnect(
/// IN SCARDHANDLE hCard,
/// IN DWORD dwDisposition
/// );
/// </summary>
/// <param name="Disposition"></param>
public override void Disconnect(DISCONNECT Disposition)
{
if (m_hCard != 0)
{
m_nLastError = SCardDisconnect(m_hCard, (uint) Disposition);
m_hCard = 0;
if (m_nLastError != 0)
{
string msg = "SCardDisconnect error: " + m_nLastError;
throw new Exception(msg);
}
ReleaseContext();
}
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardTransmit(
/// SCARDHANDLE hCard,
/// LPCSCARD_I0_REQUEST pioSendPci,
/// LPCBYTE pbSendBuffer,
/// DWORD cbSendLength,
/// LPSCARD_IO_REQUEST pioRecvPci,
/// LPBYTE pbRecvBuffer,
/// LPDWORD pcbRecvLength
/// );
/// </summary>
/// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param>
/// <returns>An APDUResponse object with the response from the card</returns>
public override APDUResponse Transmit(APDUCommand ApduCmd)
{
uint RecvLength = (uint) (ApduCmd.Le + APDUResponse.SW_LENGTH);
byte[] ApduBuffer = null;
byte[] ApduResponse = new byte[ApduCmd.Le + APDUResponse.SW_LENGTH];
SCard_IO_Request ioRequest = new SCard_IO_Request();
ioRequest.m_dwProtocol = m_nProtocol;
ioRequest.m_cbPciLength = 8;
// Build the command APDU
if (ApduCmd.Data == null)
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + ((ApduCmd.Le != 0) ? 1 : 0)];
if (ApduCmd.Le != 0)
ApduBuffer[4] = (byte) ApduCmd.Le;
}
else
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length];
for (int nI = 0; nI < ApduCmd.Data.Length; nI++)
ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] = ApduCmd.Data[nI];
ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte) ApduCmd.Data.Length;
}
ApduBuffer[0] = ApduCmd.Class;
ApduBuffer[1] = ApduCmd.Ins;
ApduBuffer[2] = ApduCmd.P1;
ApduBuffer[3] = ApduCmd.P2;
m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint) ApduBuffer.Length, IntPtr.Zero, ApduResponse, out RecvLength);
if (m_nLastError != 0)
{
string msg = "SCardTransmit error: " + m_nLastError;
throw new Exception(msg);
}
byte[] ApduData = new byte[RecvLength];
for (int nI = 0; nI < RecvLength; nI++)
ApduData[nI] = ApduResponse[nI];
return new APDUResponse(ApduData);
}
/// <summary>
/// Wraps the PSCS function
/// LONG SCardBeginTransaction(
/// SCARDHANDLE hCard
// );
/// </summary>
public override void BeginTransaction()
{
if (m_hCard != 0)
{
m_nLastError = SCardBeginTransaction(m_hCard);
if (m_nLastError != 0)
{
string msg = "SCardBeginTransaction error: " + m_nLastError;
throw new Exception(msg);
}
}
}
/// <summary>
/// Wraps the PCSC function
/// LONG SCardEndTransaction(
/// SCARDHANDLE hCard,
/// DWORD dwDisposition
/// );
/// </summary>
/// <param name="Disposition">A value from DISCONNECT enum</param>
public override void EndTransaction(DISCONNECT Disposition)
{
if (m_hCard != 0)
{
m_nLastError = SCardEndTransaction(m_hCard, (UInt32)Disposition);
if (m_nLastError != 0)
{
string msg = "SCardEndTransaction error: " + m_nLastError;
throw new Exception(msg);
}
}
}
/// <summary>
/// Gets the attributes of the card
/// </summary>
/// <param name="AttribId">Identifier for the Attribute to get</param>
/// <returns>Attribute content</returns>
public override byte[] GetAttribute(UInt32 AttribId)
{
byte[] attr = null;
UInt32 attrLen = 0;
m_nLastError = SCardGetAttrib(m_hCard, AttribId, attr, out attrLen);
if (m_nLastError == 0)
{
if (attrLen != 0)
{
attr = new byte[attrLen];
m_nLastError = SCardGetAttrib(m_hCard, AttribId, attr, out attrLen);
if (m_nLastError != 0)
{
string msg = "SCardGetAttr error: " + m_nLastError;
throw new Exception(msg);
}
}
}
else
{
string msg = "SCardGetAttr error: " + m_nLastError;
throw new Exception(msg);
}
return attr;
}
#endregion
/// <summary>
/// This function must implement a card detection mechanism.
///
/// When card insertion is detected, it must call the method CardInserted()
/// When card removal is detected, it must call the method CardRemoved()
///
/// </summary>
protected override void RunCardDetection(object Reader)
{
bool bFirstLoop = true;
UInt32 hContext = 0; // Local context
IntPtr phContext;
phContext = Marshal.AllocHGlobal(Marshal.SizeOf(hContext));
if (SCardEstablishContext((uint) SCOPE.User, IntPtr.Zero, IntPtr.Zero, phContext) == 0)
{
hContext = (uint)Marshal.ReadInt32(phContext);
Marshal.FreeHGlobal(phContext);
UInt32 nbReaders = 1;
SCard_ReaderState[] readerState = new SCard_ReaderState[nbReaders];
readerState[0].m_dwCurrentState = (UInt32) CARD_STATE.UNAWARE;
readerState[0].m_szReader = (string)Reader;
UInt32 eventState;
UInt32 currentState = readerState[0].m_dwCurrentState;
// Card detection loop
do
{
if (SCardGetStatusChange(hContext, WAIT_TIME
, readerState, nbReaders) == 0)
{
eventState = readerState[0].m_dwEventState;
currentState = readerState[0].m_dwCurrentState;
// Check state
if (((eventState & (uint) CARD_STATE.CHANGED) == (uint) CARD_STATE.CHANGED) && !bFirstLoop)
{
// State has changed
if ((eventState & (uint) CARD_STATE.EMPTY) == (uint) CARD_STATE.EMPTY)
{
// There is no card, card has been removed -> Fire CardRemoved event
CardRemoved(this, new CardRemovedEventArgs());
}
if (((eventState & (uint)CARD_STATE.PRESENT) == (uint)CARD_STATE.PRESENT) &&
((eventState & (uint) CARD_STATE.PRESENT) != (currentState & (uint) CARD_STATE.PRESENT)))
{
// There is a card in the reader -> Fire CardInserted event
CardInserted(this, new CardInsertedEventArgs());
}
if ((eventState & (uint) CARD_STATE.ATRMATCH) == (uint) CARD_STATE.ATRMATCH)
{
// There is a card in the reader and it matches the ATR we were expecting-> Fire CardInserted event
CardInserted(this, new CardInsertedEventArgs());
}
}
// The current stateis now the event state
readerState[0].m_dwCurrentState = eventState;
bFirstLoop = false;
}
Thread.Sleep(100);
if (m_bRunCardDetection == false)
break;
}
while (true); // Exit on request
}
else
{
Marshal.FreeHGlobal(phContext);
throw new Exception("PC/SC error");
}
SCardReleaseContext(hContext);
}
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace GemCard
{
public class CardRemovedEventArgs : EventArgs
{
public CardRemovedEventArgs() { }
}
}

194
GemCard/GemCard.csproj Normal file
View File

@ -0,0 +1,194 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>
</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>GemCard</AssemblyName>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<OutputType>Library</OutputType>
<RootNamespace>GemCard</RootNamespace>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<StartupObject>
</StartupObject>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>false</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<FileAlignment>4096</FileAlignment>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<FileAlignment>4096</FileAlignment>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
</PropertyGroup>
<ItemGroup>
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
</Reference>
<COMReference Include="GemCardExLib">
<Guid>{F1FF634B-BEDF-461C-A409-5B88E05F5117}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
</COMReference>
<COMReference Include="SCARDSSPLib">
<Guid>{82C38704-19F1-11D3-A11F-00C04F79F800}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
</COMReference>
<COMReference Include="stdole">
<Guid>{00020430-0000-0000-C000-000000000046}</Guid>
<VersionMajor>2</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
</COMReference>
</ItemGroup>
<ItemGroup>
<Compile Include="APDUCommand.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="APDUParam.cs" />
<Compile Include="APDUResponse.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="CardBase.cs" />
<Compile Include="CardInsertedEventArgs.cs" />
<Compile Include="CardNative.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="CardRemovedEventArgs.cs" />
<Compile Include="ICard.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="SmartCardException.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LastOpenVersion>8.0.50215</LastOpenVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ReferencePath>
</ReferencePath>
<CopyProjectDestinationFolder>
</CopyProjectDestinationFolder>
<CopyProjectUncPath>
</CopyProjectUncPath>
<CopyProjectOption>0</CopyProjectOption>
<ProjectView>ProjectFiles</ProjectView>
<ProjectTrust>0</ProjectTrust>
<PublishUrlHistory />
<InstallUrlHistory />
<SupportUrlHistory />
<UpdateUrlHistory />
<BootstrapperUrlHistory />
<ErrorReportUrlHistory />
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>
</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>
</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>false</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<StartWithIE>true</StartWithIE>
</PropertyGroup>
</Project>

149
GemCard/ICard.cs Normal file
View File

@ -0,0 +1,149 @@
using System;
namespace GemCard
{
/// <summary>
/// This interface gives access to the basic card functions. It must be implemented by a class.
/// </summary>
public interface ICard
{
/// <summary>
/// Wraps the PCSC funciton
/// LONG SCardListReaders(SCARDCONTEXT hContext,
/// LPCTSTR mszGroups,
/// LPTSTR mszReaders,
/// LPDWORD pcchReaders
/// );
/// </summary>
/// <returns>A string array of the readers</returns>
string[] ListReaders();
/// <summary>
/// Wraps the PCSC function
/// LONG SCardConnect(
/// IN SCARDCONTEXT hContext,
/// IN LPCTSTR szReader,
/// IN DWORD dwShareMode,
/// IN DWORD dwPreferredProtocols,
/// OUT LPSCARDHANDLE phCard,
/// OUT LPDWORD pdwActiveProtocol
/// );
/// </summary>
/// <param name="Reader"></param>
/// <param name="ShareMode"></param>
/// <param name="PreferredProtocols"></param>
void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols);
/// <summary>
/// Wraps the PCSC function
/// LONG SCardDisconnect(
/// IN SCARDHANDLE hCard,
/// IN DWORD dwDisposition
/// );
/// </summary>
/// <param name="Disposition"></param>
void Disconnect(DISCONNECT Disposition);
/// <summary>
/// Wraps the PCSC function
/// LONG SCardTransmit(
/// SCARDHANDLE hCard,
/// LPCSCARD_I0_REQUEST pioSendPci,
/// LPCBYTE pbSendBuffer,
/// DWORD cbSendLength,
/// LPSCARD_IO_REQUEST pioRecvPci,
/// LPBYTE pbRecvBuffer,
/// LPDWORD pcbRecvLength
/// );
/// </summary>
/// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param>
/// <returns>An APDUResponse object with the response from the card</returns>
APDUResponse Transmit(APDUCommand ApduCmd);
/// <summary>
/// Wraps the PSCS function
/// LONG SCardBeginTransaction(
/// SCARDHANDLE hCard
// );
/// </summary>
void BeginTransaction();
/// <summary>
/// Wraps the PCSC function
/// LONG SCardEndTransaction(
/// SCARDHANDLE hCard,
/// DWORD dwDisposition
/// );
/// </summary>
void EndTransaction(DISCONNECT Disposition);
/// <summary>
/// Gets the attributes of the card
/// </summary>
/// <param name="AttribId">Identifier for the Attribute to get</param>
/// <returns>Attribute content</returns>
byte[] GetAttribute(UInt32 AttribId);
}
/// <summary>
/// SCOPE context
/// </summary>
public enum SCOPE
{
/// <summary>
/// The context is a user context, and any database operations are performed within the
/// domain of the user.
/// </summary>
User,
/// <summary>
/// The context is that of the current terminal, and any database operations are performed
/// within the domain of that terminal. (The calling application must have appropriate
/// access permissions for any database actions.)
/// </summary>
Terminal,
/// <summary>
/// The context is the system context, and any database operations are performed within the
/// domain of the system. (The calling application must have appropriate access
/// permissions for any database actions.)
/// </summary>
System
}
/// <summary>
/// SHARE mode enumeration
/// </summary>
public enum SHARE
{
Exclusive = 1, /// This app. is not willing to share this card with other applications.
Shared, /// This app. is willing to share this card with other applications.
Direct, /// This app. demands direct control of the reader, so it is not available to other applications.
}
/// <summary>
/// PROTOCOL enumeration
/// </summary>
public enum PROTOCOL
{
Undefined = 0x00000000, /// There is no active protocol.
T0 = 0x00000001, /// T=0 is the active protocol.
T1 = 0x00000002, /// T=1 is the active protocol.
T0orT1 = T0 | T1, /// T=1 or T=0 can be the active protocol
Raw = 0x00010000, /// Raw is the active protocol.
Default = unchecked ((int) 0x80000000), /// Use implicit PTS.
}
/// <summary>
/// DISCONNECT action enumeration
/// </summary>
public enum DISCONNECT
{
Leave, /// Don't do anything special on close
Reset, /// Reset the card on close
Unpower, /// Power down the card on close
Eject, /// Eject(!) the card on close
}
}

View File

@ -0,0 +1,40 @@
using System;
namespace GemCard
{
/// <summary>
/// Smart card exceptions
/// </summary>
public class SmartCardException : Exception
{
public SmartCardException() : base("Smart card exception")
{
}
public SmartCardException(string Message) : base(Message)
{
}
}
public class ApduCommandException : Exception
{
public const string
NotValidDocument = "The file is not a valid APDU command document",
NoSuchCommand = "No such APDU command in the document",
ParamLeFormat = "Le parameter format is not correct",
ParamP3Format = "P3 parameter format is not correct",
NoSuchSequence = "No such APDU sequence in the document",
MissingApduOrCommand = "An Apdu or a Sequence is missing in this Sequence";
public ApduCommandException() : base("APDU command exception")
{
}
public ApduCommandException(string Message) : base(Message)
{
}
}
}

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.18.888.0")] [assembly: AssemblyVersion("2.18.893.0")]
[assembly: AssemblyFileVersion("2.18.888.0")] [assembly: AssemblyFileVersion("2.18.893.0")]

View File

@ -1,5 +1,5 @@
/// ///
/// Copyright (c) 2016 Sensus Metering Systems /// Copyright (c) 2016-2018 Sensus Slovensko a.s.
/// ///
using System; using System;
using System.Text; using System.Text;
@ -31,110 +31,6 @@ namespace Results
} }
} }
/// <summary>
/// Converts float number to a string with the specified number of significant digits
/// </summary>
/// <param name="value">Float value to be converted to a string</param>
/// <param name="validDigits">Number of significant digits: 4, 3, or 2 (otherwise a full precision number is printed)</param>
/// <returns>String representation of the float number</returns>
public static string DoubleToStr(double value, int validDigits)
{
if (-float.Epsilon <= value && value <= float.Epsilon)
{
return "0";
}
else if (validDigits == 4)
{
if (value >= 999.5 || value < -999.5) return value.ToString("F0");
else if (value >= 99.95 || value < -99.95) return value.ToString("F1");
else if (value >= 9.995 || value < -9.995) return value.ToString("F2");
else if (value >= 0.9995 || value < -0.9995) return value.ToString("F3");
else if (value >= 0.09995 || value < -0.09995) return value.ToString("F4");
else if (value >= 0.009995 || value < -0.009995) return value.ToString("F5");
else return value.ToString("F6");
}
else if (validDigits == 3)
{
if (value >= 99.5 || value < -99.5) return value.ToString("F0");
else if (value >= 9.95 || value < -9.95) return value.ToString("F1");
else if (value >= 0.995 || value < -0.995) return value.ToString("F2");
else if (value >= 0.0995 || value < -0.0995) return value.ToString("F3");
else if (value >= 0.00995 || value < -0.00995) return value.ToString("F4");
else if (value >= 0.000995 || value < -0.000995) return value.ToString("F5");
else return value.ToString("F6");
}
else if (validDigits == 2)
{
if (value >= 9.5 || value < -9.5) return value.ToString("F0");
else if (value >= 0.95 || value < -0.95) return value.ToString("F1");
else if (value >= 0.095 || value < -0.095) return value.ToString("F2");
else if (value >= 0.0095 || value < -0.0095) return value.ToString("F3");
else if (value >= 0.00095 || value < -0.00095) return value.ToString("F4");
else return value.ToString("F5");
}
else return value.ToString();
}
public static string SignificantDigitsToFmt(double value, int sigDigits)
{
if (sigDigits == 5)
{
if (value >= 9999.5 || value < -9999.5) return "F0";
else if (value >= 999.95 || value < -999.95) return "F1";
else if (value >= 99.995 || value < -99.995) return "F2";
else if (value >= 9.9995 || value < -9.9995) return "F3";
else if (value >= 0.99995 || value < -0.99995) return "F4";
else if (value >= 0.099995 || value < -0.099995) return "F5";
else if (value >= 0.0099995 || value < -0.0099995) return "F6";
else if (value >= 0.00099995 || value < -0.00099995) return "F7";
else if (value >= 0.000099995 || value < -0.000099995) return "F8";
else return "F9";
}
else if (sigDigits == 4)
{
if (value >= 999.5 || value < -999.5) return "F0";
else if (value >= 99.95 || value < -99.95) return "F1";
else if (value >= 9.995 || value < -9.995) return "F2";
else if (value >= 0.9995 || value < -0.9995) return "F3";
else if (value >= 0.09995 || value < -0.09995) return "F4";
else if (value >= 0.009995 || value < -0.009995) return "F5";
else if (value >= 0.0009995 || value < -0.0009995) return "F6";
else if (value >= 0.00009995 || value < -0.00009995) return "F7";
else return "F8";
}
else if (sigDigits == 3)
{
if (value >= 99.5 || value < -99.5) return "F0";
else if (value >= 9.95 || value < -9.95) return "F1";
else if (value >= 0.995 || value < -0.995) return "F2";
else if (value >= 0.0995 || value < -0.0995) return "F3";
else if (value >= 0.00995 || value < -0.00995) return "F4";
else if (value >= 0.000995 || value < -0.000995) return "F5";
else if (value >= 0.0000995 || value < -0.0000995) return "F6";
else return "F7";
}
else if (sigDigits == 2)
{
if (value >= 9.5 || value < -9.5) return "F0";
else if (value >= 0.95 || value < -0.95) return "F1";
else if (value >= 0.095 || value < -0.095) return "F2";
else if (value >= 0.0095 || value < -0.0095) return "F3";
else if (value >= 0.00095 || value < -0.00095) return "F4";
else if (value >= 0.000095 || value < -0.000095) return "F5";
else return "F6";
}
else /// if (sigDigits == 1)
{
if (value >= 0.95 || value < -0.95) return "F0";
else if (value >= 0.095 || value < -0.095) return "F1";
else if (value >= 0.0095 || value < -0.0095) return "F2";
else if (value >= 0.00095 || value < -0.00095) return "F3";
else if (value >= 0.000095 || value < -0.000095) return "F4";
else return "F5";
}
}
/// <summary> /// <summary>
/// Converts ErrorFlags integer to string. Supports up to 31 flags (E1..E31). /// Converts ErrorFlags integer to string. Supports up to 31 flags (E1..E31).
@ -170,6 +66,5 @@ namespace Results
return (useRedGreenColor) ? (passed ? "OK|Green" : "NOK|Red") : (passed ? "OK|White" : "NOK|White"); return (useRedGreenColor) ? (passed ? "OK|Green" : "NOK|Red") : (passed ? "OK|White" : "NOK|White");
#endif #endif
} }
} }
} }

View File

@ -465,7 +465,7 @@ namespace Results
int significantDigits; int significantDigits;
if (int.TryParse(precision.Substring(1), out significantDigits)) if (int.TryParse(precision.Substring(1), out significantDigits))
{ {
precision = Utils.SignificantDigitsToFmt(val, significantDigits); precision = Config.Utils.SignificantDigitsToFmt(val, significantDigits);
} }
} }
@ -503,7 +503,7 @@ namespace Results
int significantDigits; int significantDigits;
if (int.TryParse(precision.Substring(1), out significantDigits)) if (int.TryParse(precision.Substring(1), out significantDigits))
{ {
precision = Utils.SignificantDigitsToFmt(val1, significantDigits); precision = Config.Utils.SignificantDigitsToFmt(val1, significantDigits);
} }
} }

20
TBF.sln
View File

@ -28,6 +28,9 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dirichlet.Numerics", "Dirichlet.Numerics\Dirichlet.Numerics.csproj", "{439D0878-C76E-452B-B17D-209A89E91D36}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dirichlet.Numerics", "Dirichlet.Numerics\Dirichlet.Numerics.csproj", "{439D0878-C76E-452B-B17D-209A89E91D36}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Users", "Users\Users.csproj", "{6E5CB0E9-E1B6-4E5D-AC6E-B1049E180F2B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Users", "Users\Users.csproj", "{6E5CB0E9-E1B6-4E5D-AC6E-B1049E180F2B}"
ProjectSection(ProjectDependencies) = postProject
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697} = {8B10D15A-39DE-4B56-8DD1-710C1EB3A697}
EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserManagement", "UserManagement\UserManagement.csproj", "{B2CD81B3-AF09-4978-996C-02EDB5F819B7}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserManagement", "UserManagement\UserManagement.csproj", "{B2CD81B3-AF09-4978-996C-02EDB5F819B7}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
@ -35,9 +38,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserManagement", "UserManag
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphLib", "GraphLib\GraphLib.csproj", "{0C0A1F4D-1363-4544-A7C5-196C76D26CCA}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphLib", "GraphLib\GraphLib.csproj", "{0C0A1F4D-1363-4544-A7C5-196C76D26CCA}"
ProjectSection(ProjectDependencies) = postProject
{743DF7DB-C7B6-42EB-986D-0F485E5588E4} = {743DF7DB-C7B6-42EB-986D-0F485E5588E4}
EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonitoringDB", "MonitoringDB\MonitoringDB.csproj", "{EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonitoringDB", "MonitoringDB\MonitoringDB.csproj", "{EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GemCard", "GemCard\GemCard.csproj", "{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -154,6 +162,18 @@ Global
{EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}.Release|Mixed Platforms.Build.0 = Release|Any CPU {EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}.Release|x86.ActiveCfg = Release|Any CPU {EFEC8A31-3022-4DA7-A8F6-16D30A94C3FF}.Release|x86.ActiveCfg = Release|Any CPU
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Debug|Mixed Platforms.Build.0 = Debug|x86
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Debug|x86.ActiveCfg = Debug|x86
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Debug|x86.Build.0 = Debug|x86
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Release|Any CPU.Build.0 = Release|Any CPU
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Release|Mixed Platforms.ActiveCfg = Release|x86
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Release|Mixed Platforms.Build.0 = Release|x86
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Release|x86.ActiveCfg = Release|x86
{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}.Release|x86.Build.0 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -1,9 +1,11 @@
/// ///
/// Copyright (c) 2013-2017 Sensus Metering Systems /// Copyright (c) 2013-2018 Sensus Slovensko a.s.
/// ///
using System; using System;
using System.Windows.Forms; using System.Windows.Forms;
using TBF.Resources; using TBF.Resources;
using GemCard;
using System.Drawing;
namespace TBF.Forms namespace TBF.Forms
@ -15,12 +17,19 @@ namespace TBF.Forms
/// </summary> /// </summary>
public partial class LoginDlgWithBenchSelection : Form public partial class LoginDlgWithBenchSelection : Form
{ {
public const string UseTheTagPassword = "UseTheTag0293578";
/// Private fields /// Private fields
string alias; string alias;
string password; string password;
string benchName = null; string benchName = null;
string legalizator; string legalizator;
/// Smart card support, card S/N is used as user.Tag
GemCard.CardNative card;
string[] cardReaders;
string smartCardReader;
/// Readonly public properties to do the authorization. /// Readonly public properties to do the authorization.
public string Alias { get { return alias; } } public string Alias { get { return alias; } }
public string Password { get { return password; } } public string Password { get { return password; } }
@ -87,6 +96,39 @@ namespace TBF.Forms
testBenchComboBox.Text = benchName; testBenchComboBox.Text = benchName;
} }
} }
smartCardReader = null; /// null = No smart card reader detected
#if TURA_IPERL || TURA_SPECIAL
card = new CardNative();
cardReaders = card.ListReaders();
foreach (var crd in cardReaders)
{
if (crd.Contains("NFC"))
{
smartCardReader = crd; /// NFC smart card reader detected
Text += " (NFC)";
break;
}
}
if (!string.IsNullOrEmpty(smartCardReader))
{
card.OnCardInserted += delegate(object sndr, CardInsertedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CardInsertedEventArgs>(OnCardInserted), sndr, args); }
else OnCardInserted(sndr, args);
};
card.OnCardRemoved += delegate(object sndr, CardRemovedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CardRemovedEventArgs>(OnCardRemoved), sndr, args); }
else OnCardRemoved(sndr, args);
};
card.StartCardEvents(smartCardReader);
}
#endif
} }
void Localize() void Localize()
@ -179,5 +221,53 @@ namespace TBF.Forms
Method = 0; Method = 0;
aliasLabel.Text = GetAliasLabel(); aliasLabel.Text = GetAliasLabel();
} }
void OnCardInserted(object sender, CardInsertedEventArgs args)
{
BackColor = Color.Green;
card.Connect(smartCardReader, SHARE.Shared, PROTOCOL.T0orT1);
/// Read the serial number of the card
APDUResponse response = card.Transmit(new APDUCommand(0xFF, 0xCA, 0x00, 0x00, null, 7));
string tag = response.ToString();
card.Disconnect(DISCONNECT.Leave);
if (testBenchComboBox.SelectedItem != null)
{
alias = tag;
password = UseTheTagPassword;
benchName = testBenchComboBox.SelectedItem.ToString();
if (legalizatorComboBox.Enabled)
{
legalizator = legalizatorComboBox.Text;
Program.LocalSettings.UpdateHistory(legalizator, ref Program.LocalSettings.LastLegalizators);
}
DialogResult = DialogResult.OK;
Close();
return;
}
else
{
MessageBox.Show(Strings.PLs_select_testbench, Strings.Warning, MessageBoxButtons.OK);
}
}
void OnCardRemoved(object sender, CardRemovedEventArgs args)
{
BackColor = SystemColors.Control;
}
private void LoginDlgWithBenchSelection_FormClosing(object sender, FormClosingEventArgs e)
{
if (!string.IsNullOrEmpty(smartCardReader))
{
card.StopCardEvents();
}
}
} }
} }

View File

@ -128,6 +128,7 @@ namespace TBF.Forms
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Name = "LoginDlgWithBenchSelection"; this.Name = "LoginDlgWithBenchSelection";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LoginDlgWithBenchSelection_FormClosing);
this.Load += new System.EventHandler(this.LoginDlgWithBenchSelection_Load); this.Load += new System.EventHandler(this.LoginDlgWithBenchSelection_Load);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();

View File

@ -248,25 +248,32 @@ namespace TBF
#if TURA_IPERL || TURA_SPECIAL #if TURA_IPERL || TURA_SPECIAL
requiredGroupMembership = Grp.GID.Testers; requiredGroupMembership = Grp.GID.Testers;
#endif #endif
if (loginDlgBench.Password == LoginDlgWithBenchSelection.UseTheTagPassword)
switch (loginDlgBench.Method) {
{ loadedUser = Users.Entities.User.LoadUserByTag(loginDlgBench.Alias, db);
default: if (loadedUser != null) authorized = loadedUser.AuthorizeTag(loginDlgBench.Alias, requiredGroupMembership);
case Users.Entities.LoginMethod.UserName: }
loadedUser = Users.Entities.User.LoadUserByName(loginDlgBench.Alias, db); else
if (loadedUser != null) authorized = loadedUser.Authorize(loginDlgBench.Alias, loginDlgBench.Password, requiredGroupMembership); {
break; switch (loginDlgBench.Method)
case Users.Entities.LoginMethod.FullName: {
loadedUser = Users.Entities.User.LoadUserByFullName(loginDlgBench.Alias, db); default:
if (loadedUser != null) authorized = loadedUser.AuthorizeFullName(loginDlgBench.Alias, loginDlgBench.Password, requiredGroupMembership); case Users.Entities.LoginMethod.UserName:
break; loadedUser = Users.Entities.User.LoadUserByName(loginDlgBench.Alias, db);
case Users.Entities.LoginMethod.Number: if (loadedUser != null) authorized = loadedUser.Authorize(loginDlgBench.Alias, loginDlgBench.Password, requiredGroupMembership);
int number; break;
if (!int.TryParse(loginDlgBench.Alias, out number)) break; case Users.Entities.LoginMethod.FullName:
loadedUser = Users.Entities.User.LoadUserByNumber(number, db); loadedUser = Users.Entities.User.LoadUserByFullName(loginDlgBench.Alias, db);
if (loadedUser != null) authorized = loadedUser.AuthorizeNumber(number, loginDlgBench.Password, requiredGroupMembership); if (loadedUser != null) authorized = loadedUser.AuthorizeFullName(loginDlgBench.Alias, loginDlgBench.Password, requiredGroupMembership);
break; break;
} case Users.Entities.LoginMethod.Number:
int number;
if (!int.TryParse(loginDlgBench.Alias, out number)) break;
loadedUser = Users.Entities.User.LoadUserByNumber(number, db);
if (loadedUser != null) authorized = loadedUser.AuthorizeNumber(number, loginDlgBench.Password, requiredGroupMembership);
break;
}
}
} }
catch catch
{ {

View File

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("2.18.892.0")] [assembly: AssemblyVersion("2.18.893.0")]
[assembly: AssemblyFileVersion("2.18.892.0")] [assembly: AssemblyFileVersion("2.18.893.0")]

View File

@ -304,7 +304,7 @@ namespace TBF.Screens
private string RenderYLabel(DataSource s, float value) private string RenderYLabel(DataSource s, float value)
{ {
return string.Format("{0:0.0}", value); return value.ToString(Config.Utils.SignificantDigitsToFmt(value, 2));
} }
private void checkBox1_CheckedChanged(object sender, EventArgs e) { Program.LocalSettings.Graph1_On = checkBox1.Checked; AnyCBChanged(); } private void checkBox1_CheckedChanged(object sender, EventArgs e) { Program.LocalSettings.Graph1_On = checkBox1.Checked; AnyCBChanged(); }

View File

@ -2877,6 +2877,10 @@
<Project>{439D0878-C76E-452B-B17D-209A89E91D36}</Project> <Project>{439D0878-C76E-452B-B17D-209A89E91D36}</Project>
<Name>Dirichlet.Numerics</Name> <Name>Dirichlet.Numerics</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\GemCard\GemCard.csproj">
<Project>{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}</Project>
<Name>GemCard</Name>
</ProjectReference>
<ProjectReference Include="..\GraphLib\GraphLib.csproj"> <ProjectReference Include="..\GraphLib\GraphLib.csproj">
<Project>{0C0A1F4D-1363-4544-A7C5-196C76D26CCA}</Project> <Project>{0C0A1F4D-1363-4544-A7C5-196C76D26CCA}</Project>
<Name>GraphLib</Name> <Name>GraphLib</Name>

View File

@ -341,7 +341,7 @@ namespace TBF
} }
else if (significantDigits <= 5) else if (significantDigits <= 5)
{ {
string fmt = Results.Utils.SignificantDigitsToFmt(value, significantDigits); string fmt = Config.Utils.SignificantDigitsToFmt(value, significantDigits);
return altCulture ? value.ToString(fmt, Program.AltCulture) : value.ToString(fmt); return altCulture ? value.ToString(fmt, Program.AltCulture) : value.ToString(fmt);
} }
else else

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.18.798.0")] [assembly: AssemblyVersion("2.18.893.0")]
[assembly: AssemblyFileVersion("2.18.798.0")] [assembly: AssemblyFileVersion("2.18.893.0")]

View File

@ -16,6 +16,7 @@ namespace Users.Entities
public virtual int Id { get; protected set; } public virtual int Id { get; protected set; }
public virtual string UserName { get; set; } /// = name, alias, abbreviation public virtual string UserName { get; set; } /// = name, alias, abbreviation
public virtual string FullName { get; set; } /// = description public virtual string FullName { get; set; } /// = description
public virtual string Tag { get; set; }
public virtual int Number { get; set; } public virtual int Number { get; set; }
public virtual string Password { get; set; } public virtual string Password { get; set; }
public virtual DateTime LastPwChange { get; set; } public virtual DateTime LastPwChange { get; set; }
@ -33,6 +34,7 @@ namespace Users.Entities
this.powerUser = false; this.powerUser = false;
Groups = new List<Group>(); Groups = new List<Group>();
Number = 0; Number = 0;
Tag = string.Empty;
} }
public User(string userName, int number, bool powerUser) public User(string userName, int number, bool powerUser)
@ -61,6 +63,7 @@ namespace Users.Entities
User newUser = new User(UserName, Number, false); User newUser = new User(UserName, Number, false);
newUser.FullName = FullName; newUser.FullName = FullName;
newUser.Number = Number; newUser.Number = Number;
newUser.Tag = Tag;
newUser.Password = Password; newUser.Password = Password;
newUser.LastPwChange = LastPwChange; newUser.LastPwChange = LastPwChange;
return newUser; return newUser;
@ -250,6 +253,44 @@ namespace Users.Entities
return AuthorizeFullName(fullName, password, Grp.GID.None); return AuthorizeFullName(fullName, password, Grp.GID.None);
} }
/// <summary>
/// The FIRST of TWO possible user authorization method to be used
/// when a specific group membership is required (you can use Grp.GID.None).
/// If the user is not authorized, the current user remains to be a current user
/// (i.e. the access rights were not risen to a higher level).
/// If you require different behavior, use Unauthorize() before calling Authorize().
/// </summary>
/// <param name="tag">Tag (RFID, NFC, ... s/n)</param>
/// <param name="requiredGrupMembership"></param>
/// <returns>true = authorized</returns>
public virtual bool AuthorizeTag(string tag, Grp.GID requiredGroupMembership)
{
if (Tag == tag)
{
if (IsMemberOf(requiredGroupMembership))
{
GlobalData.CurrentUser = this;
GlobalData.LastAuthorization = DateTime.Now;
log.FatalFormat("User with Tag={0} authorized @level '{1}'", tag, requiredGroupMembership);
return true;
}
else
{
return false;
}
}
return false;
}
/// <summary>
/// The SECOND of TWO possible user authorization method to be used when
/// no specific group membership is required.
/// </summary>
public virtual bool AuthorizeTag(string tag)
{
return AuthorizeTag(tag, Grp.GID.None);
}
/// <summary> /// <summary>
/// Returns a 'User' with a given username from a database. /// Returns a 'User' with a given username from a database.
@ -371,6 +412,41 @@ namespace Users.Entities
} }
/// <summary>
/// Returns a 'User' with a given RFID/NFC tag s/n from an ARBITRARY database.
/// </summary>
/// <param name="tag">Tag of a user for the query</param>
/// <returns>reference to a 'User' (if it exists) or null</returns>
public static User LoadUserByTag(string tag, DBSettings dbSettings)
{
if (dbSettings == null || string.IsNullOrEmpty(dbSettings.ConnectionString)) return null;
DB.DbType = dbSettings.DbType;
DB.ConnectionString = dbSettings.ConnectionString;
IList<User> listOfUsers = DB.CreateSession()
.QueryOver<User>()
.Where(x => (x.Tag == tag))
.List();
if (listOfUsers.Count > 0) return listOfUsers[0];
return null;
}
/// <summary>
/// Returns a 'User' with a given RFID/NFC tag s/n from the users database.
/// </summary>
/// <param name="tag">Tag of a user for the query</param>
/// <returns>reference to a 'User' (if it exists) or null</returns>
public static User LoadUserByTag(string tag)
{
IList<User> listOfUsers = DB.CreateSession()
.QueryOver<User>()
.Where(x => (x.Tag == tag))
.List();
if (listOfUsers.Count > 0) return listOfUsers[0];
return null;
}
/// <summary> /// <summary>
/// returns an IList of all Users /// returns an IList of all Users
/// </summary> /// </summary>

View File

@ -35,8 +35,8 @@ namespace Users.Forms
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditSelectedUser)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditSelectedUser));
this.txtName = new System.Windows.Forms.TextBox(); this.txtName = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label(); this.nameLabel = new System.Windows.Forms.Label();
this.btnOk = new System.Windows.Forms.Button(); this.okBtn = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button(); this.cancelBtn = new System.Windows.Forms.Button();
this.txtPassword = new System.Windows.Forms.TextBox(); this.txtPassword = new System.Windows.Forms.TextBox();
this.passwordLabel = new System.Windows.Forms.Label(); this.passwordLabel = new System.Windows.Forms.Label();
this.txtDescription = new System.Windows.Forms.TextBox(); this.txtDescription = new System.Windows.Forms.TextBox();
@ -48,6 +48,8 @@ namespace Users.Forms
this.txtRepeatPassword = new System.Windows.Forms.TextBox(); this.txtRepeatPassword = new System.Windows.Forms.TextBox();
this.codeLabel = new System.Windows.Forms.Label(); this.codeLabel = new System.Windows.Forms.Label();
this.txtCode = new System.Windows.Forms.TextBox(); this.txtCode = new System.Windows.Forms.TextBox();
this.tagLabel = new System.Windows.Forms.Label();
this.txtTag = new System.Windows.Forms.TextBox();
this.SuspendLayout(); this.SuspendLayout();
// //
// txtName // txtName
@ -63,19 +65,19 @@ namespace Users.Forms
resources.ApplyResources(this.nameLabel, "nameLabel"); resources.ApplyResources(this.nameLabel, "nameLabel");
this.nameLabel.Name = "nameLabel"; this.nameLabel.Name = "nameLabel";
// //
// btnOk // okBtn
// //
resources.ApplyResources(this.btnOk, "btnOk"); resources.ApplyResources(this.okBtn, "okBtn");
this.btnOk.Name = "btnOk"; this.okBtn.Name = "okBtn";
this.btnOk.UseVisualStyleBackColor = true; this.okBtn.UseVisualStyleBackColor = true;
this.btnOk.Click += new System.EventHandler(this.btnOk_Click); this.okBtn.Click += new System.EventHandler(this.okBtn_Click);
// //
// btnCancel // cancelBtn
// //
resources.ApplyResources(this.btnCancel, "btnCancel"); resources.ApplyResources(this.cancelBtn, "cancelBtn");
this.btnCancel.Name = "btnCancel"; this.cancelBtn.Name = "cancelBtn";
this.btnCancel.UseVisualStyleBackColor = true; this.cancelBtn.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
// //
// txtPassword // txtPassword
// //
@ -135,18 +137,30 @@ namespace Users.Forms
this.txtCode.Name = "txtCode"; this.txtCode.Name = "txtCode";
this.txtCode.TextChanged += new System.EventHandler(this.txtCode_TextChanged); this.txtCode.TextChanged += new System.EventHandler(this.txtCode_TextChanged);
// //
// tagLabel
//
resources.ApplyResources(this.tagLabel, "tagLabel");
this.tagLabel.Name = "tagLabel";
//
// txtTag
//
resources.ApplyResources(this.txtTag, "txtTag");
this.txtTag.Name = "txtTag";
//
// EditSelectedUser // EditSelectedUser
// //
resources.ApplyResources(this, "$this"); resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tagLabel);
this.Controls.Add(this.txtTag);
this.Controls.Add(this.codeLabel); this.Controls.Add(this.codeLabel);
this.Controls.Add(this.txtCode); this.Controls.Add(this.txtCode);
this.Controls.Add(this.repeatPasswordLabel); this.Controls.Add(this.repeatPasswordLabel);
this.Controls.Add(this.txtRepeatPassword); this.Controls.Add(this.txtRepeatPassword);
this.Controls.Add(this.groupsLabel); this.Controls.Add(this.groupsLabel);
this.Controls.Add(this.checkedListBoxGroups); this.Controls.Add(this.checkedListBoxGroups);
this.Controls.Add(this.btnCancel); this.Controls.Add(this.cancelBtn);
this.Controls.Add(this.btnOk); this.Controls.Add(this.okBtn);
this.Controls.Add(this.descriptionLabel); this.Controls.Add(this.descriptionLabel);
this.Controls.Add(this.passwordLabel); this.Controls.Add(this.passwordLabel);
this.Controls.Add(this.nameLabel); this.Controls.Add(this.nameLabel);
@ -157,6 +171,7 @@ namespace Users.Forms
this.MaximizeBox = false; this.MaximizeBox = false;
this.Name = "EditSelectedUser"; this.Name = "EditSelectedUser";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.EditSelectedUser_FormClosing);
this.Load += new System.EventHandler(this.EditSelectedUser_Load); this.Load += new System.EventHandler(this.EditSelectedUser_Load);
this.Shown += new System.EventHandler(this.EditSelectedUser_Shown); this.Shown += new System.EventHandler(this.EditSelectedUser_Shown);
this.ResumeLayout(false); this.ResumeLayout(false);
@ -168,8 +183,8 @@ namespace Users.Forms
private System.Windows.Forms.TextBox txtName; private System.Windows.Forms.TextBox txtName;
private System.Windows.Forms.Label nameLabel; private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Button btnOk; private System.Windows.Forms.Button okBtn;
private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.Button cancelBtn;
private System.Windows.Forms.TextBox txtPassword; private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Label passwordLabel; private System.Windows.Forms.Label passwordLabel;
private System.Windows.Forms.TextBox txtDescription; private System.Windows.Forms.TextBox txtDescription;
@ -181,5 +196,7 @@ namespace Users.Forms
private System.Windows.Forms.TextBox txtRepeatPassword; private System.Windows.Forms.TextBox txtRepeatPassword;
private System.Windows.Forms.Label codeLabel; private System.Windows.Forms.Label codeLabel;
private System.Windows.Forms.TextBox txtCode; private System.Windows.Forms.TextBox txtCode;
private System.Windows.Forms.Label tagLabel;
private System.Windows.Forms.TextBox txtTag;
} }
} }

View File

@ -8,6 +8,8 @@ using System.Windows.Forms;
using NHibernate; using NHibernate;
using Users.Entities; using Users.Entities;
using Users.Resources; using Users.Resources;
using GemCard;
using System.Drawing;
namespace Users.Forms namespace Users.Forms
{ {
@ -18,12 +20,18 @@ namespace Users.Forms
bool[] oriGroupMember; /// index is gid, size is Grp.Count bool[] oriGroupMember; /// index is gid, size is Grp.Count
/// Smart card support, card S/N is used as user.Tag
GemCard.CardNative card;
string[] cardReaders;
string smartCardReader;
public EditSelectedUser() public EditSelectedUser()
{ {
InitializeComponent(); InitializeComponent();
this.toolTip1.SetToolTip(this.txtName, string.Format(Strings.max_0_alphanum_chars, 20)); this.toolTip1.SetToolTip(this.txtName, string.Format(Strings.max_0_alphanum_chars, 20));
oriGroupMember = new bool[Grp.Count]; oriGroupMember = new bool[Grp.Count];
btnOk.Enabled = false; okBtn.Enabled = false;
} }
public EditSelectedUser(NHibernate.ISession session, User user) public EditSelectedUser(NHibernate.ISession session, User user)
@ -39,10 +47,47 @@ namespace Users.Forms
txtName.Text = user.UserName; txtName.Text = user.UserName;
txtCode.Text = user.Number.ToString(); txtCode.Text = user.Number.ToString();
txtTag.Text = string.IsNullOrEmpty(user.Tag) ? string.Empty : user.Tag;
txtDescription.Text = user.FullName; txtDescription.Text = user.FullName;
txtPassword.Text = string.Empty; txtPassword.Text = string.Empty;
txtRepeatPassword.Text = string.Empty; txtRepeatPassword.Text = string.Empty;
ShowGroups(); ShowGroups();
smartCardReader = null; /// null = No smart card reader detected
#if TURA_IPERL || TURA_SPECIAL
card = new CardNative();
cardReaders = card.ListReaders();
foreach (var crd in cardReaders)
{
if (crd.Contains("NFC"))
{
smartCardReader = crd; /// NFC smart card reader detected
Text += " (NFC)";
break;
}
}
if (!string.IsNullOrEmpty(smartCardReader))
{
card.OnCardInserted += delegate(object sndr, CardInsertedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CardInsertedEventArgs>(OnCardInserted), sndr, args); }
else OnCardInserted(sndr, args);
};
card.OnCardRemoved += delegate(object sndr, CardRemovedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CardRemovedEventArgs>(OnCardRemoved), sndr, args); }
else OnCardRemoved(sndr, args);
};
card.StartCardEvents(smartCardReader);
}
txtTag.Enabled = true;
#endif
} }
void Localize() void Localize()
@ -52,10 +97,11 @@ namespace Users.Forms
passwordLabel.Text = Strings.Password; passwordLabel.Text = Strings.Password;
repeatPasswordLabel.Text = Strings.Repeat_password; repeatPasswordLabel.Text = Strings.Repeat_password;
codeLabel.Text = Strings.User_code; codeLabel.Text = Strings.User_code;
tagLabel.Text = Strings.Tag;
descriptionLabel.Text = Strings.DescriptionColHdr; descriptionLabel.Text = Strings.DescriptionColHdr;
groupsLabel.Text = Strings.Groups; groupsLabel.Text = Strings.Groups;
btnOk.Text = Strings.OkBtnText; okBtn.Text = Strings.OkBtnText;
btnCancel.Text = Strings.CancelBtnText; cancelBtn.Text = Strings.CancelBtnText;
} }
public void ShowGroups() public void ShowGroups()
@ -81,12 +127,18 @@ namespace Users.Forms
public bool Save() public bool Save()
{ {
// todo: check if this name is given to another user // todo: check if this name is given to another user
if (IsUserNameAllreadyTaken(txtName.Text)) if (IsUserNameAlreadyTaken(txtName.Text))
{ {
MessageBox.Show(Strings.Username_taken); MessageBox.Show(Strings.Username_taken);
return false; return false;
} }
if (IsTagAlreadyTaken(txtTag.Text))
{
MessageBox.Show(Strings.Tag_taken);
return false;
}
ITransaction transaction = session.BeginTransaction(); ITransaction transaction = session.BeginTransaction();
try try
@ -96,6 +148,7 @@ namespace Users.Forms
user.UserName = txtName.Text; user.UserName = txtName.Text;
user.FullName = txtDescription.Text; user.FullName = txtDescription.Text;
user.Number = int.Parse(txtCode.Text); user.Number = int.Parse(txtCode.Text);
user.Tag = string.IsNullOrEmpty(txtTag.Text) ? null : txtTag.Text;
if (txtPassword.Text != string.Empty) if (txtPassword.Text != string.Empty)
{ {
@ -146,19 +199,41 @@ namespace Users.Forms
/// <summary> /// <summary>
/// returns true if the username allready exists for another user /// returns true if the username allready exists for another user
/// </summary> /// </summary>
private bool IsUserNameAllreadyTaken(string Username) private bool IsUserNameAlreadyTaken(string userName)
{ {
// have a look into all other users // Have a look into all other users
IList<User> ListOfUsers = User.GetAllUsers(); IList<User> ListOfUsers = User.GetAllUsers();
foreach (var person in ListOfUsers) foreach (var person in ListOfUsers)
{ {
if (person.Id != user.Id) if (person.Id != user.Id)
{ {
// other user /// Other user then the current one
if (person.UserName.ToLower() == Username.ToLower()) if (person.UserName.ToLower() == userName.ToLower())
{ {
// Name is equal, so allready taken return true; // Name is equal = already taken
return true; }
}
}
return false;
}
/// <summary>
/// returns true if the username allready exists for another user
/// </summary>
private bool IsTagAlreadyTaken(string tag)
{
if (string.IsNullOrEmpty(tag)) return false; /// No tag
// Have a look into all other users
IList<User> ListOfUsers = User.GetAllUsers();
foreach (var person in ListOfUsers)
{
if (person.Id != user.Id)
{
// Other user then the current one
if (person.Tag == tag)
{
return true; // Tag is equal = already taken
} }
} }
} }
@ -166,7 +241,7 @@ namespace Users.Forms
} }
private void btnOk_Click(object sender, EventArgs e) private void okBtn_Click(object sender, EventArgs e)
{ {
if (Save()) if (Save())
{ {
@ -175,7 +250,7 @@ namespace Users.Forms
} }
} }
private void btnCancel_Click(object sender, EventArgs e) private void cancelBtn_Click(object sender, EventArgs e)
{ {
DialogResult = DialogResult.Cancel; DialogResult = DialogResult.Cancel;
this.Close(); this.Close();
@ -196,9 +271,36 @@ namespace Users.Forms
{ {
int userCode; int userCode;
btnOk.Enabled = (txtName.Text != string.Empty) okBtn.Enabled = (txtName.Text != string.Empty)
&& int.TryParse(txtCode.Text, out userCode) && int.TryParse(txtCode.Text, out userCode)
&& (txtPassword.Text == txtRepeatPassword.Text); && (txtPassword.Text == txtRepeatPassword.Text);
} }
void OnCardInserted(object sender, CardInsertedEventArgs args)
{
BackColor = Color.Green;
card.Connect(smartCardReader, SHARE.Shared, PROTOCOL.T0orT1);
/// Read the serial number of the card
APDUResponse response = card.Transmit(new APDUCommand(0xFF, 0xCA, 0x00, 0x00, null, 7));
txtTag.Text = response.ToString();
card.Disconnect(DISCONNECT.Leave);
}
void OnCardRemoved(object sender, CardRemovedEventArgs args)
{
BackColor = SystemColors.Control;
}
private void EditSelectedUser_FormClosing(object sender, FormClosingEventArgs e)
{
if (!string.IsNullOrEmpty(smartCardReader))
{
card.StopCardEvents();
}
}
} }
} }

View File

@ -138,7 +138,7 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;txtName.ZOrder" xml:space="preserve"> <data name="&gt;&gt;txtName.ZOrder" xml:space="preserve">
<value>13</value> <value>15</value>
</data> </data>
<data name="nameLabel.AutoSize" type="System.Boolean, mscorlib"> <data name="nameLabel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
@ -165,58 +165,62 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;nameLabel.ZOrder" xml:space="preserve"> <data name="&gt;&gt;nameLabel.ZOrder" xml:space="preserve">
<value>10</value> <value>12</value>
</data> </data>
<data name="btnOk.Location" type="System.Drawing.Point, System.Drawing"> <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<value>137, 356</value> <data name="okBtn.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data> </data>
<data name="btnOk.Size" type="System.Drawing.Size, System.Drawing"> <data name="okBtn.Location" type="System.Drawing.Point, System.Drawing">
<value>84, 40</value> <value>137, 365</value>
</data> </data>
<data name="btnOk.TabIndex" type="System.Int32, mscorlib"> <data name="okBtn.Size" type="System.Drawing.Size, System.Drawing">
<value>10</value> <value>94, 31</value>
</data> </data>
<data name="btnOk.Text" xml:space="preserve"> <data name="okBtn.TabIndex" type="System.Int32, mscorlib">
<value>15</value>
</data>
<data name="okBtn.Text" xml:space="preserve">
<value>OK</value> <value>OK</value>
</data> </data>
<data name="&gt;&gt;btnOk.Name" xml:space="preserve"> <data name="&gt;&gt;okBtn.Name" xml:space="preserve">
<value>btnOk</value> <value>okBtn</value>
</data> </data>
<data name="&gt;&gt;btnOk.Type" xml:space="preserve"> <data name="&gt;&gt;okBtn.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>
<data name="&gt;&gt;btnOk.Parent" xml:space="preserve"> <data name="&gt;&gt;okBtn.Parent" xml:space="preserve">
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;btnOk.ZOrder" xml:space="preserve"> <data name="&gt;&gt;okBtn.ZOrder" xml:space="preserve">
<value>7</value> <value>9</value>
</data> </data>
<data name="btnCancel.Location" type="System.Drawing.Point, System.Drawing"> <data name="cancelBtn.Location" type="System.Drawing.Point, System.Drawing">
<value>253, 356</value> <value>243, 365</value>
</data> </data>
<data name="btnCancel.Size" type="System.Drawing.Size, System.Drawing"> <data name="cancelBtn.Size" type="System.Drawing.Size, System.Drawing">
<value>84, 40</value> <value>94, 31</value>
</data> </data>
<data name="btnCancel.TabIndex" type="System.Int32, mscorlib"> <data name="cancelBtn.TabIndex" type="System.Int32, mscorlib">
<value>11</value> <value>16</value>
</data> </data>
<data name="btnCancel.Text" xml:space="preserve"> <data name="cancelBtn.Text" xml:space="preserve">
<value>Cancel</value> <value>Cancel</value>
</data> </data>
<data name="&gt;&gt;btnCancel.Name" xml:space="preserve"> <data name="&gt;&gt;cancelBtn.Name" xml:space="preserve">
<value>btnCancel</value> <value>cancelBtn</value>
</data> </data>
<data name="&gt;&gt;btnCancel.Type" xml:space="preserve"> <data name="&gt;&gt;cancelBtn.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>
<data name="&gt;&gt;btnCancel.Parent" xml:space="preserve"> <data name="&gt;&gt;cancelBtn.Parent" xml:space="preserve">
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;btnCancel.ZOrder" xml:space="preserve"> <data name="&gt;&gt;cancelBtn.ZOrder" xml:space="preserve">
<value>6</value> <value>8</value>
</data> </data>
<data name="txtPassword.Location" type="System.Drawing.Point, System.Drawing"> <data name="txtPassword.Location" type="System.Drawing.Point, System.Drawing">
<value>137, 38</value> <value>137, 35</value>
</data> </data>
<data name="txtPassword.PasswordChar" type="System.Char, mscorlib" xml:space="preserve"> <data name="txtPassword.PasswordChar" type="System.Char, mscorlib" xml:space="preserve">
<value>*</value> <value>*</value>
@ -237,13 +241,13 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;txtPassword.ZOrder" xml:space="preserve"> <data name="&gt;&gt;txtPassword.ZOrder" xml:space="preserve">
<value>12</value> <value>14</value>
</data> </data>
<data name="passwordLabel.AutoSize" type="System.Boolean, mscorlib"> <data name="passwordLabel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
</data> </data>
<data name="passwordLabel.Location" type="System.Drawing.Point, System.Drawing"> <data name="passwordLabel.Location" type="System.Drawing.Point, System.Drawing">
<value>9, 41</value> <value>9, 38</value>
</data> </data>
<data name="passwordLabel.Size" type="System.Drawing.Size, System.Drawing"> <data name="passwordLabel.Size" type="System.Drawing.Size, System.Drawing">
<value>53, 13</value> <value>53, 13</value>
@ -264,10 +268,10 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;passwordLabel.ZOrder" xml:space="preserve"> <data name="&gt;&gt;passwordLabel.ZOrder" xml:space="preserve">
<value>9</value> <value>11</value>
</data> </data>
<data name="txtDescription.Location" type="System.Drawing.Point, System.Drawing"> <data name="txtDescription.Location" type="System.Drawing.Point, System.Drawing">
<value>137, 122</value> <value>137, 135</value>
</data> </data>
<data name="txtDescription.Multiline" type="System.Boolean, mscorlib"> <data name="txtDescription.Multiline" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
@ -276,7 +280,7 @@
<value>200, 59</value> <value>200, 59</value>
</data> </data>
<data name="txtDescription.TabIndex" type="System.Int32, mscorlib"> <data name="txtDescription.TabIndex" type="System.Int32, mscorlib">
<value>7</value> <value>12</value>
</data> </data>
<data name="&gt;&gt;txtDescription.Name" xml:space="preserve"> <data name="&gt;&gt;txtDescription.Name" xml:space="preserve">
<value>txtDescription</value> <value>txtDescription</value>
@ -288,19 +292,19 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;txtDescription.ZOrder" xml:space="preserve"> <data name="&gt;&gt;txtDescription.ZOrder" xml:space="preserve">
<value>11</value> <value>13</value>
</data> </data>
<data name="descriptionLabel.AutoSize" type="System.Boolean, mscorlib"> <data name="descriptionLabel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
</data> </data>
<data name="descriptionLabel.Location" type="System.Drawing.Point, System.Drawing"> <data name="descriptionLabel.Location" type="System.Drawing.Point, System.Drawing">
<value>9, 125</value> <value>9, 138</value>
</data> </data>
<data name="descriptionLabel.Size" type="System.Drawing.Size, System.Drawing"> <data name="descriptionLabel.Size" type="System.Drawing.Size, System.Drawing">
<value>60, 13</value> <value>60, 13</value>
</data> </data>
<data name="descriptionLabel.TabIndex" type="System.Int32, mscorlib"> <data name="descriptionLabel.TabIndex" type="System.Int32, mscorlib">
<value>6</value> <value>11</value>
</data> </data>
<data name="descriptionLabel.Text" xml:space="preserve"> <data name="descriptionLabel.Text" xml:space="preserve">
<value>Description</value> <value>Description</value>
@ -315,16 +319,16 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;descriptionLabel.ZOrder" xml:space="preserve"> <data name="&gt;&gt;descriptionLabel.ZOrder" xml:space="preserve">
<value>8</value> <value>10</value>
</data> </data>
<data name="checkedListBoxGroups.Location" type="System.Drawing.Point, System.Drawing"> <data name="checkedListBoxGroups.Location" type="System.Drawing.Point, System.Drawing">
<value>137, 190</value> <value>137, 199</value>
</data> </data>
<data name="checkedListBoxGroups.Size" type="System.Drawing.Size, System.Drawing"> <data name="checkedListBoxGroups.Size" type="System.Drawing.Size, System.Drawing">
<value>200, 154</value> <value>200, 154</value>
</data> </data>
<data name="checkedListBoxGroups.TabIndex" type="System.Int32, mscorlib"> <data name="checkedListBoxGroups.TabIndex" type="System.Int32, mscorlib">
<value>9</value> <value>14</value>
</data> </data>
<data name="&gt;&gt;checkedListBoxGroups.Name" xml:space="preserve"> <data name="&gt;&gt;checkedListBoxGroups.Name" xml:space="preserve">
<value>checkedListBoxGroups</value> <value>checkedListBoxGroups</value>
@ -336,19 +340,19 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;checkedListBoxGroups.ZOrder" xml:space="preserve"> <data name="&gt;&gt;checkedListBoxGroups.ZOrder" xml:space="preserve">
<value>5</value> <value>7</value>
</data> </data>
<data name="groupsLabel.AutoSize" type="System.Boolean, mscorlib"> <data name="groupsLabel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
</data> </data>
<data name="groupsLabel.Location" type="System.Drawing.Point, System.Drawing"> <data name="groupsLabel.Location" type="System.Drawing.Point, System.Drawing">
<value>9, 190</value> <value>9, 199</value>
</data> </data>
<data name="groupsLabel.Size" type="System.Drawing.Size, System.Drawing"> <data name="groupsLabel.Size" type="System.Drawing.Size, System.Drawing">
<value>41, 13</value> <value>41, 13</value>
</data> </data>
<data name="groupsLabel.TabIndex" type="System.Int32, mscorlib"> <data name="groupsLabel.TabIndex" type="System.Int32, mscorlib">
<value>8</value> <value>13</value>
</data> </data>
<data name="groupsLabel.Text" xml:space="preserve"> <data name="groupsLabel.Text" xml:space="preserve">
<value>Groups</value> <value>Groups</value>
@ -363,7 +367,7 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;groupsLabel.ZOrder" xml:space="preserve"> <data name="&gt;&gt;groupsLabel.ZOrder" xml:space="preserve">
<value>4</value> <value>6</value>
</data> </data>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value> <value>17, 17</value>
@ -371,12 +375,11 @@
<data name="repeatPasswordLabel.AutoSize" type="System.Boolean, mscorlib"> <data name="repeatPasswordLabel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
</data> </data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="repeatPasswordLabel.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms"> <data name="repeatPasswordLabel.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value> <value>NoControl</value>
</data> </data>
<data name="repeatPasswordLabel.Location" type="System.Drawing.Point, System.Drawing"> <data name="repeatPasswordLabel.Location" type="System.Drawing.Point, System.Drawing">
<value>9, 69</value> <value>9, 63</value>
</data> </data>
<data name="repeatPasswordLabel.Size" type="System.Drawing.Size, System.Drawing"> <data name="repeatPasswordLabel.Size" type="System.Drawing.Size, System.Drawing">
<value>90, 13</value> <value>90, 13</value>
@ -397,10 +400,10 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;repeatPasswordLabel.ZOrder" xml:space="preserve"> <data name="&gt;&gt;repeatPasswordLabel.ZOrder" xml:space="preserve">
<value>2</value> <value>4</value>
</data> </data>
<data name="txtRepeatPassword.Location" type="System.Drawing.Point, System.Drawing"> <data name="txtRepeatPassword.Location" type="System.Drawing.Point, System.Drawing">
<value>137, 66</value> <value>137, 60</value>
</data> </data>
<data name="txtRepeatPassword.PasswordChar" type="System.Char, mscorlib" xml:space="preserve"> <data name="txtRepeatPassword.PasswordChar" type="System.Char, mscorlib" xml:space="preserve">
<value>*</value> <value>*</value>
@ -421,7 +424,7 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;txtRepeatPassword.ZOrder" xml:space="preserve"> <data name="&gt;&gt;txtRepeatPassword.ZOrder" xml:space="preserve">
<value>3</value> <value>5</value>
</data> </data>
<data name="codeLabel.AutoSize" type="System.Boolean, mscorlib"> <data name="codeLabel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
@ -430,13 +433,13 @@
<value>NoControl</value> <value>NoControl</value>
</data> </data>
<data name="codeLabel.Location" type="System.Drawing.Point, System.Drawing"> <data name="codeLabel.Location" type="System.Drawing.Point, System.Drawing">
<value>9, 97</value> <value>9, 88</value>
</data> </data>
<data name="codeLabel.Size" type="System.Drawing.Size, System.Drawing"> <data name="codeLabel.Size" type="System.Drawing.Size, System.Drawing">
<value>32, 13</value> <value>32, 13</value>
</data> </data>
<data name="codeLabel.TabIndex" type="System.Int32, mscorlib"> <data name="codeLabel.TabIndex" type="System.Int32, mscorlib">
<value>12</value> <value>6</value>
</data> </data>
<data name="codeLabel.Text" xml:space="preserve"> <data name="codeLabel.Text" xml:space="preserve">
<value>Code</value> <value>Code</value>
@ -451,16 +454,16 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;codeLabel.ZOrder" xml:space="preserve"> <data name="&gt;&gt;codeLabel.ZOrder" xml:space="preserve">
<value>0</value> <value>2</value>
</data> </data>
<data name="txtCode.Location" type="System.Drawing.Point, System.Drawing"> <data name="txtCode.Location" type="System.Drawing.Point, System.Drawing">
<value>137, 94</value> <value>137, 85</value>
</data> </data>
<data name="txtCode.Size" type="System.Drawing.Size, System.Drawing"> <data name="txtCode.Size" type="System.Drawing.Size, System.Drawing">
<value>66, 20</value> <value>200, 20</value>
</data> </data>
<data name="txtCode.TabIndex" type="System.Int32, mscorlib"> <data name="txtCode.TabIndex" type="System.Int32, mscorlib">
<value>13</value> <value>7</value>
</data> </data>
<data name="&gt;&gt;txtCode.Name" xml:space="preserve"> <data name="&gt;&gt;txtCode.Name" xml:space="preserve">
<value>txtCode</value> <value>txtCode</value>
@ -472,6 +475,60 @@
<value>$this</value> <value>$this</value>
</data> </data>
<data name="&gt;&gt;txtCode.ZOrder" xml:space="preserve"> <data name="&gt;&gt;txtCode.ZOrder" xml:space="preserve">
<value>3</value>
</data>
<data name="tagLabel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="tagLabel.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="tagLabel.Location" type="System.Drawing.Point, System.Drawing">
<value>9, 113</value>
</data>
<data name="tagLabel.Size" type="System.Drawing.Size, System.Drawing">
<value>26, 13</value>
</data>
<data name="tagLabel.TabIndex" type="System.Int32, mscorlib">
<value>8</value>
</data>
<data name="tagLabel.Text" xml:space="preserve">
<value>Tag</value>
</data>
<data name="&gt;&gt;tagLabel.Name" xml:space="preserve">
<value>tagLabel</value>
</data>
<data name="&gt;&gt;tagLabel.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;tagLabel.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;tagLabel.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="txtTag.Enabled" type="System.Boolean, mscorlib">
<value>False</value>
</data>
<data name="txtTag.Location" type="System.Drawing.Point, System.Drawing">
<value>137, 110</value>
</data>
<data name="txtTag.Size" type="System.Drawing.Size, System.Drawing">
<value>200, 20</value>
</data>
<data name="txtTag.TabIndex" type="System.Int32, mscorlib">
<value>9</value>
</data>
<data name="&gt;&gt;txtTag.Name" xml:space="preserve">
<value>txtTag</value>
</data>
<data name="&gt;&gt;txtTag.Type" xml:space="preserve">
<value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;txtTag.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;txtTag.ZOrder" xml:space="preserve">
<value>1</value> <value>1</value>
</data> </data>
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

View File

@ -94,6 +94,7 @@ namespace Users.Forms
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Name = "LoginDlg"; this.Name = "LoginDlg";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LoginDlg_FormClosing);
this.Load += new System.EventHandler(this.LoginDlg_Load); this.Load += new System.EventHandler(this.LoginDlg_Load);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();

View File

@ -1,9 +1,11 @@
/// ///
/// Copyright (c) 2017 Sensus Metering Systems /// Copyright (c) 2017-2018 Sensus Slovensko a.s.
/// ///
using System; using System;
using System.Windows.Forms; using System.Windows.Forms;
using GemCard;
using Users.Resources; using Users.Resources;
using System.Drawing;
namespace Users.Forms namespace Users.Forms
{ {
@ -19,11 +21,14 @@ namespace Users.Forms
Grp.GID requiredGroupMembership = Grp.GID.Invalid; Grp.GID requiredGroupMembership = Grp.GID.Invalid;
bool noDatabase; bool noDatabase;
/// Smart card support, card S/N is used as user.Tag
GemCard.CardNative card;
string[] cardReaders;
string smartCardReader;
public Users.Entities.LoginMethod Method; public Users.Entities.LoginMethod Method;
public string VersionString; public string VersionString;
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
@ -79,6 +84,39 @@ namespace Users.Forms
userNameTextBox.Select(); userNameTextBox.Select();
else else
passwordTextBox.Select(); passwordTextBox.Select();
smartCardReader = null; /// null = No smart card reader detected
#if TURA_IPERL || TURA_SPECIAL
card = new CardNative();
cardReaders = card.ListReaders();
foreach (var crd in cardReaders)
{
if (crd.Contains("NFC"))
{
smartCardReader = crd; /// NFC smart card reader detected
Text += " (NFC)";
break;
}
}
if (!string.IsNullOrEmpty(smartCardReader))
{
card.OnCardInserted += delegate(object sndr, CardInsertedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CardInsertedEventArgs>(OnCardInserted), sndr, args); }
else OnCardInserted(sndr, args);
};
card.OnCardRemoved += delegate(object sndr, CardRemovedEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CardRemovedEventArgs>(OnCardRemoved), sndr, args); }
else OnCardRemoved(sndr, args);
};
card.StartCardEvents(smartCardReader);
}
#endif
} }
void Localize() void Localize()
@ -124,27 +162,31 @@ namespace Users.Forms
foreach (var db in dbs) foreach (var db in dbs)
{ {
Users.Entities.User loadedUser = Users.Entities.User.LoadUserByName(user, db); try
if (loadedUser != null) {
{ Users.Entities.User loadedUser = Users.Entities.User.LoadUserByName(user, db);
switch (Method) if (loadedUser != null)
{ {
default: switch (Method)
case Entities.LoginMethod.UserName: {
authorized = (requiredGroupMembership == Grp.GID.Invalid) ? loadedUser.Authorize(user, password) : loadedUser.Authorize(user, password, requiredGroupMembership); default:
break; case Entities.LoginMethod.UserName:
case Entities.LoginMethod.FullName: authorized = (requiredGroupMembership == Grp.GID.Invalid) ? loadedUser.Authorize(user, password) : loadedUser.Authorize(user, password, requiredGroupMembership);
authorized = (requiredGroupMembership == Grp.GID.Invalid) ? loadedUser.AuthorizeFullName(user, password) : loadedUser.AuthorizeFullName(user, password, requiredGroupMembership); break;
break; case Entities.LoginMethod.FullName:
case Entities.LoginMethod.Number: authorized = (requiredGroupMembership == Grp.GID.Invalid) ? loadedUser.AuthorizeFullName(user, password) : loadedUser.AuthorizeFullName(user, password, requiredGroupMembership);
int number; break;
if (!int.TryParse(user, out number)) break; case Entities.LoginMethod.Number:
authorized = (requiredGroupMembership == Grp.GID.Invalid) ? loadedUser.AuthorizeNumber(number, password) : loadedUser.AuthorizeNumber(number, password, requiredGroupMembership); int number;
break; if (!int.TryParse(user, out number)) break;
} authorized = (requiredGroupMembership == Grp.GID.Invalid) ? loadedUser.AuthorizeNumber(number, password) : loadedUser.AuthorizeNumber(number, password, requiredGroupMembership);
} break;
}
}
}
catch (Exception) { }
if (authorized) break; if (authorized) break;
authorizedAs = Entities.AuthorizedAs.LocalUser; authorizedAs = Entities.AuthorizedAs.LocalUser;
} }
@ -200,5 +242,65 @@ namespace Users.Forms
okButton_Click(sender, e); okButton_Click(sender, e);
} }
} }
void OnCardInserted(object sender, CardInsertedEventArgs args)
{
BackColor = Color.Green;
card.Connect(smartCardReader, SHARE.Shared, PROTOCOL.T0orT1);
/// Read the serial number of the card
APDUResponse response = card.Transmit(new APDUCommand(0xFF, 0xCA, 0x00, 0x00, null, 7));
string tag = response.ToString();
card.Disconnect(DISCONNECT.Leave);
DBSettings[] dbs = new DBSettings[] { GlobalData.RemoteUsersDB, GlobalData.LocalUsersDB };
bool authorized = false;
Entities.AuthorizedAs authorizedAs = Entities.AuthorizedAs.RemoteUser;
///
foreach (var db in dbs)
{
try
{
Users.Entities.User loadedUser = Users.Entities.User.LoadUserByTag(tag, db);
if (loadedUser != null)
{
authorized = (requiredGroupMembership == Grp.GID.Invalid) ? loadedUser.AuthorizeTag(tag) : loadedUser.AuthorizeTag(tag, requiredGroupMembership);
}
}
catch (Exception) { }
if (authorized) break;
authorizedAs = Entities.AuthorizedAs.LocalUser;
}
if (authorized)
{
Users.GlobalData.AuthorizedAs = authorizedAs;
DialogResult = DialogResult.OK;
Close();
return;
}
MessageBox.Show(Strings.Invalid_username_or_password, Strings.Error, MessageBoxButtons.OK);
DialogResult = DialogResult.None;
return;
}
void OnCardRemoved(object sender, CardRemovedEventArgs args)
{
BackColor = SystemColors.Control;
}
private void LoginDlg_FormClosing(object sender, FormClosingEventArgs e)
{
if (!string.IsNullOrEmpty(smartCardReader))
{
card.StopCardEvents();
}
}
} }
} }

View File

@ -36,10 +36,13 @@ namespace Users.Forms
deleteButton.Text = Strings.RemoveBtnText; deleteButton.Text = Strings.RemoveBtnText;
closeButton.Text = Strings.CloseBtnText; closeButton.Text = Strings.CloseBtnText;
listViewUsers.Columns.Add(Strings.User_name, 120); listViewUsers.Columns.Add(Strings.User_name, 100);
listViewUsers.Columns.Add(Strings.User_code, 80); listViewUsers.Columns.Add(Strings.User_code, 70);
listViewUsers.Columns.Add(Strings.Full_name, 160); listViewUsers.Columns.Add(Strings.Full_name, 150);
listViewUsers.Columns.Add(Strings.Groups, 300); #if TURA_IPERL || TURA_SPECIAL
listViewUsers.Columns.Add(Strings.Tag, 110);
#endif
listViewUsers.Columns.Add(Strings.Groups, 370);
try try
{ {
@ -79,6 +82,9 @@ namespace Users.Forms
ListViewItem item = new ListViewItem(u.UserName); ListViewItem item = new ListViewItem(u.UserName);
item.SubItems.Add(u.Number.ToString()); item.SubItems.Add(u.Number.ToString());
item.SubItems.Add(u.FullName); item.SubItems.Add(u.FullName);
#if TURA_IPERL || TURA_SPECIAL
item.SubItems.Add(string.IsNullOrEmpty(u.Tag) ? string.Empty : u.Tag);
#endif
item.SubItems.Add(grps); item.SubItems.Add(grps);
item.Tag = u; item.Tag = u;
this.listViewUsers.Items.Add(item); this.listViewUsers.Items.Add(item);
@ -115,8 +121,11 @@ namespace Users.Forms
private void editButton_Click(object sender, EventArgs e) private void editButton_Click(object sender, EventArgs e)
{ {
new Forms.EditSelectedUser(session, (User)listViewUsers.SelectedItems[0].Tag).ShowDialog(); if (listViewUsers.SelectedItems.Count == 1 && listViewUsers.SelectedItems[0].Tag is User)
ListUsers(); {
new Forms.EditSelectedUser(session, (User)listViewUsers.SelectedItems[0].Tag).ShowDialog();
ListUsers();
}
} }
private void listViewUsers_DoubleClick(object sender, EventArgs e) private void listViewUsers_DoubleClick(object sender, EventArgs e)

View File

@ -126,7 +126,7 @@
<value>0, 0</value> <value>0, 0</value>
</data> </data>
<data name="listViewUsers.Size" type="System.Drawing.Size, System.Drawing"> <data name="listViewUsers.Size" type="System.Drawing.Size, System.Drawing">
<value>480, 502</value> <value>821, 502</value>
</data> </data>
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="listViewUsers.TabIndex" type="System.Int32, mscorlib"> <data name="listViewUsers.TabIndex" type="System.Int32, mscorlib">
@ -247,7 +247,7 @@
<value>0, 502</value> <value>0, 502</value>
</data> </data>
<data name="statusStrip1.Size" type="System.Drawing.Size, System.Drawing"> <data name="statusStrip1.Size" type="System.Drawing.Size, System.Drawing">
<value>615, 22</value> <value>956, 22</value>
</data> </data>
<data name="statusStrip1.TabIndex" type="System.Int32, mscorlib"> <data name="statusStrip1.TabIndex" type="System.Int32, mscorlib">
<value>2</value> <value>2</value>
@ -331,10 +331,10 @@
<value>1</value> <value>1</value>
</data> </data>
<data name="splitContainer1.Size" type="System.Drawing.Size, System.Drawing"> <data name="splitContainer1.Size" type="System.Drawing.Size, System.Drawing">
<value>615, 502</value> <value>956, 502</value>
</data> </data>
<data name="splitContainer1.SplitterDistance" type="System.Int32, mscorlib"> <data name="splitContainer1.SplitterDistance" type="System.Int32, mscorlib">
<value>480</value> <value>821</value>
</data> </data>
<data name="splitContainer1.TabIndex" type="System.Int32, mscorlib"> <data name="splitContainer1.TabIndex" type="System.Int32, mscorlib">
<value>3</value> <value>3</value>
@ -358,7 +358,7 @@
<value>6, 13</value> <value>6, 13</value>
</data> </data>
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing"> <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
<value>615, 524</value> <value>956, 524</value>
</data> </data>
<data name="$this.Text" xml:space="preserve"> <data name="$this.Text" xml:space="preserve">
<value>User Management</value> <value>User Management</value>

View File

@ -1,5 +1,5 @@
/// ///
/// Copyright (c) 2016 Sensus Metering Systems /// Copyright (c) 2016-2018 Sensus Slovensko a.s.
/// ///
using FluentNHibernate.Mapping; using FluentNHibernate.Mapping;
@ -12,7 +12,10 @@ namespace Users.Mappings
Id(x => x.Id); Id(x => x.Id);
Map(x => x.UserName).Column("Name"); Map(x => x.UserName).Column("Name");
Map(x => x.Number); Map(x => x.Number);
Map(x => x.Password); #if TURA_IPERL || TURA_SPECIAL
Map(x => x.Tag);
#endif
Map(x => x.Password);
Map(x => x.FullName).Column("Description"); Map(x => x.FullName).Column("Description");
Map(x => x.LastPwChange); Map(x => x.LastPwChange);
HasMany(x => x.Groups) HasMany(x => x.Groups)

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.18.843.0")] [assembly: AssemblyVersion("2.18.893.0")]
[assembly: AssemblyFileVersion("2.18.843.0")] [assembly: AssemblyFileVersion("2.18.893.0")]

View File

@ -330,6 +330,24 @@ namespace Users.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to NFC Tag.
/// </summary>
internal static string Tag {
get {
return ResourceManager.GetString("Tag", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This NFC tag has already been taken. Please use another one..
/// </summary>
internal static string Tag_taken {
get {
return ResourceManager.GetString("Tag_taken", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to tester. /// Looks up a localized string similar to tester.
/// </summary> /// </summary>

View File

@ -216,4 +216,7 @@
<data name="invalid" xml:space="preserve"> <data name="invalid" xml:space="preserve">
<value>neplatný</value> <value>neplatný</value>
</data> </data>
<data name="Tag_taken" xml:space="preserve">
<value>Tento NFC tag již byl použit. Prosím, použite jiný.</value>
</data>
</root> </root>

View File

@ -228,4 +228,10 @@
<data name="invalid" xml:space="preserve"> <data name="invalid" xml:space="preserve">
<value>invalid</value> <value>invalid</value>
</data> </data>
<data name="Tag" xml:space="preserve">
<value>NFC Tag</value>
</data>
<data name="Tag_taken" xml:space="preserve">
<value>This NFC tag has already been taken. Please use another one.</value>
</data>
</root> </root>

View File

@ -91,7 +91,12 @@
<DependentUpon>Strings.resx</DependentUpon> <DependentUpon>Strings.resx</DependentUpon>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup>
<ProjectReference Include="..\GemCard\GemCard.csproj">
<Project>{8B10D15A-39DE-4B56-8DD1-710C1EB3A697}</Project>
<Name>GemCard</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Forms\EditSelectedUser.resx"> <EmbeddedResource Include="Forms\EditSelectedUser.resx">
<DependentUpon>EditSelectedUser.cs</DependentUpon> <DependentUpon>EditSelectedUser.cs</DependentUpon>

View File

@ -4,6 +4,8 @@ rmdir /s /q DeviceTest\bin
rmdir /s /q DeviceTest\obj rmdir /s /q DeviceTest\obj
rmdir /s /q Dirichlet.Numerics\bin rmdir /s /q Dirichlet.Numerics\bin
rmdir /s /q Dirichlet.Numerics\obj rmdir /s /q Dirichlet.Numerics\obj
rmdir /s /q GemCard\bin
rmdir /s /q GemCard\obj
rmdir /s /q GraphLib\bin rmdir /s /q GraphLib\bin
rmdir /s /q GraphLib\obj rmdir /s /q GraphLib\obj
rmdir /s /q MonitoringDB\bin rmdir /s /q MonitoringDB\bin