Skip to content

Commit

Permalink
More progress on the TLV side
Browse files Browse the repository at this point in the history
  • Loading branch information
benallard committed Sep 21, 2011
1 parent 6c415cf commit 80d7a27
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 11 deletions.
6 changes: 6 additions & 0 deletions pythoncardx/framework/tlv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ class TLVException(CardRuntimeException):
BERTag = bertag.BERTag
PrimitiveBERTag = bertag.PrimitiveBERTag
ConstructedBERTag = bertag.ConstructedBERTag

from pythoncardx.framework.tlv import bertlv

BERTLV = bertlv.BERTLV
PrimitiveBERTLV = bertlv.PrimitiveBERTLV
ConstructedBERTLV = bertlv.ConstructedBERTLV
54 changes: 43 additions & 11 deletions pythoncardx/framework/tlv/bertag.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
"""
Credits have to be given there:
http:https://code.activestate.com/recipes/577244-simple-ber-decoding-in-python/
"""

from pythoncardx.framework.tlv import TLVException

class toBytes(object):
""" This make the toBytes function both static and not static
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 obj._toBytesBound
return getattr(obj, self.boundname)
else:
return BERTag._toBytesStatic
return getattr(objtype, self.staticname)

class BERTag(object):
BER_TAG_CLASS_MASK_APPLICATION = 0
Expand All @@ -26,20 +35,34 @@ class BERTag(object):
def __init__(self):
self._tagClass = 0
self._tagNumber = 0
self._size = 0

@staticmethod
def getInstance(bArray, bOff):
if (bArray[bOff] >> 5) & 0x1:
tag = ConstructedBERTag()
else:
tag = PrimitiveBERTag()
tag.init(bArray, bOff)
return tag

def init(self, bArray, bOff):
""" supposedly abstract """
self._tagClass = bArray[bOff] >> 6
self._PC = (bArray[bOff] >> 5) & 0x1
if (bArray[bOff] & 0x1f) == 0x1f:
self._tagNumber = 0
bOff += 1
while (bArray[bOff] & 0x80) == 0x80:
bLen = 1
while (bArray[bOff+bLen] & 0x80) == 0x80:
self._tagNumber = self._tagNumber << 7
self._tagNumber += bArray[bOff] & 0x7f
bOff += 1
self._tagNumber += bArray[bOff+bLen] & 0x7f
bLen += 1
self._tagNumber = self._tagNumber << 7
self._tagNumber += bArray[bOff] & 0x7f
self._tagNumber += bArray[bOff+bLen] & 0x7f
self._size = bLen
else:
self._tagNumber = bArray[bOff] & 0x1f
self._size = 1

def _toBytesBound(self, outBuf, bOffset):
outBuf[bOffset] = self._tagClass << 6
Expand All @@ -62,15 +85,24 @@ def _toBytesBound(self, outBuf, bOffset):
#clear the high bit on the last part
outBuf[bOffset+bLen-1] &= 0x7f
return bLen

@staticmethod
def _toBytesStatic(tagClass, isConstructed, tagNumber, outArray, bOff):
tag = {True: ConstructedBERTag,
False: PrimitiveBERTag}[isConstructed]()
tag.init(tagClass, tagNumber)
return tag.toBytes(outArray, bOff)
toBytes = NotAlwaysStatic('_toBytesBound', '_toBytesStatic')

def _sizeBound(self):
return self._size

@staticmethod
def _sizeStatic(berTagArray, bOff):
tag = BERTag()
tag.init(berTagArray, bOff)
return tag.size()
size = NotAlwaysStatic('_sizeBound', '_sizeStatic')

toBytes = toBytes()

class PrimitiveBERTag(BERTag):
def __init__(self):
Expand Down
89 changes: 89 additions & 0 deletions pythoncardx/framework/tlv/bertlv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
Credits have to be given there:
http:https://code.activestate.com/recipes/577244-simple-ber-decoding-in-python/
"""

from pythoncardx.framework.tlv.bertag import BERTag

from copy import copy

def _getLength(bArray):
""" returns a tuple: (length, value) about the L of the TLV """
if (bArray[0] & 0x80) == 0x80:
# extended length
length = bArray[0] & 0x7f
value = 0
for i in reversed(bArray[1:length+1]):
value = value << 8
value += i
return (length, value)
else:
return (1, bArray[0])

class BERTLV(object):
def __init__(self):
self._tag = None
self._length = 0
self._value = None
self._size = 0

@staticmethod
def getInstance(bArray, bOff, bLen):
tag = BERTag.getInstance(bArray, bOff)
if tag._PC:
tlv = ConstructedBERTLV(0)
else:
tlv = PrimitiveBERTLV(0)
bOff += tag.size()
l, length = _getLength(bArray[bOff:])
tlv.init(tag, bArray, bOff + l, bLen - tag.size() - l)
return tlv

def init(self, bArray, bOff, bLen):
""" supposedly abstract """
self = BERTLV.getInstance(bArray, bOff, bLen)
return self.size()

def getTag(self):
return self._tag

def getLength(self):
return self._length

def size(self):
return self._size

class ConstructedBERTLV(BERTLV):
def __init__(self, numValueBytes):
BERTLV.__init__(self)

def init(self, param1, *args):
if isinstance(param1, BERTag):
tag = param1
(vArray, vOff, vLen) = args
self._tag = copy(tag)
self._length = vLen
self._value = vArray[vOff:vOff+vLen]
return self.size()
else:
bArray = param1
(bOff, bLen) = args
return BERTLV.init(self, bArray, bOff, bLen)


class PrimitiveBERTLV(BERTLV):
def __init__(self, numValueBytes):
BERTLV.__init__(self)

def init(self, param1, *args):
if isinstance(param1, BERTag):
tag = param1
(vArray, vOff, vLen) = args
self._tag = copy(tag)
self._length = vLen
self._value = vArray[vOff:vOff+vLen]
return self.size()
else:
bArray = param1
(bOff, bLen) = args
return BERTLV.init(self, bArray, bOff, bLen)

0 comments on commit 80d7a27

Please sign in to comment.