aboutsummaryrefslogtreecommitdiffstats
path: root/cards/vrs_application.py
blob: 1c171531dacee1d03b85e677e6714e97ba5bde00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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())