[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher/HTTP - HTTPCharsets.py:1.1.2.1 HTTPRequest.py:1.3.2.1 HTTPResponse.py:1.3.2.1 IHTTPResponse.py:1.2.2.1

Stephan Richter srichter@cbu.edu
Fri, 14 Jun 2002 10:49:03 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/Publisher/HTTP
In directory cvs.zope.org:/tmp/cvs-serv20580/lib/python/Zope/Publisher/HTTP

Modified Files:
      Tag: srichter-z3-unicode-branch
	HTTPRequest.py HTTPResponse.py IHTTPResponse.py 
Added Files:
      Tag: srichter-z3-unicode-branch
	HTTPCharsets.py 
Log Message:
Branch-specifc commit, so that Barry and Fred can help me debug the existing
errors.


=== Added File Zope3/lib/python/Zope/Publisher/HTTP/HTTPCharsets.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Retrieval of browser character set information.

$Id: HTTPCharsets.py,v 1.1.2.1 2002/06/14 14:48:33 srichter Exp $
"""

from Zope.I18n.IUserPreferredCharsets import IUserPreferredCharsets


def sort_charsets(x, y):
    if y[1] == 'UTF-8':
        return 1
    if x[1] == 'UTF-8':
        return -1    
    return cmp(y, x)


class HTTPCharsets:

    __implements__ =  IUserPreferredCharsets

    def __init__(self, request):
        self.request = request

    ############################################################
    # Implementation methods for interface
    # Zope.I18n.IUserPreferredCharsets.

    def getPreferredCharsets(self):
        '''See interface IUserPreferredCharsets'''
        charsets = []
        for charset in self.request.get('HTTP_ACCEPT_CHARSET', '').split(','):
            charset = charset.strip()
            if charset:
                if ';' in charset:
                    charset, quality = charset.split(';')
                    quality = float(quality[2:])
                else:
                    quality = 1.0
                charsets.append((quality, charset))
        # UTF-8 is **always** preferred over anything else
        charsets.sort(sort_charsets)
        return map(lambda c: c[1], charsets)

    #
    ############################################################


=== Zope3/lib/python/Zope/Publisher/HTTP/HTTPRequest.py 1.3 => 1.3.2.1 ===
         self.__setupURLBase()
 
+        self.getResponse().setCharsetUsingRequest(self)
+
+
     def __setupURLBase(self):
 
         get_env = self._environ.get


=== Zope3/lib/python/Zope/Publisher/HTTP/HTTPResponse.py 1.3 => 1.3.2.1 ===
 
 import sys, re
-from types import StringType, ClassType
+from types import StringType, UnicodeType, ClassType
 from cgi import escape
 
+from Zope.ComponentArchitecture import getAdapter
+
 from Zope.Publisher.BaseResponse import BaseResponse
 from Zope.Publisher.Exceptions import Redirect
 from IHTTPResponse import IHTTPResponse
 from IHTTPApplicationResponse import IHTTPApplicationResponse
 from Zope.Exceptions.ExceptionFormatter import format_exception
+from Zope.I18n.IUserPreferredCharsets import IUserPreferredCharsets
 
 # Possible HTTP status responses
 status_reasons = {
@@ -110,6 +113,7 @@
         '_status',              # The response status (usually an integer)
         '_reason',              # The reason that goes with the status
         '_status_set',          # Boolean: status explicitly set
+        '_charset',             # String: character set for the output
         )
 
 
@@ -125,7 +129,8 @@
         self._status = 599
         self._reason = 'No status set'
         self._status_set = 0
-
+        self._charset = None
+        
 
     def setHeaderOutput(self, header_output):
         self._header_output = header_output
@@ -263,6 +268,21 @@
 
         cookie['value']=value
 
+
+    def setCharset(self, charset=None):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        self._charset = charset
+
+
+    def setCharsetUsingRequest(self, request):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        envadaptor = getAdapter(request, IUserPreferredCharsets)
+        try:
+            charset = envadaptor.getPreferredCharsets()[0]
+        except:
+            charset = 'UTF-8'
+        self.setCharset(charset)
+
     #
     ############################################################
 
@@ -274,7 +294,7 @@
     # from: Zope.Publisher.IPublisherResponse.IPublisherResponse
 
     def setBody(self, body):
-        self._body = str(body)
+        self._body = unicode(body)
         if not self._status_set:
             self.setStatus(200)
 
@@ -289,7 +309,7 @@
                 self.redirect(v.getLocation())
                 return
         else:
-            title = tname = str(t)
+            title = tname = unicode(t)
 
         # Throwing non-protocol-specific exceptions is a good way
         # for apps to control the status code.
@@ -424,8 +444,15 @@
         if not self._wrote_headers:
             self.outputHeaders()
             self._wrote_headers = 1
+
+        if self.getHeader('content-type', '').startswith('text') and \
+               self._charset is not None and \
+               type(data) is UnicodeType:
+            data = data.encode(self._charset)
+
         self._outstream.write(data)
 
+
     def outputBody(self):
         """
         Outputs the response body.
@@ -459,7 +486,7 @@
 
             try:
                 result.append('    (Info: %s)' %
-                               str(locals['__traceback_info__']))
+                               unicode(locals['__traceback_info__']))
             except: pass
             tb = tb.tb_next
             n = n+1


=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPResponse.py 1.2 => 1.2.2.1 ===
 
         """
+
+    def setCharset(charset=None):
+        """Set the character set into which the response body should be
+           encoded. If None is passed in then no encoding will be done to
+           the output body.
+
+           The default character set is None.
+        """
+
+    def setCharsetUsingRequest(request):
+        """This convinience function determines the character set based on the
+           HTTP header information.
+        """