Commit ef651b61 authored by 's avatar

fixed regression in Unauthorized handling:

In previous Zope versions string exceptions were used and all exceptions
re-raised. This doesn't work with each kind of exception, but we can still do
it with Unauthorized exceptions. This way the special handling for Unauthorized
exceptions works again, HTTPResponse._unauthorized is called again. This is now
done after rendering to make sure we don't break logging and custom views.
parent e32b20fe
...@@ -11,6 +11,8 @@ http://docs.zope.org/zope2/releases/. ...@@ -11,6 +11,8 @@ http://docs.zope.org/zope2/releases/.
Bugs Fixed Bugs Fixed
++++++++++ ++++++++++
- LP #372632, comments #15ff.: Fixed regression in Unauthorized handling.
- LP #563229: Process "evil" JSON cookies which contain double quotes in - LP #563229: Process "evil" JSON cookies which contain double quotes in
violation of RFC 2965 / 2616. violation of RFC 2965 / 2616.
......
...@@ -115,7 +115,8 @@ Handle zExceptions.Redirect. ...@@ -115,7 +115,8 @@ Handle zExceptions.Redirect.
... ...
Redirect: LOCATION Redirect: LOCATION
Handle zExceptions.Unauthorized. Handle zExceptions.Unauthorized. We take the 'WWW-Authenticate' header as a
sign that HTTPResponse._unauthorized was called.
>>> from zExceptions import Unauthorized >>> from zExceptions import Unauthorized
>>> app.test_folder_1_.foo.exception = Unauthorized('ERROR VALUE') >>> app.test_folder_1_.foo.exception = Unauthorized('ERROR VALUE')
...@@ -129,6 +130,8 @@ Handle zExceptions.Unauthorized. ...@@ -129,6 +130,8 @@ Handle zExceptions.Unauthorized.
True True
>>> 'Error Value: ERROR VALUE' in browser.contents >>> 'Error Value: ERROR VALUE' in browser.contents
True True
>>> browser.headers['WWW-Authenticate']
'basic realm="Zope2"'
>>> browser.handleErrors = False >>> browser.handleErrors = False
>>> browser.open('http://localhost/test_folder_1_/foo') >>> browser.open('http://localhost/test_folder_1_/foo')
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE # FOR A PARTICULAR PURPOSE.
# #
############################################################################## ##############################################################################
"""Initialize the Zope2 Package and provide a published module """Initialize the Zope2 Package and provide a published module
...@@ -23,14 +23,12 @@ from Acquisition import aq_parent ...@@ -23,14 +23,12 @@ from Acquisition import aq_parent
from Acquisition.interfaces import IAcquirer from Acquisition.interfaces import IAcquirer
from App.config import getConfiguration from App.config import getConfiguration
from time import asctime from time import asctime
from types import StringType, ListType
from zExceptions import upgradeException from zExceptions import upgradeException
from zExceptions import Redirect from zExceptions import Redirect
from zExceptions import Unauthorized from zExceptions import Unauthorized
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
import transaction import transaction
import AccessControl.User import AccessControl.User
import App.FindHomes
import ExtensionClass import ExtensionClass
import imp import imp
import logging import logging
...@@ -206,7 +204,7 @@ class ZPublisherExceptionHook: ...@@ -206,7 +204,7 @@ class ZPublisherExceptionHook:
# raise the rendered value as the exception value # raise the rendered value as the exception value
# (basically the same that 'raise_standardErrorMessage' # (basically the same that 'raise_standardErrorMessage'
# does. The view is named 'index.html' because that's what # does. The view is named 'index.html' because that's what
# Zope 3 uses as well. # zope.publisher uses as well.
view = queryMultiAdapter((v, REQUEST), name=u'index.html') view = queryMultiAdapter((v, REQUEST), name=u'index.html')
if view is not None: if view is not None:
if IAcquirer.providedBy(view) and IAcquirer.providedBy(published): if IAcquirer.providedBy(view) and IAcquirer.providedBy(published):
...@@ -214,13 +212,19 @@ class ZPublisherExceptionHook: ...@@ -214,13 +212,19 @@ class ZPublisherExceptionHook:
else: else:
view.__parent__ = published view.__parent__ = published
v = view() v = view()
if issubclass(t, Unauthorized):
# Re-raise Unauthorized to make sure it is handled
# correctly. We can't do that with all exceptions
# because some don't work with the rendered v as
# argument.
raise t, v, traceback
response = REQUEST.RESPONSE response = REQUEST.RESPONSE
response.setStatus(t) response.setStatus(t)
response.setBody(v) response.setBody(v)
return response return response
if (published is None or published is app or if (published is None or published is app or
type(published) is ListType): isinstance(published, list)):
# At least get the top-level object # At least get the top-level object
published=app.__bobo_traverse__(REQUEST).__of__( published=app.__bobo_traverse__(REQUEST).__of__(
RequestContainer(REQUEST)) RequestContainer(REQUEST))
...@@ -254,12 +258,18 @@ class ZPublisherExceptionHook: ...@@ -254,12 +258,18 @@ class ZPublisherExceptionHook:
error_log_url=error_log_url) error_log_url=error_log_url)
if result is not None: if result is not None:
t, v, traceback = result t, v, traceback = result
if issubclass(t, Unauthorized):
# Re-raise Unauthorized to make sure it is handled
# correctly. We can't do that with all exceptions
# because some don't work with the rendered v as
# argument.
raise t, v, traceback
response = REQUEST.RESPONSE response = REQUEST.RESPONSE
response.setStatus(t) response.setStatus(t)
response.setBody(v) response.setBody(v)
return response return response
except TypeError: except TypeError:
# Pre 2.6 call signature # BBB: Pre Zope 2.6 call signature
f(client, REQUEST, t, v, traceback) f(client, REQUEST, t, v, traceback)
finally: finally:
......
...@@ -347,7 +347,6 @@ def registerExceptionView(for_): ...@@ -347,7 +347,6 @@ def registerExceptionView(for_):
class ExceptionViewsTest(PlacelessSetup, ExceptionHookTestCase): class ExceptionViewsTest(PlacelessSetup, ExceptionHookTestCase):
def testCustomExceptionViewUnauthorized(self): def testCustomExceptionViewUnauthorized(self):
from ZPublisher.HTTPResponse import HTTPResponse
from AccessControl import Unauthorized from AccessControl import Unauthorized
registerExceptionView(IUnauthorized) registerExceptionView(IUnauthorized)
def f(): def f():
...@@ -355,8 +354,7 @@ class ExceptionViewsTest(PlacelessSetup, ExceptionHookTestCase): ...@@ -355,8 +354,7 @@ class ExceptionViewsTest(PlacelessSetup, ExceptionHookTestCase):
request = self._makeRequest() request = self._makeRequest()
client = StandardClient() client = StandardClient()
v = self.call_exc_value(client, request, f) v = self.call_exc_value(client, request, f)
self.failUnless(isinstance(v, HTTPResponse), v) self.failUnless(isinstance(v, Unauthorized), v)
self.failUnless(v.status == 401, (v.status, 401))
self.failUnless("Exception View: Unauthorized" in str(v)) self.failUnless("Exception View: Unauthorized" in str(v))
self.failUnless("Context: StandardClient" in str(v)) self.failUnless("Context: StandardClient" in str(v))
......
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