[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher/HTTP - DefaultPublisher.py:1.2 HTTPRequest.py:1.2 HTTPResponse.py:1.2 IHTTPApplicationRequest.py:1.2 IHTTPApplicationResponse.py:1.2 IHTTPCredentials.py:1.2 IHTTPPublisher.py:1.2 IHTTPRequest.py:1.2 IHTTPResponse.py:1.2 __init__.py:1.2 http.zcml:1.2

Jim Fulton jim@zope.com
Mon, 10 Jun 2002 19:30:05 -0400


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

Added Files:
	DefaultPublisher.py HTTPRequest.py HTTPResponse.py 
	IHTTPApplicationRequest.py IHTTPApplicationResponse.py 
	IHTTPCredentials.py IHTTPPublisher.py IHTTPRequest.py 
	IHTTPResponse.py __init__.py http.zcml 
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.

=== Zope3/lib/python/Zope/Publisher/HTTP/DefaultPublisher.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""blisher.py,v 1.1.2.2 2002/04/02 02:20:33 srichter Exp $
+"""
+from IHTTPPublisher import IHTTPPublisher
+
+
+class DefaultPublisher:
+
+    __implements__ =  IHTTPPublisher
+
+    ############################################################
+    # Implementation methods for interface
+    # Zope.Publisher.HTTP.IHTTPPublisher
+
+    def publishTraverse(self, request, name):
+        'See Zope.Publisher.HTTP.IHTTPPublisher.IHTTPPublisher'
+
+        return getattr(self, name)
+
+    #
+    ############################################################


=== Zope3/lib/python/Zope/Publisher/HTTP/HTTPRequest.py 1.1 => 1.2 === (432/532 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$
+"""
+
+import re, time, random
+from urllib import quote, splitport
+from types import StringType
+
+from Zope.Publisher.BaseRequest import BaseRequest
+
+from HTTPResponse import HTTPResponse
+from IHTTPCredentials import IHTTPCredentials
+from IHTTPRequest import IHTTPRequest
+from IHTTPApplicationRequest import IHTTPApplicationRequest
+
+from Zope.Publisher.RequestDataProperty \
+     import RequestDataProperty, RequestDataMapper, RequestDataGetter
+
+class CookieMapper(RequestDataMapper):
+    _mapname = '_cookies'
+
+class HeaderGetter(RequestDataGetter):
+    _gettrname = 'getHeader'
+
+_marker = object()
+
+class URLGetter:
+
+    def __init__(self, request):
+        self.__request = request
+
+    def __str__(self):
+        return self.__request.getURL()
+
+    def __getitem__(self, name):
+        i = int(name)
+        try:

[-=- -=- -=- 432 lines omitted -=- -=- -=-]

+    for key, val in env.items():
+        while key.startswith('REDIRECT_'):
+            key=key[9:]
+        dict[key]=val
+    if 'HTTP_CGI_AUTHORIZATION' in dict:
+        dict['HTTP_AUTHORIZATION']=dict['HTTP_CGI_AUTHORIZATION']
+        try: del dict['HTTP_CGI_AUTHORIZATION']
+        except: pass
+    return dict
+
+
+def parse_cookie(
+    text,
+    result=None,
+    qparmre=re.compile(
+    '([\x00- ]*([^\x00- ;,="]+)="([^"]*)"([\x00- ]*[;,])?[\x00- ]*)'),
+    parmre=re.compile(
+    '([\x00- ]*([^\x00- ;,="]+)=([^\x00- ;,"]*)([\x00- ]*[;,])?[\x00- ]*)'),
+    ):
+
+    if result is None: result={}
+    already_have=result.has_key
+
+    mo_q = qparmre.match(text)
+
+    if mo_q:
+        # Match quoted correct cookies
+
+        l     = len(mo_q.group(1))
+        name  = mo_q.group(2)
+        value = mo_q.group(3)
+
+    else:
+        # Match evil MSIE cookies ;)
+
+        mo_p = parmre.match(text)
+
+        if mo_p:
+            l     = len(mo_p.group(1))
+            name  = mo_p.group(2)
+            value = mo_p.group(3)
+
+        else: 
+            return result 
+
+    if not already_have(name): result[name]=value
+
+    return apply(parse_cookie,(text[l:],result))
+
+


=== Zope3/lib/python/Zope/Publisher/HTTP/HTTPResponse.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+'''HTTP Response Output formatter
+
+$Id$'''
+
+import sys, re
+from types import StringType, ClassType
+from cgi import escape
+
+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
+
+# Possible HTTP status responses
+status_reasons = {
+100: 'Continue',
+101: 'Switching Protocols',
+102: 'Processing',
+200: 'OK',
+201: 'Created',
+202: 'Accepted',
+203: 'Non-Authoritative Information',
+204: 'No Content',
+205: 'Reset Content',
+206: 'Partial Content',
+207: 'Multi-Status',
+300: 'Multiple Choices',
+301: 'Moved Permanently',
+302: 'Moved Temporarily',
+303: 'See Other',
+304: 'Not Modified',
+305: 'Use Proxy',
+307: 'Temporary Redirect',
+400: 'Bad Request',
+401: 'Unauthorized',
+402: 'Payment Required',
+403: 'Forbidden',
+404: 'Not Found',
+405: 'Method Not Allowed',
+406: 'Not Acceptable',
+407: 'Proxy Authentication Required',
+408: 'Request Time-out',
+409: 'Conflict',
+410: 'Gone',
+411: 'Length Required',
+412: 'Precondition Failed',
+413: 'Request Entity Too Large',
+414: 'Request-URI Too Large',
+415: 'Unsupported Media Type',
+416: 'Requested range not satisfiable',
+417: 'Expectation Failed',
+422: 'Unprocessable Entity',
+423: 'Locked',
+424: 'Failed Dependency',
+500: 'Internal Server Error',
+501: 'Not Implemented',
+502: 'Bad Gateway',
+503: 'Service Unavailable',
+504: 'Gateway Time-out',
+505: 'HTTP Version not supported',
+507: 'Insufficient Storage',
+}
+
+status_codes={}
+# Add mappings for builtin exceptions and
+# provide text -> error code lookups.
+for key, val in status_reasons.items():
+    status_codes[val.replace(' ', '').lower()] = key
+    status_codes[val.lower()] = key
+    status_codes[key] = key
+    status_codes[str(key)] = key
+
+en = [n.lower() for n in dir(__builtins__) if n.endswith('Error')]
+
+for name in en:
+    status_codes[name] = 500
+
+
+accumulate_header = {'set-cookie': 1}.has_key
+
+
+
+class HTTPResponse (BaseResponse):
+
+    __implements__ = IHTTPResponse, IHTTPApplicationResponse, \
+                     BaseResponse.__implements__
+
+    __slots__ = (
+        '_header_output',       # Hook object to collaborate with a server
+                                # for header generation. 
+        '_headers',
+        '_cookies',
+        '_accumulated_headers', # Headers that can have multiples
+        '_wrote_headers',
+        '_streaming',
+        '_status',              # The response status (usually an integer)
+        '_reason',              # The reason that goes with the status
+        '_status_set',          # Boolean: status explicitly set
+        )
+
+
+    def __init__(self, outstream, header_output = None):
+        self._header_output = header_output
+
+        super(HTTPResponse, self).__init__(outstream)
+        self._headers = {} 
+        self._cookies = {} 
+        self._accumulated_headers = []
+        self._wrote_headers = 0
+        self._streaming = 0
+        self._status = 599
+        self._reason = 'No status set'
+        self._status_set = 0
+
+
+    def setHeaderOutput(self, header_output):
+        self._header_output = header_output
+        
+
+    ############################################################
+    # Implementation methods for interface
+    # Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse
+
+    def setStatus(self, status, reason=None):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        if status is None:
+            status = 200
+        else:
+            if isinstance(status, StringType):
+                status = status.lower()
+            if status in status_codes:
+                status = status_codes[status]
+            else:
+                status = 500
+        self._status = status
+
+        if reason is None:
+            if status == 200:
+                reason = 'Ok'
+            elif status in status_reasons:
+                reason = status_reasons[status]
+            else:
+                reason = 'Unknown'
+        self._reason = reason
+        self._status_set = 1
+
+
+    def getStatus(self):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        return self._status
+
+
+    def setHeader(self, name, value, literal=0):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        key = name.lower()
+        if accumulate_header(key):
+            self.addHeader(name, value)
+        else:
+            name = literal and name or key
+            self._headers[name]=value
+
+
+    def addHeader(self, name, value):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        accum = self._accumulated_headers
+        accum.append('%s: %s' % (name, value))
+
+
+    def getHeader(self, name, default=None):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        return self._headers.get(name, default)
+
+
+    def getHeaders(self):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        result = {}
+        headers = self._headers
+
+        if (not self._streaming and not ('content-length' in headers)
+            and not ('transfer-encoding' in headers)):
+            self._updateContentLength()
+
+        result["X-Powered-By"] = "Zope (www.zope.org), Python (www.python.org)"
+
+        for key, val in headers.items():
+            if key.lower() == key:
+                # only change non-literal header names
+                key = key.capitalize()
+                start = 0
+                location = key.find('-', start)
+                while location >= start:
+                    key = "%s-%s" % (key[:location],
+                                     key[location+1:].capitalize())
+                    start = location + 1
+                    location = key.find('-', start)
+            result[key] = val
+
+        return result
+
+
+    def appendToHeader(self, name, value, delimiter=','):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        headers = self._headers
+        if name in headers:
+            h = self._header[name]
+            h = "%s%s\r\n\t%s" % (h, delimiter, value)
+        else: h = value
+        self.setHeader(name, h)
+
+
+    def appendToCookie(self, name, value):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        cookies = self._cookies
+        if name in cookies:
+            cookie = cookies[name]
+        else: cookie = cookies[name] = {}
+        if 'value' in cookie:
+            cookie['value'] = '%s:%s' % (cookie['value'], value)
+        else: cookie['value'] = value
+
+
+    def expireCookie(self, name, **kw):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+        dict={'max_age':0, 'expires':'Wed, 31-Dec-97 23:59:59 GMT'}
+        for k, v in kw.items():
+            dict[k]=v
+        cookies=self._cookies
+        if name in cookies:
+            # Cancel previous setCookie().
+            del cookies[name]
+        self.setCookie(name, 'deleted', **dict)
+
+
+    def setCookie(self, name, value, **kw):
+        'See Zope.Publisher.HTTP.IHTTPResponse.IHTTPResponse'
+
+        cookies=self._cookies
+        if name in cookies:
+            cookie=cookies[name]
+        else:
+            cookie=cookies[name]={}
+
+        for k, v in kw.items():
+            cookie[k]=v
+
+        cookie['value']=value
+
+    #
+    ############################################################
+
+    ############################################################
+    # Implementation methods for interface
+    # Zope.Publisher.BaseResponse.IResponse
+
+    ######################################
+    # from: Zope.Publisher.IPublisherResponse.IPublisherResponse
+
+    def setBody(self, body):
+        self._body = body
+        if not self._status_set:
+            self.setStatus(200)
+
+    def handleException(self, exc_info):
+        """
+        Calls self.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 = ''.join(format_exception(t, v, exc_info[2], as_html=1))
+        body = self._html(title, "%s" % tb)
+        self.setBody(body)
+
+
+    def internalError(self):
+        'See Zope.Publisher.IPublisherResponse.IPublisherResponse'
+        self.setStatus(500, "The engines can't take any more, Jim!")
+
+
+    def _html(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 retry(self):
+        """
+        Returns a response object to be used in a retry attempt
+        """
+        return self.__class__(self._outstream,
+                              self._header_output)
+
+    def _updateContentLength(self):
+        blen = str(len(self._body))
+        if blen.endswith('L'):
+            blen = blen[:-1]
+        self.setHeader('content-length', blen)
+
+    def redirect(self, location, status=302):
+        """Causes a redirection without raising an error"""
+        self.setStatus(status)
+        self.setHeader('Location', location)
+        return location
+
+    def _cookie_list(self):
+        cookie_list = []
+        for name, attrs in self._cookies.items():
+
+            # Note that as of May 98, IE4 ignores cookies with
+            # quoted cookie attr values, so only the value part
+            # of name=value pairs may be quoted.
+
+            cookie='Set-Cookie: %s="%s"' % (name, attrs['value'])
+            for name, value in attrs.items():
+                name = name.lower()
+                if name == 'expires':
+                    cookie = '%s; Expires=%s' % (cookie,value)
+                elif name == 'domain':
+                    cookie = '%s; Domain=%s' % (cookie,value)
+                elif name == 'path':
+                    cookie = '%s; Path=%s' % (cookie,value)
+                elif name == 'max_age':
+                    cookie = '%s; Max-Age=%s' % (cookie,value)
+                elif name == 'comment':
+                    cookie = '%s; Comment=%s' % (cookie,value)
+                elif name == 'secure' and value:
+                    cookie = '%s; Secure' % cookie
+            cookie_list.append(cookie)
+
+        # XXX: Should really check size of cookies here!
+        
+        return cookie_list
+
+
+    def getHeaderText(self, m):
+        lst = ['Status: %s %s' % (self._status, self._reason)]
+        items = m.items()
+        items.sort()
+        lst.extend(map(lambda x: '%s: %s' % x, items))
+        lst.extend(self._cookie_list())
+        lst.extend(self._accumulated_headers)
+        return ('%s\r\n\r\n' % '\r\n'.join(lst))
+
+
+    def outputHeaders(self):
+        headers = self.getHeaders()
+        header_output = self._header_output
+        if header_output is not None:
+            # Use the IHeaderOutput interface.
+            header_output.setResponseStatus(self._status, self._reason)
+            header_output.setResponseHeaders(headers)
+            header_output.appendResponseHeaders(self._cookie_list())
+            header_output.appendResponseHeaders(self._accumulated_headers)
+        else:
+            # Write directly to outstream.
+            headers_text = self.getHeaderText(headers)
+            self._outstream.write(headers_text)
+
+
+    ######################################
+    # from: Zope.Publisher.IApplicationResponse.IApplicationResponse
+
+    # XXX: Mmh, it seems that write has a different meaning here
+    #      compared to BaseResponse
+
+    def write(self, string):
+        """See Zope.Publisher.IApplicationResponse.IApplicationResponse
+
+        Return data as a stream
+
+        HTML data may be returned using a stream-oriented interface.
+        This allows the browser to display partial results while
+        computation of a response to proceed.
+
+        The published object should first set any output headers or
+        cookies on the response object.
+
+        Note that published objects must not generate any errors
+        after beginning stream-oriented output. 
+
+        """
+        if streaming:
+            self._streaming = 1
+        self.output(string)
+
+    #
+    ############################################################
+
+
+    def output(self, data):
+        if not self._wrote_headers:
+            self.outputHeaders()
+            self._wrote_headers = 1
+        self._outstream.write(data)
+
+    def outputBody(self):
+        """
+        Outputs the response body.
+        """
+        self.output(self._body)
+
+
+    def _formatException(etype, value, tb, limit=None):
+        import traceback
+        result=['Traceback (innermost last):']
+        if limit is None:
+            if hasattr(sys, 'tracebacklimit'):
+                limit = sys.tracebacklimit
+        n = 0
+        while tb is not None and (limit is None or n < limit):
+            frame = tb.tb_frame
+            lineno = tb.tb_lineno
+            co = frame.f_code
+            filename = co.co_filename
+            name = co.co_name
+            locals = frame.f_locals
+            globals = frame.f_globals
+            modname = globals.get('__name__', filename)
+            result.append('  Module %s, line %d, in %s'
+                          % (modname,lineno,name))
+            try:
+                result.append('    (Object: %s)' %
+                               locals[co.co_varnames[0]].__name__)
+            except:
+                pass
+
+            try:
+                result.append('    (Info: %s)' %
+                               str(locals['__traceback_info__']))
+            except: pass
+            tb = tb.tb_next
+            n = n+1
+        result.append(' '.join(traceback.format_exception_only(etype, value)))
+        return result
+
+
+    def _createTracebackString(self, t, v, tb):
+        tb = self._formatException(t, v, tb, 200)
+        return '\n'.join(tb)


=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPApplicationRequest.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Zope.Publisher.IApplicationRequest import IApplicationRequest
+from Interface.Attribute import Attribute
+
+class IHTTPApplicationRequest(IApplicationRequest):
+    """HTTP request data.
+    
+    This object provides access to request data.  This includes, the
+    input headers, server data, and cookies.
+
+    Request objects are created by the object publisher and will be
+    passed to published objects through the argument name, REQUEST.
+
+    The request object is a mapping object that represents a
+    collection of variable to value mappings.  In addition, variables
+    are divided into four categories:
+
+      - Environment variables
+
+        These variables include input headers, server data, and other
+        request-related data.  The variable names are as <a
+        href="http://hoohoo.ncsa.uiuc.edu/cgi/env.html">specified</a>
+        in the <a
+        href="http://hoohoo.ncsa.uiuc.edu/cgi/interface.html">CGI
+        specification</a>
+
+      - Cookies
+
+        These are the cookie data, if present.
+
+      - Other
+
+        Data that may be set by an application object.
+
+    The request object may be used as a mapping object, in which case
+    values will be looked up in the order: environment variables,
+    other variables, cookies, and special.    
+    """
+
+    def __getitem__(key):
+        """Return HTTP request data 
+
+        Request data sre retrieved from one of:
+
+        - Environment variables
+
+          These variables include input headers, server data, and other
+          request-related data.  The variable names are as <a
+          href="http://hoohoo.ncsa.uiuc.edu/cgi/env.html">specified</a>
+          in the <a
+          href="http://hoohoo.ncsa.uiuc.edu/cgi/interface.html">CGI
+          specification</a>
+
+        - Cookies
+
+          These are the cookie data, if present.
+
+        Cookies are searched before environmental data.
+        """
+
+    def getCookies():
+        """Return the cookie data
+
+        Data are returned as a mapping object, mapping cookie name to value.
+        """
+
+        return IMapping(str, str)
+
+    cookies = Attribute(
+        """Request cookie data
+
+        This is a read-only mapping from variable name to value.
+        """)
+
+    def getHeader(name, default=None):
+        """Get a header value
+
+        Return the named HTTP header, or an optional default
+        argument or None if the header is not found. Note that
+        both original and CGI-ified header names are recognized,
+        e.g. 'Content-Type', 'CONTENT_TYPE' and 'HTTP_CONTENT_TYPE'
+        should all return the Content-Type header, if available.
+        """
+
+    headers = Attribute(
+        """Request header data
+
+        This is a read-only mapping from variable name to value.
+        """)
+
+    URL = Attribute(
+        """Request URL data
+
+        When convered to a string, this gives the effective published URL.
+
+        This is object can also be used as a mapping object. The keys
+        must be integers or strings that can be converted to
+        integers. A non-negative integer returns a URL n steps from
+        the URL of the top-level application objects. A negative
+        integer gives a URL that is -n steps back from the effective
+        URL.
+
+        For example, 'request.URL[-2]' is equivalent to the Zope 2
+        'request["URL2"]'. The notion is that this would be used in
+        path expressions, like 'request/URL/-2'.
+        """)
+        
+
+    def getURL(level=0, path_only=0):
+        """Return the published URL with level names removed from the end.
+
+        If path_only is true, then only a path will be returned.
+        """
+
+    def getApplicationURL(depth=0, path_only=0):
+        """Return the application URL plus depth steps
+
+        If path_only is true, then only a path will be returned.
+        """
+
+    


=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPApplicationResponse.py 1.1 => 1.2 ===
+#
+# 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$
+"""
+
+from Zope.Publisher.IApplicationResponse import IApplicationResponse
+from Interface.Attribute import Attribute
+
+
+class IHTTPApplicationResponse(IApplicationResponse):
+    """HTTP Response
+    """
+
+    def redirect(location, status=302):
+        """Causes a redirection without raising an error.
+        """
+
+


=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPCredentials.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+from Interface import Interface
+
+class IHTTPCredentials(Interface):
+
+    # XXX Eventially this will be a different method
+    def _authUserPW():
+        """Return (login, password) if there are basic credentials;
+        return None if there aren't."""
+
+    def unauthorized(challenge):
+        """Issue a 401 Unauthorized error (asking for login/password).
+        The challenge is the value of the WWW-Authenticate header."""


=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPPublisher.py 1.1 => 1.2 ===
+#
+# 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$
+"""
+
+from Interface import Interface
+
+class IHTTPPublisher(Interface):
+
+    def publishTraverse(request, name):
+        """Lookup a name
+
+        The request argument is the publisher request object.
+        """


=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPRequest.py 1.1 => 1.2 ===
+#
+# 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$
+"""
+
+from Interface import Interface
+
+
+# XXX Should we extend IRequest?
+
+class IHTTPRequest(Interface):
+
+    def setPathSuffix(steps):
+        """Add additional traversal steps to be taken after all other traversal
+
+        This is used to handle HTTP request methods (except for GET
+        and POST in the case of browser requests) and XML-RPC methods.
+        """
+
+    
+
+


=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPResponse.py 1.1 => 1.2 ===
+#
+# 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$
+"""
+
+from Interface import Interface
+
+
+class IHTTPResponse(Interface):
+    """An object representation of an HTTP response.
+    
+    The Response type encapsulates all possible responses to HTTP
+    requests.  Responses are normally created by the object publisher.
+    A published object may recieve the response object as an argument
+    named 'RESPONSE'.  A published object may also create it's own
+    response object.  Normally, published objects use response objects
+    to:
+
+    - Provide specific control over output headers,
+
+    - Set cookies, or
+
+    - Provide stream-oriented output.
+
+    If stream oriented output is used, then the response object
+    passed into the object must be used.
+    """
+
+    def getStatus():
+        """Returns the current HTTP status code as an integer.
+        """
+
+
+    def setStatus(status, reason=None):
+        """Sets the HTTP status code of the response
+
+        The argument may either be an integer or a string from { OK,
+        Created, Accepted, NoContent, MovedPermanently,
+        MovedTemporarily, NotModified, BadRequest, Unauthorized,
+        Forbidden, NotFound, InternalError, NotImplemented,
+        BadGateway, ServiceUnavailable } that will be converted to the
+        correct integer value.
+        """
+
+
+    def setHeader(name, value, literal=0):
+        """Sets an HTTP return header "name" with value "value"
+
+        The previous value is cleared. If the literal flag is true,
+        the case of the header name is preserved, otherwise
+        word-capitalization will be performed on the header name on
+        output.        
+        """
+
+
+    def addHeader(name, value):
+        """Add an HTTP Header
+        
+        Sets a new HTTP return header with the given value, while retaining
+        any previously set headers with the same name.
+
+        """
+
+
+    def getHeader(name, default=None):
+         """Gets a header value
+         
+         Returns the value associated with a HTTP return header, or
+         'default' if no such header has been set in the response
+         yet.
+         """
+
+
+    def getHeaders():
+        """Returns a mapping of correctly-cased header names to values.
+        """
+        
+
+    def appendToCookie(name, value):
+        """Append text to a cookie value
+        
+        If a value for the cookie has previously been set, the new
+        value is appended to the old one separated by a colon.
+        """
+
+
+    def expireCookie(name, **kw):
+        """Causes an HTTP cookie to be removed from the browser
+        
+        The response will include an HTTP header that will remove the cookie
+        corresponding to "name" on the client, if one exists. This is
+        accomplished by sending a new cookie with an expiration date
+        that has already passed. Note that some clients require a path
+        to be specified - this path must exactly match the path given
+        when creating the cookie. The path can be specified as a keyword
+        argument.
+        """
+
+
+    def setCookie(name, value, **kw):
+        """Sets an HTTP cookie on the browser
+
+        The response will include an HTTP header that sets a cookie on
+        cookie-enabled browsers with a key "name" and value
+        "value". This overwrites any previously set value for the
+        cookie in the Response object.
+        """
+
+    def appendToHeader(name, value, delimiter=","):
+        """Appends a value to a header
+        
+        Sets an HTTP return header "name" with value "value",
+        appending it following a comma if there was a previous value
+        set for the header.
+
+        """


=== Zope3/lib/python/Zope/Publisher/HTTP/__init__.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+HTTP publisher
+"""


=== Zope3/lib/python/Zope/Publisher/HTTP/http.zcml 1.1 => 1.2 ===
+   xmlns='http://namespaces.zope.org/zope'
+   xmlns:security='http://namespaces.zope.org/security'
+>
+
+  <content class=".HTTPRequest.">
+    <security:require
+        permission="Zope.View"
+        interface=".IHTTPApplicationRequest."/>
+  </content>
+
+  <content class=".HTTPRequest.URLGetter">
+    <security:require
+        permission="Zope.View" 
+        attributes="get __getitem__ __str__" />
+  </content>
+
+</zopeConfigure>