Package smartcard :: Module CardMonitoring
[hide private]
[frames] | no frames]

Source Code for Module smartcard.CardMonitoring

  1  """Smart card insertion/removal monitoring classes. 
  2   
  3  CardObserver is a base class for objects that are to be notified 
  4  upon smart card insertion/removal. 
  5   
  6  CardMonitor is a singleton object notifying registered CardObservers 
  7  upon reader insertion/removal. 
  8   
  9  __author__ = "http://www.gemalto.com" 
 10   
 11  Copyright 2001-2011 gemalto 
 12  Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 
 13   
 14  This file is part of pyscard. 
 15   
 16  pyscard is free software; you can redistribute it and/or modify 
 17  it under the terms of the GNU Lesser General Public License as published by 
 18  the Free Software Foundation; either version 2.1 of the License, or 
 19  (at your option) any later version. 
 20   
 21  pyscard is distributed in the hope that it will be useful, 
 22  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 23  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 24  GNU Lesser General Public License for more details. 
 25   
 26  You should have received a copy of the GNU Lesser General Public License 
 27  along with pyscard; if not, write to the Free Software 
 28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 29  """ 
 30   
 31  from sys import exc_info 
 32  from threading import Thread, Event 
 33  from time import sleep 
 34   
 35  from smartcard.System import readers 
 36  from smartcard.Exceptions import CardRequestTimeoutException 
 37  from smartcard.Observer import Observer 
 38  from smartcard.Observer import Observable 
 39   
 40  from smartcard.CardType import AnyCardType 
 41  from smartcard.CardRequest import CardRequest 
 42   
 43  _START_ON_DEMAND_ = False 
 44   
 45   
 46  # CardObserver interface 
47 -class CardObserver(Observer):
48 """ 49 CardObserver is a base abstract class for objects that are to be notified 50 upon smartcard reader insertion/removal. 51 """ 52
53 - def __init__(self):
54 pass
55
56 - def update(self, observable, (addedcards, removedcards)):
57 """Called upon reader insertion/removal. 58 59 observable: 60 addedcards: list of added readers causing notification 61 removedcards: list of removed readers causing notification 62 """ 63 pass
64 65
66 -class CardMonitor:
67 """Class that monitors smart card insertion/removal. 68 and notify observers 69 70 note: a card monitoring thread will be running 71 as long as the card monitor has observers, or CardMonitor.stop() 72 is called. Do not forget to delete all your observers by 73 calling deleteObserver, or your program will run forever... 74 75 Uses the singleton pattern from Thinking in Python 76 Bruce Eckel, http://mindview.net/Books/TIPython to make sure 77 there is only one CardMonitor. 78 """ 79
80 - class __CardMonitorSingleton(Observable):
81 """The real smartcard monitor class. 82 83 A single instance of this class is created 84 by the public CardMonitor class. 85 """ 86
87 - def __init__(self):
88 Observable.__init__(self) 89 if _START_ON_DEMAND_: 90 self.rmthread = None 91 else: 92 self.rmthread = CardMonitoringThread(self)
93
94 - def addObserver(self, observer):
95 """Add an observer. 96 97 We only start the card monitoring thread when 98 there are observers. 99 """ 100 Observable.addObserver(self, observer) 101 if _START_ON_DEMAND_: 102 if self.countObservers() > 0 and self.rmthread == None: 103 self.rmthread = CardMonitoringThread(self) 104 else: 105 observer.update(self, (self.rmthread.cards, []))
106
107 - def deleteObserver(self, observer):
108 """Remove an observer. 109 110 We delete the CardMonitoringThread reference when there 111 are no more observers. 112 """ 113 Observable.deleteObserver(self, observer) 114 if _START_ON_DEMAND_: 115 if self.countObservers() == 0: 116 if self.rmthread != None: 117 self.rmthread = None
118
119 - def __str__(self):
120 return 'CardMonitor'
121 122 # the singleton 123 instance = None 124
125 - def __init__(self):
128
129 - def __getattr__(self, name):
130 return getattr(self.instance, name)
131 132
133 -class CardMonitoringThread:
134 """Card insertion thread. 135 This thread waits for card insertion. 136 """ 137
139 """The real card monitoring thread class. 140 141 A single instance of this class is created 142 by the public CardMonitoringThread class. 143 """ 144
145 - def __init__(self, observable):
146 Thread.__init__(self) 147 self.observable = observable 148 self.stopEvent = Event() 149 self.stopEvent.clear() 150 self.cards = [] 151 self.setDaemon(True)
152 153 # the actual monitoring thread
154 - def run(self):
155 """Runs until stopEvent is notified, and notify 156 observers of all card insertion/removal. 157 """ 158 self.cardrequest = CardRequest(timeout=0.1) 159 while self.stopEvent.isSet() != 1: 160 try: 161 currentcards = self.cardrequest.waitforcardevent() 162 163 addedcards = [] 164 for card in currentcards: 165 if not self.cards.__contains__(card): 166 addedcards.append(card) 167 168 removedcards = [] 169 for card in self.cards: 170 if not currentcards.__contains__(card): 171 removedcards.append(card) 172 173 if addedcards != [] or removedcards != []: 174 self.cards = currentcards 175 self.observable.setChanged() 176 self.observable.notifyObservers((addedcards, removedcards)) 177 178 # when CardMonitoringThread.__del__() is invoked in 179 # response to shutdown, e.g., when execution of the 180 # program is done, other globals referenced by the 181 # __del__() method may already have been deleted. 182 # this causes ReaderMonitoringThread.run() to except 183 # with a TypeError or AttributeError 184 except TypeError: 185 pass 186 except AttributeError: 187 pass 188 189 except: 190 try: 191 import sys 192 print sys.exc_info()[1] 193 print sys.exc_info()[2] 194 print sys.exc_info()[0] 195 except: 196 pass
197 198 # stop the thread by signaling stopEvent
199 - def stop(self):
200 self.stopEvent.set()
201 202 # the singleton 203 instance = None 204
205 - def __init__(self, observable):
209
210 - def __getattr__(self, name):
211 if self.instance: 212 return getattr(self.instance, name)
213 214 # commented to avoid bad clean-up sequence of python where __del__ 215 # is called when some objects it uses are already gargabe collected 216 #def __del__(self): 217 # if CardMonitoringThread.instance!=None: 218 # CardMonitoringThread.instance.stop() 219 # CardMonitoringThread.instance = None 220 221 222 if __name__ == "__main__": 223 from smartcard.CardMonitoring import CardMonitor 224 print 'insert or remove cards in the next 10 seconds' 225 226 # a simple card observer that prints added/removed cards
227 - class printobserver(CardObserver):
228
229 - def __init__(self, obsindex):
230 self.obsindex = obsindex
231
232 - def update(self, observable, (addedcards, removedcards)):
233 print "%d - added: " % self.obsindex, addedcards 234 print "%d - removed: " % self.obsindex, removedcards
235
236 - class testthread(Thread):
237
238 - def __init__(self, obsindex):
239 Thread.__init__(self) 240 self.readermonitor = CardMonitor() 241 self.obsindex = obsindex 242 self.observer = None
243
244 - def run(self):
245 # create and register observer 246 self.observer = printobserver(self.obsindex) 247 self.readermonitor.addObserver(self.observer) 248 sleep(10) 249 self.readermonitor.deleteObserver(self.observer)
250 251 t1 = testthread(1) 252 t2 = testthread(2) 253 t1.start() 254 t2.start() 255