Platforms to show: All Mac Windows Linux Cross-Platform
Required plugins for this example: MBS Mac64bit Plugin, MBS Main Plugin, MBS MacBase Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /Mac64bit/eidReader/eidReader
This example is the version from Sat, 7th Dec 2018.
Project "eidReader.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
EventHandler Sub Open()
End EventHandler
Note "About"
This is for reading belgian identity cards with a smartcard reader on MacOS
App must be codesigned with entitlement and built for 64-bit.
End Class
Class MainWindow Inherits Window
Control List Inherits Listbox
ControlInstance List Inherits Listbox
End Control
EventHandler Sub Open()
#if Target32Bit then
#pragma error Build in 64-bit please!
#endif
if TKSmartCardSlotManager.Available then
// Note that defaultManager instance is accessible only if the calling application
// has 'com.apple.security.smartcard' entitlement set to Boolean:YES. If the calling
// application does not have this entitlement, this will raise exception!
slotManager = new TKSmartCardSlotManager
slotManager.OpenFirstSlot
else
log "needs MacOS 10.10 or newer."
end if
Exception r as UnsupportedOperationException
MsgBox r.message
End EventHandler
Property slotManager As TKSmartCardSlotManager
End Class
MenuBar MainMenuBar
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem EditSeparator1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem EditSeparator2 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
Class TKSmartCardSlotManager Inherits TKSmartCardSlotManagerMBS
EventHandler Sub gotSlotWithName(name as string, slot as TKSmartCardSlotMBS, tag as variant)
log "Got slot: "+slot.Name
self.currentSlot = slot
// connect event
AddHandler slot.StateChanged, WeakAddressOf SlotStateChanged
slot.SetDelegate
if slot.State = slot.kStateValidCard then
ReadSlot slot
end if
End EventHandler
EventHandler Sub slotNamesChanged()
log "Slot names changed."
OpenFirstSlot
End EventHandler
Function GetString(items as Dictionary, id as integer) As String
dim m as MemoryBlock = items.Lookup(id, nil)
if m <> nil then
return DefineEncoding(m, encodings.UTF8)
end if
End Function
Sub OpenFirstSlot()
dim slotNames() as string = me.slotNames
if slotNames.Ubound = -1 then
// no slot?
log "No slot?"
else
dim SlotName as string = slotNames(0)
log "Slots: "+Join(slotNames, ", ")
if currentSlot <> nil then
if currentSlot.Name = SlotName then
// already selected
return
end if
end if
Log "Open slot: "+SlotName
me.getSlotWithName SlotName
end if
End Sub
Sub ReadSlot(slot as TKSmartCardSlotMBS)
if hasSession then return // already working with a card!
smartcard = slot.makeSmartCard
// connect event
'AddHandler smartcard.BeginSessionCompleted, WeakAddressOf SmartcardBeginSessionCompleted
'smartcard.SetDelegate
'smartcard.beginSession
hasSession = true
smartcard.beginSessionWithDelegate WeakAddressOf SmartcardBeginSessionCompleted
End Sub
Sub SlotStateChanged(slot as TKSmartCardSlotMBS)
Select case slot.State
case slot.kStateEmpty
log "Slot "+slot.Name+" is empty."
case slot.kStateMissing
log "Slot "+slot.Name+" is missing."
self.currentSlot = nil
case slot.kStateValidCard
log "Slot "+slot.Name+" is valid card."
ReadSlot slot
case slot.kStateProbing
log "Slot "+slot.Name+" is probing."
case slot.kStateMuteCard
log "Slot "+slot.Name+" is mute card."
end Select
End Sub
Sub SmartcardBeginSessionCompleted(success as Boolean, error as NSErrorMBS, tag as Variant)
log CurrentMethodName
log "success: "+str(success)
if success then
smartcard.readFileWithDelegate(basicInfoFile, WeakAddressOf basicInfoFileReadCompleted)
end if
End Sub
Shared Function addressFile() As MemoryBlock
dim m as new MemoryBlock(4)
m.UInt8Value(0) = &hDF
m.UInt8Value(1) = &h01
m.UInt8Value(2) = &h40
m.UInt8Value(3) = &h33
return m
End Function
Sub addressFileReadCompleted(FileName as MemoryBlock, Content as MemoryBlock, error as NSErrorMBS, tag as Variant)
log CurrentMethodName
dim StreetLen as integer = content.UInt8Value(1)
dim Street as string = DefineEncoding(content.MidB(2, StreetLen), encodings.UTF8)
log "Street: "+Street
dim postalCodeLen as integer = content.UInt8Value(1+2+StreetLen)
dim postalCode as string = DefineEncoding(content.MidB(2+2+StreetLen, postalCodeLen), encodings.UTF8)
log "PostalCode: "+postalCode
dim cityLen as integer = content.UInt8Value(1+2+2+postalCodeLen+StreetLen)
dim city as string = DefineEncoding(content.MidB(2+2+2+postalCodeLen+StreetLen, cityLen), encodings.UTF8)
log "City: "+city
smartcard.readFileWithDelegate(photoFile, WeakAddressOf photoFileReadCompleted)
End Sub
Shared Function basicInfoFile() As MemoryBlock
dim m as new MemoryBlock(4)
m.UInt8Value(0) = &hDF
m.UInt8Value(1) = &h01
m.UInt8Value(2) = &h40
m.UInt8Value(3) = &h31
return m
End Function
Sub basicInfoFileReadCompleted(FileName as MemoryBlock, Content as MemoryBlock, error as NSErrorMBS, tag as Variant)
log CurrentMethodName
// split items
dim items as new Dictionary
dim cursor as integer = 2
while cursor < content.Size and content.UInt8Value(cursor-2) <> 0
dim length as integer = content.UInt8Value(cursor-1)
dim t as integer = content.UInt8Value(cursor-2)
items.Value(t) = content.MidB(cursor, length)
cursor = cursor + length + 2
wend
const kfileStructureVersion = 0
const kcardNumber = 1
const kchipNumber = 2
const kvalidityStart = 3
const kvalidityEnd = 4
const kreleasePlace = 5
const knationalIdNumber = 6
const klastName = 7
const kfirstName = 8
const kotherName = 9
const knationality = 10
const kbirthPlace = 11
const kbirthDate = 12
const ksex = 13
const knobleCondition = 14
const kdocumentType = 15
const kspecialStatus = 16
const kpictureHash = 17
const kduplicate = 18
const kspecialOrganisation = 19
const kmemberOfFamily = 20
const kprotection = 21
dim cardNumber as string = GetString(items, kcardNumber)
dim validityStart as string = GetString(items, kvalidityStart)
dim validityEnd as string = GetString(items, kvalidityEnd)
dim birthPlace as string = GetString(items, kbirthPlace)
dim nationalIdNumber as string = GetString(items, knationalIdNumber)
dim lastName as string = GetString(items, klastName)
dim firstName as string = GetString(items, kfirstName)
dim otherName as string = GetString(items, kotherName)
dim nationality as string = GetString(items, knationality)
dim releasePlace as string = GetString(items, kreleasePlace)
log "cardNumber: "+cardNumber
log "validityStart: "+validityStart
log "validityEnd: "+validityEnd
log "birthPlace: "+birthPlace
log "nationalIdNumber: "+nationalIdNumber
log "lastName: "+lastName
log "firstName: "+firstName
log "otherName: "+otherName
log "nationality: "+nationality
log "releasePlace: "+releasePlace
// next, get address
smartcard.readFileWithDelegate(addressFile, WeakAddressOf addressFileReadCompleted)
End Sub
Sub getBasicInfo()
End Sub
Shared Function idFile() As MemoryBlock
dim m as new MemoryBlock(4)
m.UInt8Value(0) = &hDF
m.UInt8Value(1) = &h01
m.UInt8Value(2) = &h40
m.UInt8Value(3) = &h38
return m
End Function
Shared Function photoFile() As MemoryBlock
dim m as new MemoryBlock(4)
m.UInt8Value(0) = &hDF
m.UInt8Value(1) = &h01
m.UInt8Value(2) = &h40
m.UInt8Value(3) = &h35
return m
End Function
Sub photoFileReadCompleted(FileName as MemoryBlock, Content as MemoryBlock, error as NSErrorMBS, tag as Variant)
log CurrentMethodName
dim p as Picture = Picture.FromData(content)
if p <> nil then
PicWindow.Backdrop = p
end if
smartcard.endSession
hasSession = false
End Sub
Property currentSlot As TKSmartCardSlotMBS
Property hasSession As Boolean
Property smartcard As TKSmartCardMBS
End Class
Module Module1
Sub Log(s as string)
MainWindow.List.AddRow s
End Sub
End Module
Module SmartCardUtil
End Module
Class PicWindow Inherits Window
End Class
End Project
See also:
The items on this page are in the following plugins: MBS Mac64bit Plugin.