diff 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
line wrap: on
line diff
--- a/mercurial/templater.py	Mon Feb 27 09:15:59 2006 -0800
+++ b/mercurial/templater.py	Mon Feb 27 09:35:43 2006 -0800
@@ -1,6 +1,32 @@
 import re
 from demandload import demandload
-demandload(globals(), "cgi os time urllib util")
+from i18n import gettext as _
+demandload(globals(), "cStringIO cgi os time urllib util")
+
+esctable = {
+    '\\': '\\',
+    'r': '\r',
+    't': '\t',
+    'n': '\n',
+    'v': '\v',
+    }
+
+def parsestring(s):
+    fp = cStringIO.StringIO()
+    escape = False
+    first = s[0]
+    if len(s) < 2: raise SyntaxError(_('string too short'))
+    if first not in "'\"": raise SyntaxError(_('invalid quote'))
+    if s[-1] != first: raise SyntaxError(_('unmatched quotes'))
+    for c in s[1:-1]:
+        if escape:
+            fp.write(esctable.get(c, c))
+            escape = False
+        elif c == '\\': escape = True
+        elif c == first: raise SyntaxError(_('string ends early'))
+        else: fp.write(c)
+    if escape: raise SyntaxError(_('unterminated escape'))
+    return fp.getvalue()
 
 class templater(object):
     def __init__(self, mapfile, filters={}, defaults={}):
@@ -10,10 +36,16 @@
         self.filters = filters
         self.defaults = defaults
 
+        i = 0
         for l in file(mapfile):
-            m = re.match(r'(\S+)\s*=\s*(".*"|\'.*\')$', l)
+            i += 1
+            m = re.match(r'(\S+)\s*=\s*(["\'].*["\'])$', l)
             if m:
-                self.cache[m.group(1)] = eval(m.group(2))
+                try:
+                    s = m.group(2)
+                    self.cache[m.group(1)] = parsestring(s)
+                except SyntaxError, inst:
+                    raise SyntaxError('%s:%s: %s' % (mapfile, i, inst.args[0]))
             else:
                 m = re.match(r'(\S+)\s*=\s*(\S+)', l)
                 if m: