[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>