Hello Dennis and Bryan!
You were absolutely right. I should show you real code instead of brain
fucking. I am very sorry.
Please find below real code. Sorry for amount of sources.
Main aspect of program is all process should be in one determined sequence
containing 3 stages. They are defined as stage1(), stage2() and stage3() in
appMainFrame()
Execution started when Start button presses (handler def OnStart() in
appMainFrame() ). At the same time CardsObserver calls
appMainFrame.addCards() to increment counter and in each stages wait this
counter.
All other code from library.
Kind regards,
/Gelios
#######################Main application:################################
#exception class
class NotASIMCardException:
def __init__( self, message ):
self.message = message
def __str__(self):
return repr( self.message )
class SmartCardOperations:
def getATR( self, readerDescr ):
atr=""
self.attachedReaders = readers()
for reader in self.attachedReaders:
if readerDescr == str( reader ):
connection=reader.createConnection()
try:
connection.connect()
atr=toHexString( connection.getATR() )
connection.disconnect()
except NoCardException:
atr="no card inserted"
return atr
def decodeICCID( self, iccidBytes ):
resIccid = []
#swap bytes
i = 0
while i < len(iccidBytes):
strTmp = str( hex( iccidBytes ) )
if len(strTmp) == 3:
strTmp = strTmp[0] + strTmp[1] + "0" + strTmp[2]
resIccid += [strTmp[3] + strTmp[2]]
i += 1
#remove last 2 bytes
resIccid = resIccid[:-2]
#remove first last digit
strTmp = str( resIccid[i-3] )
if len(strTmp) == 1:
strTmp += "0"
resIccid[i-3] = strTmp[0]
return resIccid
def getICCID(self, readerDescr):
self.attachedReaders = readers()
for reader in self.attachedReaders:
if readerDescr == str( reader ):
session = smartcard.Session( reader )
try:
data, sw1, sw2 = session.sendCommandAPDU( SELECT +
DF_ROOT )
data, sw1, sw2 = session.sendCommandAPDU( SELECT +
EF_ICCID )
data, sw1, sw2 = session.sendCommandAPDU( READ_BINARY +
[0x0A])
if sw1 == 0x90 or sw1 == 0x91:
msg = "Ok"
else:
msg = "ICCID read error. Error code: " +
str(hex(sw1)) + str(hex(sw2))
session.close()
except NoCardException:
msg = "ICCID read error. Error code: " + str(hex(sw1)) +
str(hex(sw2))
return msg, self.decodeICCID(data), data
def getADM0( self, readerDescr, iccid ):
self.attachedReaders = readers()
for reader in self.attachedReaders:
if readerDescr == str( reader ):
session = smartcard.Session( reader )
try:
data, sw1, sw2 = session.sendCommandAPDU( SAM_SEND_ICCID
+ iccid )
resBytesStr = str(sw1) + ' ' + str(sw2)
if resBytesStr != "61 08":
msg = "?????? ?????? ? SAM ??????"
return msg, None
data, sw1, sw2 = session. sendCommandAPDU(
SAM_GET_ADM0 )
except NoCardException:
msg = "ADM0 getting error. Error code: " + str(hex(sw1))
+ str(hex(sw2))
msg = "Ok"
return msg, data
def chgEfLnd( self, iccid, adm0 ):
self.attachedReaders = readers()
for reader in self.attachedReaders:
if readerDescr == str( reader ):
session = smartcard.Session( reader )
try:
data, sw1, sw2 = session.sendCommandAPDU(
VERIFY_KEY_SIMERA3 + adm0 )
resBytesStr = str(sw1) + ' ' + str(sw2)
if resBytesStr == "98 04" or resBytesStr == "98 40":
msg = "?????? ??????? ? ?????"
return msg
data, sw1, sw2 = session.sendCommandAPDU( SELECT +
DF_ROOT )
data, sw1, sw2 = session.sendCommandAPDU( SELECT +
DF_GSM )
data, sw1, sw2 = session.sendCommandAPDU( DELETE_FILE )
if sw1 != 0x90 or sw1 != 0x91:
msg = "?????? ??????? ? ?????"
return msg
data, sw1, sw2 = session.sendCommandAPDU( SELECT +
DF_GSM )
data, sw1, sw2 = session.sendCommandAPDU(
smartcard.util.toBytes(CREATE_FILE_APDU)
if sw1 != 0x90 or sw1 != 0x91:
msg = "?????? ??????? ? ?????"
return msg
except NoCardException:
msg = "ADM0 getting error. Error code: " + str(hex(sw1))
+ str(hex(sw2))
msg = "Ok"
return msg
class appMainFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, pos=(150,150),
size=(640,400), style = wx.CAPTION | wx.MINIMIZE_BOX | wx.CLOSE_BOX |
wx.SYSTEM_MENU)
self.panel = wx.Panel(self)
# select reader controls
self.selectReaderTxt = wx.StaticText(self.panel, -1, "??????????
???????? reader: ", pos = (10, 12), size = (170, 21))
self.readerChoice = wx.Choice(self.panel, 120, pos = (180, 10), size
= (230,21), choices=['?? ??????'])
self.readerChoice.Select( 0 )
EVT_CHOICE( self, 120, self.selectReader)
self.cardDescr = wx.TextCtrl(self.panel, -1, "????? ?? ?????????",
pos = (415, 10), size = (205,21), style = wx.TE_READONLY )
self.staticLine2 = wx.StaticLine( self.panel, 210, pos = (10, 40),
size = (610, 2) )
#Log
self.logAreaTxt = wx.StaticText(self.panel, -1, "??????: ", pos =
(10, 50), size = (105, 21))
self.logArea = wx.TextCtrl( self.panel, 301, "", pos = (10, 72),
size = (610, 260), style=wx.TE_MULTILINE | wx.TE_READONLY )
self.saveLogButton = wx.Button( self.panel, -1, "?????? ??????? ?
????", pos = (20, 345) )
EVT_BUTTON( self, self.saveLogButton.GetId(), self.OnSaveLog )
#Buttons
self.resetButton = wx.Button( self.panel, -1, "?????", pos = (300,
345) )
self.startButton = wx.Button( self. panel, -1, "?????", pos = (380,
345) )
self.closeButton = wx.Button( self.panel, -1, "?????", pos = (460,
345) )
EVT_BUTTON( self, self.resetButton.GetId(), self.OnReset )
EVT_BUTTON( self, self.startButton.GetId(), self.OnStart )
EVT_BUTTON( self, self.closeButton.GetId(), self.OnClose )
# Set properties
self.SetTitle(title)
self.Layout()
#Smart card operations
self.scOps = SmartCardOperations()
self.START = False
self.step = None
self.cardEvent = threading.Event()
def selectReader(self, event):
self.selectedReader = event.GetString()
self.cardDescr.SetValue( self.scOps.getATR(self.selectedReader) )
def removeReaders( self, removedreaders ):
for readerToRemove in removedreaders:
self.readerChoice.Delete( self.readerChoice.FindString( str(
readerToRemove ) ) )
def addReaders( self, addedreaders ):
for readerToAdd in addedreaders:
self.readerChoice.Append( str ( readerToAdd ) )
def removeCards( self, removedcards ):
if self.readerChoice.GetSelection() != 0:
self.cardDescr.SetValue("????? ?? ?????????.")
else:
self.cardDescr.SetValue("?? ?????? reader.")
def addCards( self, cardsToAdd ):
if self.readerChoice.GetSelection() != 0:
self.cardDescr.SetValue(
self.scOps.getATR(self.selectedReader) )
if self.START == True:
rpdb2.settrace()
if self.step != None:
self.step.release()
#self.cardEvent.set()
def OnReset( self, event ):
if self.step != None:
self.step = None
self.START = False
self.logArea.AppendText("????? ????????. ??? ?????? ???????
?????\n")
event.Skip()
def OnClose( self, event ):
sys.exit()
event.Skip()
def OnStart( self, event ):
self.START = True
self.step = threading.Semaphore(0)
if self.step == 0:
#start process
#STAGE 1
self.logArea.AppendText( "1. ?????????? ???????? ??????????????
????? ? reader\n" )
iccid, plainIccid = self.stage1()
if iccid == None:
event.Skip()
return None
self.logArea.AppendText( "?????????? ?????? ??????????????
?????\n" )
#STAGE 2
self.logArea.AppendText( "2. ?????????? ???????? SAM ????? ?
reader\n" )
adm0 = self.stage2( plainIccid )
if adm0 == None:
event.Skip()
return None
self.logArea.AppendText( "?????????? ?????? SAM ?????\n" )
#STAGE 3
self.logArea.AppendText( "3. ?????????? ???????? ??????????????
????? ? reader\n" )
result = self.stage3(iccid, adm0)
if result == True:
self.logArea.AppendText( "????? ??????? ??????????\n" )
else:
self.logArea.AppendText( "?????? ????????? ?????.\n" )
else:
self.logArea.AppendText( "??????? ??? ???????? ? ????????????
??????????????????. ??????? ????? ? ??????? ??????\n" )
self.step = None
self.START = False
def stage1( self ):
#wait SIM card insertion
while self.step != 1:
pass
rpdb2.settrace()
###########################BLOCKING HERE##################################
if not self.cardEvent.isSet():
self.cardEvent.wait()
self.cardEvent.clear()
#check inserted card is a SIM card
msg, atr = self.scOps.getATR( self.selectedReader )
while atr == SAM_ATR:
self.logArea.AppendText( "??????????? ????? ???????? SAM ??????.
?????????? ???????? SIM ????? ? reader\n" )
########## Decrement semaphore value##############
self.step.acquire()
msg, atr = self.scOps.getATR( self.selectedReader )
if msg != "Ok":
self.logArea.AppendText( "?????? ?????? ?????. ??????? ?????
? ??????? ??????\n" )
return None, None
#read iccid of sim card
msg, iccid, plainIccid = self.scOps.getICCID( self.selectedReader )
if msg != "Ok":
self.logArea.AppendText( "?????? ?????? ?????. ??????? ????? ?
??????? ??????\n" )
return None, None
return iccid, plainIccid
def stage2( self, iccid ):
#wait SAM card insertion
while self.step != 2:
pass
#while not self.cardEvent.isSet():
# self.cardEvent.wait()
#self.cardEvent.clear()
#check is it SAM card
msg, atr = self.scOps.getATR( self.selectedReader )
while atr != SAM_ATR:
self.logArea.AppendText( "??????????? ????? ???????? ?? SAM
??????. ?????????? ???????? SAM ????? ? reader\n" )
########## Decrement semaphore value##############
self.step.acquire()
msg, atr = self.scOps.getATR( self.selectedReader )
if msg != "Ok":
self.logArea.AppendText( "?????? ?????? ?????. ??????? ?????
? ??????? ??????\n" )
return None
#get ADM0 key
msg, adm0 = self.scOps.getADM0( self.selectedReader, iccid )
if msg != "Ok":
self.logArea.AppendText( "?????? ?????? ? SAM ??????.
??????? ????? ? ??????? ??????\n" )
return None
return adm0
def stage3( self, old_iccid, adm0 ):
#wait SIM card insertion
while self.step != 3:
pass
#while not self.cardEvent.isSet():
# self.cardEvent.wait()
#self.cardEvent.clear()
#check ATR
msg, atr = self.scOps.getATR( self.selectedReader )
while atr == SAM_ATR:
self.logArea.AppendText( "??????????? ????? ???????? ?? SAM
??????. ?????????? ???????? SAM ????? ? reader\n" )
########## Decrement semaphore value##############
self.step.acquire()
msg, atr = self.scOps.getATR( self.selectedReader )
if msg != "Ok":
return False
#check iccid
msg, new_iccid, plain_new_iccid = self.scOps.getICCID(
self.selectedReader )
if msg != "Ok":
return False
while old_iccid != new_iccid:
if old_iccid != new_iccid:
self.logArea.AppendText( "? reader ????????? ????? ? ICCID="
+ str(new_iccid) + ". ????????? ??????? ????? ? ICCID=" + str(old_iccid))
msg = self.scOps.chgEfLnd(plain_new_iccid, adm0)
if msg != "Ok":
return False
return True
def OnSaveLog(self, event):
dlg = wx.FileDialog(self, "Choose a file", ".", "", "*.*", wx.OPEN)
try:
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
logfile = open(filename, 'w')
logfile.write(self.logArea.GetValue())
logfile.close()
finally:
dlg.Destroy()
def showMessage( self, message, title):
msgWin = wxMessageDialog ( None, message, title, wxOK )
msgWin.ShowModal()
msgWin.Destroy()
class ReadersObserver:
def __init__ ( self, frame ):
self.mainFrame = frame
def update( self, observable, ( addedreaders, removedreaders ) ):
self.mainFrame.removeReaders( removedreaders )
self.mainFrame.addReaders( addedreaders )
class CardsObserver:
def __init__( self, frame ):
self.mainFrame = frame
def update( self, observable, ( addedcards, removedcards ) ):
self.mainFrame.removeCards( removedcards )
self.mainFrame.addCards( addedcards )
class appChgLnd(wx.PySimpleApp):
def OnInit(self):
#create frame
self.appFrame = appMainFrame(None, "SimUpdate")
self.SetTopWindow( self.appFrame )
#create observer class instances
readersObserver = ReadersObserver( self.appFrame )
cardsObserver = CardsObserver( self.appFrame )
#subscribe to readers monitor and card monitor
self.cardsMonitor = CardMonitor()
self.cardsMonitor.addObserver( cardsObserver )
self.readersMonitor = ReaderMonitor()
self.readersMonitor.addObserver( readersObserver )
#show frame
self.appFrame.Show(True)
return True
if __name__ == '__main__':
try:
app = appChgLnd(0)
app.MainLoop()
except:
traceback.print_exc( file=open('errors.log', 'w'))
########################################## CARD
OBSERVER###################################
from sys import exc_info
from threading import Thread, Event
from time import sleep
from smartcard.System import readers
from smartcard.Exceptions import CardRequestTimeoutException
from smartcard.Observer import Observer
from smartcard.Observer import Observable
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
# CardObserver interface
class CardObserver(Observer):
"""
CardObserver is a base abstract class for objects that are to be
notified
upon smartcard reader insertion/removal.
"""
def __init__(self):
pass
def update( self, observable, (addedcards, removedcards) ):
"""Called upon reader insertion/removal.
observable:
addedcards: list of added readers causing notification
removedcards: list of removed readers causing notification
"""
pass
class CardMonitor:
"""Class that monitors smart card insertion/removal.
and notify observers
"""
class __CardMonitorSingleton( Observable ):
"""The real smartcard monitor class.
A single instance of this class is created
by the public CardMonitor class.
"""
def __init__(self):
Observable.__init__(self)
self.rmthread=None
def addObserver(self, observer):
"""Add an observer.
We only start the card monitoring thread when
there are observers.
"""
Observable.addObserver( self, observer )
if self.countObservers()>0 and self.rmthread==None:
self.rmthread = CardMonitoringThread( self )
def deleteObserver(self, observer):
"""Remove an observer.
We delete the CardMonitoringThread reference when there
are no more observers.
"""
Observable.deleteObserver( self, observer )
if self.countObservers()==0:
if self.rmthread!=None:
self.rmthread=None
# the singleton
instance = None
def __init__(self):
if not CardMonitor.instance:
CardMonitor.instance = CardMonitor.__CardMonitorSingleton()
def __getattr__(self, name):
return getattr(self.instance, name)
class CardMonitoringThread:
"""Card insertion thread.
This thread waits for card insertion.
"""
class __CardMonitoringThreadSingleton( Thread ):
"""The real card monitoring thread class.
A single instance of this class is created
by the public CardMonitoringThread class.
"""
def __init__(self, observable):
Thread.__init__(self)
self.observable=observable
self.stopEvent = Event()
self.stopEvent.clear()
self.cards = []
self.cardrequest = CardRequest( timeout=2 )
self.setDaemon(True)
# the actual monitoring thread
def run(self):
"""Runs until stopEvent is notified, and notify
observers of all card insertion/removal.
"""
while self.stopEvent.isSet()!=1:
try:
currentcards = self.cardrequest.waitforcardevent()
addedcards=[]
for card in currentcards:
if not self.cards.__contains__( card ):
addedcards.append( card )
removedcards=[]
for card in self.cards:
if not currentcards.__contains__( card ):
removedcards.append( card )
if addedcards!=[] or removedcards!=[]:
self.cards=currentcards
self.observable.setChanged()
self.observable.notifyObservers( (addedcards,
removedcards) )
except:
import sys
print sys.exc_info()[1]
print sys.exc_info()[2]
print sys.exc_info()[0]
# stop the thread by signaling stopEvent
def stop(self):
self.stopEvent.set()
# the singleton
instance = None
def __init__(self, observable):
if not CardMonitoringThread.instance:
CardMonitoringThread.instance =
CardMonitoringThread.__CardMonitoringThreadSingleton( observable )
CardMonitoringThread.instance.start()
def __getattr__(self, name):
return getattr(self.instance, name)
def __del__(self):
if CardMonitoringThread.instance!=None:
CardMonitoringThread.instance.stop()
CardMonitoringThread.instance = None
##################################### GENERAL
OBSERVER##############################
Class support for "observer" pattern.
The observer class is the base class
for all smartcard package observers.
"""
from smartcard.Synchronization import *
class Observer:
def update(observable, arg):
'''Called when the observed object is
modified. You call an Observable object's
notifyObservers method to notify all the
object's observers of the change.'''
pass
class Observable(Synchronization):
def __init__(self):
self.obs = []
self.changed = 0
Synchronization.__init__(self)
def addObserver(self, observer):
if observer not in self.obs:
self.obs.append(observer)
def deleteObserver(self, observer):
self.obs.remove(observer)
def notifyObservers(self, arg = None):
'''If 'changed' indicates that this object
has changed, notify all its observers, then
call clearChanged(). Each observer has its
update() called with two arguments: this
observable object and the generic 'arg'.'''
self.mutex.acquire()
try:
if not self.changed: return
# Make a local copy in case of synchronous
# additions of observers:
localArray = self.obs[:]
self.clearChanged()
finally:
self.mutex.release()
# Updating is not required to be synchronized:
for observer in localArray:
observer.update(self, arg)
def deleteObservers(self): self.obs = []
def setChanged(self): self.changed = 1
def clearChanged(self): self.changed = 0
def hasChanged(self): return self.changed
def countObservers(self): return len(self.obs)
synchronize(Observable,
"addObserver deleteObserver deleteObservers " +
"setChanged clearChanged hasChanged " +
"countObservers")
#:~
############################ SYNC######################
Simple emulation of Java's 'synchronized'
keyword, from Peter Norvig.
"""
from threading import RLock
def synchronized(method):
def f(*args):
self = args[0]
self.mutex.acquire();
# print method.__name__, 'acquired'
try:
return apply(method, args)
finally:
self.mutex.release();
# print method.__name__, 'released'
return f
def synchronize(klass, names=None):
"""Synchronize methods in the given class.
Only synchronize the methods whose names are
given, or all methods if names=None."""
if type(names)==type(''): names = names.split()
for (name, val) in klass.__dict__.items():
if callable(val) and name != '__init__' and \
(names == None or name in names):
# print "synchronizing", name
klass.__dict__[name] = synchronized(val)
# You can create your own self.mutex, or inherit
# from this class:
class Synchronization:
def __init__(self):
self.mutex = RLock()
#:~