[Zope-Checkins] SVN: Zope/branches/2.10/ Launchpad #267834: proper separation of HTTP header fields

Laurence Rowe l at lrowe.co.uk
Sat Apr 25 20:07:42 EDT 2009


Log message for revision 99500:
  Launchpad #267834: proper separation of HTTP header fields    
          using CRLF as requested by RFC 2616. (merged 90980, 92625)

Changed:
  U   Zope/branches/2.10/doc/CHANGES.txt
  U   Zope/branches/2.10/lib/python/OFS/tests/testRanges.py
  U   Zope/branches/2.10/lib/python/Testing/ZopeTestCase/functional.py
  U   Zope/branches/2.10/lib/python/Testing/tests/test_makerequest.py
  U   Zope/branches/2.10/lib/python/ZPublisher/HTTPResponse.py
  U   Zope/branches/2.10/lib/python/ZPublisher/tests/testHTTPResponse.py

-=-
Modified: Zope/branches/2.10/doc/CHANGES.txt
===================================================================
--- Zope/branches/2.10/doc/CHANGES.txt	2009-04-25 23:45:05 UTC (rev 99499)
+++ Zope/branches/2.10/doc/CHANGES.txt	2009-04-26 00:07:42 UTC (rev 99500)
@@ -27,6 +27,9 @@
 
     Bugs fixed
 
+      - Launchpad #267834: proper separation of HTTP header fields    
+        using CRLF as requested by RFC 2616. (merged 90980, 92625)
+
       - Launchpad #348223: optimize catalog query by breaking out early from
         loop over indexes if the result set is already empty.
 

Modified: Zope/branches/2.10/lib/python/OFS/tests/testRanges.py
===================================================================
--- Zope/branches/2.10/lib/python/OFS/tests/testRanges.py	2009-04-25 23:45:05 UTC (rev 99499)
+++ Zope/branches/2.10/lib/python/OFS/tests/testRanges.py	2009-04-26 00:07:42 UTC (rev 99500)
@@ -102,7 +102,7 @@
 
         # Chop off any printed headers (only when response.write was used)
         if body:
-            body = string.split(body, '\n\n', 1)[1]
+            body = string.split(body, '\r\n\r\n', 1)[1]
 
         return body + rv
 

Modified: Zope/branches/2.10/lib/python/Testing/ZopeTestCase/functional.py
===================================================================
--- Zope/branches/2.10/lib/python/Testing/ZopeTestCase/functional.py	2009-04-25 23:45:05 UTC (rev 99499)
+++ Zope/branches/2.10/lib/python/Testing/ZopeTestCase/functional.py	2009-04-26 00:07:42 UTC (rev 99500)
@@ -106,7 +106,7 @@
 class ResponseWrapper:
     '''Decorates a response object with additional introspective methods.'''
 
-    _bodyre = re.compile('^$^\n(.*)', re.MULTILINE | re.DOTALL)
+    _bodyre = re.compile('\r\n\r\n(.*)', re.MULTILINE | re.DOTALL)
 
     def __init__(self, response, outstream, path):
         self._response = response

Modified: Zope/branches/2.10/lib/python/Testing/tests/test_makerequest.py
===================================================================
--- Zope/branches/2.10/lib/python/Testing/tests/test_makerequest.py	2009-04-25 23:45:05 UTC (rev 99499)
+++ Zope/branches/2.10/lib/python/Testing/tests/test_makerequest.py	2009-04-26 00:07:42 UTC (rev 99500)
@@ -51,7 +51,7 @@
         item.REQUEST.RESPONSE.write('aaa')
         out.seek(0)
         written = out.read()
-        self.failUnless(written.startswith('Status: 200 OK\n'))
+        self.failUnless(written.startswith('Status: 200 OK\r\n'))
         self.failUnless(written.endswith('\naaa'))
 
     def test_environ(self):

Modified: Zope/branches/2.10/lib/python/ZPublisher/HTTPResponse.py
===================================================================
--- Zope/branches/2.10/lib/python/ZPublisher/HTTPResponse.py	2009-04-25 23:45:05 UTC (rev 99499)
+++ Zope/branches/2.10/lib/python/ZPublisher/HTTPResponse.py	2009-04-26 00:07:42 UTC (rev 99500)
@@ -221,7 +221,7 @@
             # It has already been determined.
             return
 
-        if (isinstance(status, types.ClassType)
+        if (isinstance(status, (type, types.ClassType))
          and issubclass(status, Exception)):
             status = status.__name__
 
@@ -246,17 +246,18 @@
         if lock:
              self._locked_status = 1
 
-    def setHeader(self, name, value, literal=0):
+    def setHeader(self, name, value, literal=0, scrubbed=False):
         '''\
         Sets an HTTP return header "name" with value "value", clearing
         the previous value set for the header, if one exists. If the
         literal flag is true, the case of the header name is preserved,
         otherwise the header name will be lowercased.'''
-        name, value = _scrubHeader(name, value)
+        if not scrubbed:
+            name, value = _scrubHeader(name, value)
         key = name.lower()
         if accumulate_header(key):
             self.accumulated_headers = (
-                "%s%s: %s\n" % (self.accumulated_headers, name, value))
+                "%s%s: %s\r\n" % (self.accumulated_headers, name, value))
             return
         name = literal and name or key
         self.headers[name] = value
@@ -279,7 +280,7 @@
         any previously set headers with the same name.'''
         name, value = _scrubHeader(name, value)
         self.accumulated_headers = (
-            "%s%s: %s\n" % (self.accumulated_headers, name, value))
+            "%s%s: %s\r\n" % (self.accumulated_headers, name, value))
 
     __setitem__ = setHeader
 
@@ -471,21 +472,20 @@
 
         # Encode the Unicode data as requested
 
-        if self.headers.has_key('content-type'):
-            match = charset_re.match(self.headers['content-type'])
+        ct = self.headers.get('content-type')
+        if ct:
+            match = charset_re.match(ct)
             if match:
                 encoding = match.group(1)
                 body = body.encode(encoding)
                 body = fix_xml_preamble(body, encoding)
                 return body
             else:
-
-                ct = self.headers['content-type']
                 if ct.startswith('text/') or ct.startswith('application/'):
                     self.headers['content-type'] = '%s; charset=%s' % (ct, default_encoding)
 
         # Use the default character encoding
-        body = body.encode(default_encoding,'replace')
+        body = body.encode(default_encoding, 'replace')
         body = fix_xml_preamble(body, default_encoding)
         return body
 
@@ -593,10 +593,10 @@
         headers = self.headers
         if headers.has_key(name):
             h = headers[name]
-            h = "%s%s\n\t%s" % (h,delimiter,value)
+            h = "%s%s\r\n\t%s" % (h,delimiter,value)
         else:
             h = value
-        self.setHeader(name,h)
+        self.setHeader(name,h, scrubbed=True)
 
     def isHTML(self, s):
         s = s.lstrip()
@@ -895,7 +895,7 @@
         if self.cookies:
             headersl = headersl+self._cookie_list()
         headersl[len(headersl):] = [self.accumulated_headers, body]
-        return '\n'.join(headersl)
+        return '\r\n'.join(headersl)
 
     def write(self,data):
         """\

Modified: Zope/branches/2.10/lib/python/ZPublisher/tests/testHTTPResponse.py
===================================================================
--- Zope/branches/2.10/lib/python/ZPublisher/tests/testHTTPResponse.py	2009-04-25 23:45:05 UTC (rev 99499)
+++ Zope/branches/2.10/lib/python/ZPublisher/tests/testHTTPResponse.py	2009-04-26 00:07:42 UTC (rev 99500)
@@ -72,10 +72,10 @@
         response = self._makeOne()
         response.setHeader('foo', 'bar')
         response.appendHeader('foo', 'foo')
-        self.assertEqual(response.headers.get('foo'), 'bar,\n\tfoo')
+        self.assertEqual(response.headers.get('foo'), 'bar,\r\n\tfoo')
         response.setHeader('xxx', 'bar')
         response.appendHeader('XXX', 'foo')
-        self.assertEqual(response.headers.get('xxx'), 'bar,\n\tfoo')
+        self.assertEqual(response.headers.get('xxx'), 'bar,\r\n\tfoo')
 
     def test_setHeader(self):
         response = self._makeOne()
@@ -151,7 +151,7 @@
         response.addHeader('Location',
                            'http://www.ietf.org/rfc/\r\nrfc2616.txt')
         self.assertEqual(response.accumulated_headers,
-                         'Location: http://www.ietf.org/rfc/rfc2616.txt\n')
+                         'Location: http://www.ietf.org/rfc/rfc2616.txt\r\n')
 
     def test_appendHeader_drops_CRLF(self):
         # RFC2616 disallows CRLF in a header value.
@@ -176,8 +176,9 @@
         response.setHeader('Set-Cookie',
                        'violation="http://www.ietf.org/rfc/\r\nrfc2616.txt"')
         self.assertEqual(response.accumulated_headers,
-                'Set-Cookie: allowed="OK"\n' +
-                'Set-Cookie: violation="http://www.ietf.org/rfc/rfc2616.txt"\n')
+                'Set-Cookie: allowed="OK"\r\n' +
+                'Set-Cookie: '
+                'violation="http://www.ietf.org/rfc/rfc2616.txt"\r\n')
 
 
 def test_suite():



More information about the Zope-Checkins mailing list