diff --git a/news/125.bugfix.1 b/news/125.bugfix.1 new file mode 100644 index 00000000..8c9bc333 --- /dev/null +++ b/news/125.bugfix.1 @@ -0,0 +1,3 @@ +searchForMembers: always use utf-8 instead of checking default_charset. +This code was still getting the ``IPropertiesTool`` utility. +[maurits] diff --git a/news/125.bugfix.2 b/news/125.bugfix.2 new file mode 100644 index 00000000..e03522bf --- /dev/null +++ b/news/125.bugfix.2 @@ -0,0 +1,2 @@ +Restore searching for member when query uses bytes instead of text. +[maurits] diff --git a/src/Products/PlonePAS/plugins/property.py b/src/Products/PlonePAS/plugins/property.py index 775e2c45..f2a4f76f 100644 --- a/src/Products/PlonePAS/plugins/property.py +++ b/src/Products/PlonePAS/plugins/property.py @@ -6,11 +6,11 @@ from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from BTrees.OOBTree import OOBTree +from plone.base.utils import safe_text from Products.CMFCore.utils import getToolByName from Products.PlonePAS.interfaces.plugins import IMutablePropertiesPlugin from Products.PlonePAS.sheet import MutablePropertySheet from Products.PlonePAS.sheet import validateValue -from Products.PlonePAS.utils import safe_unicode from Products.PluggableAuthService.interfaces.plugins import IPropertiesPlugin from Products.PluggableAuthService.interfaces.plugins import IUserEnumerationPlugin from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin @@ -219,9 +219,9 @@ def testMemberData(self, memberdata, criteria, exact_match=False): return False if isStringType(testvalue): - testvalue = safe_unicode(testvalue.lower()) + testvalue = safe_text(testvalue.lower()) if isStringType(value): - value = safe_unicode(value.lower()) + value = safe_text(value.lower()) if exact_match: if value != testvalue: diff --git a/src/Products/PlonePAS/tests/test_membershiptool.py b/src/Products/PlonePAS/tests/test_membershiptool.py index b0d3480b..c380e73d 100644 --- a/src/Products/PlonePAS/tests/test_membershiptool.py +++ b/src/Products/PlonePAS/tests/test_membershiptool.py @@ -904,7 +904,7 @@ def testSearchByRequestObj(self): self.assertEqual(len(search(REQUEST=dict(name="jürgen"))), 1) - self.assertEqual(len(search(REQUEST=dict(name="jürgen"))), 1) + self.assertEqual(len(search(REQUEST=dict(name="jürgen".encode()))), 1) class TestDefaultUserAndPasswordNotChanged(unittest.TestCase): diff --git a/src/Products/PlonePAS/tools/membership.py b/src/Products/PlonePAS/tools/membership.py index 50310fbe..d25e897c 100644 --- a/src/Products/PlonePAS/tools/membership.py +++ b/src/Products/PlonePAS/tools/membership.py @@ -11,8 +11,8 @@ from DateTime import DateTime from io import BytesIO from OFS.Image import Image +from plone.base.utils import safe_text from plone.protect.interfaces import IDisableCSRFProtection -from Products.CMFCore.interfaces import IPropertiesTool from Products.CMFCore.MembershipTool import MembershipTool as BaseTool from Products.CMFCore.permissions import ListPortalMembers from Products.CMFCore.permissions import ManagePortal @@ -27,12 +27,10 @@ from Products.PlonePAS.events import UserLoggedOutEvent from Products.PlonePAS.interfaces import membership from Products.PlonePAS.utils import cleanId -from Products.PlonePAS.utils import safe_unicode from Products.PlonePAS.utils import scale_image from zExceptions import BadRequest from ZODB.POSException import ConflictError from zope import event -from zope.component import getUtility from zope.interface import alsoProvides from zope.interface import implementer @@ -44,27 +42,6 @@ default_portrait = "defaultUser.png" logger = logging.getLogger("PlonePAS") -_marker = dict() # type: ignore - - -def _unicodify_structure(value, charset=_marker): - """Convert value to unicode.""" - if charset is _marker: - ptool = getUtility(IPropertiesTool) - charset = ptool.getProperty("default_charset", None) - - if isinstance(value, str): - return charset and safe_unicode(value, charset) or safe_unicode(value) - if isinstance(value, list): - return [_unicodify_structure(val, charset) for val in value] - if isinstance(value, tuple): - return tuple(_unicodify_structure(entry, charset) for entry in value) - if isinstance(value, dict): - for key, val in value.items(): - value[key] = _unicodify_structure(val, charset) - return value - return value - @implementer(membership.IMembershipTool) class MembershipTool(BaseTool): @@ -189,8 +166,8 @@ def searchForMembers(self, REQUEST=None, **kw): if REQUEST is not None: searchmap = REQUEST for key, value in searchmap.items(): - if isinstance(value, str): - searchmap[key] = _unicodify_structure(value) + if isinstance(value, bytes): + searchmap[key] = safe_text(value) else: searchmap = kw diff --git a/src/Products/PlonePAS/utils.py b/src/Products/PlonePAS/utils.py index c259c66e..d3987e2d 100644 --- a/src/Products/PlonePAS/utils.py +++ b/src/Products/PlonePAS/utils.py @@ -3,6 +3,14 @@ from Products.PluggableAuthService.interfaces.plugins import IGroupsPlugin import urllib +import zope.deferredimport + + +zope.deferredimport.deprecated( + "You should use plone.base.utils.safe_text instead. " + "This alias will be removed in Plone 7.0", + safe_unicode="plone.base.utils:safe_text", +) def unique(iterable): @@ -178,18 +186,6 @@ def getGroupsForPrincipal(principal, plugins, request=None): return list(groups) -def safe_unicode(value, encoding="utf-8"): - """Converts a value to unicode, even it is already a unicode string.""" - if isinstance(value, str): - return value - elif isinstance(value, str): - try: - value = str(value, encoding) - except UnicodeDecodeError: - value = value.decode("utf-8", "replace") - return value - - # Imported from Products.CMFCore.MemberdataTool as it has now been removed. class CleanupTemp: """Used to cleanup _v_temps at the end of the request."""