Showing posts with label Libraries. Show all posts
Showing posts with label Libraries. Show all posts

Friday, May 18, 2012

Belgium eID Card Reader Application

A friend of mine, Tim, asked me to write up a simple application
that's able to read out the Belgium ID cards.

This is what I ended up with...
A few things you need to know:
  • Reference the Interop.EIDLIBCTRLLib.dll
  • Target the x86 platform (the dll only exists in a 32bit flavour)




























eID Reader Binaries
eID Reader Source Code

The actual eID Object : were all the “Magic” Happens…

Friend Class eIDObject

#Region "Events"

    Protected Friend Event Init_Failed()
    Protected Friend Event Exit_Failed()
    Protected Friend Event Finished_InfoRetrieval()

#End Region

#Region "Variables"

    Protected Friend ErrorMessage As String

    Private lHandle As Integer = Nothing
    Private Eidlib1 As New EIDLIBCTRLLib.EIDlib
    Private RetStatus As EIDLIBCTRLLib.RetStatus = Nothing
    Private MapColPicture As New EIDLIBCTRLLib.MapCollection
    Private MapColID As New EIDLIBCTRLLib.MapCollection
    Private MapColAddress As New EIDLIBCTRLLib.MapCollection
    Private CertifCheck As New EIDLIBCTRLLib.CertifCheck

#End Region

#Region "BEID Properties"

#Region "BEID Card Info"

    Private strCardNumber As String
    Protected Friend ReadOnly Property CardNumber() As String
        Get
            Return strCardNumber
        End Get
    End Property

    Private strChipNumber As String
    Protected Friend ReadOnly Property ChipNumber() As String
        Get
            Return strChipNumber
        End Get
    End Property

    Private strIssuingMunicipality As String
    Protected Friend ReadOnly Property IssuingMunicipality() As String
        Get
            Return strIssuingMunicipality
        End Get
    End Property

    'START DATE - INITIAL DATE
    Private dateBeginValidityDate As Date
    Protected Friend ReadOnly Property BeginValidityDate() As Date
        Get
            Return dateBeginValidityDate
        End Get
    End Property

    Private strBegVal As Object

    Private strBegValDag As String
    Protected Friend ReadOnly Property BeginValidityDay() As String
        Get
            Return strBegValDag
        End Get
    End Property

    Private strBegValMaand As String
    Protected Friend ReadOnly Property BeginValidityMonth() As String
        Get
            Return strBegValMaand
        End Get
    End Property

    Private strBegValJaar As String
    Protected Friend ReadOnly Property BeginValidityYear() As String
        Get
            Return strBegValJaar
        End Get
    End Property

    'END DATE - EXPIRE DATE
    Private dateEndValidityDate As Date
    Protected Friend ReadOnly Property EndValidityDate() As Date
        Get
            Return dateEndValidityDate
        End Get
    End Property

    Private strEndVal As Object
    Private strEndValDag As String
    Protected Friend ReadOnly Property EndValidityDay() As String
        Get
            Return strEndValDag
        End Get
    End Property

    Private strEndValMaand As String
    Protected Friend ReadOnly Property EndValidityMonth() As String
        Get
            Return strEndValMaand
        End Get
    End Property

    Private strEndValJaar As String
    Protected Friend ReadOnly Property EndValidityYear() As String
        Get
            Return strEndValJaar
        End Get
    End Property

#End Region

#Region "BEID Person Info"
    Private strName As String
    Protected Friend ReadOnly Property Name() As String
        Get
            Return strName
        End Get
    End Property

    Private strFirstName1 As String
    Protected Friend ReadOnly Property FirstName() As String
        Get
            Return strFirstName1
        End Get
    End Property

    Private strFirstName2 As String
    Protected Friend ReadOnly Property FirstName2() As String
        Get
            Return strFirstName2
        End Get
    End Property

    Private strBirthPlace As String
    Protected Friend ReadOnly Property BirthPlace() As String
        Get
            Return strBirthPlace
        End Get
    End Property

    Private strBirthDate As String
    Protected Friend ReadOnly Property BirthDate() As String
        Get
            Return strBirthDate
        End Get
    End Property

    Private strGender As String
    Protected Friend ReadOnly Property Gender() As String
        Get
            Return strGender
        End Get
    End Property

    Private strNationality As String
    Protected Friend ReadOnly Property Nationality() As String
        Get
            Return strNationality
        End Get
    End Property

    Private strNationalNumber As String
    Protected Friend ReadOnly Property NationalNumber() As String
        Get
            Return strNationalNumber
        End Get
    End Property
#End Region

#Region "BEID Adres Info"
    Private strStreet As String
    Protected Friend ReadOnly Property Street() As String
        Get
            Return strStreet
        End Get
    End Property

    Private strStreetNumber As String
    Protected Friend ReadOnly Property StreetNumber() As String
        Get
            Return strStreetNumber
        End Get
    End Property

    Private strZIPCode As String
    Protected Friend ReadOnly Property ZIPCode() As String
        Get
            Return strZIPCode
        End Get
    End Property

    Private strMunicipality As String
    Protected Friend ReadOnly Property Municipality() As String
        Get
            Return strMunicipality
        End Get
    End Property

#End Region

#Region "BEID Picture Info"

    Private imgPicture As Global.System.Drawing.Image
    Protected Friend ReadOnly Property Picture() As Global.System.Drawing.Image
        Get
            Return imgPicture
        End Get

    End Property

#End Region

#End Region

#Region "Constructor"

    Protected Friend Sub New()
    End Sub

#End Region

#Region "Methods"

    Private Function eID_Init() As Boolean
        Try
            RetStatus = Eidlib1.Init("", 0, 0, lHandle)
            If (RetStatus.GetGeneral = 0) Then
                Return True
            Else
                ErrorMessage = "Unable to initialize eID Reader!"
                RaiseEvent Init_Failed()
                Return False
            End If
        Catch ex As Exception
            ErrorMessage = "Unable to initialize eID Reader!" + vbCrLf + GetErrorInfo(ex)
            RaiseEvent Init_Failed()
            Return False
        End Try
    End Function

    Private Function eID_Exit() As Boolean
        Try
            RetStatus = Eidlib1.Exit()
            Return True
        Catch ex As Exception
            ErrorMessage = "Unable to exit eID Reader!" + vbCrLf + GetErrorInfo(ex)
            RaiseEvent Exit_Failed()
            Return False
        Finally
            'release all objects
            RetStatus = Nothing
            GC.Collect()
            GC.WaitForPendingFinalizers()
        End Try
    End Function

    Protected Friend Function RetrieveInformation() As Boolean
        'reset errormessage
        ErrorMessage = ""
        Try
            If eID_Init() Then
                ' get the info stored on the Belgium eID card & populate the properties
                RetStatus = Eidlib1.GetID(MapColID, CertifCheck)

                'card
                strChipNumber = MapColID.GetValue("ChipNumber")
                strCardNumber = MapColID.GetValue("CardNumber")
                strBegVal = MapColID.GetValue("BeginValidityDate")
                strEndVal = MapColID.GetValue("EndValidityDate")
                strIssuingMunicipality = MapColID.GetValue("IssuingMunicipality")
                '        'Opsplitsen begindatum
                strBegValDag = Microsoft.VisualBasic.Right(strBegVal, 2)
                strBegValMaand = Microsoft.VisualBasic.Mid(strBegVal, 5, 2)
                strBegValJaar = Microsoft.VisualBasic.Left(strBegVal, 4)
                '        'Opsplitsen einddatum
                strEndValDag = Microsoft.VisualBasic.Right(strEndVal, 2)
                strEndValMaand = Microsoft.VisualBasic.Mid(strEndVal, 5, 2)
                strEndValJaar = Microsoft.VisualBasic.Left(strEndVal, 4)
                dateBeginValidityDate = CDate(strBegValDag & "/" & strBegValMaand & "/" & strBegValJaar)
                dateEndValidityDate = CDate(strEndValDag & "/" & strEndValMaand & "/" & strEndValJaar)
                'person
                strName = MapColID.GetValue("Name")
                strFirstName1 = MapColID.GetValue("FirstName1")
                strFirstName2 = MapColID.GetValue("FirstName2")
                strBirthDate = MapColID.GetValue("BirthDate")
                'transform birthdate
                Dim d As String = ""
                Dim m As String = ""
                Dim y As String = ""

                d = Microsoft.VisualBasic.Right(strBirthDate, 2)
                m = Microsoft.VisualBasic.Mid(strBirthDate, 5, 2)
                y = Microsoft.VisualBasic.Left(strBirthDate, 4)
                strBirthDate = CDate(d & "/" & m & "/" & y)
                strBirthPlace = MapColID.GetValue("BirthPlace")
                strGender = MapColID.GetValue("Gender")
                strNationality = UCase(MapColID.GetValue("Nationality"))
                strNationalNumber = MapColID.GetValue("NationalNumber")
                'address
                RetStatus = Eidlib1.GetAddress(MapColAddress, CertifCheck)
                strStreet = Trim(MapColAddress.GetValue("Street")) 'Neerhofstraat 26
                'get street number
                strStreetNumber = strStreet.Substring(strStreet.LastIndexOf(" ") + 1)
                'get street
                strStreet = strStreet.Substring(0, strStreet.LastIndexOf(" "))
                strZIPCode = MapColAddress.GetValue("ZIPCode")
                strMunicipality = MapColAddress.GetValue("Municipality")
                'get picture
                Dim s As IO.MemoryStream = Nothing
                Dim o() As Byte = Nothing
                Dim raw As EIDLIBCTRLLib.Raw = Nothing
                Try
                    Eidlib1.GetRawData(raw)
                    raw.GetPictureData(o)
                    s = New IO.MemoryStream(o)
                    imgPicture = Global.System.Drawing.Image.FromStream(s)
                    s.Dispose()
                    s = Nothing
                Catch ex As Exception
                    ErrorMessage = "Unable to retrieve picture from eID card!" + vbCrLf + GetErrorInfo(ex)
                Finally
                    If Not s Is Nothing Then
                        s.Dispose()
                        s = Nothing
                    End If
                End Try
            Else
                Return False
            End If
            Return True
        Catch ex As Exception
            ErrorMessage = "Unable to retrieve information from eID card!" + vbCrLf + GetErrorInfo(ex)
            Return False
        Finally
            eID_Exit()
            RaiseEvent Finished_InfoRetrieval()
        End Try
    End Function

    Protected Friend Function ExportInformationToFile(ByVal filename As String) As Boolean
        Dim txtwriter As IO.StreamWriter = Nothing
        Try
            If Not String.IsNullOrEmpty(filename) Then

                txtwriter = New IO.StreamWriter(filename)
                txtwriter.WriteLine("CARDNUMBER=" + Me.CardNumber)
                txtwriter.WriteLine("BEGINVALIDITY=" + Me.BeginValidityDate)
                txtwriter.WriteLine("ENDVALIDITY=" + Me.EndValidityDate)
                txtwriter.WriteLine("ISSUINGMUNICIPALITY=" + Me.IssuingMunicipality)
                txtwriter.WriteLine("FIRSTNAME=" + Me.FirstName + IIf(Me.FirstName2 = "", "", " " + Me.FirstName2))
                txtwriter.WriteLine("SURNAME=" + Me.Name)
                txtwriter.WriteLine("GENDER=" + Me.Gender)
                txtwriter.WriteLine("NATIONALITY=" + Me.Nationality)
                txtwriter.WriteLine("BIRTHDATE=" + Me.BirthDate)
                txtwriter.WriteLine("BIRTHPLACE=" + Me.BirthPlace)
                txtwriter.WriteLine("NATIONALNUMBER=" + Me.NationalNumber)
                txtwriter.WriteLine("STREET=" + Me.Street)
                txtwriter.WriteLine("STREETNUMBER=" + Me.StreetNumber)
                txtwriter.WriteLine("ZIP=" + Me.ZIPCode)
                txtwriter.WriteLine("CITY=" + Me.Municipality)
                txtwriter.Close()
                Return True
            Else
                ErrorMessage = "Export Filename is empty!"
                Return False
            End If
        Catch ex As Exception
            ErrorMessage = "Unable to write eID card Information to file : " + filename + GetErrorInfo(ex)
            Return False
        Finally
            If Not txtwriter Is Nothing Then
                txtwriter.Dispose()
                txtwriter = Nothing
            End If
        End Try
    End Function

    Protected Friend Function ExportPictureToFile(ByVal filename As String) As Boolean
        Try
            If Not Me.Picture Is Nothing Then
                Me.Picture.Save(filename, Drawing.Imaging.ImageFormat.Jpeg)
                Return True
            Else
                ErrorMessage = "No picture found!"
                Return False
            End If
        Catch ex As Exception
            ErrorMessage = "Unable to export the picture to : " + filename + GetErrorInfo(ex)
            Return False
        End Try
    End Function

#End Region
   
End Class

Thursday, May 3, 2012

Create Shortcuts using late binding

Simply create a new shortcut using some late binding, instead of having to reference the Windows Scripting Host : IWshRuntimeLibrary

Usage:
Shortcut.Create_Shortcut(PathtoExecutable, PathToShortcutFolder, ShortCutName,ExecutableFolderPath, Description, "", 0, 0)

 
Imports System.Runtime.CompilerServices
Imports Microsoft.VisualBasic.CompilerServices
Public Class Shortcut
Public Shared Function Create_Shortcut(ByVal Target_Path As String, ByVal Shortcut_Path As String, ByVal Shortcut_Name As String, _
ByVal Working_Directory As String, ByVal Description As String, ByVal Arguments As String, ByVal Window_Style As Integer, ByVal Icon_Num As Integer) As Boolean
Try
Dim objectValue As Object = RuntimeHelpers.GetObjectValue(Interaction.CreateObject("WScript.Shell", ""))
Dim objectValue2 As Object = RuntimeHelpers.GetObjectValue(NewLateBinding.LateGet(objectValue, Nothing, _
"CreateShortcut", New Object() {Shortcut_Path & "\" & Shortcut_Name & ".lnk"}, Nothing, Nothing, Nothing))
NewLateBinding.LateSet(objectValue2, Nothing, "TargetPath", New Object() {Target_Path}, Nothing, Nothing)
NewLateBinding.LateSet(objectValue2, Nothing, "WorkingDirectory", New Object() {Working_Directory}, Nothing, Nothing)
NewLateBinding.LateSet(objectValue2, Nothing, "Arguments", New Object() {Arguments}, Nothing, Nothing)
NewLateBinding.LateSet(objectValue2, Nothing, "WindowStyle", New Object() {Window_Style}, Nothing, Nothing)
NewLateBinding.LateSet(objectValue2, Nothing, "Description", New Object() {Description}, Nothing, Nothing)
NewLateBinding.LateSet(objectValue2, Nothing, "IconLocation", New Object() {Target_Path & "," _
& Conversions.ToString(Icon_Num)}, Nothing, Nothing)
NewLateBinding.LateCall(objectValue2, Nothing, "Save", New Object() {}, Nothing, Nothing, Nothing, True)
Return True
Catch ex As Exception
Return False
End Try
End Function
End Class

A special thanks to Tirthraaj Gobin for comming up with this solution...
http://social.msdn.microsoft.com/Forums/en-US/vbide/thread/126c09a2-6f38-4747-9ddd-55ff977fcba0?prof=required

Tuesday, February 15, 2011

FileDB - A C# database to store files

When browsing through the codeplex website, I found an interesting project.
A simple easy to use storage container, in the past I used QVFS
http://www.codeproject.com/KB/vb/QVFS.aspx .
But this project seems to be abandoned. This seems to be very promising, the only thing I'm missing, that is available in QVFS is the ability
to create a folder structure inside the virtual storage file. On the other hand QVFS uses 2 files, 1 info file and a data file as this FileDB uses only 1 file.

Ripped of CodePlex website : http://filedb.codeplex.com/
Credits go to mbdavid http://www.codeplex.com/site/users/view/mbdavid

 

FileDB - Project Description




FileDB is a free, fast, lightweight C# (v3.5) DLL project to store, retrieve and delete files using a single archive file as a container on disk.
It's ideal for storing files (all kind, all sizes) without databases and keeping them organized on a single disk file.



  • First stable version was launched
  • Improvements on concurrent write access
  • New method: Export - Export all files to a directory

using Numeria.IO;

var pathDB = @"C:\Temp\MyDB.fdb";

// Creating an empty FileDB archive
FileDB.CreateEmptyFile(pathDB);

// Store file from input stream
var info = FileDB.Store(pathDB, "MyFileName.jpg", inputStream);
// -or- store directly from the file itself
var info = FileDB.Store(pathDB, @"C:\Temp\MyPhoto.jpg");

// The 'info' variable returned contains information about your file (generated GUID, filename, file-length, mime-type)
var fileGuid = info.ID;

// Reading file inside FileDB and writing it on an output stream (also available to write it directly to a file)
var info = FileDB.Read(pathDB, fileGuid, outputStream);

// Deleting a file
var ok = FileDB.Delete(pathDB, fileGuid);


FileDB Methods



  • CreateEmptyFile - Create an empty data file archive
  • Store - Store from file/stream to the data file
  • Read - Search a fileID and restore it to output file/stream
  • Delete - Delete a file
  • ListFiles - List all files inside the archive
  • Shrink - Reorganize archive removing unused disk space
  • Export - Export files inside archive to a directory

All operations have a static method helper or can be used from a FileDB instance.


ASP.NET MVC Example

Below is a basic example to store/retrieve/delete information in a ASP.NET MVC Controller



private string pathDB = @"C:\Temp\MvcDemo.fdb";

// Uploading a file
[HttpPost]
public ActionResult Upload()
{
HttpPostedFileBase file = Request.Files[0] as HttpPostedFileBase;

if (file.ContentLength > 0)
FileDB.Store(pathDB, file.FileName, file.InputStream);

return RedirectToAction("Index");
}

// Download
[HttpGet]
public ActionResult Download(string id)
{
// Using a classic way to download a file, instead of FileContentResult mode.
// Optimizing for big files. Your webserver will not consume CPU/Memory to download this file (even very large files)

using (var db = new FileDB(pathDB, FileAccess.Read))
{
var info = db.Search(Guid.Parse(id));

Response.Buffer = false;
Response.BufferOutput = false;
Response.ContentType = info.MimeType;
Response.AppendHeader("Content-Length", info.FileLength.ToString());
Response.AppendHeader("content-disposition", "attachment; filename=" + info.FileName);

db.Read(info.ID, Response.OutputStream);

return new EmptyResult();
}
}


Why?


Well, all web developers already had this problem: "I need to store same user files (photos, documents, ...) and I need to save them on my web server. But where? File system or database?"
(See some discussion in http://stackoverflow.com/questions/3748/storing-images-in-db-yea-or-nay#3756)
The problem is: the database was not designed to store files. ADO.NET doesn't have a good method to work with streams (only byte[]).
For small files (less then 100K) it works very nice. But what happens with a 10Mb file? 100Mb? It's terrible! The solution: work on file system!
The file system has a problem too: what if my user wants to upload 300 files? And what if I have 2000 users?
You will have thousands of files to backup and manage, and this will be a pain.
My idea: a single archive (or a single archive per user) to store only user uploaded files.
I use the SQL Server database to store the ID file reference (GUID) and FileDB does the rest of the job, storing and managing the files and bytes.


How FileDB works?


FileDB was designed to be fast, very simple, file-based and works with all file sizes.
FileDB doesn't consume lots of memory because it works only with streams (no byte[]).
The data structure is built with two kinds of pages: IndexPage and DataPage.
- The IndexPage stores information about the file descriptor and it's organized in a binary tree structure.
- The DataPage stores the file bytes.

Both pages have 4096 bytes (plus 100 bytes to file header). Each page has its own header to store information about the data inside the page.
You can delete a file inside the archive and the empty data pages will be used on next insert. Or you can shrink database to get your non-used bytes.
FileDB caches (in memory) only index pages, to be faster on a second search.


Limitations

I've made many tests to check performance and limitations with all file sizes.
To protect against many clients changing data on same archive, FileDB uses read share mode.
This way many users can search/read simultaneously but only one user can write (store/delete) at a time.
FileDB class also implements IDisposable so you can use it inside a using code.


using(var db = new FileDB(pathDB, FileAccess.ReadWrite))
{
db.Store(@"C:\Temp\MyPhoto.jpg");
}



The data size limitations are based on .NET MaxValue constants. FileDB works with UInt32 (4 bytes unsigned), which limits each file to 4GB and the database to 16TB (4096 Pages * UInt32.MaxValue).