aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenryk Plötz <henryk@ploetzli.ch>2010-10-15 17:58:54 +0200
committerHenryk Plötz <henryk@ploetzli.ch>2010-10-15 17:58:54 +0200
commit20b8d8167ee864c88287412da224d93c17381a08 (patch)
tree6da5a168fcc5244d168e086be4070c561d89ea21
parent2cc37817d7fbc0f2f10cf09090f9ac06f6bbbc7e (diff)
Add generic response chaining capability
-rw-r--r--cards/generic_card.py10
-rw-r--r--tests/utilstest.py9
-rw-r--r--utils.py7
3 files changed, 24 insertions, 2 deletions
diff --git a/cards/generic_card.py b/cards/generic_card.py
index 64d4bcb..37e3a0a 100644
--- a/cards/generic_card.py
+++ b/cards/generic_card.py
@@ -147,10 +147,16 @@ class Card:
def _send_with_retry(self, apdu):
result = self._real_send(apdu)
- if self.check_sw(result.sw, self.PURPOSE_GET_RESPONSE):
+ while self.check_sw(result.sw, self.PURPOSE_GET_RESPONSE):
## Need to call GetResponse
gr_apdu = self.COMMAND_GET_RESPONSE
- result = self._real_send(gr_apdu)
+ tmp = self._real_send(gr_apdu)
+
+ if not callable(result.append):
+ result = tmp
+ break
+ else:
+ result = result.append(tmp)
return result
diff --git a/tests/utilstest.py b/tests/utilstest.py
index 65b74b6..42d34f4 100644
--- a/tests/utilstest.py
+++ b/tests/utilstest.py
@@ -36,3 +36,12 @@ class APDUCase1Tests(unittest.TestCase):
self.assertEqual(self.a4.render(), a4_2.render())
+class APDUChainTests(unittest.TestCase):
+
+ def testChain(self):
+ a = utils.R_APDU("abcd\x61\x04")
+ b = utils.R_APDU("efgh\x90\x00")
+
+ c = a.append(b)
+
+ self.assertEqual("abcdefgh\x90\x00", c.render())
diff --git a/utils.py b/utils.py
index e68007f..00533dc 100644
--- a/utils.py
+++ b/utils.py
@@ -224,6 +224,10 @@ class Transmission_Frame(object):
parts.append("data=%r" % self.data)
return "%s(%s)" % (self.__class__.__name__, ", ".join(parts))
+
+ # Stub for implementation in subclasses
+ # Semantics should be: c=a.append(b) <=> c.data == a.data + b.data and c.status == b.status
+ append = None
class Command_Frame(Transmission_Frame):
pass
@@ -472,6 +476,9 @@ class R_APDU(Response_Frame,APDU):
def render(self):
"Return this APDU as a binary string"
return self.data + self.sw
+
+ def append(self, other):
+ return R_APDU(self.data + other.data + other.sw)
APDU.COMMAND_CLASS = C_APDU
APDU.RESPONSE_CLASS = R_APDU