summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2018-03-23 13:40:44 +0300
committerYuval Adam <_@yuv.al>2018-04-02 11:15:41 +0300
commit1fe372cad7ed896a790ff689ec938b7df87c577f (patch)
treee49222ce944db30ff9245a2580443f313348198a
parentf490ac2834aaa98c485333b9107aa179f010d651 (diff)
Megazord WIP
-rw-r--r--viewstate/parse.py93
-rw-r--r--viewstate/viewstate.py4
2 files changed, 65 insertions, 32 deletions
diff --git a/viewstate/parse.py b/viewstate/parse.py
index 99110f1..66573a2 100644
--- a/viewstate/parse.py
+++ b/viewstate/parse.py
@@ -3,6 +3,25 @@ from datetime import datetime
from .exceptions import ViewStateException
+class ViewStateParser(object):
+ def get_subparsers(self):
+ return {c.marker: c for c in self.__class__.__subclasses__()}
+
+ def parse(self, b):
+ SUBPARSERS = self.get_subparsers()
+ marker, *remain = b
+ try:
+ return SUBPARSERS[marker]().parse(remain)
+ except KeyError:
+ raise ViewStateException('Unknown marker')
+
+
+class Const(object):
+ def parse(self):
+ return self.const, self.remain
+
+class NoneConst(ViewStateParser)
+
CONSTS = {
100: None,
101: '',
@@ -14,39 +33,53 @@ CONSTS = {
def parse_const(b):
return CONSTS.get(b, None)
-def parse_int(b):
- n = 0
- bits = 0
- i = 0
- while (bits < 32):
- tmp = b[i]
- i += 1
- n |= (tmp & 0x7f) << bits
- if not (tmp & 0x80):
- return n, b[i:]
- bits += 7
- return n, b[i:] # overflow
-def parse_string(b):
- n = b[0]
- n, remain = parse_int(b)
- s = remain[:n]
- return s.decode(), remain[n:]
+class Integer(ViewStateParser):
+ marker = 0x02
-def parse_enum(b):
- if b[0] in (0x29, 0x2a):
- enum, remain = parse_string(b[1:])
- elif b[0] == 0x2b:
- enum, remain = parse_int(b[1:])
- val, remain = parse_int(remain) # unsure about this part
- final = 'Enum: {}, val: {}'.format(enum, val)
- return final, remain
+ def parse(self, b):
+ n = 0
+ bits = 0
+ i = 0
+ while (bits < 32):
+ tmp = b[i]
+ i += 1
+ n |= (tmp & 0x7f) << bits
+ if not (tmp & 0x80):
+ return n, b[i:]
+ bits += 7
+ return n, b[i:] # overflow
+
+
+class String(ViewStateParser):
+ marker = (0x05, 0x1e)
+
+ def parse(self, b):
+ n = b[0]
+ n, remain = Integer().parse(b)
+ s = remain[:n]
+ return s.decode(), remain[n:]
+
+class Enum(ViewStateParser):
+ marker = 0x0b
+
+ def parse(self, b):
+ if b[0] in (0x29, 0x2a):
+ enum, remain = String().parse(b[1:])
+ elif b[0] == 0x2b:
+ enum, remain = Integer().parse(b[1:])
+ val, remain = Integer().parse(remain) # unsure about this part
+ final = 'Enum: {}, val: {}'.format(enum, val)
+ return final, remain
+
+class Color(ViewStateParser):
+ marker = 0x0a
-def parse_color(b):
- # No specification for color parsing, we're assuming it's just two bytes
- # One example we have is that `\n\x91\x01` is parsed as `Color: Color [Salmon]`
- # Originally reported in https://github.com/yuvadm/viewstate/issues/2
- return 'Color: unknown', b[2:]
+ def parse(self, b):
+ # No specification for color parsing, we're assuming it's just two bytes
+ # One example we have is that `\n\x91\x01` is parsed as `Color: Color [Salmon]`
+ # Originally reported in https://github.com/yuvadm/viewstate/issues/2
+ return 'Color: unknown', b[2:]
def parse_pair(b):
first, remain = parse(b)
diff --git a/viewstate/viewstate.py b/viewstate/viewstate.py
index 994f1b1..c08e011 100644
--- a/viewstate/viewstate.py
+++ b/viewstate/viewstate.py
@@ -2,7 +2,7 @@ from base64 import b64decode, b64encode
from binascii import Error as BinAsciiError
from .exceptions import ViewStateException
-from .parse import parse
+from .parse import ViewStateParser
class ViewState(object):
@@ -42,7 +42,7 @@ class ViewState(object):
if not self.is_valid():
raise ViewStateException('Cannot decode invalid viewstate, bad preamble')
- self.decoded, self.remainder = parse(self.body)
+ self.decoded, self.remainder = ViewStateParser().parse(self.body)
if self.remainder:
if len(self.remainder) == 20: