changelog shortlog tags changeset files revisions annotate raw

parse_sessionsstore.py

changeset 20: b6b0e9bc226d
author: Greg Darke <greg+laptop@tsukasa.net.au>
date: Thu Apr 16 00:45:45 2009 +1000 (15 months ago)
permissions: -rwxr-xr-x
description: Ignore some stuff
1#!/usr/bin/env python
2# Copyright 2008 Greg Darke <greg+laptop@tsukasa.net.au>
3# Licensed for distribution under the GPL version 2, check COPYING for details
4# Program to parse Firefox 3's sessionstore.js file (the list of webpages to restore)
5
6import collections
7
8class ParseException(Exception):
9 pass
10
11class JSBooleanTrue(object):
12 @staticmethod
13 def isValidStart(ch):
14 return ch =='t'
15
16 @staticmethod
17 def parse(data):
18 assert data.popleft() == 't'
19 assert data.popleft() == 'r'
20 assert data.popleft() == 'u'
21 assert data.popleft() == 'e'
22 return True
23
24class JSBooleanFalse(object):
25 @staticmethod
26 def isValidStart(ch):
27 return ch =='f'
28
29 @staticmethod
30 def parse(data):
31 assert data.popleft() == 'f'
32 assert data.popleft() == 'a'
33 assert data.popleft() == 'l'
34 assert data.popleft() == 's'
35 assert data.popleft() == 'e'
36 return False
37
38class JSDigits(object):
39 @staticmethod
40 def isValidStart(ch):
41 return ch.isdigit()
42
43 @staticmethod
44 def parse(data):
45 assert data[0].isdigit()
46 ret = []
47
48 while data[0].isdigit():
49 ret.append(data.popleft())
50
51 return int(''.join(ret))
52
53class JSDoubleString(object):
54 @staticmethod
55 def isValidStart(ch):
56 return ch == '"'
57
58 @staticmethod
59 def parse(data):
60 assert data.popleft() == '"'
61 ret = []
62
63 while data[0] != '"':
64 ret.append(data.popleft())
65 assert data.popleft() == '"'
66
67 return ''.join(ret)
68
69class JSList(object):
70 @staticmethod
71 def isValidStart(ch):
72 return ch == '['
73
74 @staticmethod
75 def parse(data):
76 VALID_VALUES = (JSDict, )
77 assert data.popleft() == '['
78 ret = []
79
80 while True:
81 for valueType in VALID_VALUES:
82 if valueType.isValidStart(data[0]):
83 value = valueType.parse(data)
84 break
85 else:
86 raise ParseException, 'Unknown valueType start "%s"' % (data[0], )
87
88 ret.append(value)
89
90 if data[0] == ',':
91 data.popleft() # There are more entries
92 while data[0] == ' ':
93 data.popleft()
94 else:
95 break
96
97 assert data.popleft() == ']'
98 return ret
99
100class JSDictIdentifier(object):
101 _validChars = "_abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZ'"
102 @classmethod
103 def isValidStart(cls, ch):
104 return ch in cls._validChars
105
106 @classmethod
107 def parse(cls, data):
108 if data[0] not in cls._validChars:
109 raise ParseException, 'Expected character, but got "%s"' % (data[0], )
110 ret = []
111
112 if data[0] == "'": # Data is quoted
113 assert data.popleft() == "'"
114 while data[0] != "'":
115 ret.append(data.popleft())
116 assert data.popleft() == "'"
117 else:
118 while data[0] != ':':
119 ret.append(data.popleft())
120
121 return ''.join(ret)
122
123class JSDict(object):
124 @staticmethod
125 def isValidStart(ch):
126 return ch == '{'
127
128 @staticmethod
129 def parse(data):
130 VALID_VALUES = (
131 JSList,
132 JSDoubleString,
133 JSDigits,
134 JSDict,
135 JSBooleanTrue, JSBooleanFalse,
136 )
137 assert data.popleft() == '{'
138 ret = {}
139
140 if data[0] == '}':
141 # Empty dictionary
142 return ret
143
144 while True:
145 identifier = JSDictIdentifier.parse(data)
146 assert data.popleft() == ':'
147
148 for valueType in VALID_VALUES:
149 if valueType.isValidStart(data[0]):
150 value = valueType.parse(data)
151 break
152 else:
153 raise ParseException, 'Unknown valueType start %s' % (data[0], )
154
155 if identifier in ret:
156 raise ParseException, 'The identifier "%s" is already in the dict' % (identifier, )
157
158 ret[identifier] = value
159 if data[0] == ',':
160 data.popleft() # There are more entires
161 while data[0] == ' ':
162 data.popleft()
163 else:
164 break
165
166 assert data.popleft() == '}'
167 return ret
168
169
170def parseSessionStore(data):
171 data = collections.deque(data)
172 assert data.popleft() == '('
173 ret = JSDict.parse(data)
174 assert data.popleft() == ')'
175 assert len(data) == 0
176 return ret
177
178def main(filename):
179 import cgitb
180 import pprint
181 cgitb.enable(format='text')
182
183 pprint.pprint(parseSessionStore(file(filename).read()))
184
185if __name__ == "__main__":
186 import sys
187 try:
188 filename = sys.argv[1]
189 except IndexError:
190 print >>sys.stderr, 'Usage: %s path_to_sessionstore.js' % (sys.argv[0], )
191 sys.exit(1)
192 main(filename)
193
194__all__ = ('parseSessionStore', )