Skip to content
This repository has been archived by the owner on May 13, 2020. It is now read-only.

Commit

Permalink
Use trusted path expression for trusted engine. Also, fix issue with …
Browse files Browse the repository at this point in the history
…missing ``request`` variable from template context. Dependencies upgrade to point releases.
  • Loading branch information
malthe committed Jul 14, 2011
1 parent 7a18f8b commit 3f722a8
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 24 deletions.
10 changes: 10 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Changelog
=========

In next release ...

- Use trusted path expression for trusted expression engine.
[malthe]

- Fixed template context issues where a ``request`` would be required
by the path expression compiler but not provided (typically when in
a situation where the user is unauthorized to view content).
[malthe]

2.1-rc1 (2011-07-14)
~~~~~~~~~~~~~~~~~~~~

Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

version = '2.1-rc1'
version = '2.1-dev'

setup(name='five.pt',
version=version,
Expand All @@ -25,8 +25,8 @@
zip_safe=False,
install_requires=[
'setuptools',
'z3c.pt>=2.0-rc3',
'Chameleon>=2.0-rc14',
'z3c.pt>=2.0',
'Chameleon>=2.0',
'sourcecodegen',
],
entry_points="""
Expand Down
28 changes: 21 additions & 7 deletions src/five/pt/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,16 @@ def render(ob, request):
return ob


class FiveTraverser(object):
class BoboAwareZopeTraverse(object):
traverse_method = 'restrictedTraverse'

def __call__(self, base, request, call, *path_items):
"""See ``zope.app.pagetemplate.engine``."""

length = len(path_items)
if length:
i = 0
method = self.traverse_method
while i < length:
name = path_items[i]
i += 1
Expand All @@ -98,7 +101,8 @@ def __call__(self, base, request, call, *path_items):
if isinstance(base, dict):
base = base[name]
elif ITraversable.providedBy(base):
base = base.restrictedTraverse(name)
traverser = getattr(base, method)
base = traverser(name)
else:
base = traversePathElement(
base, name, path_items[i:], request=request)
Expand All @@ -114,12 +118,22 @@ def __call__(self, base, request, call, *path_items):
return base


class TrustedBoboAwareZopeTraverse(BoboAwareZopeTraverse):
traverse_method = 'unrestrictedTraverse'


class PathExpr(expressions.PathExpr):
exceptions = zope2_exceptions

traverser = Static(
template("cls()", cls=Symbol(FiveTraverser), mode="eval")
)
traverser = Static(template(
"cls()", cls=Symbol(BoboAwareZopeTraverse), mode="eval"
))


class TrustedPathExpr(PathExpr):
traverser = Static(template(
"cls()", cls=Symbol(TrustedBoboAwareZopeTraverse), mode="eval"
))


class NocallExpr(expressions.NocallExpr, PathExpr):
Expand Down Expand Up @@ -169,7 +183,7 @@ def visit_Name(self, node):
return node


class SecurePythonExpr(expressions.PythonExpr):
class UntrustedPythonExpr(expressions.PythonExpr):
rm = RestrictionMutator()
rt = RestrictionTransform()

Expand All @@ -186,7 +200,7 @@ def parse(self, string):
node = ast24_parse(decoded, 'eval').node
MutatingWalker.walk(node, self.rm)
string = generate_code(node)
value = super(SecurePythonExpr, self).parse(string)
value = super(UntrustedPythonExpr, self).parse(string)
self.rt.visit(value)
self.nt.visit(value)
return value
29 changes: 15 additions & 14 deletions src/five/pt/patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
from chameleon.tal import RepeatDict

from .expressions import PathExpr
from .expressions import TrustedPathExpr
from .expressions import ProviderExpr
from .expressions import NocallExpr
from .expressions import ExistsExpr
from .expressions import SecurePythonExpr
from .expressions import UntrustedPythonExpr


# Declare Chameleon's repeat dictionary public
Expand All @@ -37,7 +38,7 @@

# Zope 2 Page Template expressions
_secure_expression_types = {
'python': SecurePythonExpr,
'python': UntrustedPythonExpr,
'string': StringExpr,
'not': NotExpr,
'exists': ExistsExpr,
Expand All @@ -53,7 +54,7 @@
'string': StringExpr,
'not': NotExpr,
'exists': ExistsExpr,
'path': PathExpr,
'path': TrustedPathExpr,
'provider': ProviderExpr,
'nocall': NocallExpr,
}
Expand Down Expand Up @@ -110,7 +111,7 @@ def create_interpreter(cls, *args, **kwargs):
class ChameleonTALInterpreter(object):
def __init__(self, template, macros, context, stream, tal=True, **kwargs):
self.template = template
self.econtext = context.vars
self.context = context.vars
self.repeat = context.repeat_vars
self.stream = stream
self.tal = tal
Expand All @@ -119,21 +120,21 @@ def __call__(self):
if self.tal is False:
result = self.template.body
else:
econtext = self.econtext
context = self.context

# Swap out repeat dictionary for Chameleon implementation
# and store wrapped dictionary in new variable -- this is
# in turn used by the secure Python expression
# implementation whenever a 'repeat' symbol is found
econtext['wrapped_repeat'] = econtext['repeat']
econtext['repeat'] = RepeatDict(self.repeat)

result = self.template.render(
path=self.template.evaluate_path,
exists=self.template.evaluate_exists,
test=test,
**econtext
)
context['wrapped_repeat'] = context['repeat']
context['repeat'] = RepeatDict(self.repeat)

# XXX: This could be implemented as a transform which uses
# the turnary operator in place of calls to the test
# function.
context.setdefault('test', test)

result = self.template.render(**context)

self.stream.write(result)

Expand Down

0 comments on commit 3f722a8

Please sign in to comment.