Skip to content

Commit

Permalink
Lot of stuff, Mainly in the pythoncardx/framework part
Browse files Browse the repository at this point in the history
  • Loading branch information
benallard committed Sep 22, 2011
1 parent 1e5edd4 commit 4ea152b
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 36 deletions.
2 changes: 1 addition & 1 deletion pythoncard/framework/apdu.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(self, bytesarr):
if len(bytesarr) > 4:
# there is a P3
P3len = 1
if (bytesarr[ISO7816.OFFSET_LC] == 0) and (len(bytesarr) > 5):
if (bytesarr[ISO7816.OFFSET_LC] == 0) and (len(bytesarr) > ISO7816.OFFSET_LC + 3):
# P3 is extended
P3len = 3
for i in xrange(ISO7816.OFFSET_LC, ISO7816.OFFSET_LC + P3len):
Expand Down
21 changes: 21 additions & 0 deletions pythoncard/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class NotAlwaysStatic(object):
""" This makes a function both static and not static
credits goes there (in decreasing order of importance).
http:https://users.rcn.com/python/download/Descriptor.htm
and there:
http:https://stackoverflow.com/questions/114214/class-method-differences-in-python-bound-unbound-and-static/114289#114289
and here:
http:https://code.activestate.com/recipes/52304-static-methods-aka-class-methods-in-python/
For examples of uses see pythoncardx/framework/tlv/bertag.py
"""
def __init__(self, boundname, staticname):
self.boundname = boundname
self.staticname = staticname

def __get__(self, obj, objtype=None):
if obj is not None:
return getattr(obj, self.boundname)
else:
return getattr(objtype, self.staticname)
Empty file.
61 changes: 61 additions & 0 deletions pythoncardx/framework/math.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from python.lang import NullPointerException, ArithmeticException

def from_bcd(data):
"""
>>> from_bcd(0x59)
59
"""
return int(hex(data)[2:])

def from_hex(data):
"""
>>> from_hex(0x59)
786
"""
return data

class BigNumber(object):
FORMAT_BCD = 1
FORMAT_HEX = 2

def __init__(self, maxBytes):
if maxBytes <= 0:
raise ArithmeticException()
self.maxBytes = maxBytes
self._value = None

def init(self, bArray, bOff, bLen, arrayFormat):
if bLen == 0:
raise ArithmeticException()
if arrayFormat not in (self.FORMAT_BCD, self.FORMAT_HEX):
raise ArithmeticException()
if bArray is None:
raise NullPointerException()
if arrayFormat == self.FORMAT_BCD:
self._value = 0
for i in xrange(bLen):
self._value *= 100
self._value += from_bcd(bArray[bOff+i])
elif arrayFormat == self.FORMAT_HEX:
self._value = 0
for i in xrange(bLen):
self._value = self._value << 8
self._value += bArray[bOff+i]

@staticmethod
def getMaxBytesSupported():
# We have to lie there for practical reasons
return 20

def multiply(self, bArray, bOff, bLen, arrayFormat):
other = BigNumber(70)
other.init(bArray, bOff, bLen, arrayFormat)
self._value *= other._value

def compareTo(self, operand):
if self._value == operand._value:
return 0
elif self._value > operand._value:
return 1
else:
return -1
44 changes: 21 additions & 23 deletions pythoncardx/framework/tlv/bertag.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,15 @@
http:https://code.activestate.com/recipes/577244-simple-ber-decoding-in-python/
"""

from pythoncardx.framework.tlv import TLVException
from pythoncard.utils import NotAlwaysStatic

class NotAlwaysStatic(object):
""" This makes a function both static and not static
credits goes there (in decreasing order of importance).
http:https://users.rcn.com/python/download/Descriptor.htm
and there:
http:https://stackoverflow.com/questions/114214/class-method-differences-in-python-bound-unbound-and-static/114289#114289
and here:
http:https://code.activestate.com/recipes/52304-static-methods-aka-class-methods-in-python/
"""
def __init__(self, boundname, staticname):
self.boundname = boundname
self.staticname = staticname

def __get__(self, obj, objtype=None):
if obj is not None:
return getattr(obj, self.boundname)
else:
return getattr(objtype, self.staticname)
def sanitycheck(array):
mask = (1 << 8) - 1
for i in range(len(array)):
if array[i] > ((1 << (8)-1) - 1):
array[i] = -(~(array[i]-1) & mask)

from pythoncardx.framework.tlv import TLVException

class BERTag(object):
BER_TAG_CLASS_MASK_APPLICATION = 0
Expand All @@ -49,7 +38,7 @@ def getInstance(bArray, bOff):
def init(self, bArray, bOff):
""" supposedly abstract """
self._tagClass = bArray[bOff] >> 6
self._PC = (bArray[bOff] >> 5) & 0x1
self._tagConstr = bool(bArray[bOff] & 0x20)
if (bArray[bOff] & 0x1f) == 0x1f:
self._tagNumber = 0
bLen = 1
Expand All @@ -66,9 +55,10 @@ def init(self, bArray, bOff):

def _toBytesBound(self, outBuf, bOffset):
outBuf[bOffset] = self._tagClass << 6
outBuf[bOffset] += self._PC << 5
outBuf[bOffset] += (self._tagConstr and 1 or 0) << 5
if self._tagNumber <= 30:
outBuf[bOffset] += self._tagNumber
sanitycheck(outBuf)
return 1
else:
tagNumber = self._tagNumber
Expand All @@ -84,6 +74,7 @@ def _toBytesBound(self, outBuf, bOffset):
bLen += 1
#clear the high bit on the last part
outBuf[bOffset+bLen-1] &= 0x7f
sanitycheck(outBuf)
return bLen
@staticmethod
def _toBytesStatic(tagClass, isConstructed, tagNumber, outArray, bOff):
Expand All @@ -103,11 +94,18 @@ def _sizeStatic(berTagArray, bOff):
return tag.size()
size = NotAlwaysStatic('_sizeBound', '_sizeStatic')

def __str__(self):
return '<BERTag: %d%s, %d>' % (self._tagClass, self._tagConstr and ', CONSTR' or '', self._tagNumber)

def __eq__(self, other):
return ((self._tagClass == other._tagClass) and
(self._tagConstr == other._tagConstr) and
(self._tagNumber == other._tagNumber))

class PrimitiveBERTag(BERTag):
def __init__(self):
BERTag.__init__(self)
self._PC = 0 # primitive
self._tagConstr = False # primitive

def init(self, param1, param2):
self._tagClass = None
Expand All @@ -126,7 +124,7 @@ def init(self, param1, param2):
class ConstructedBERTag(BERTag):
def __init__(self):
BERTag.__init__(self)
self._PC = 1 # constructed
self._tagConstr = True # constructed

def init(self, param1, param2):
self._tagClass = None
Expand Down
49 changes: 47 additions & 2 deletions pythoncardx/framework/tlv/bertlv.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
http:https://code.activestate.com/recipes/577244-simple-ber-decoding-in-python/
"""

from pythoncard.utils import NotAlwaysStatic

from pythoncard.framework import Util
from pythoncardx.framework.tlv.bertag import BERTag

from copy import copy
Expand Down Expand Up @@ -30,7 +33,7 @@ def __init__(self):
@staticmethod
def getInstance(bArray, bOff, bLen):
tag = BERTag.getInstance(bArray, bOff)
if tag._PC:
if tag._tagConstr:
tlv = ConstructedBERTLV(0)
else:
tlv = PrimitiveBERTLV(0)
Expand All @@ -47,12 +50,40 @@ def init(self, bArray, bOff, bLen):
def getTag(self):
return self._tag

def getLength(self):
def _getLengthBound(self):
return self._length
@staticmethod
def _getLengthStatic(berTLVArray, bOff):
tag = BERTag.getInstance(berTLVArray, bOff)
lenOff = bOff + tag.size()
(llen, length) = _getLength(berTLVArray[lenOff:])
return tag.size() + llen + length
getLength = NotAlwaysStatic('_getLengthBound', '_getLengthStatic')

def size(self):
return self._size

def _toBytesBound(self, outBuf, bOff):
bLen = self._tag.toBytes(outBuf, bOff)
if self._length > 127:
length = self._length
chunks = []
while length > 127:
chunks.append(length & 0xff)
length = length >> 8
chunk.reverse()
lLen = len(chunk)
outBuf[bOff+bLen] = 0x80 | lLen
bLen += 1
Util.arrayCopy(chunk, 0, outBuf, bOff+bLen, lLen)
bLen += lLen
else:
outBuf[bOff+bLen] = self._length
bLen += 1
Util.arrayCopy(self._value, 0, outBuf, bOff+bLen, self._length)
return bLen + self._length
toBytes = _toBytesBound

class ConstructedBERTLV(BERTLV):
def __init__(self, numValueBytes):
BERTLV.__init__(self)
Expand All @@ -70,6 +101,20 @@ def init(self, param1, *args):
(bOff, bLen) = args
return BERTLV.init(self, bArray, bOff, bLen)

def _appendBound(self, aTLV):
array = [0 for i in range(aTLV.size())]
aTLV.toBytes(array, 0)
self._value.extend(array)
self._length += aTLV.size()
return self.size()
@staticmethod
def _appendStatic(berTLVInArray, bTLVInOff, berTLVOutArray, bTLVOutOff):
# that's a funny one, actually, it is a CopyArrayAtomic (or not)
# but just with the length parameter missing ...
length = BERTLV.getLength(berTLVInArray, bTLVInOff)
Util.arrayCopy(berTLVInArray, bTLVInOff, berTLVOutArray, bTLVOutOff, length)
append = NotAlwaysStatic('_appendBound', '_appendStatic')


class PrimitiveBERTLV(BERTLV):
def __init__(self, numValueBytes):
Expand Down
Empty file.
56 changes: 56 additions & 0 deletions pythoncardx/framework/util/intx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import warnings

def signed(value, depth):
"""
return the signed value of the number on the specified depth
"""
mask = (1 << (depth*8)) - 1
if value > ((1 << (depth*8)-1) - 1):
return -(~(value-1) & mask)
else:
return value

def s4(i):
return signed(i, 4)

def sanatize(array):
for i in range(len(array)):
array[i] = signed(array[i], 1)

class JCint(object):

@staticmethod

def getInt(bArray, bOff):
i = bArray[bOff] << 24 + \
bArray[bOff + 1] << 16 + \
bArray[bOff + 2] << 8 + \
bArray[bOff + 3]
return s4(i)

@staticmethod
def makeInt(*args):
if len(args) == 4:
(b1, b2, b3, b4) = args
i = b1 << 24 + b2 << 16 + b3 << 8 + b4
return s4(i)
else:
(s1, s2) = args
i = s1 << 16 + s2
return s4(i)

@staticmethod
def makeTransientIntArray(length, event):
warnings.warn("Array is not transient")
return [0 for i in range(length)]

@staticmethod
def setInt(bArray, bOff, iValue1, iValue2):
# ints are transmited as two params ...
iVal = JCint.makeInt(iValue1, iValue2)
print bArray, bOff, iVal
bArray[bOff] = (iVal >> 24) & 0xff
bArray[bOff + 1] = iVal >> 16 & 0xff
bArray[bOff + 2] = iVal >> 8 & 0xff
bArray[bOff + 3] = iVal & 0xff
return bOff + 4
22 changes: 22 additions & 0 deletions test/testTLVTLV.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import unittest

from pythoncardx.framework.tlv import BERTag, PrimitiveBERTag, ConstructedBERTag, \
BERTLV, PrimitiveBERTLV, ConstructedBERTLV

class BERTLVTest(unittest.TestCase):

def testConstrInit(self):
tag = ConstructedBERTag()
tag.init(3, 1)
self.assertEquals(3, tag._tagClass)
self.assertEquals(1, tag._PC)
self.assertEquals(1, tag._tagNumber)
array = [0 for i in range(10)]
tag.toBytes(array, 0)
tlv = BERTLV.getInstance(array, 0, 2)
self.assertEquals(tag, tlv.getTag())

class StaticTest(unittest.TestCase):

def testtoBytes(self):
pass
21 changes: 11 additions & 10 deletions test/testTLVTag.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

from pythoncardx.framework.tlv import BERTag, PrimitiveBERTag, ConstructedBERTag

class BERTagTest(unittest.TestCase):

def testConstrInit(self):
tag = ConstructedBERTag()
tag.init(3, 1)
self.assertEquals(3, tag._tagClass)
self.assertEquals(True, tag._tagConstr)
self.assertEquals(1, tag._tagNumber)

class StaticTest(unittest.TestCase):

def testtoBytes(self):
Expand All @@ -14,13 +23,5 @@ def testtoBytes(self):
self.assertEquals(0xff, array[1])
self.assertEquals(0x7f, array[2])

self.assertEquals(2, BERTag,toBytes())

class BERTagTest(unittest.TestCase):

def testConstrInit(self):
tag = ConstructedBERTag()
tag.init(3, 1)
self.assertEquals(3, tag._tagClass)
self.assertEquals(1, tag._PC)
self.assertEquals(1, tag._tagNumber)
self.assertEquals(1, BERTag.toBytes(3, True, 1, array, 3))
self.assertEquals(0xe1, array[3])

0 comments on commit 4ea152b

Please sign in to comment.