diff options
author | Henryk Plötz <henryk@ploetzli.ch> | 2010-02-24 02:57:44 +0100 |
---|---|---|
committer | Henryk Plötz <henryk@ploetzli.ch> | 2010-02-24 02:57:44 +0100 |
commit | 86c77780224304db61378b6e01f2f86c48e50fb3 (patch) | |
tree | d6dce1830f4c027b3d7f36a5dd6bf7dbf09d3d3d /cards | |
parent | 2f244a208318cd4c40f99dbf1f09101878e14dc0 (diff) |
Add VRS application and GUI (Public transport in Koeln and Bonn)
Diffstat (limited to 'cards')
-rw-r--r-- | cards/vrs_application.py | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/cards/vrs_application.py b/cards/vrs_application.py new file mode 100644 index 0000000..549bb84 --- /dev/null +++ b/cards/vrs_application.py @@ -0,0 +1,117 @@ +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()) + + |