comparison mercurial/templater.py @ 1901:c64bef3d7043

use safer string parser for template engine.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Mon, 27 Feb 2006 09:35:43 -0800
parents f2815605186e
children 1cc5f25653a3
comparison
equal deleted inserted replaced
1900:f2815605186e 1901:c64bef3d7043
1 import re 1 import re
2 from demandload import demandload 2 from demandload import demandload
3 demandload(globals(), "cgi os time urllib util") 3 from i18n import gettext as _
4 demandload(globals(), "cStringIO cgi os time urllib util")
5
6 esctable = {
7 '\\': '\\',
8 'r': '\r',
9 't': '\t',
10 'n': '\n',
11 'v': '\v',
12 }
13
14 def parsestring(s):
15 fp = cStringIO.StringIO()
16 escape = False
17 first = s[0]
18 if len(s) < 2: raise SyntaxError(_('string too short'))
19 if first not in "'\"": raise SyntaxError(_('invalid quote'))
20 if s[-1] != first: raise SyntaxError(_('unmatched quotes'))
21 for c in s[1:-1]:
22 if escape:
23 fp.write(esctable.get(c, c))
24 escape = False
25 elif c == '\\': escape = True
26 elif c == first: raise SyntaxError(_('string ends early'))
27 else: fp.write(c)
28 if escape: raise SyntaxError(_('unterminated escape'))
29 return fp.getvalue()
4 30
5 class templater(object): 31 class templater(object):
6 def __init__(self, mapfile, filters={}, defaults={}): 32 def __init__(self, mapfile, filters={}, defaults={}):
7 self.cache = {} 33 self.cache = {}
8 self.map = {} 34 self.map = {}
9 self.base = os.path.dirname(mapfile) 35 self.base = os.path.dirname(mapfile)
10 self.filters = filters 36 self.filters = filters
11 self.defaults = defaults 37 self.defaults = defaults
12 38
39 i = 0
13 for l in file(mapfile): 40 for l in file(mapfile):
14 m = re.match(r'(\S+)\s*=\s*(".*"|\'.*\')$', l) 41 i += 1
42 m = re.match(r'(\S+)\s*=\s*(["\'].*["\'])$', l)
15 if m: 43 if m:
16 self.cache[m.group(1)] = eval(m.group(2)) 44 try:
45 s = m.group(2)
46 self.cache[m.group(1)] = parsestring(s)
47 except SyntaxError, inst:
48 raise SyntaxError('%s:%s: %s' % (mapfile, i, inst.args[0]))
17 else: 49 else:
18 m = re.match(r'(\S+)\s*=\s*(\S+)', l) 50 m = re.match(r'(\S+)\s*=\s*(\S+)', l)
19 if m: 51 if m:
20 self.map[m.group(1)] = os.path.join(self.base, m.group(2)) 52 self.map[m.group(1)] = os.path.join(self.base, m.group(2))
21 else: 53 else: