From c87482bdeecee473c19ffaba4cb28c6ceff43f99 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 1 Sep 2013 10:24:00 -0500 Subject: [PATCH] fixed issue 1590 --- VERSION | 2 +- gluon/contrib/markmin/markmin2html.py | 64 +++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index fa9cee3a..22718795 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.6.0-development+timestamp.2013.09.01.09.34.39 +Version 2.6.0-development+timestamp.2013.09.01.10.23.10 diff --git a/gluon/contrib/markmin/markmin2html.py b/gluon/contrib/markmin/markmin2html.py index e0854ccc..1fe4f9f7 100755 --- a/gluon/contrib/markmin/markmin2html.py +++ b/gluon/contrib/markmin/markmin2html.py @@ -4,6 +4,7 @@ # recreated by Vladyslav Kozlovskyy # license MIT/BSD/GPL import re +import ast from cgi import escape from string import maketrans @@ -532,7 +533,7 @@ LINK = '\x07' DISABLED_META = '\x08' LATEX = '' regex_URL=re.compile(r'@/(?P\w*)/(?P\w*)/(?P\w*(\.\w+)?)(/(?P[\w\.\-/]+))?') -regex_env=re.compile(r'@\{(?P[\w\-\.]+?)(\:(?P.*?))?\}') +regex_env2=re.compile(r'@\{(?P[\w\-\.]+?)(\:(?P.*?))?\}') regex_expand_meta = re.compile('('+META+'|'+DISABLED_META+'|````)') regex_dd=re.compile(r'\$\$(?P.*?)\$\$') regex_code = re.compile('('+META+'|'+DISABLED_META+r'|````)|(``(?P.+?)``(?::(?P[a-zA-Z][_a-zA-Z\-\d]*)(?:\[(?P

[^\]]*)\])?)?)',re.S) @@ -553,6 +554,53 @@ regex_markmin_escape = re.compile(r"(\\*)(['`:*~\\[\]{}@\$+\-.#\n])") regex_backslash = re.compile(r"\\(['`:*~\\[\]{}@\$+\-.#\n])") ttab_in = maketrans("'`:*~\\[]{}@$+-.#\n", '\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x05') ttab_out = maketrans('\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x05',"'`:*~\\[]{}@$+-.#\n") +regex_quote = re.compile('(?P\w+?)\s*\=\s*') + +def make_dict(b): + return '{%s}' % regex_quote.sub("'\g':",b) + +def safe_eval(node_or_string, env): + """ + Safely evaluate an expression node or a string containing a Python + expression. The string or node provided may only consist of the following + Python literal structures: strings, numbers, tuples, lists, dicts, booleans, + and None. + """ + _safe_names = {'None': None, 'True': True, 'False': False} + _safe_names.update(env) + if isinstance(node_or_string, basestring): + node_or_string = ast.parse(node_or_string, mode='eval') + if isinstance(node_or_string, ast.Expression): + node_or_string = node_or_string.body + def _convert(node): + if isinstance(node, ast.Str): + return node.s + elif isinstance(node, ast.Num): + return node.n + elif isinstance(node, ast.Tuple): + return tuple(map(_convert, node.elts)) + elif isinstance(node, ast.List): + return list(map(_convert, node.elts)) + elif isinstance(node, ast.Dict): + return dict((_convert(k), _convert(v)) for k, v + in zip(node.keys, node.values)) + elif isinstance(node, ast.Name): + if node.id in _safe_names: + return _safe_names[node.id] + elif isinstance(node, ast.BinOp) and \ + isinstance(node.op, (Add, Sub)) and \ + isinstance(node.right, Num) and \ + isinstance(node.right.n, complex) and \ + isinstance(node.left, Num) and \ + isinstance(node.left.n, (int, long, float)): + left = node.left.n + right = node.right.n + if isinstance(node.op, Add): + return left + right + else: + return left - right + raise ValueError('malformed string') + return _convert(node_or_string) def markmin_escape(text): """ insert \\ before markmin control characters: '`:*~[]{}@$ """ @@ -571,15 +619,22 @@ def replace_at_urls(text,url): return regex_URL.sub(u1,text) def replace_components(text,env): + # not perfect but acceptable def u2(match, env=env): f = env.get(match.group('a'), match.group(0)) if callable(f): + b = match.group('b') try: - f = f(match.group('b')) + b = safe_eval(make_dict(b),env) + except: + pass + try: + f = f(**b) if isinstance(b,dict) else f(b) except Exception, e: f = 'ERROR: %s' % e return str(f) - return regex_env.sub(u2, text) + text = regex_env2.sub(u2, text) + return text def autolinks_simple(url): """ @@ -844,6 +899,9 @@ def render(text, >>> render("**@{probe:1}**", environment=dict(probe=lambda t:"test %s" % t)) '

test 1

' + >>> render("**@{probe:t=a}**", environment=dict(probe=lambda t:"test %s" % t, a=1)) + '

test 1

' + >>> render('[[id1 [span **messag** in ''markmin''] ]] ... [[**link** to id [link\\\'s title] #mark1]]') '
'

span messag in markmin ... link to id