Commit 92047edf authored by 's avatar

- If `IBrowserPage` is provided by a view, form input is decoded.

parent f9cea257
...@@ -28,6 +28,9 @@ Bugs Fixed ...@@ -28,6 +28,9 @@ Bugs Fixed
Features Added Features Added
++++++++++++++ ++++++++++++++
- ZPublisher: If `IBrowserPage` is provided by a view, form input is decoded.
This makes it easier to use ``zope.formlib`` and ``z3c.form`` in Zope 2.
- Report success or failure (when known) of creating a new user with - Report success or failure (when known) of creating a new user with
the addzope2user script. the addzope2user script.
......
...@@ -40,7 +40,6 @@ from AccessControl.tainted import TaintedString ...@@ -40,7 +40,6 @@ from AccessControl.tainted import TaintedString
from ZPublisher.BaseRequest import BaseRequest from ZPublisher.BaseRequest import BaseRequest
from ZPublisher.BaseRequest import quote from ZPublisher.BaseRequest import quote
from ZPublisher.Converters import get_converter from ZPublisher.Converters import get_converter
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.maybe_lock import allocate_lock from ZPublisher.maybe_lock import allocate_lock
# Flags # Flags
...@@ -1150,6 +1149,12 @@ class HTTPRequest(BaseRequest): ...@@ -1150,6 +1149,12 @@ class HTTPRequest(BaseRequest):
other['PATH_INFO'] = path = "%s/%s" % (path,meth) other['PATH_INFO'] = path = "%s/%s" % (path,meth)
self._hacked_path = 1 self._hacked_path = 1
def postProcessInputs(self):
"""Process the values in request.form to decode strings to unicode.
"""
for name, value in self.form.iteritems():
self.form[name] = _decode(value, default_encoding)
def resolve_url(self, url): def resolve_url(self, url):
# Attempt to resolve a url into an object in the Zope # Attempt to resolve a url into an object in the Zope
# namespace. The url must be a fully-qualified url. The # namespace. The url must be a fully-qualified url. The
...@@ -1754,3 +1759,16 @@ def _filterPasswordFields(items): ...@@ -1754,3 +1759,16 @@ def _filterPasswordFields(items):
result.append((k, v)) result.append((k, v))
return result return result
def _decode(value, charset):
"""Recursively look for string values and decode.
"""
if isinstance(value, list):
return [_decode(v, charset) for v in value]
elif isinstance(value, tuple):
return tuple(_decode(v, charset) for v in value)
elif isinstance(value, dict):
return dict((k, _decode(v, charset)) for k, v in value.iteritems())
elif isinstance(value, str):
return unicode(value, charset, 'replace')
return value
...@@ -15,18 +15,25 @@ ...@@ -15,18 +15,25 @@
import sys, os import sys, os
import transaction import transaction
from Response import Response
from Request import Request
from maybe_lock import allocate_lock
from mapply import mapply
from zExceptions import Redirect from zExceptions import Redirect
from zope.event import notify
from zope.publisher.interfaces import ISkinnable from zope.publisher.interfaces import ISkinnable
from zope.publisher.interfaces.browser import IBrowserPage
from zope.publisher.skinnable import setDefaultSkin from zope.publisher.skinnable import setDefaultSkin
from zope.security.management import newInteraction, endInteraction from zope.security.management import newInteraction, endInteraction
from zope.event import notify
from pubevents import PubStart, PubSuccess, PubFailure, \ from .mapply import mapply
PubBeforeCommit, PubAfterTraversal, PubBeforeAbort from .maybe_lock import allocate_lock
from .pubevents import PubAfterTraversal
from .pubevents import PubBeforeAbort
from .pubevents import PubBeforeCommit
from .pubevents import PubFailure
from .pubevents import PubStart
from .pubevents import PubSuccess
from .Request import Request
from .Response import Response
class Retry(Exception): class Retry(Exception):
"""Raise this to retry a request """Raise this to retry a request
...@@ -114,6 +121,9 @@ def publish(request, module_name, after_list, debug=0, ...@@ -114,6 +121,9 @@ def publish(request, module_name, after_list, debug=0,
object=request.traverse(path, validated_hook=validated_hook) object=request.traverse(path, validated_hook=validated_hook)
if IBrowserPage.providedBy(object):
request.postProcessInputs()
notify(PubAfterTraversal(request)) notify(PubAfterTraversal(request))
if transactions_manager: if transactions_manager:
......
import unittest import unittest
from zope.testing.cleanup import cleanUp
class RecordTests(unittest.TestCase): class RecordTests(unittest.TestCase):
def test_repr(self): def test_repr(self):
...@@ -11,8 +14,12 @@ class RecordTests(unittest.TestCase): ...@@ -11,8 +14,12 @@ class RecordTests(unittest.TestCase):
d = eval(r) d = eval(r)
self.assertEqual(d, rec.__dict__) self.assertEqual(d, rec.__dict__)
class HTTPRequestTests(unittest.TestCase): class HTTPRequestTests(unittest.TestCase):
def tearDown(self):
cleanUp()
def _getTargetClass(self): def _getTargetClass(self):
from ZPublisher.HTTPRequest import HTTPRequest from ZPublisher.HTTPRequest import HTTPRequest
return HTTPRequest return HTTPRequest
...@@ -634,7 +641,33 @@ class HTTPRequestTests(unittest.TestCase): ...@@ -634,7 +641,33 @@ class HTTPRequestTests(unittest.TestCase):
self.assertEquals(req.cookies['multi2'], self.assertEquals(req.cookies['multi2'],
'cookie data with unquoted spaces') 'cookie data with unquoted spaces')
def test_postProcessInputs(self):
from ZPublisher.HTTPRequest import default_encoding
_NON_ASCII = u'\xc4\xd6\xdc'
req = self._makeOne()
req.form = {'foo': _NON_ASCII.encode(default_encoding),
'foo_list': [_NON_ASCII.encode(default_encoding), 'SPAM'],
'foo_tuple': (_NON_ASCII.encode(default_encoding), 'HAM'),
'foo_dict': {'foo': _NON_ASCII, 'bar': 'EGGS'}}
req.postProcessInputs()
self.assertTrue(isinstance(req.form['foo'], unicode))
self.assertEqual(req.form['foo'], _NON_ASCII)
self.assertTrue(isinstance(req.form['foo_list'], list))
self.assertTrue(isinstance(req.form['foo_list'][0], unicode))
self.assertEqual(req.form['foo_list'][0], _NON_ASCII)
self.assertTrue(isinstance(req.form['foo_list'][1], unicode))
self.assertEqual(req.form['foo_list'][1], u'SPAM')
self.assertTrue(isinstance(req.form['foo_tuple'], tuple))
self.assertTrue(isinstance(req.form['foo_tuple'][0], unicode))
self.assertEqual(req.form['foo_tuple'][0], _NON_ASCII)
self.assertTrue(isinstance(req.form['foo_tuple'][1], unicode))
self.assertEqual(req.form['foo_tuple'][1], u'HAM')
self.assertTrue(isinstance(req.form['foo_dict'], dict))
self.assertTrue(isinstance(req.form['foo_dict']['foo'], unicode))
self.assertEqual(req.form['foo_dict']['foo'], _NON_ASCII)
self.assertTrue(isinstance(req.form['foo_dict']['bar'], unicode))
self.assertEqual(req.form['foo_dict']['bar'], u'EGGS')
def test_close_removes_stdin_references(self): def test_close_removes_stdin_references(self):
# Verifies that all references to the input stream go away on # Verifies that all references to the input stream go away on
......
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