[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher/Browser - BrowserRequest.py:1.1.2.1 BrowserResponse.py:1.1.2.1 IBrowserRequest.py:1.1.2.1 IVirtualHostRequest.py:1.1.2.1 Request.py:NONE Response.py:NONE

Stephan Richter srichter@cbu.edu
Sun, 24 Mar 2002 13:34:49 -0500


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

Added Files:
      Tag: Zope3-publisher-refactor-branch
	BrowserRequest.py BrowserResponse.py IBrowserRequest.py 
	IVirtualHostRequest.py 
Removed Files:
      Tag: Zope3-publisher-refactor-branch
	Request.py Response.py 
Log Message:
Continued refactoring:

- I think everything in ./HTTP and ./Browser is now refactored and I 
  created some interfaces to support that.

- Jim should probably look over at the refactoring again.

- Tests are still needed everywhere and the code in general is probably 
  horribly broken.

Note: This is being committed, so that other people (i.e. Jim) can also 
      keep working on this branch.



=== Added File Zope3/lib/python/Zope/Publisher/Browser/BrowserRequest.py === (611/711 lines abridged)
##############################################################################
#
# 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
# 
##############################################################################
"""

$Id: BrowserRequest.py,v 1.1.2.1 2002/03/24 18:34:48 srichter Exp $
"""

from urllib import quote, unquote, splittype, splitport
from cgi_names import isCGI_NAME, hide_key
from Zope.Publisher.Converters import get_converter
from Zope.Publisher.HTTP.HTTPRequest import HTTPRequest

from IBrowserRequest import IBrowserRequest

# Flas Constants
SEQUENCE = 1,
DEFAULT = 2,
RECORD = 4,
RECORDS = 8,
REC = 12, # RECORD|RECORDS
EMPTY = 16,
CONVERTED = 32,

search_type = re.compile('(:[a-zA-Z][a-zA-Z0-9_]+|\\.[xy])$').search


class BrowserRequest(HTTPRequest):

    __implements__ = IBrowserRequest


    __computed_urls = ()   # Names of computed URLx variables
    __script = ()          # SERVER_URL + __script + quoted_steps == full URL
    __server_script = ''   # __server_script + quoted_steps = full URL
    __server_url = ''      # Possible munged server_url


    # _viewtype is overridden from the BaseRequest 
    #  to implement IBrowserPublisher

[-=- -=- -=- 611 lines omitted -=- -=- -=-]

            environ=self.environ
            if environ.has_key(key) and (not hide_key(key)):
                return environ[key]
            return ''

        if v is _marker:
            v = self.common.get(key, _marker)

        return default

    get.__permission__ = 'Zope.Public'

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



    def _resetURLs(self):
        self.URL = '/'.join(
            [self.getServerURL()] + self._script + self.quoted_steps)
        for x in self._computed_urls:
            del self.other[x]
        self._computed_urls = ()


    def _deduceServerURL(self):
        environ = self.environ
        have_env = environ.has_key

        if have_env('HTTPS') and (
            environ['HTTPS'] == "on" or environ['HTTPS'] == "ON"):
            protocol = 'https'

        elif (have_env('SERVER_PORT_SECURE') and 
              environ['SERVER_PORT_SECURE'] == "1"):
            protocol = 'https'
        else: protocol = 'http'

        if have_env('HTTP_HOST'):
            host = environ['HTTP_HOST'].strip()
            hostname, port = splitport(host)

        else:
            hostname = environ.get('SERVER_NAME', '').strip()
            port = environ.get('SERVER_PORT', '')
        self.setServerURL(protocol=protocol, hostname=hostname, port=port)
        return self.getServerURL()

    
    _key_handlers = BaseRequest._key_handlers.copy()


=== Added File Zope3/lib/python/Zope/Publisher/Browser/BrowserResponse.py ===
# Copyright (c) 2001 Zope Corporation and Contributors.  All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (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.

'''HTTP Response Output formatter

$Id: BrowserResponse.py,v 1.1.2.1 2002/03/24 18:34:48 srichter Exp $'''
__version__='$Revision: 1.1.2.1 $'[11:-2]

import sys, re
from types import StringType, ClassType
from cgi import escape

from Zope.Publisher.HTTP.HTTPResponse import HTTPResponse
from Zope.Publisher.Exceptions import Redirect


start_of_header_search=re.compile('(<head[^>]*>)', re.IGNORECASE).search
base_re_search=re.compile('(<base.*?>)',re.I).search


class BrowserResponse(HTTPResponse):
    """ """

    def setBody(self, body):
        """
        Sets the body of the response
        
        Sets the return body equal to the (string) argument "body". Also
        updates the "content-length" return header.

        If the body is a 2-element tuple, then it will be treated
        as (title,body)
        
        If is_error is true then the HTML will be formatted as a Zope error
        message instead of a generic HTML page.
        """
        body = str(body)

        if not response.headers.has_key('content-type'):
            c = (self.__isHTML(body) and 'text/html' or 'text/plain')
            response.setHeader('content-type', c)

        content_type = response.headers['content-type']
        if is_text_html(content_type):
            # Some browsers interpret certain characters in Latin 1 as html
            # special characters. These cannot be removed by html_quote,
            # because this is not the case for all encodings.
            body = body.replace('\213', '&lt;')
            body = body.replace('\233', '&gt;')

        body = self.__insertBase(response, body)
        self._body = body
        self._updateContentLength()
        return response


    def handleException(self, exc_info):
        """
        Calls response.setBody() with an error response.
        """
        t, v = exc_info[:2]
        if isinstance(t, ClassType):
            title = tname = t.__name__
            if issubclass(t, Redirect):
                self.redirect(v.getLocation())
                return
        else:
            title = tname = str(t)

        # Throwing non-protocol-specific exceptions is a good way
        # for apps to control the status code.
        self.setStatus(tname)

        tb = escape(traceback_string(t, v, exc_info[2]))
        body = self.__wrapInHTML(title, "<pre>\n%s\n</pre>" % tb)
        self.setBody(body)


    def __isHTML(self, str):
        s = str.strip().lower()
        return s.startswith('<html>') or s.startswith('<!doctype html')


    def __wrapInHTML(self, title, content):
        t = escape(title)
        return (
            "<html><head><title>%s</title></head>\n"
            "<body><h2>%s</h2>\n"
            "%s\n"
            "</body></html>\n" %
            (t, t, content)
            )


    def __insertBase(self, body):
        # Only insert a base tag if content appears to be html.
        content_type = self.getHeader('content-type', '')
        if content_type and content_type != 'text/html':
            return body

        if self.base:
            if body:
                match = start_of_header_search(body)
                if match is not None:
                    index = match.start(0) + len(match.group(0))
                    ibase = base_re_search(body)
                    if ibase is None:
                        body = ('%s\n<base href="%s" />\n%s' %
                                (body[:index], self.base, body[index:]))
        return body


=== Added File Zope3/lib/python/Zope/Publisher/Browser/IBrowserRequest.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
# 
##############################################################################
"""

$Id: IBrowserRequest.py,v 1.1.2.1 2002/03/24 18:34:48 srichter Exp $
"""

from Zope.Publisher.HTTP.IHTTPRequest import IHTTPRequest
from IVirtualHostRequest import IVirtualHostRequest


class IBrowserRequest(IHTTPRequest, IVirtualHostRequest):
    """Browser-specific Rquest functionality.

    Note that the browser is special in many ways, since it exposes
    the Request object to the end-developer.
    """

    def computeURLn(key, n, pathonly):
        """Compute the nth URL of the path.
        """
        

    def computeBASEn(key, n, pathonly):
        """Compute the nth BASE of the path.
        """


    def setServerURL(protocol=None, hostname=None, port=None):
        """Set the parts of generated URLs.
        """


    def getServerURL(self, defaut=None):
        """Get the Server URL string.
        """


=== Added File Zope3/lib/python/Zope/Publisher/Browser/IVirtualHostRequest.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
# 
##############################################################################
"""

$Id: IVirtualHostRequest.py,v 1.1.2.1 2002/03/24 18:34:48 srichter Exp $
"""

from Interface import Interface

class IVirtualHostRequest(Interface):
    """The support for virtual hosts in Zope is very important.

    In order to make virtual hosts working, we need to support several
    methods in our Request object. This interface defines the required
    methods.
    """

    def setVirtualRoot(path, hard=0):
        """Treat the current publishing object as a VirtualRoot.
        """


    def convertPhysicalPathToVirtualPath(path):
        """Remove the path to the VirtualRoot from a physical path.
        """


    def convertPhysicalPathToURL(path, relative=0):
        """Convert a physical path into a URL in the current context.
        """


    def getPhysicalPathFromURL(URL):
        """Convert a URL into a physical path in the current context.

        If the URL makes no sense in light of the current virtual
        hosting context, a ValueError is raised.
        """

    def getEffectiveURL(self):
        """Return the effective URL.
        """

=== Removed File Zope3/lib/python/Zope/Publisher/Browser/Request.py ===

=== Removed File Zope3/lib/python/Zope/Publisher/Browser/Response.py ===