136 lines
3.8 KiB
Python
136 lines
3.8 KiB
Python
|
# we perform no validation
|
||
|
class PHPDeserializer:
|
||
|
def __init__(self, string):
|
||
|
self.string = string
|
||
|
if string is None:
|
||
|
self.length = 0
|
||
|
else:
|
||
|
self.length = len(string)
|
||
|
self.cursor = 0
|
||
|
|
||
|
def deserializeInteger(self):
|
||
|
start = self.cursor
|
||
|
|
||
|
done = False
|
||
|
while not done:
|
||
|
if self.cursor < self.length:
|
||
|
currentChar = self.string[self.cursor]
|
||
|
if currentChar.isdigit():
|
||
|
self.cursor = self.cursor + 1
|
||
|
else:
|
||
|
done = True
|
||
|
else:
|
||
|
done = True
|
||
|
|
||
|
length = self.cursor - start
|
||
|
if length > 0:
|
||
|
dInteger = int(self.string[start:self.cursor])
|
||
|
else:
|
||
|
dInteger = 0
|
||
|
|
||
|
return dInteger
|
||
|
|
||
|
def deserializeBoolean(self):
|
||
|
start = self.cursor
|
||
|
|
||
|
if self.cursor < self.length:
|
||
|
currentChar = self.string[self.cursor]
|
||
|
if currentChar == "0":
|
||
|
dBoolean = False
|
||
|
else:
|
||
|
dBoolean = True
|
||
|
self.cursor = self.cursor + 1
|
||
|
else:
|
||
|
dBoolean = None
|
||
|
|
||
|
return dBoolean
|
||
|
|
||
|
def deserializeString(self):
|
||
|
length = self.deserializeInteger()
|
||
|
start = self.cursor + 2
|
||
|
end = start+length
|
||
|
value = self.string[start:end]
|
||
|
self.cursor = end + 1
|
||
|
|
||
|
return value
|
||
|
|
||
|
def deserializeArray(self):
|
||
|
isHash = False
|
||
|
max = self.deserializeInteger()
|
||
|
dArray = [ None ] * max
|
||
|
|
||
|
self.cursor = self.cursor + 2
|
||
|
count = 0
|
||
|
while count < max:
|
||
|
elementIndex = self.deserialize()
|
||
|
self.cursor = self.cursor + 1
|
||
|
element = self.deserialize()
|
||
|
if isHash:
|
||
|
if type(elementIndex) == int:
|
||
|
elementIndex = "%d" % elementIndex
|
||
|
else:
|
||
|
if type(elementIndex) != int:
|
||
|
dArray = self._arrayToHash(dArray)
|
||
|
isHash = True
|
||
|
dArray[elementIndex] = element
|
||
|
self.cursor = self.cursor + 1
|
||
|
count = count + 1
|
||
|
|
||
|
if self.string[self.cursor] != "}":
|
||
|
raise Exception, \
|
||
|
("inconsistency detected in serialized string at character %d:\n%s"
|
||
|
% (self.cursor, self._exceptionSample()))
|
||
|
|
||
|
return dArray
|
||
|
|
||
|
def _exceptionSample(self):
|
||
|
if self.cursor > 30:
|
||
|
start = self.cursor - 30
|
||
|
prefix = "..."
|
||
|
else:
|
||
|
start = 0
|
||
|
prefix = ""
|
||
|
carret = self.cursor + len(prefix) - start
|
||
|
length = len(self.string)
|
||
|
if self.cursor + 30 < length:
|
||
|
end = self.cursor + 30
|
||
|
suffix = "..."
|
||
|
else:
|
||
|
end = length
|
||
|
suffix = ""
|
||
|
|
||
|
sample = self.string[start:end]
|
||
|
while sample[0] == " ":
|
||
|
carret = carret - 1
|
||
|
sample = sample[1:]
|
||
|
|
||
|
return "%s%s%s\n%s^" % (prefix, sample, suffix, carret * " ")
|
||
|
|
||
|
def _arrayToHash(self, array):
|
||
|
dHash = {}
|
||
|
count = 0
|
||
|
for element in array:
|
||
|
dHash["%d" % count] = element
|
||
|
count = count + 1
|
||
|
|
||
|
return dHash
|
||
|
|
||
|
def deserialize(self):
|
||
|
dObject = None
|
||
|
|
||
|
if self.string is not None and self.length > 0:
|
||
|
currentChar = self.string[self.cursor]
|
||
|
self.cursor = self.cursor + 2
|
||
|
if currentChar == 'a':
|
||
|
dObject = self.deserializeArray()
|
||
|
elif currentChar == 's':
|
||
|
dObject = self.deserializeString()
|
||
|
elif currentChar == 'i':
|
||
|
dObject = self.deserializeInteger()
|
||
|
elif currentChar == 'b':
|
||
|
dObject = self.deserializeBoolean()
|
||
|
elif currentChar == 'N':
|
||
|
dObject = None
|
||
|
|
||
|
return dObject
|