118 lines
4.3 KiB
Python
118 lines
4.3 KiB
Python
from generic_application import Application
|
|
import struct, 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())
|
|
|
|
|