Log message for revision 107725: LP #246983: Unicode conflict resolution on variables inside 'string:' expressions
Changed: U Zope/branches/2.12/doc/CHANGES.rst U Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py U Zope/branches/2.12/src/Products/PageTemplates/Expressions.py U Zope/branches/2.12/src/Products/PageTemplates/tests/testExpressions.py U Zope/branches/2.12/src/Products/PageTemplates/tests/testZopePageTemplate.py -=- Modified: Zope/branches/2.12/doc/CHANGES.rst =================================================================== --- Zope/branches/2.12/doc/CHANGES.rst 2010-01-05 22:37:00 UTC (rev 107724) +++ Zope/branches/2.12/doc/CHANGES.rst 2010-01-06 01:31:21 UTC (rev 107725) @@ -11,6 +11,9 @@ Bugs Fixed ++++++++++ +- LP #246983: Enabled unicode conflict resolution on variables inside "string:" + expressions in TALES. + - Fixed possible TypeError while sending multipart emails. - Also look for ZEXP imports within the clienthome directory. This Modified: Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py =================================================================== --- Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py 2010-01-05 22:37:00 UTC (rev 107724) +++ Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py 2010-01-06 01:31:21 UTC (rev 107725) @@ -37,13 +37,13 @@ from zope.tales.expressions import DeferExpr from zope.tales.expressions import NotExpr from zope.tales.expressions import PathExpr - from zope.tales.expressions import StringExpr from zope.tales.expressions import Undefs from zope.tales.pythonexpr import PythonExpr from zope.contentprovider.tales import TALESProviderExpression from Products.PageTemplates.DeferExpr import LazyExpr from Products.PageTemplates.Expressions import TrustedZopePathExpr from Products.PageTemplates.Expressions import SecureModuleImporter + from Products.PageTemplates.Expressions import UnicodeAwareStringExpr vptf = self._makeOne('seagull.pt') engine = vptf.pt_getEngine() @@ -51,7 +51,7 @@ self.assertEqual(engine.types['path'], TrustedZopePathExpr) self.assertEqual(engine.types['exists'], TrustedZopePathExpr) self.assertEqual(engine.types['nocall'], TrustedZopePathExpr) - self.assertEqual(engine.types['string'], StringExpr) + self.assertEqual(engine.types['string'], UnicodeAwareStringExpr) self.assertEqual(engine.types['python'], PythonExpr) self.assertEqual(engine.types['not'], NotExpr) self.assertEqual(engine.types['defer'], DeferExpr) Modified: Zope/branches/2.12/src/Products/PageTemplates/Expressions.py =================================================================== --- Zope/branches/2.12/src/Products/PageTemplates/Expressions.py 2010-01-05 22:37:00 UTC (rev 107724) +++ Zope/branches/2.12/src/Products/PageTemplates/Expressions.py 2010-01-06 01:31:21 UTC (rev 107725) @@ -372,12 +372,26 @@ return False return ob1 == ob2 +class UnicodeAwareStringExpr(StringExpr): + + def __call__(self, econtext): + vvals = [] + if isinstance(self._expr, unicode): + # coerce values through the Unicode Conflict Resolver + evaluate = econtext.evaluateText + else: + evaluate = econtext.evaluate + for var in self._vars: + v = evaluate(var) + vvals.append(v) + return self._expr % tuple(vvals) + def createZopeEngine(zpe=ZopePathExpr): e = ZopeEngine() e.iteratorFactory = PathIterator for pt in zpe._default_type_names: e.registerType(pt, zpe) - e.registerType('string', StringExpr) + e.registerType('string', UnicodeAwareStringExpr) e.registerType('python', ZRPythonExpr.PythonExpr) e.registerType('not', NotExpr) e.registerType('defer', DeferExpr) Modified: Zope/branches/2.12/src/Products/PageTemplates/tests/testExpressions.py =================================================================== --- Zope/branches/2.12/src/Products/PageTemplates/tests/testExpressions.py 2010-01-05 22:37:00 UTC (rev 107724) +++ Zope/branches/2.12/src/Products/PageTemplates/tests/testExpressions.py 2010-01-06 01:31:21 UTC (rev 107725) @@ -25,12 +25,20 @@ __allow_access_to_unprotected_subobjects__ = 1 def __call__(self): return 'dummy' + + management_page_charset = 'iso-8859-15' class DummyDocumentTemplate: __allow_access_to_unprotected_subobjects__ = 1 isDocTemp = True def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw): return 'dummy' + + def absolute_url(self, relative=0): + url = 'dummy' + if not relative: + url = "http://server/" + url + return url _DEFAULT_BINDINGS = dict( one = 1, @@ -38,6 +46,12 @@ blank = '', dummy = Dummy(), dummy2 = DummyDocumentTemplate(), + eightbit = 'äüö', + # ZopeContext needs 'context' and 'template' keys for unicode + # conflict resolution, and 'context' needs a + # 'management_page_charset' + context = Dummy(), + template = DummyDocumentTemplate(), ) if bindings is None: @@ -158,6 +172,34 @@ ec = self._makeContext() self.assertEquals(ec.evaluate(' \n'), None) + def test_unicode(self): + # All our string expressions are unicode now + eng = self._makeEngine() + ec = self._makeContext() + # XXX: can't do ec.evaluate(u'string:x') directly because ZopeContext + # only bothers compiling true strings, not unicode strings + result = ec.evaluate(eng.compile(u'string:x')) + self.assertEqual(result, u'x') + self.failUnless(isinstance(result, unicode)) + + def test_mixed(self): + # 8-bit strings in unicode string expressions cause UnicodeDecodeErrors + eng = self._makeEngine() + ec = self._makeContext() + expr = eng.compile(u'string:$eightbit') + self.assertRaises(UnicodeDecodeError, + ec.evaluate, expr) + # But registering an appropriate IUnicodeEncodingConflictResolver + # should fix it + from zope.component import provideUtility + from Products.PageTemplates.unicodeconflictresolver \ + import StrictUnicodeEncodingConflictResolver + from Products.PageTemplates.interfaces \ + import IUnicodeEncodingConflictResolver + provideUtility(StrictUnicodeEncodingConflictResolver, + IUnicodeEncodingConflictResolver) + self.assertEqual(ec.evaluate(expr), u'äüö') + class UntrustedEngineTests(EngineTestsBase, unittest.TestCase): def _makeEngine(self): Modified: Zope/branches/2.12/src/Products/PageTemplates/tests/testZopePageTemplate.py =================================================================== --- Zope/branches/2.12/src/Products/PageTemplates/tests/testZopePageTemplate.py 2010-01-05 22:37:00 UTC (rev 107724) +++ Zope/branches/2.12/src/Products/PageTemplates/tests/testZopePageTemplate.py 2010-01-06 01:31:21 UTC (rev 107725) @@ -202,6 +202,26 @@ state = cPickle.dumps(empty, protocol=1) clone = cPickle.loads(state) + def testBug246983(self): + # See https://bugs.launchpad.net/bugs/246983 + self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', 'utf-8') + self.app.REQUEST.set('data', u'üöä'.encode('utf-8')) + # Direct inclusion of encoded strings is hadled normally by the unicode + # conflict resolver + textDirect = """ + <tal:block content="request/data" /> + """.strip() + manage_addPageTemplate(self.app, 'test', text=textDirect) + zpt = self.app['test'] + self.assertEquals(zpt.pt_render(), u'üöä') + # Indirect inclusion of encoded strings through String Expressions + # should be resolved as well. + textIndirect = """ + <tal:block content="string:x ${request/data}" /> + """.strip() + zpt.pt_edit(textIndirect, zpt.content_type) + self.assertEquals(zpt.pt_render(), u'x üöä') + def testDebugFlags(self): # Test for bug 229549 manage_addPageTemplate(self.app, 'test',
_______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org https://mail.zope.org/mailman/listinfo/zope-checkins