[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher/Browser - BrowserRequest.py:1.1.4.1 BrowserResponse.py:1.1.4.1 IBrowserApplicationRequest.py:1.1.2.3 IBrowserPublication.py:1.1.4.1 IBrowserRequest.py:1.1.4.1 IVirtualHostRequest.py:1.1.4.1 cgi_names.py:1.1.4.1 AttributePublisher.py:1.1.2.10 IBrowserPublisher.py:1.1.2.7
Jim Fulton
jim@zope.com
Tue, 26 Mar 2002 16:26:29 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/Publisher/Browser
In directory cvs.zope.org:/tmp/cvs-serv7731/Zope/Publisher/Browser
Modified Files:
Tag: Zope-3x-branch
AttributePublisher.py IBrowserPublisher.py
Added Files:
Tag: Zope-3x-branch
BrowserRequest.py BrowserResponse.py
IBrowserApplicationRequest.py IBrowserPublication.py
IBrowserRequest.py IVirtualHostRequest.py cgi_names.py
Log Message:
Merged the publication refactoring branch into the main branch.
Also renamed:
browser_reaverse -> publishTraverse
browser_default -> browserDefault
=== Added File Zope3/lib/python/Zope/Publisher/Browser/BrowserRequest.py === (418/518 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.4.1 2002/03/26 21:25:58 jim Exp $
"""
import re
from cgi import FieldStorage
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 IBrowserPublisher import IBrowserPublisher
from IBrowserRequest import IBrowserRequest
from IBrowserPublication import IBrowserPublication
from IBrowserApplicationRequest import IBrowserApplicationRequest
from BrowserResponse import BrowserResponse
# 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__ = (HTTPRequest.__implements__,
IBrowserRequest, IBrowserPublication,
IBrowserApplicationRequest,
)
[-=- -=- -=- 418 lines omitted -=- -=- -=-]
######################################
# from: Interface.Common.Mapping.IReadMapping
def get(self, key, default=None):
'See Interface.Common.Mapping.IReadMapping'
result = self._form.get(key, self)
if result is not self: return result
result = self._cookies.get(key, self)
if result is not self: return result
result = self._environ.get(key, self)
if result is not self: return result
return default
#
############################################################
class RedirectingBrowserRequest(BrowserRequest):
"""Browser requests that redirect when the actual and effective URLs differ
"""
use_redirect = 1
class TestRequest(BrowserRequest):
def __init__(self, body_instream=None, outstream=None, environ=None, **kw):
_testEnv = {
'SERVER_URL': 'http://127.0.0.1',
'HTTP_HOST': '127.0.0.1',
'CONTENT_LENGTH': '0',
'GATEWAY_INTERFACE': 'TestFooInterface/1.0',
}
if environ:
_testEnv.update(environ)
if kw:
_testEnv.update(kw)
if body_instream is None:
from StringIO import StringIO
body_instream = StringIO('')
if outstream is None:
outstream = StringIO()
super(TestRequest, self).__init__(body_instream, outstream, _testEnv)
=== 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.4.1 2002/03/26 21:25:58 jim Exp $'''
__version__='$Revision: 1.1.4.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):
"""Browser response
"""
__slots__ = (
'_base', # The base href
)
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 self._headers.has_key('content-type'):
c = (self.__isHTML(body) and 'text/html' or 'text/plain')
self.setHeader('content-type', c)
content_type = self._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', '<')
body = body.replace('\233', '>')
body = self.__insertBase(body)
self._body = body
self._updateContentLength()
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 getattr(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
def getBase(self):
return getattr(self, '_base', '')
def setBase(self, base):
self._base = base
latin1_alias_match = re.compile(
r'text/html(\s*;\s*charset=((latin)|(latin[-_]?1)|'
r'(cp1252)|(cp819)|(csISOLatin1)|(IBM819)|(iso-ir-100)|'
r'(iso[-_]8859[-_]1(:1987)?)))?$',re.I).match
def is_text_html(content_type):
return (content_type == 'text/html' or
latin1_alias_match(content_type) is not None)
=== Zope3/lib/python/Zope/Publisher/Browser/IBrowserApplicationRequest.py 1.1.2.2 => 1.1.2.3 ===
+#
+# 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.HTTP.IHTTPApplicationRequest import IHTTPApplicationRequest
+from Interface.Attribute import Attribute
+
+class IBrowserApplicationRequest(IHTTPApplicationRequest):
+ """Browser-specific requests
+ """
+
+ def __getitem__(key):
+ """Return Browser 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.
+
+ - Form data
+
+ Form data are searched before cookies, which are searched
+ before environmental data.
+ """
+
+ form = Attribute(
+ """Form data
+
+ This is a read-only mapping from name to form value for the name.
+ """)
=== Added File Zope3/lib/python/Zope/Publisher/Browser/IBrowserPublication.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
#
##############################################################################
"""
Revision information:
$Id: IBrowserPublication.py,v 1.1.4.1 2002/03/26 21:25:58 jim Exp $
"""
from Zope.Publisher.IPublication import IPublication
class IBrowserPublication (IPublication):
"""
Object publication framework.
"""
def getDefaultTraversal(request, ob):
"""Get the default published object for the request
Allows a default view to be added to traversal.
Returns (ob, steps_reversed).
"""
=== 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.4.1 2002/03/26 21:25:58 jim 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.
"""
=== 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.4.1 2002/03/26 21:25:58 jim 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.
"""
=== Added File Zope3/lib/python/Zope/Publisher/Browser/cgi_names.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.
#cgi hotfix:
import cgi
if not hasattr(cgi, 'valid_boundary'):
try: import cgi_hotfix
except ImportError: pass
isCGI_NAME = {
# These fields are placed in request.environ instead of request.form.
'SERVER_SOFTWARE' : 1,
'SERVER_NAME' : 1,
'GATEWAY_INTERFACE' : 1,
'SERVER_PROTOCOL' : 1,
'SERVER_PORT' : 1,
'REQUEST_METHOD' : 1,
'PATH_INFO' : 1,
'PATH_TRANSLATED' : 1,
'SCRIPT_NAME' : 1,
'QUERY_STRING' : 1,
'REMOTE_HOST' : 1,
'REMOTE_ADDR' : 1,
'AUTH_TYPE' : 1,
'REMOTE_USER' : 1,
'REMOTE_IDENT' : 1,
'CONTENT_TYPE' : 1,
'CONTENT_LENGTH' : 1,
'SERVER_URL': 1,
}.has_key
hide_key={
'HTTP_AUTHORIZATION':1,
'HTTP_CGI_AUTHORIZATION': 1,
}.has_key
=== Zope3/lib/python/Zope/Publisher/Browser/AttributePublisher.py 1.1.2.9 => 1.1.2.10 ===
# Zope.Publisher.Browser.IBrowserPublisher.
- def browser_traverse(self, request, name):
+ def publishTraverse(self, request, name):
'''See interface IBrowserPublisher'''
if name.endswith('.html'):
@@ -24,6 +24,6 @@
return getattr(self, name)
- def browser_default(self, request):
+ def browserDefault(self, request):
'''See interface IBrowserPublisher'''
return self, ("index.html",)
=== Zope3/lib/python/Zope/Publisher/Browser/IBrowserPublisher.py 1.1.2.6 => 1.1.2.7 ===
class IBrowserPublisher(Interface):
- def browser_traverse(request, name):
+ def publishTraverse(request, name):
"""Lookup a name
The request argument is the publisher request object.
"""
- def browser_default(request):
+ def browserDefault(request):
"""Provide the default object
The default object is expressed as a (possibly different)
@@ -26,13 +26,13 @@
Returns an object and a sequence of names. If the sequence of
names is not empty, then a traversal step is made for each name.
After the publisher gets to the end of the sequence, it will
- call browser_default on the last traversed object.
+ call browserDefault on the last traversed object.
Normal usage is to return self for object and a default view name.
The publisher calls this method at the end of each traversal path. If
a non-empty sequence of names is returned, the publisher will traverse
- those names and call browser_default again at the end.
+ those names and call browserDefault again at the end.
Note that if additional traversal steps are indicated (via a
nonempty sequence of names), then the publisher will try to adjust