cyberflex-shell/cards/vrs_application.py

118 lines
4.3 KiB
Python

from generic_application import Application
import struct, sha, binascii, os, datetime, sys, time
from iso_7816_4_card import ISO_7816_4_Card
import utils, TLV_utils, generic_card
class VRS_Application(Application):
DRIVER_NAME = ["VRS"]
AID_LIST = [
"d2760000254b414e4d303100",
"d2760001354b414e4d303100",
]
class VrsTicket(object):
def __init__(self):
self._birthdate = None
self._maindata = []
self._mainblob = None
self._rawdata = None
self._tlvdata = None
self._card = None
def from_card(cls, card, record_no = 1):
if not isinstance(card, VRS_Application):
if not isinstance(card, ISO_7816_4_Card):
raise ValueError, "card must be a VRS_Application object or a ISO_7816_4_Card object, not %s" % type(card)
else:
result = card.select_application(binascii.a2b_hex(VRS_Application.AID_LIST[0]))
if not card.check_sw(result.sw):
raise EnvironmentError, "card did not accept SELECT APPLICATION, sw was %02x %02x" % (result.sw1, result.sw2)
assert isinstance(card, VRS_Application)
c = cls()
c._card = card
result = card.open_file("\x0c\x05")
if card.check_sw(result.sw):
contents = card.read_record(record_no, 4)
if len(contents) > 0:
c._parse( contents )
else:
raise KeyError, "No ticket in record no. %i" % record_no
else:
raise EnvironmentError, "card did not accept SELECT FILE, sw was %02x %02x" % (result.sw1, result.sw2)
return c
def _parse(self, contents):
self._rawdata = contents
self._tlvdata = TLV_utils.unpack(contents)
tmp = TLV_utils.tlv_find_tag(self._tlvdata, 0xEA, num_results = 1)
if len(tmp) == 0:
raise ValueError, "Can't parse information file, tag 0xEA not found"
tmp = TLV_utils.tlv_find_tag(tmp, 0x85, num_results = 1)
if len(tmp) == 0:
raise ValueError, "Can't parse information file, tag 0x85 not found"
self._mainblob = tmp[0][2]
tmp = self._mainblob
some_id, tmp = tmp[:4], tmp[4:]
ascii_field_len = ord(tmp[0])
tmp = tmp[1:]
ascii_field, tmp = tmp[:ascii_field_len], tmp[ascii_field_len:]
self._maindata = ascii_field.split(" ")
if len(tmp) > 0:
if tmp[0] == "\x01":
tmp = tmp[1:]
birthdate_bin, tmp = tmp[:4], tmp[4:]
birthdate = binascii.b2a_hex(birthdate_bin)
self._birthdate = datetime.date( int(birthdate[0:4]), int(birthdate[4:6]), int(birthdate[6:8]) )
if len(tmp) > 0:
print "Warning: unparsed data trailing: %r" % tmp
from_card = classmethod(from_card)
def getter(index, encoding=None):
def g(self):
if self._maindata is None or len(self._maindata) <= index:
return None
if encoding is None:
return unicode( self._maindata[index] )
else:
return unicode( self._maindata[index], encoding = encoding )
return g
def _get_alter(self):
now = datetime.date.fromtimestamp( time.time() )
diff = now.year-self.geburtsdatum.year
thisyearsbirthday = datetime.date( now.year, self.geburtsdatum.month, self.geburtsdatum.day )
if now < thisyearsbirthday: diff = diff - 1
return diff
def __str__(self):
return "%s: %s %s" % (self.tickettyp, self.name_klar, self.abonr)
tickettyp = property(getter(0))
rnummer = property(getter(1))
gueltigkeit = property(getter(2))
feld4 = property(getter(3))
name_raw = property(getter(4))
vorname = property(lambda self: self.name_raw and "".join(self.name_raw.split(",_")[1:]).replace("_", " "))
nachname = property(lambda self: self.name_raw and "".join(self.name_raw.split(",_")[:1]).replace("_", " "))
name_klar = property(lambda self: self.vorname + " " + self.nachname)
schule = abonr = property(getter(5,'cp850'))
geburtsdatum = property(lambda self: self._birthdate)
alter = property(lambda self: self._birthdate and self._get_alter())