From cc29d5564825541f1d21068fca2c61bda3923c92 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Mon, 19 Feb 2018 23:29:37 +0100 Subject: Refactor file structure --- viewstate/__init__.py | 2 +- viewstate/core.py | 103 ------------------------------------------------- viewstate/parse.py | 62 +++++++++++++++++++++++++++++ viewstate/viewstate.py | 43 +++++++++++++++++++++ 4 files changed, 106 insertions(+), 104 deletions(-) delete mode 100644 viewstate/core.py create mode 100644 viewstate/parse.py create mode 100644 viewstate/viewstate.py diff --git a/viewstate/__init__.py b/viewstate/__init__.py index c166e0c..b6858bb 100644 --- a/viewstate/__init__.py +++ b/viewstate/__init__.py @@ -1,3 +1,3 @@ -from .core import ViewState +from .viewstate import ViewState from .exceptions import ViewStateException diff --git a/viewstate/core.py b/viewstate/core.py deleted file mode 100644 index b86afc7..0000000 --- a/viewstate/core.py +++ /dev/null @@ -1,103 +0,0 @@ -from base64 import b64decode, b64encode -from binascii import Error as BinAsciiError - -from .exceptions import ViewStateException - -CONSTS = { - 100: {}, - 101: '', - 102: 0, - 103: True, - 104: False -} - -def parse_const(b): - return CONSTS.get(b, None) - -def parse_string(b): - n = b[0] - s = b[1:n+1] - return s.decode(), b[n+1:] - -def parse_pair(b): - first, remain = parse(b) - second, remain = parse(remain) - return (first, second), remain - -def parse_array(b): - n = b[0] - l = [] - remain = b[1:] - for _ in range(n): - val, remain = parse(remain) - l.append(val) - return l, remain - -def parse_dict(b): - n = b[0] - d = {} - remain = b[1:] - for _ in range(n): - k, remain = parse(remain) - v, remain = parse(remain) - d[k] = v - return d, remain - -def parse(b): - - if not b: - return None - else: - assert type(b) == bytes().__class__ - - if 100 <= b[0] <= 104: - return parse_const(b[0]), b[1:] - elif b[0] == 0x5: - return parse_string(b[1:]) - elif b[0] == 0xf: - return parse_pair(b[1:]) - elif b[0] == 0x16: - return parse_array(b[1:]) - elif b[0] == 0x18: - return parse_dict(b[1:]) - else: - raise ViewStateException('Unable to parse remainder of bytes {}'.format(b)) - return b, bytes() - - -class ViewState(object): - - def __init__(self, base64=None, raw=None): - if base64: - self.base64 = base64 - try: - self.raw = b64decode(self.base64) - except BinAsciiError as bae: - raise ViewStateException('Cannot decode base64 input') - elif raw: - self.raw = raw - self.decoded = None - - @property - def preamble(self): - return self.raw[:2] - - @property - def body(self): - return self.raw[2:] - - def is_valid(self): - format_marker = b'\xff' - version_marker = b'\x01' - preamble = format_marker + version_marker - - try: - return self.preamble == preamble - except AttributeError: - return False - - def decode(self): - if not self.is_valid(): - raise ViewStateException('Cannot decode invalid viewstate, bad preamble') - self.decoded, self.remainder = parse(self.body) - return self.decoded diff --git a/viewstate/parse.py b/viewstate/parse.py new file mode 100644 index 0000000..0692c5c --- /dev/null +++ b/viewstate/parse.py @@ -0,0 +1,62 @@ +from .exceptions import ViewStateException + +CONSTS = { + 100: {}, + 101: '', + 102: 0, + 103: True, + 104: False +} + +def parse_const(b): + return CONSTS.get(b, None) + +def parse_string(b): + n = b[0] + s = b[1:n+1] + return s.decode(), b[n+1:] + +def parse_pair(b): + first, remain = parse(b) + second, remain = parse(remain) + return (first, second), remain + +def parse_array(b): + n = b[0] + l = [] + remain = b[1:] + for _ in range(n): + val, remain = parse(remain) + l.append(val) + return l, remain + +def parse_dict(b): + n = b[0] + d = {} + remain = b[1:] + for _ in range(n): + k, remain = parse(remain) + v, remain = parse(remain) + d[k] = v + return d, remain + +def parse(b): + if not b: + return None + else: + assert type(b) == bytes().__class__ + + if 100 <= b[0] <= 104: + return parse_const(b[0]), b[1:] + elif b[0] == 0x5: + return parse_string(b[1:]) + elif b[0] == 0xf: + return parse_pair(b[1:]) + elif b[0] == 0x16: + return parse_array(b[1:]) + elif b[0] == 0x18: + return parse_dict(b[1:]) + else: + raise ViewStateException('Unable to parse remainder of bytes {}'.format(b)) + return b, bytes() + diff --git a/viewstate/viewstate.py b/viewstate/viewstate.py new file mode 100644 index 0000000..a4e86cd --- /dev/null +++ b/viewstate/viewstate.py @@ -0,0 +1,43 @@ +from base64 import b64decode, b64encode +from binascii import Error as BinAsciiError + +from .exceptions import ViewStateException +from .parse import parse + + +class ViewState(object): + + def __init__(self, base64=None, raw=None): + if base64: + self.base64 = base64 + try: + self.raw = b64decode(self.base64) + except BinAsciiError as bae: + raise ViewStateException('Cannot decode base64 input') + elif raw: + self.raw = raw + self.decoded = None + + @property + def preamble(self): + return self.raw[:2] + + @property + def body(self): + return self.raw[2:] + + def is_valid(self): + format_marker = b'\xff' + version_marker = b'\x01' + preamble = format_marker + version_marker + + try: + return self.preamble == preamble + except AttributeError: + return False + + def decode(self): + if not self.is_valid(): + raise ViewStateException('Cannot decode invalid viewstate, bad preamble') + self.decoded, self.remainder = parse(self.body) + return self.decoded -- cgit v1.3.1