1 """wxPython panel display cards/readers as a TreeCtrl.
2
3 __author__ = "gemalto http://www.gemalto.com"
4
5 Copyright 2001-2011 gemalto
6 Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
7
8 This file is part of pyscard.
9
10 pyscard is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14
15 pyscard is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with pyscard; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 """
24
25
26 from threading import RLock
27 from smartcard.Exceptions import CardConnectionException, NoCardException
28 from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver
29 from smartcard.CardMonitoring import CardMonitor, CardObserver
30 from smartcard.util import toHexString
31
32 import smartcard.wx.SimpleSCardApp
33 from smartcard.wx import ICO_SMARTCARD, ICO_READER
34
35
36 import wx
37
38
40 """Base class for the smart card and reader tree controls."""
41
42 - def __init__(self,
43 parent,
44 ID=wx.NewId(),
45 pos=wx.DefaultPosition,
46 size=wx.DefaultSize,
47 style=0,
48 clientpanel=None):
49 """Constructor. Initializes a smartcard or reader tree control."""
50 wx.TreeCtrl.__init__(self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS)
51
52 self.clientpanel = clientpanel
53 self.parent = parent
54
55 isz = (16, 16)
56 il = wx.ImageList(isz[0], isz[1])
57 self.capindex = il.Add(wx.ArtProvider_GetBitmap(wx.ART_HELP_BOOK, wx.ART_OTHER, isz))
58 self.fldrindex = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz))
59 self.fldropenindex = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz))
60 if None != ICO_SMARTCARD:
61 self.cardimageindex = il.Add(wx.Bitmap(ICO_SMARTCARD, wx.BITMAP_TYPE_ICO))
62 if None != ICO_READER:
63 self.readerimageindex = il.Add(wx.Bitmap(ICO_READER, wx.BITMAP_TYPE_ICO))
64 self.il = il
65 self.SetImageList(self.il)
66
68 self.Refresh()
69 wx.PostEvent(self, wx.PaintEvent())
70
71
73 """The CardTreeCtrl monitors inserted cards and notifies the
74 application client dialog of any card activation."""
75
76 - def __init__(self,
77 parent,
78 ID=wx.NewId(),
79 pos=wx.DefaultPosition,
80 size=wx.DefaultSize,
81 style=0,
82 clientpanel=None):
83 """Constructor. Create a smartcard tree control."""
84 BaseCardTreeCtrl.__init__(self, parent, ID, pos, size,
85 wx.TR_SINGLE | wx.TR_NO_BUTTONS,
86 clientpanel)
87
88 self.root = self.AddRoot("Smartcards")
89 self.SetPyData(self.root, None)
90 self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal)
91 self.SetItemImage(self.root, self.fldropenindex, wx.TreeItemIcon_Expanded)
92 self.Expand(self.root)
93
95 """Called when a card is inserted.
96 Adds a smart card to the smartcards tree."""
97 parentnode = self.root
98 for cardtoadd in addedcards:
99 childCard = self.AppendItem(parentnode, toHexString(cardtoadd.atr))
100 self.SetItemText(childCard, toHexString(cardtoadd.atr))
101 self.SetPyData(childCard, cardtoadd)
102 self.SetItemImage(childCard, self.cardimageindex, wx.TreeItemIcon_Normal)
103 self.SetItemImage(childCard, self.cardimageindex, wx.TreeItemIcon_Expanded)
104 self.Expand(childCard)
105 self.Expand(self.root)
106 self.EnsureVisible(self.root)
107 self.Repaint()
108
110 """Called when a card is removed.
111 Removes a card from the tree."""
112 parentnode = self.root
113 for cardtoremove in removedcards:
114 (childCard, cookie) = self.GetFirstChild(parentnode)
115 while childCard.IsOk():
116 if self.GetItemText(childCard) == toHexString(cardtoremove.atr):
117 self.Delete(childCard)
118 (childCard, cookie) = self.GetNextChild(parentnode, cookie)
119 self.Expand(self.root)
120 self.EnsureVisible(self.root)
121 self.Repaint()
122
123
125 """The ReaderTreeCtrl monitors inserted cards and readers and notifies the
126 application client dialog of any card activation."""
127
128 - def __init__(self,
129 parent,
130 ID=wx.NewId(),
131 pos=wx.DefaultPosition,
132 size=wx.DefaultSize,
133 style=0,
134 clientpanel=None):
135 """Constructor. Create a reader tree control."""
136
137 BaseCardTreeCtrl.__init__(self, parent, ID, pos, size,
138 wx.TR_SINGLE | wx.TR_NO_BUTTONS, clientpanel)
139
140 self.mutex = RLock()
141
142 self.root = self.AddRoot("Smartcard Readers")
143 self.SetPyData(self.root, None)
144 self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal)
145 self.SetItemImage(self.root, self.fldropenindex, wx.TreeItemIcon_Expanded)
146 self.Expand(self.root)
147
148 - def AddATR(self, readernode, atr):
149 """Add an ATR to a reader node."""
150 capchild = self.AppendItem(readernode, atr)
151 self.SetPyData(capchild, None)
152 self.SetItemImage(capchild, self.cardimageindex, wx.TreeItemIcon_Normal)
153 self.SetItemImage(capchild, self.cardimageindex, wx.TreeItemIcon_Expanded)
154 self.Expand(capchild)
155 return capchild
156
171
173 """Called when a card is inserted.
174 Adds the smart card child to the reader node."""
175 self.mutex.acquire()
176 try:
177 parentnode = self.root
178 for cardtoadd in addedcards:
179 (childReader, cookie) = self.GetFirstChild(parentnode)
180 found = False
181 while childReader.IsOk() and not found:
182 if self.GetItemText(childReader) == str(cardtoadd.reader):
183 (childCard, cookie2) = self.GetFirstChild(childReader)
184 self.SetItemText(childCard, toHexString(cardtoadd.atr))
185 self.SetPyData(childCard, cardtoadd)
186 found = True
187 else:
188 (childReader, cookie) = self.GetNextChild(parentnode, cookie)
189
190
191
192
193
194 if not found:
195 childReader = self.AppendItem(parentnode, str(cardtoadd.reader))
196 self.SetPyData(childReader, cardtoadd.reader)
197 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Normal)
198 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Expanded)
199 childCard = self.AddATR(childReader, toHexString(cardtoadd.atr))
200 self.SetPyData(childCard, cardtoadd)
201 self.Expand(childReader)
202
203 self.Expand(self.root)
204 finally:
205 self.mutex.release()
206 self.EnsureVisible(self.root)
207 self.Repaint()
208
210 """Called when a reader is inserted.
211 Adds the smart card reader to the smartcard readers tree."""
212 self.mutex.acquire()
213
214 try:
215 parentnode = self.root
216 for readertoadd in addedreaders:
217
218 found = False
219 (childReader, cookie) = self.GetFirstChild(parentnode)
220 while childReader.IsOk() and not found:
221 if self.GetItemText(childReader) == str(readertoadd):
222 found = True
223 else:
224 (childReader, cookie) = self.GetNextChild(parentnode, cookie)
225 if not found:
226 childReader = self.AppendItem(parentnode, str(readertoadd))
227 self.SetPyData(childReader, readertoadd)
228 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Normal)
229 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Expanded)
230 self.AddATR(childReader, self.GetATR(readertoadd))
231 self.Expand(childReader)
232 self.Expand(self.root)
233 finally:
234 self.mutex.release()
235 self.EnsureVisible(self.root)
236 self.Repaint()
237
239 """Called when a card is removed.
240 Removes the card from the tree."""
241 self.mutex.acquire()
242 try:
243 parentnode = self.root
244 for cardtoremove in removedcards:
245 (childReader, cookie) = self.GetFirstChild(parentnode)
246 found = False
247 while childReader.IsOk() and not found:
248 if self.GetItemText(childReader) == str(cardtoremove.reader):
249 (childCard, cookie2) = self.GetFirstChild(childReader)
250 self.SetItemText(childCard, 'no card inserted')
251 found = True
252 else:
253 (childReader, cookie) = self.GetNextChild(parentnode, cookie)
254 self.Expand(self.root)
255 finally:
256 self.mutex.release()
257 self.EnsureVisible(self.root)
258 self.Repaint()
259
261 """Called when a reader is removed.
262 Removes the reader from the smartcard readers tree."""
263 self.mutex.acquire()
264 try:
265 parentnode = self.root
266 for readertoremove in removedreaders:
267 (childReader, cookie) = self.GetFirstChild(parentnode)
268 while childReader.IsOk():
269 if self.GetItemText(childReader) == str(readertoremove):
270 self.Delete(childReader)
271 else:
272 (childReader, cookie) = self.GetNextChild(parentnode, cookie)
273 self.Expand(self.root)
274 finally:
275 self.mutex.release()
276 self.EnsureVisible(self.root)
277 self.Repaint()
278
279
281 """Panel containing the smart card and reader tree controls."""
282
284 """Inner CardObserver. Gets notified of card insertion
285 removal by the CardMonitor."""
286
288 self.cardtreectrl = cardtreectrl
289
290 - def update(self, observable, (addedcards, removedcards)):
291 """CardObserver callback that is notified when cards are added or removed."""
292 self.cardtreectrl.OnRemoveCards(removedcards)
293 self.cardtreectrl.OnAddCards(addedcards)
294
296 """Inner ReaderObserver. Gets notified of reader insertion/removal
297 by the ReaderMonitor."""
298
300 self.readertreectrl = readertreectrl
301
302 - def update(self, observable, (addedreaders, removedreaders)):
303 """ReaderObserver callback that is notified when readers are added or removed."""
304 self.readertreectrl.OnRemoveReaders(removedreaders)
305 self.readertreectrl.OnAddReaders(addedreaders)
306
307 - def __init__(self, parent, appstyle, clientpanel):
308 """Constructor. Create a smartcard and reader tree control on the
309 left-hand side of the application main frame.
310 parent: the tree panel parent
311 appstyle: a combination of the following styles (bitwise or |)
312 TR_SMARTCARD: display a smartcard tree panel
313 TR_READER: display a reader tree panel
314 default is TR_DEFAULT = TR_SMARTCARD
315 clientpanel: the client panel to notify of smartcard and reader events
316 """
317 wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS)
318
319 sizer = wx.BoxSizer(wx.VERTICAL)
320
321
322 if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD:
323 self.cardtreectrl = CardTreeCtrl(self, clientpanel=clientpanel)
324
325
326 self.cardtreecardobserver = self._CardObserver(self.cardtreectrl)
327
328
329 self.cardmonitor = CardMonitor()
330 self.cardmonitor.addObserver(self.cardtreecardobserver)
331
332 sizer.Add(self.cardtreectrl, flag=wx.EXPAND | wx.ALL, proportion=1)
333
334
335 if appstyle & smartcard.wx.SimpleSCardApp.TR_READER:
336 self.readertreectrl = ReaderTreeCtrl(self, clientpanel=clientpanel)
337
338
339 self.readertreereaderobserver = self._ReaderObserver(self.readertreectrl)
340
341
342 self.readermonitor = ReaderMonitor()
343 self.readermonitor.addObserver(self.readertreereaderobserver)
344
345
346 self.readertreecardobserver = self._CardObserver(self.readertreectrl)
347
348
349 self.cardmonitor = CardMonitor()
350 self.cardmonitor.addObserver(self.readertreecardobserver)
351
352 sizer.Add(self.readertreectrl, flag=wx.EXPAND | wx.ALL, proportion=1)
353
354 self.SetSizer(sizer)
355 self.SetAutoLayout(True)
356
358 """Called on panel destruction."""
359
360 if hasattr(self, cardmonitor):
361 self.cardmonitor.deleteObserver(self.cardtreecardobserver)
362 if hasattr(self, readermonitor):
363 self.readermonitor.deleteObserver(self.readertreereaderobserver)
364 self.cardmonitor.deleteObserver(self.readertreecardobserver)
365 event.Skip()
366