Commit 528a7b0f authored by Andreas Jung's avatar Andreas Jung

- implemented some unicode encoding conflict resolvers

- configuration through ZCML
- additional useful logging
parent a558fa87
...@@ -18,8 +18,9 @@ for Python expressions, string literals, and paths. ...@@ -18,8 +18,9 @@ for Python expressions, string literals, and paths.
$Id$ $Id$
""" """
import sys import logging
from zope.component import getUtility
from zope.interface import implements from zope.interface import implements
from zope.tales.tales import Context, Iterator from zope.tales.tales import Context, Iterator
from zope.tales.expressions import PathExpr, StringExpr, NotExpr from zope.tales.expressions import PathExpr, StringExpr, NotExpr
...@@ -34,13 +35,17 @@ import OFS.interfaces ...@@ -34,13 +35,17 @@ import OFS.interfaces
from MultiMapping import MultiMapping from MultiMapping import MultiMapping
from Acquisition import aq_base from Acquisition import aq_base
from zExceptions import NotFound, Unauthorized from zExceptions import NotFound, Unauthorized
from Products.Five.browser.providerexpression import Z2ProviderExpression from Products.Five.browser.providerexpression import Z2ProviderExpression
from Products.PageTemplates import ZRPythonExpr from Products.PageTemplates import ZRPythonExpr
from Products.PageTemplates.DeferExpr import LazyExpr from Products.PageTemplates.DeferExpr import LazyExpr
from Products.PageTemplates.GlobalTranslationService import getGlobalTranslationService from Products.PageTemplates.GlobalTranslationService import getGlobalTranslationService
from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
SecureModuleImporter = ZRPythonExpr._SecureModuleImporter() SecureModuleImporter = ZRPythonExpr._SecureModuleImporter()
LOG = logging.getLogger('Expressions')
# BBB 2005/05/01 -- remove after 12 months # BBB 2005/05/01 -- remove after 12 months
import zope.deprecation import zope.deprecation
from zope.deprecation import deprecate from zope.deprecation import deprecate
...@@ -183,9 +188,9 @@ class ZopeContext(Context): ...@@ -183,9 +188,9 @@ class ZopeContext(Context):
""" """
text = self.evaluate(expr) text = self.evaluate(expr)
# print expr, repr(text), text.__class__
if text is self.getDefault() or text is None: if text is self.getDefault() or text is None:
# XXX: should be unicode???
return text return text
if isinstance(text, unicode): if isinstance(text, unicode):
...@@ -193,26 +198,20 @@ class ZopeContext(Context): ...@@ -193,26 +198,20 @@ class ZopeContext(Context):
return text return text
elif isinstance(text, str): elif isinstance(text, str):
# waahhh...a standard string # bahh...non-unicode string..we need to convert it to unicode
# trying to be somewhat smart...this must be resolver = getUtility(IUnicodeEncodingConflictResolver)
# replaced with some kind of configurable
# UnicodeEncodingConflictResolver (what a name)
try: try:
return unicode(text) return resolver.resolve(self.contexts['context'], text, expr)
except UnicodeDecodeError,e:
except UnicodeDecodeError: LOG.error("""UnicodeDecodeError detected for expression "%s"\n"""
# check for management_page_charset property, default to Python's """Resolver class: %s\n"""
# default encoding """Exception text: %s\n"""
"""Template: %s\n"""
encoding = getattr(self.contexts['context'], 'management_page_charset', sys.getdefaultencoding()) """Rendered text: %r""" % \
(expr, resolver.__class__, e,
try: self.contexts['template'].absolute_url(1), text))
return unicode(text, encoding) raise
except UnicodeDecodeError:
# errors='replace' sucks...it's fine for now
return unicode(text, encoding, 'replace')
else: else:
# This is a weird culprit ...calling unicode() on non-string # This is a weird culprit ...calling unicode() on non-string
......
<configure xmlns="http://namespaces.zope.org/zope" <configure xmlns="http://namespaces.zope.org/zope">
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:five="http://namespaces.zope.org/five">
<utility <utility
provides="zope.component.interfaces.IFactory" provides="Products.PageTemplates.interfaces.IUnicodeEncodingConflictResolver"
component="Products.PageTemplates.unicodeconflictresolver.UnicodeEncodingResolverFactory" component="Products.PageTemplates.unicodeconflictresolver.DefaultUnicodeEncodingConflictResolver"
/> />
</configure> </configure>
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
from zope.interface import Interface from zope.interface import Interface
class IUnicodeEncodingConflictResolver(Interface): class IUnicodeEncodingConflictResolver(Interface):
""" A utility that tries to convert a non-unicode string into
a Python unicode by implementing some policy in order
to figure out a possible encoding - either through the
calling context, the location or the system environment
"""
def resolve(context, text): def resolve(context, text, expression):
""" Returns 'text' as unicode string. """ Returns 'text' as unicode string.
'context' is the current context object 'context' is the current context object.
'expression' is the original expression (can be used for
logging purposes)
""" """
########################################################################### ##############################################################################
# TextIndexNG V 3
# The next generation TextIndex for Zope
# #
# This software is governed by a license. See # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
# LICENSE.txt for the terms of this license. #
########################################################################### # This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
import sys
from zope.interface import implements
from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
default_encoding = sys.getdefaultencoding()
from zope.component.interfaces import IFactory class DefaultUnicodeEncodingConflictResolver:
from zope.interface import implements, implementedBy """ This resolver implements the old-style behavior and will
raise an exception in case of the string 'text' can't be converted
propertly to unicode.
"""
from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver implements(IUnicodeEncodingConflictResolver)
class UnicodeEncodingResolver: def resolve(self, context, text, expression):
return unicode(text)
DefaultUnicodeEncodingConflictResolver = DefaultUnicodeEncodingConflictResolver()
implements(IUnicodeEncodingConflictResolver)
def __init__(self, context, text): class Z2UnicodeEncodingConflictResolver:
self.context = context """ This resolver tries to lookup the encoding from the
self.text = text 'management_page_charset' property and defaults to
sys.getdefaultencoding().
"""
implements(IUnicodeEncodingConflictResolver)
def resolve(self, context, text): def __init__(self, mode='strict'):
return unicode(self.text, errors='replace') self.mode = mode
class UnicodeEncodingResolverFactory: def resolve(self, context, text, expression):
implements(IFactory)
def __call__(self, context, text): try:
return UnicodeEncodingResolver(context, text) return unicode(text)
except UnicodeDecodeError:
encoding = getattr(context, 'managment_page_charset', default_encoding)
return unicode(text, encoding, self.mode)
def getInterfaces(self):
return implementedBy(UnicodeEncodingResolverFactory)
UnicodeEncodingResolverFactory = UnicodeEncodingResolverFactory() StrictUnicodeEncodingConflictResolver = Z2UnicodeEncodingConflictResolver('strict')
ReplacingUnicodeEncodingConflictResolver = Z2UnicodeEncodingConflictResolver('replace')
IgnoringUnicodeEncodingConflictResolver = Z2UnicodeEncodingConflictResolver('ignore')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment