def test_evoque_local_nested_from_string(self): td = Domain(DEFAULT_DIR, restricted=RESTRICTED, errors=ERRORS) src = open(join(DEFAULT_DIR, "evoque_local_nested.html")).read() name = "fromstr" nested_name = name + "#label" data = dict(title="A Title", param="A Param") r = "<h1>A Title</h1><p>some A Param text</p>" # Load a from_string template that locally-nests another template td.set_template(name, src=src, from_string=True) t1 = td.get_template(name) # Verify nested template is not yet loaded self.assertEqual(False, t1.collection.has_template(nested_name)) # Evoque, and verify response (multiple times, ensure data stays ok) self.assertEqual(r, t1.evoque(data)) # data as locals self.assertEqual(r, t1.evoque(**data)) # data as kw self.assertEqual(r, t1.evoque(data)) # data as locals self.assertEqual(r, t1.evoque(**data)) # data as kw # Verify nested template is now loaded self.assertEqual(True, t1.collection.has_template(nested_name)) # Verify that tring to set nested template will fail self.assertRaises((ValueError,), td.set_template, nested_name, src=src, from_string=True) t2 = td.get_template(nested_name) self.assertEqual(t2.ts, "<h1>%(title)s</h1><p>some %(param)s text</p>") self.assertEqual(r, t2.evoque(**data))
def test_from_string_td(self): td = Domain(DEFAULT_DIR, restricted=RESTRICTED, errors=ERRORS) src = "<h1>${title}</h1><p>some ${param} text</p>" data = dict(title="A Title", param="A Param") r = "<h1>A Title</h1><p>some A Param text</p>" td.set_template("fromstr", src=src, from_string=True) t = td.get_template("fromstr") self.assertEqual(r, t.evoque(**data))
def test_expr_formatting(self): td = Domain(DEFAULT_DIR, restricted=RESTRICTED, errors=ERRORS) data = dict(amount=1.0/3) src = "${amount!.4f}" td.set_template("t1", src=src, from_string=True) self.assertEqual("0.3333", td.get_template("t1").evoque(**data)) src = "${ amount ! .3f }" td.set_template("t2", src=src, from_string=True) self.assertEqual("0.333", td.get_template("t2").evoque(**data))
def evoque_template(template, vars, *more_vars, **kw_vars): domain=Domain(os.getcwd(), errors=4) # we actually don't care about the first arg domain.set_template('template', src=template) tmp=domain.get_template('template') cvars=vars.copy() for v in more_vars: try: cvars.update(v) except Exception as e: print "caught %s" % e for k,v in kw_vars.items(): cvars[k]=kw_vars[k] return tmp.evoque(cvars)
def evoque_mq(verbose=False): from evoque.domain import Domain DEFAULT_DIR = os.path.join(BASEDIR, 'evoque') td = Domain(DEFAULT_DIR) import cgi td.set_on_globals("quote", cgi.escape) template_string = """<table> $for{ row in table } <tr>$for{ col in row }<td>${quote(col)}</td>$rof</tr> $rof </table> $test{ table=[("a","b","c","d","<escape-me/>","f","g","h","i","j")] } """ td.set_template("bigtable", src=template_string, quoting="str", from_string=True) t = td.get_template("bigtable") def render(): return t.evoque({'table':TABLE_DATA}) if verbose: pr(t.ts) pr('--------------------------------------------------------') pr(render()[:300] + "...") return render
def evoque(verbose=False, quoting="xml", restricted=False, template_string=None): from evoque.domain import Domain DEFAULT_DIR = os.path.join(BASEDIR, 'evoque') td = Domain(DEFAULT_DIR, restricted=restricted, errors=4, quoting=quoting) if template_string is None: # $begin{evoque_template} template_string = """<table> $for{ row in table } <tr>$for{ col in row }<td>${col}</td>$rof</tr> $rof </table> $test{ table=[("a","b","c","d","<escape-me/>","f","g","h","i","j")] } """ # $end{evoque_template} td.set_template("bigtable", src=template_string, quoting=quoting) t = td.get_template("bigtable") t.test() def render(): return t.evoque({'table':TABLE_DATA}) if verbose: #open("/tmp/evoque_bench_bigtable_evoque.html", "w").write(render()) pr(t.ts) pr('--------------------------------------------------------') pr(render()[:300] + "...") return render
def test_svn_keywords(self): td = Domain(DEFAULT_DIR, restricted=RESTRICTED, errors=ERRORS) src = "%s %s" %(__url__, __revision__) td.set_template("svnkw", src=src, from_string=True) self.assertEqual(src, td.get_template("svnkw").evoque())
class RestrictedTest(unittest.TestCase): def __init__(self, *args, **kw): super(RestrictedTest, self).__init__(*args, **kw) self.domain = Domain(DEFAULT_DIR, restricted=True, errors=4) self.domain.log.setLevel(logging_level) self.count = 0 def get_template_from_expr(self, expr): self.count += 1 name = "tfs%s" % (self.count) src = "${%s}" % (expr) self.domain.set_template(name, src=src, from_string=True) return self.domain.get_template(name) def test_restricted(self): for bi in DISALLOW_BUILTINS: t = self.get_template_from_expr(bi) self.assertRaises((LookupError, NameError), t.evoque) def test_inquisitive(self): # on a function object, evoque() for expr in [ "evoque."+attr for attr in RESTRICTED_ATTRS ]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError,), t.evoque) # on a function object, evoque(), with space between "." and attr name for expr in [ "evoque. "+attr for attr in RESTRICTED_ATTRS ]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError,), t.evoque) def test_unsafe_str_expressions(self): # NameError, unsafe builtins for expr in [ "open('test.txt', 'w')", "getattr(int, '_' + '_abs_' + '_')", ]: t = self.get_template_from_expr(expr) self.assertRaises((NameError,), t.evoque) # LookupError for expr in [ # lowlevel tricks to access 'object' "().__class__.mro()[1].__subclasses__()", "type(1)._" + "_abs_" + "_", "()."+"_"*2+"class"+"_"*2+".mro()[1]."+"_"*2+"subclasses"+"_"*2+"()", ]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError,), t.evoque) # SyntaxError for expr in [ # attempt to access global enviroment where fun was defined "def x(): pass; print x.func_globals", # statement, SyntaxError # attempt to execute code which never terminates "while 1: pass", # statement, SyntaxError ]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError, SyntaxError,), t.evoque) # RuntimeError # http://groups.google.com/group/comp.lang.python/browse_thread/thread/689ea92183b91f06 for expr in [ # Mark Wooding "inspect.func_globals['_'*2+'builtins'+'_'*2].open('"+__file__+"').read()", "inspect.func_globals['_'*2+'builtins'+'_'*2]", # Daniel Diniz "(x for x in ()).throw('bork')," "(x for x in range(1)).gi_frame.f_globals.clear()", #"open('where_is_ma_beer.txt', 'w').write('Thanks for the fun')", ]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError, RuntimeError, AttributeError), t.evoque) def test_unsafe_file_expressions(self): # Create a new domain for this, to be able to run with a different # errors setting td = Domain(DEFAULT_DIR, restricted=True, errors=2, quoting="str") name = 'restricted_exprs.txt' t = td.get_template(name) result = """ [EvalError(().__class__.mro()[1].__subclasses__())] ().__class__.mro()[1].__subclasses__() ().__class__.mro()[1].__subclasses__() [EvalError(eval(expr))] [EvalError(evoque("test", src="${"+expr+"}", from_string=True))] """ self.assertEqual(result, t.evoque())
def home(request): ctx = {} domain = Domain(os.path.abspath("."), restricted=True) #marginal template security, people can still DOS us. Don't tell anyone. if request.POST: form=AceForm(request.POST) if form.is_valid(): success=True try: testargs={'args': 'test'} domain.set_template("test", src=form.cleaned_data['target'], data=testargs, from_string=True, quoting='str') compiledTmpl=domain.get_template('test') except: ctx['flash']=Flash(message="Sorry, we couldn't add that ARC. The Target provided couldn't be compiled. See http://evoque.gizmojo.org/syntax/ for details.", level="error") success=False if success: name = form.cleaned_data['name'] shortcut = form.cleaned_data['shortcut'] target = form.cleaned_data['target'] command_type = form.cleaned_data['command_type'] new_ace= Ace(name=name, shortcut=shortcut, target=target, command_type=command_type) new_ace.save() ctx['arc_added']=new_ace else: ctx['flash']=Flash(message="Sorry, we couldn't add that ARC. Please try again", level='alert-block') ctx['form_add']=form elif request.GET.get('q') is not None and len(request.GET.get('q').split()) > 0: q = request.GET.get('q').lower().split() reqstr = '%s' % ' '.join(map(str,q[1:])) ace = Ace.objects.filter(shortcut=q[0]) if ace: arglist = map(lambda x: 'arg'+x.__str__(), xrange(0, len(q))) #creating arglist=['arg0','arg1','argN'] args = dict(zip(arglist, q)) #creating args={'arg0': 'some arguement', etc} if len(args) is 1: #so evoque doesn't die on empty arguments args["arg1"] = None args['jargs']="var %s = ['%s']" % ('args', "','".join(q[1:])) #args in javascript args['pargs']=q #pythonic args args['args']=reqstr #args in a single string args['arc']=ace.get().name target = ace.get().target domain.set_template("target", src=target, data=args, from_string=True, quoting='str') compiledTargetTmpl=domain.get_template("target") result=compiledTargetTmpl.evoque() if ace.get().command_type.name == u'redirect': return redirect(result) template = ace.get().command_type.template args['ace'] = result domain.set_template("template", src=template, data=args, quoting='str', raw=False, from_string=True) compiledTmpl=domain.get_template('template') ctx['template'] = compiledTmpl.evoque() else: gotoGoogle='/?q=g+%s' % ''.join(map(str,q)) return redirect(gotoGoogle) # not found, it's google's problem now (feature parity with pre-ACE) elif request.GET.get('q') is not None: ctx['flash']=Flash(message="Begin typing to search for ARCs. Try creating your own ARCs!", level="info") initial = {'q':"Search ARCS"} form = SearchForm() ctx['form'] = form if 'form_add' not in ctx: ctx['form_add'] = AceForm ctx['arcs'] = escapeTargets(Ace.objects.all()) return render_to_response('home.html',ctx,context_instance=RequestContext(request))
class RestrictedTest(unittest.TestCase): def __init__(self, *args, **kw): super(RestrictedTest, self).__init__(*args, **kw) self.domain = Domain(DEFAULT_DIR, restricted=True, errors=4) self.domain.log.setLevel(logging_level) self.count = 0 def get_template_from_expr(self, expr): self.count += 1 name = "tfs%s" % (self.count) src = "${%s}" % (expr) self.domain.set_template(name, src=src, from_string=True) return self.domain.get_template(name) def test_restricted(self): for bi in DISALLOW_BUILTINS: t = self.get_template_from_expr(bi) self.assertRaises((LookupError, NameError), t.evoque) def test_inquisitive(self): # on a function object, evoque() for expr in ["evoque." + attr for attr in RESTRICTED_ATTRS]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError, ), t.evoque) # on a function object, evoque(), with space between "." and attr name for expr in ["evoque. " + attr for attr in RESTRICTED_ATTRS]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError, ), t.evoque) def test_unsafe_str_expressions(self): # NameError, unsafe builtins for expr in [ "open('test.txt', 'w')", "getattr(int, '_' + '_abs_' + '_')", ]: t = self.get_template_from_expr(expr) self.assertRaises((NameError, ), t.evoque) # LookupError for expr in [ # lowlevel tricks to access 'object' "().__class__.mro()[1].__subclasses__()", "type(1)._" + "_abs_" + "_", "()." + "_" * 2 + "class" + "_" * 2 + ".mro()[1]." + "_" * 2 + "subclasses" + "_" * 2 + "()", ]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError, ), t.evoque) # SyntaxError for expr in [ # attempt to access global enviroment where fun was defined "def x(): pass; print x.func_globals", # statement, SyntaxError # attempt to execute code which never terminates "while 1: pass", # statement, SyntaxError ]: t = self.get_template_from_expr(expr) self.assertRaises(( LookupError, SyntaxError, ), t.evoque) # RuntimeError # http://groups.google.com/group/comp.lang.python/browse_thread/thread/689ea92183b91f06 for expr in [ # Mark Wooding "inspect.func_globals['_'*2+'builtins'+'_'*2].open('" + __file__ + "').read()", "inspect.func_globals['_'*2+'builtins'+'_'*2]", # Daniel Diniz "(x for x in ()).throw('bork')," "(x for x in range(1)).gi_frame.f_globals.clear()", #"open('where_is_ma_beer.txt', 'w').write('Thanks for the fun')", ]: t = self.get_template_from_expr(expr) self.assertRaises((LookupError, RuntimeError, AttributeError), t.evoque) def test_unsafe_file_expressions(self): # Create a new domain for this, to be able to run with a different # errors setting td = Domain(DEFAULT_DIR, restricted=True, errors=2, quoting="str") name = 'restricted_exprs.txt' t = td.get_template(name) result = """ [EvalError(().__class__.mro()[1].__subclasses__())] ().__class__.mro()[1].__subclasses__() ().__class__.mro()[1].__subclasses__() [EvalError(eval(expr))] [EvalError(evoque("test", src="${"+expr+"}", from_string=True))] """ self.assertEqual(result, t.evoque())