This works by polling the card every second via opensc-tool --atr The radio buttons have been removed to have enough space for the new label git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@148 96b47cad-a561-4643-ad3b-153ac7d7599c
235 lines
7.6 KiB
Python
235 lines
7.6 KiB
Python
#!/usr/bin/env python
|
|
|
|
import sys, os
|
|
import subprocess
|
|
from threading import Thread, Event
|
|
try:
|
|
import pygtk
|
|
pygtk.require("2.0")
|
|
except:
|
|
pass
|
|
try:
|
|
import gtk, gobject, glib
|
|
import pango
|
|
except:
|
|
sys.exit(1)
|
|
|
|
#glade_dir is set by the build system
|
|
from pinpad_globals import *
|
|
|
|
class PinpadGTK:
|
|
"""This a simple GTK based GUI to enter a PIN"""
|
|
|
|
def __init__(self):
|
|
btn_names = ["btnOne", "btnTwo", "btnThree", "btnFour", "btnFive",
|
|
"btnSix", "btnSeven", "btnEight", "btnNine", "btnDel",
|
|
"btnZero", "btnOk"]
|
|
|
|
self.pin = ""
|
|
|
|
#Set the Glade file
|
|
self.gladefile = glade_dir + "/pinpad.glade"
|
|
self.builder = gtk.Builder()
|
|
try:
|
|
self.builder.add_from_file(self.gladefile)
|
|
except glib.GError, e:
|
|
popup = gtk.MessageDialog(None, gtk.DIALOG_MODAL,
|
|
gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
|
|
e.message)
|
|
popup.run()
|
|
popup.destroy()
|
|
raise e
|
|
|
|
#Get the Main Window, and connect the "destroy" event
|
|
#Create our dictionay and connect it
|
|
dic = { "on_btnOne_clicked" : self.digit_clicked,
|
|
"on_btnTwo_clicked" : self.digit_clicked,
|
|
"on_btnThree_clicked" : self.digit_clicked,
|
|
"on_btnFour_clicked" : self.digit_clicked,
|
|
"on_btnFive_clicked" : self.digit_clicked,
|
|
"on_btnSix_clicked" : self.digit_clicked,
|
|
"on_btnSeven_clicked" : self.digit_clicked,
|
|
"on_btnEight_clicked" : self.digit_clicked,
|
|
"on_btnNine_clicked" : self.digit_clicked,
|
|
"on_btnZero_clicked" : self.digit_clicked,
|
|
"on_btnOk_clicked" : self.btnOk_clicked,
|
|
"on_btnDel_clicked" : self.btnDel_clicked,
|
|
"on_MainWindow_destroy_event" : gtk.main_quit,
|
|
"on_MainWindow_destroy" : gtk.main_quit }
|
|
|
|
self.builder.connect_signals(dic)
|
|
|
|
#Change the font for the text field
|
|
txtOutput = self.builder.get_object("txtOutput")
|
|
font = pango.FontDescription("Monospace")
|
|
txtOutput.modify_font(pango.FontDescription("sans 24"))
|
|
|
|
#Look for card and set the label accordingly
|
|
lbl_cardStatus = self.builder.get_object("lbl_cardStatus")
|
|
self.cardChecker = cardChecker(lbl_cardStatus, ePA_ATR)
|
|
gobject.idle_add(self.cardChecker.start)
|
|
|
|
#Change the font for the buttons
|
|
#For this you have to retrieve the label of each button and change
|
|
#its font
|
|
for name in btn_names:
|
|
btn = self.builder.get_object(name)
|
|
if btn.get_use_stock():
|
|
lbl = btn.child.get_children()[1]
|
|
elif isinstance(btn.child, gtk.Label):
|
|
lbl = btn.child
|
|
else:
|
|
raise ValueError("Button does not have a label")
|
|
|
|
if (name == "btnOk" or name == "btnDel"):
|
|
lbl.modify_font(pango.FontDescription("sans 16"))
|
|
else:
|
|
lbl.modify_font(pango.FontDescription("sans 20"))
|
|
|
|
#Prepare the Progress Bar window for later use
|
|
self.progressWindow = Popup(self.builder)
|
|
|
|
#Display Main Window
|
|
self.window = self.builder.get_object("MainWindow")
|
|
self.window.show()
|
|
|
|
if (self.window):
|
|
self.window.connect("destroy", self.shutdown)
|
|
|
|
def shutdown(self, widget):
|
|
self.cardChecker.stop()
|
|
self.cardChecker.join()
|
|
gtk.main_quit()
|
|
|
|
def digit_clicked(self, widget):
|
|
c = widget.get_label()
|
|
lbl = self.builder.get_object("txtOutput")
|
|
txt = lbl.get_text()
|
|
if len(txt) < 6:
|
|
lbl.set_text(txt + '*')
|
|
self.pin += widget.get_label()
|
|
|
|
def btnOk_clicked(self, widget):
|
|
|
|
#Check which radio button is checked, so we know what kind of secret to
|
|
#use for PACE
|
|
env_arg = os.environ
|
|
env_arg["PIN"] = self.pin #We alway use the eID-PIN
|
|
|
|
#We have to provide the type of secret to use via a command line parameter
|
|
param = "--pin"
|
|
|
|
try:
|
|
p = subprocess.Popen(["pace-tool", param, "-v"],
|
|
stdout=subprocess.PIPE, env=env_arg, close_fds=True)
|
|
except OSError, e:
|
|
popup = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL |
|
|
gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR,
|
|
gtk.BUTTONS_OK, "pace-tool wurde nicht gefunden.")
|
|
popup.run()
|
|
popup.destroy()
|
|
return
|
|
|
|
line = p.stdout.readline()
|
|
self.progressWindow.show()
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
while line:
|
|
self.progressWindow.inc_fraction()
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
line = p.stdout.readline()
|
|
|
|
ret = p.poll()
|
|
self.progressWindow.hide()
|
|
|
|
if (ret == 0):
|
|
popup = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL |
|
|
gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO,
|
|
gtk.BUTTONS_OK, "PIN wurde korrekt eingegeben")
|
|
res = popup.run()
|
|
gtk.main_quit()
|
|
else:
|
|
lbl = self.builder.get_object("txtOutput")
|
|
popup = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL |
|
|
gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING,
|
|
gtk.BUTTONS_OK,
|
|
"PIN wurde falsch eingegeben. Bitte erneut versuchen")
|
|
res = popup.run()
|
|
popup.destroy()
|
|
lbl.set_text("")
|
|
self.pin = ""
|
|
|
|
def btnDel_clicked(self, widget):
|
|
self.pin = self.pin[:-1]
|
|
lbl = self.builder.get_object("txtOutput")
|
|
txt = lbl.get_text()
|
|
if len(txt) < 6:
|
|
lbl.set_text(len(self.pin) * '*')
|
|
|
|
|
|
class Popup(object):
|
|
|
|
def __init__(self, builder):
|
|
self.builder = builder
|
|
self.window = self.builder.get_object("progWindow")
|
|
self.progbar = self.builder.get_object("progBar")
|
|
|
|
def show(self):
|
|
self.window.show()
|
|
|
|
def hide(self):
|
|
self.window.hide()
|
|
|
|
def inc_fraction(self):
|
|
fraction = self.progbar.get_fraction()
|
|
if fraction < 1.0:
|
|
fraction += 0.1
|
|
else:
|
|
fraction = 0.0
|
|
self.progbar.set_fraction(fraction)
|
|
|
|
class cardChecker(Thread):
|
|
""" This class searches for a card with a given ATR and displays
|
|
wether or not it was found on the label of a widget """
|
|
|
|
def __init__(self, widget, atr, intervall=1):
|
|
Thread.__init__(self)
|
|
self._finished = Event()
|
|
self.widget = widget
|
|
self.targetATR = atr
|
|
self.intervall = intervall
|
|
|
|
def __cardCheck(self):
|
|
"""
|
|
Actually this method should make use of pyscard, but I couldn't make
|
|
it run on the OpenMoko yet. Therefor we call opensc-tool instead, which
|
|
leads to higher delays """
|
|
|
|
try:
|
|
p = subprocess.Popen(["opensc-tool", "--atr"], stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE, close_fds=True)
|
|
|
|
line = p.stdout.readline().rstrip()
|
|
if line == self.targetATR:
|
|
gobject.idle_add(self.widget.set_label, STR_CARD_FOUND)
|
|
else:
|
|
gobject.idle_add(self.widget.set_label, STR_NO_CARD)
|
|
|
|
except OSError, e:
|
|
pass #FIXME
|
|
|
|
def run(self):
|
|
while (True):
|
|
if self._finished.isSet(): return
|
|
self.__cardCheck()
|
|
self._finished.wait(self.intervall)
|
|
|
|
def stop(self):
|
|
self._finished.set()
|
|
|
|
if __name__ == "__main__":
|
|
gobject.threads_init()
|
|
pinpad = PinpadGTK()
|
|
gtk.main()
|