Commit 68deba35 authored by Martijn Pieters's avatar Martijn Pieters

Collector #2300: delimit *all* headers with CRLF; accumulated_headers and...

Collector #2300: delimit *all* headers with CRLF; accumulated_headers and appendHeader use \n for delimeters and never get corrected on output
parent 2032469b
...@@ -4,6 +4,12 @@ Zope Changes ...@@ -4,6 +4,12 @@ Zope Changes
Change information for previous versions of Zope can be found in the Change information for previous versions of Zope can be found in the
file HISTORY.txt. file HISTORY.txt.
Zope 2.9.8 (unreleased)
Bugs fixed
- Collector #2300: delimit *all* HTTP Response headers with CRLF.
Zope 2.9.7 (2007/03/25) Zope 2.9.7 (2007/03/25)
Bugs fixed Bugs fixed
......
...@@ -114,8 +114,15 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -114,8 +114,15 @@ class ZServerHTTPResponse(HTTPResponse):
self._chunking=1 self._chunking=1
else: else:
self.setHeader('Connection','close') self.setHeader('Connection','close')
for key, val in headers.items(): headers = headers.items()
for line in self.accumulated_headers.splitlines():
if line[0] == '\t':
headers[-1][1] += '\n' + line
continue
headers.append(line.split(': ', 1))
for key, val in headers:
if key.lower()==key: if key.lower()==key:
# only change non-literal header names # only change non-literal header names
key="%s%s" % (key[:1].upper(), key[1:]) key="%s%s" % (key[:1].upper(), key[1:])
...@@ -125,10 +132,13 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -125,10 +132,13 @@ class ZServerHTTPResponse(HTTPResponse):
key="%s-%s%s" % (key[:l],key[l+1:l+2].upper(),key[l+2:]) key="%s-%s%s" % (key[:l],key[l+1:l+2].upper(),key[l+2:])
start=l+1 start=l+1
l=key.find('-',start) l=key.find('-',start)
val = val.replace('\n\t', '\r\n\t')
append("%s: %s" % (key, val)) append("%s: %s" % (key, val))
if self.cookies: if self.cookies:
headersl=headersl+self._cookie_list() headersl.extend(self._cookie_list())
headersl[len(headersl):]=[self.accumulated_headers, body]
append('')
append(body)
return "\r\n".join(headersl) return "\r\n".join(headersl)
_tempfile=None _tempfile=None
...@@ -151,6 +161,7 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -151,6 +161,7 @@ class ZServerHTTPResponse(HTTPResponse):
""" """
if type(data) != type(''): if type(data) != type(''):
raise TypeError('Value must be a string') raise TypeError('Value must be a string')
......
...@@ -56,7 +56,7 @@ class ZServerResponseTestCase(unittest.TestCase): ...@@ -56,7 +56,7 @@ class ZServerResponseTestCase(unittest.TestCase):
one = ZServerHTTPResponse(stdout=DummyChannel()) one = ZServerHTTPResponse(stdout=DummyChannel())
self.assertRaises(AssertionError, self.assertRaises(AssertionError,
one.setBody, test_streamiterator()) one.setBody, test_streamiterator())
class DummyChannel: class DummyChannel:
def __init__(self): def __init__(self):
self.out = StringIO() self.out = StringIO()
...@@ -92,8 +92,46 @@ class test_streamiterator: ...@@ -92,8 +92,46 @@ class test_streamiterator:
return self.data return self.data
raise StopIteration raise StopIteration
class ZServerHTTPResponseTestCase(unittest.TestCase):
"""Test ZServer HTTPResponse object"""
def _makeOne(self):
return ZServerHTTPResponse()
def testToString(self):
response = self._makeOne()
response.headers = {
'content-type': 'text/plain',
'all-lower-case': 'foo',
'Title-Cased': 'bar',
'mixed-CasED': 'spam',
'multilined': 'eggs\n\tham'}
response.accumulated_headers = 'foo-bar: bar\n\tbaz\nFoo-bar: monty\n'
response.cookies = dict(foo=dict(value='bar'))
response.body = 'A body\nwith multiple lines\n'
result = str(response)
headers, body = result.rsplit('\r\n\r\n')
self.assertEqual(body, response.body)
self.assertTrue(headers.startswith('HTTP/1.0 200 OK\r\n'))
# 15 header lines all delimited by \r\n
self.assertEqual(
['\n' in line for line in headers.split('\r\n')],
15 * [False])
self.assertTrue('Multilined: eggs\r\n\tham\r\n' in headers)
self.assertTrue('Foo-Bar: bar\r\n\tbaz\r\n' in headers)
def test_suite(): def test_suite():
return unittest.makeSuite(ZServerResponseTestCase) suite = unittest.TestSuite()
suite.addTests((
unittest.makeSuite(ZServerResponseTestCase),
unittest.makeSuite(ZServerHTTPResponseTestCase)
))
return suite
if __name__ == "__main__": if __name__ == "__main__":
unittest.main(defaultTest="test_suite") unittest.main(defaultTest="test_suite")
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