[Checkins] SVN: zope.publisher/trunk/ Fixed the check for untrusted redirects introduced in 3.9.0 so it works with virtual hosting.
Thomas Lotze
tl at gocept.com
Thu Oct 8 05:37:22 EDT 2009
Log message for revision 104912:
Fixed the check for untrusted redirects introduced in 3.9.0 so it works with virtual hosting.
Changed:
U zope.publisher/trunk/CHANGES.txt
U zope.publisher/trunk/src/zope/publisher/http.py
U zope.publisher/trunk/src/zope/publisher/tests/test_http.py
-=-
Modified: zope.publisher/trunk/CHANGES.txt
===================================================================
--- zope.publisher/trunk/CHANGES.txt 2009-10-08 09:25:43 UTC (rev 104911)
+++ zope.publisher/trunk/CHANGES.txt 2009-10-08 09:37:22 UTC (rev 104912)
@@ -4,9 +4,9 @@
3.9.3 (unreleased)
------------------
-- Nothing changed yet.
+- Fixed the check for untrusted redirects introduced in 3.9.0 so it works with
+ virtual hosting.
-
3.9.2 (2009-10-07)
------------------
Modified: zope.publisher/trunk/src/zope/publisher/http.py
===================================================================
--- zope.publisher/trunk/src/zope/publisher/http.py 2009-10-08 09:25:43 UTC (rev 104911)
+++ zope.publisher/trunk/src/zope/publisher/http.py 2009-10-08 09:37:22 UTC (rev 104912)
@@ -874,17 +874,19 @@
def redirect(self, location, status=None, trusted=False):
"""Causes a redirection without raising an error"""
-
+
# convert to a string, as the location could be non-string
# convertable to string, for example, an URLGetter instance
location = str(location)
-
+
if not trusted:
- scheme, target_host, path, query, fragment = (
- urlparse.urlsplit(location))
- if target_host and target_host != self._request.get('HTTP_HOST'):
- raise ValueError(
- "Untrusted redirect to host %r not allowed." % target_host)
+ target_host = extract_host(location)
+ if target_host:
+ app_host = extract_host(self._request.getApplicationURL())
+ if target_host != app_host:
+ raise ValueError(
+ "Untrusted redirect to host %r not allowed."
+ % target_host)
if status is None:
# parse the HTTP version and set default accordingly
@@ -938,6 +940,15 @@
return cmp(y, x)
+def extract_host(url):
+ scheme, host, path, query, fragment = urlparse.urlsplit(url)
+ if ':' not in host:
+ port = DEFAULT_PORTS.get(scheme)
+ if port:
+ host = '%s:%s' % (host, port)
+ return host
+
+
class HTTPCharsets(object):
zope.component.adapts(IHTTPRequest)
zope.interface.implements(IUserPreferredCharsets)
Modified: zope.publisher/trunk/src/zope/publisher/tests/test_http.py
===================================================================
--- zope.publisher/trunk/src/zope/publisher/tests/test_http.py 2009-10-08 09:25:43 UTC (rev 104911)
+++ zope.publisher/trunk/src/zope/publisher/tests/test_http.py 2009-10-08 09:37:22 UTC (rev 104912)
@@ -308,6 +308,34 @@
'http://my-friends.com', trusted=True)
self.assertEquals('http://my-friends.com', location)
+ # We can redirect to our own full server URL, with or without a port
+ # being specified. Let's explicitly set a host name to test this is
+ # this is how virtual hosting works:
+ request.setApplicationServer('example.com')
+ location = request.response.redirect('http://example.com')
+ self.assertEquals('http://example.com', location)
+
+ request.setApplicationServer('example.com', port=8080)
+ location = request.response.redirect('http://example.com:8080')
+ self.assertEquals('http://example.com:8080', location)
+
+ # The default port for HTTP and HTTPS may be omitted:
+ request.setApplicationServer('example.com')
+ location = request.response.redirect('http://example.com:80')
+ self.assertEquals('http://example.com:80', location)
+
+ request.setApplicationServer('example.com', port=80)
+ location = request.response.redirect('http://example.com')
+ self.assertEquals('http://example.com', location)
+
+ request.setApplicationServer('example.com', 'https')
+ location = request.response.redirect('https://example.com:443')
+ self.assertEquals('https://example.com:443', location)
+
+ request.setApplicationServer('example.com', 'https', 443)
+ location = request.response.redirect('https://example.com')
+ self.assertEquals('https://example.com', location)
+
def testUnregisteredStatus(self):
# verify we can set the status to an unregistered int value
request = self._createRequest({}, '')
More information about the checkins
mailing list