Commit fa0d2dcb authored by Tres Seaver's avatar Tres Seaver

PEP8-ify.

parent cbf5b2ee
############################################################################## ##############################################################################
# #
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. # Copyright (c) 2002-2009 Zope Corporation and Contributors.
# All Rights Reserved.
# #
# This software is subject to the provisions of the Zope Public License, # This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
...@@ -15,17 +16,19 @@ ...@@ -15,17 +16,19 @@
$Id$ $Id$
""" """
import re, sys, os, time, random, codecs, tempfile from cgi import escape
from types import StringType, UnicodeType from cgi import FieldStorage
from BaseRequest import BaseRequest, quote import codecs
from HTTPResponse import HTTPResponse
from cgi import FieldStorage, escape
from urllib import unquote, splittype, splitport
from copy import deepcopy from copy import deepcopy
from Converters import get_converter import os
from TaintedString import TaintedString import random
from maybe_lock import allocate_lock import re
xmlrpc=None # Placeholder for module that we'll import if we have to. import sys
import tempfile
import time
from urllib import unquote
from urllib import splittype
from urllib import splitport
from zope.i18n.interfaces import IUserPreferredLanguages from zope.i18n.interfaces import IUserPreferredLanguages
from zope.i18n.locales import locales, LoadLocaleError from zope.i18n.locales import locales, LoadLocaleError
...@@ -33,6 +36,26 @@ from zope.interface import implements ...@@ -33,6 +36,26 @@ from zope.interface import implements
from zope.publisher.base import DebugFlags from zope.publisher.base import DebugFlags
from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserRequest
from ZPublisher.BaseRequest import BaseRequest
from ZPublisher.BaseRequest import quote
from ZPublisher.Converters import get_converter
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.maybe_lock import allocate_lock
from ZPublisher.TaintedString import TaintedString
# Flags
SEQUENCE = 1
DEFAULT = 2
RECORD = 4
RECORDS = 8
REC = RECORD | RECORDS
EMPTY = 16
CONVERTED = 32
# Placeholders for module that we'll import if we have to.
xmlrpc = None
base64 = None
# This may get overwritten during configuration # This may get overwritten during configuration
default_encoding = 'iso-8859-15' default_encoding = 'iso-8859-15'
...@@ -57,23 +80,31 @@ isCGI_NAME = { ...@@ -57,23 +80,31 @@ isCGI_NAME = {
'SERVER_URL': 1, 'SERVER_URL': 1,
}.has_key }.has_key
hide_key={'HTTP_AUTHORIZATION':1, hide_key = {'HTTP_AUTHORIZATION':1, 'HTTP_CGI_AUTHORIZATION': 1}.has_key
'HTTP_CGI_AUTHORIZATION': 1,
}.has_key
default_port={'http': '80', 'https': '443'} default_port = {'http': '80', 'https': '443'}
tainting_env = str(os.environ.get('ZOPE_DTML_REQUEST_AUTOQUOTE', '')).lower() tainting_env = str(os.environ.get('ZOPE_DTML_REQUEST_AUTOQUOTE', '')).lower()
TAINTING_ENABLED = tainting_env not in ('disabled', '0', 'no') TAINTING_ENABLED = tainting_env not in ('disabled', '0', 'no')
_marker = []
# The trusted_proxies configuration setting contains a sequence
# of front-end proxies that are trusted to supply an accurate
# X_FORWARDED_FOR header. If REMOTE_ADDR is one of the values in this list
# and it has set an X_FORWARDED_FOR header, ZPublisher copies REMOTE_ADDR
# into X_FORWARDED_BY, and the last element of the X_FORWARDED_FOR list
# into REMOTE_ADDR. X_FORWARDED_FOR is left unchanged.
# The ZConfig machinery may sets this attribute on initialization
# if any trusted-proxies are defined in the configuration file.
_marker=[] trusted_proxies = []
class NestedLoopExit( Exception ): class NestedLoopExit(Exception):
pass pass
class HTTPRequest(BaseRequest): class HTTPRequest(BaseRequest):
"""\ """ Model HTTP request data.
Model HTTP request data.
This object provides access to request data. This includes, the This object provides access to request data. This includes, the
input headers, form data, server data, and cookies. input headers, form data, server data, and cookies.
...@@ -129,26 +160,26 @@ class HTTPRequest(BaseRequest): ...@@ -129,26 +160,26 @@ class HTTPRequest(BaseRequest):
implements(IBrowserRequest) implements(IBrowserRequest)
_hacked_path=None _hacked_path = None
args=() args = ()
_file=None _file = None
_urls = () _urls = ()
retry_max_count=3 retry_max_count = 3
def supports_retry(self): def supports_retry(self):
if self.retry_count < self.retry_max_count: if self.retry_count < self.retry_max_count:
time.sleep(random.uniform(0, 2**(self.retry_count))) time.sleep(random.uniform(0, 2 ** (self.retry_count)))
return 1 return 1
def retry(self): def retry(self):
self.retry_count=self.retry_count+1 self.retry_count = self.retry_count + 1
self.stdin.seek(0) self.stdin.seek(0)
r=self.__class__(stdin=self.stdin, r = self.__class__(stdin=self.stdin,
environ=self._orig_env, environ=self._orig_env,
response=self.response.retry() response=self.response.retry(),
) )
r.retry_count=self.retry_count r.retry_count = self.retry_count
return r return r
def close(self): def close(self):
...@@ -171,9 +202,12 @@ class HTTPRequest(BaseRequest): ...@@ -171,9 +202,12 @@ class HTTPRequest(BaseRequest):
return server_url return server_url
oldprotocol, oldhost = splittype(server_url) oldprotocol, oldhost = splittype(server_url)
oldhostname, oldport = splitport(oldhost[2:]) oldhostname, oldport = splitport(oldhost[2:])
if protocol is None: protocol = oldprotocol if protocol is None:
if hostname is None: hostname = oldhostname protocol = oldprotocol
if port is None: port = oldport if hostname is None:
hostname = oldhostname
if port is None:
port = oldport
if (port is None or default_port[protocol] == port): if (port is None or default_port[protocol] == port):
host = hostname host = hostname
...@@ -186,7 +220,7 @@ class HTTPRequest(BaseRequest): ...@@ -186,7 +220,7 @@ class HTTPRequest(BaseRequest):
def setVirtualRoot(self, path, hard=0): def setVirtualRoot(self, path, hard=0):
""" Treat the current publishing object as a VirtualRoot """ """ Treat the current publishing object as a VirtualRoot """
other = self.other other = self.other
if isinstance(path, StringType) or isinstance(path, UnicodeType): if isinstance(path, str) or isinstance(path, unicode):
path = path.split('/') path = path.split('/')
self._script[:] = map(quote, filter(None, path)) self._script[:] = map(quote, filter(None, path))
del self._steps[:] del self._steps[:]
...@@ -274,38 +308,41 @@ class HTTPRequest(BaseRequest): ...@@ -274,38 +308,41 @@ class HTTPRequest(BaseRequest):
self._locale = locales.getLocale(None, None, None) self._locale = locales.getLocale(None, None, None)
def __init__(self, stdin, environ, response, clean=0): def __init__(self, stdin, environ, response, clean=0):
self._orig_env=environ self._orig_env = environ
# Avoid the overhead of scrubbing the environment in the # Avoid the overhead of scrubbing the environment in the
# case of request cloning for traversal purposes. If the # case of request cloning for traversal purposes. If the
# clean flag is set, we know we can use the passed in # clean flag is set, we know we can use the passed in
# environ dict directly. # environ dict directly.
if not clean: environ=sane_environment(environ) if not clean:
environ = sane_environment(environ)
if environ.has_key('HTTP_AUTHORIZATION'): if environ.has_key('HTTP_AUTHORIZATION'):
self._auth=environ['HTTP_AUTHORIZATION'] self._auth = environ['HTTP_AUTHORIZATION']
response._auth=1 response._auth = 1
del environ['HTTP_AUTHORIZATION'] del environ['HTTP_AUTHORIZATION']
self.stdin=stdin self.stdin = stdin
self.environ=environ self.environ = environ
have_env=environ.has_key have_env = environ.has_key
get_env=environ.get get_env = environ.get
self.response=response self.response = response
other=self.other={'RESPONSE': response} other = self.other = {'RESPONSE': response}
self.form={} self.form = {}
self.taintedform={} self.taintedform = {}
self.steps=[] self.steps = []
self._steps=[] self._steps = []
self._lazies={} self._lazies = {}
self._debug = DebugFlags() self._debug = DebugFlags()
# We don't set up the locale initially but just on first access # We don't set up the locale initially but just on first access
self._locale = _marker self._locale = _marker
if environ.has_key('REMOTE_ADDR'): if environ.has_key('REMOTE_ADDR'):
self._client_addr = environ['REMOTE_ADDR'] self._client_addr = environ['REMOTE_ADDR']
if environ.has_key('HTTP_X_FORWARDED_FOR') and self._client_addr in trusted_proxies: if (environ.has_key('HTTP_X_FORWARDED_FOR') and
# REMOTE_ADDR is one of our trusted local proxies. Not really very remote at all. self._client_addr in trusted_proxies):
# The proxy can tell us the IP of the real remote client in the forwarded-for header # REMOTE_ADDR is one of our trusted local proxies.
# Not really very remote at all. The proxy can tell us the
# IP of the real remote client in the forwarded-for header
# Skip the proxy-address itself though # Skip the proxy-address itself though
forwarded_for = [ forwarded_for = [
e.strip() e.strip()
...@@ -321,18 +358,22 @@ class HTTPRequest(BaseRequest): ...@@ -321,18 +358,22 @@ class HTTPRequest(BaseRequest):
################################################################ ################################################################
# Get base info first. This isn't likely to cause # Get base info first. This isn't likely to cause
# errors and might be useful to error handlers. # errors and might be useful to error handlers.
b=script=get_env('SCRIPT_NAME','').strip() b = script = get_env('SCRIPT_NAME','').strip()
# _script and the other _names are meant for URL construction # _script and the other _names are meant for URL construction
self._script = map(quote, filter(None, script.split( '/'))) self._script = map(quote, filter(None, script.split( '/')))
while b and b[-1]=='/': b=b[:-1] while b and b[-1] == '/':
b = b[:-1]
p = b.rfind('/') p = b.rfind('/')
if p >= 0: b=b[:p+1] if p >= 0:
else: b='' b = b[:p+1]
while b and b[0]=='/': b=b[1:] else:
b = ''
while b and b[0] == '/':
b = b[1:]
server_url=get_env('SERVER_URL',None) server_url = get_env('SERVER_URL',None)
if server_url is not None: if server_url is not None:
other['SERVER_URL'] = server_url = server_url.strip() other['SERVER_URL'] = server_url = server_url.strip()
else: else:
...@@ -342,7 +383,8 @@ class HTTPRequest(BaseRequest): ...@@ -342,7 +383,8 @@ class HTTPRequest(BaseRequest):
elif (have_env('SERVER_PORT_SECURE') and elif (have_env('SERVER_PORT_SECURE') and
environ['SERVER_PORT_SECURE'] == "1"): environ['SERVER_PORT_SECURE'] == "1"):
protocol = 'https' protocol = 'https'
else: protocol = 'http' else:
protocol = 'http'
if have_env('HTTP_HOST'): if have_env('HTTP_HOST'):
host = environ['HTTP_HOST'].strip() host = environ['HTTP_HOST'].strip()
...@@ -355,9 +397,9 @@ class HTTPRequest(BaseRequest): ...@@ -355,9 +397,9 @@ class HTTPRequest(BaseRequest):
# back and do anything with it later. # back and do anything with it later.
# #
# if port is None and environ.has_key('SERVER_PORT'): # if port is None and environ.has_key('SERVER_PORT'):
# s_port=environ['SERVER_PORT'] # s_port = environ['SERVER_PORT']
# if s_port not in ('80', '443'): # if s_port not in ('80', '443'):
# port=s_port # port = s_port
else: else:
hostname = environ['SERVER_NAME'].strip() hostname = environ['SERVER_NAME'].strip()
...@@ -365,23 +407,29 @@ class HTTPRequest(BaseRequest): ...@@ -365,23 +407,29 @@ class HTTPRequest(BaseRequest):
self.setServerURL(protocol=protocol, hostname=hostname, port=port) self.setServerURL(protocol=protocol, hostname=hostname, port=port)
server_url = other['SERVER_URL'] server_url = other['SERVER_URL']
if server_url[-1:]=='/': server_url=server_url[:-1] if server_url[-1:] == '/':
server_url = server_url[:-1]
if b: self.base="%s/%s" % (server_url,b) if b:
else: self.base=server_url self.base = "%s/%s" % (server_url,b)
while script[:1]=='/': script=script[1:] else:
if script: script="%s/%s" % (server_url,script) self.base = server_url
else: script=server_url while script[:1] == '/':
other['URL']=self.script=script script = script[1:]
if script:
script = "%s/%s" % (server_url,script)
else:
script = server_url
other['URL'] = self.script = script
other['method'] = environ.get('REQUEST_METHOD', 'GET').upper() other['method'] = environ.get('REQUEST_METHOD', 'GET').upper()
################################################################ ################################################################
# Cookie values should *not* be appended to existing form # Cookie values should *not* be appended to existing form
# vars with the same name - they are more like default values # vars with the same name - they are more like default values
# for names not otherwise specified in the form. # for names not otherwise specified in the form.
cookies={} cookies = {}
taintedcookies={} taintedcookies = {}
k=get_env('HTTP_COOKIE','') k = get_env('HTTP_COOKIE','')
if k: if k:
parse_cookie(k, cookies) parse_cookie(k, cookies)
for k, v in cookies.items(): for k, v in cookies.items():
...@@ -394,7 +442,7 @@ class HTTPRequest(BaseRequest): ...@@ -394,7 +442,7 @@ class HTTPRequest(BaseRequest):
istainted = 1 istainted = 1
if istainted: if istainted:
taintedcookies[k] = v taintedcookies[k] = v
self.cookies=cookies self.cookies = cookies
self.taintedcookies = taintedcookies self.taintedcookies = taintedcookies
def processInputs( def processInputs(
...@@ -404,7 +452,7 @@ class HTTPRequest(BaseRequest): ...@@ -404,7 +452,7 @@ class HTTPRequest(BaseRequest):
DEFAULT=2, DEFAULT=2,
RECORD=4, RECORD=4,
RECORDS=8, RECORDS=8,
REC=12, # RECORD|RECORDS REC=12, # RECORD | RECORDS
EMPTY=16, EMPTY=16,
CONVERTED=32, CONVERTED=32,
hasattr=hasattr, hasattr=hasattr,
...@@ -417,19 +465,21 @@ class HTTPRequest(BaseRequest): ...@@ -417,19 +465,21 @@ class HTTPRequest(BaseRequest):
We need to delay input parsing so that it is done under We need to delay input parsing so that it is done under
publisher control for error handling purposes. publisher control for error handling purposes.
""" """
response=self.response response = self.response
environ=self.environ environ = self.environ
method=environ.get('REQUEST_METHOD','GET') method = environ.get('REQUEST_METHOD','GET')
if method != 'GET': fp=self.stdin if method != 'GET':
else: fp=None fp = self.stdin
else:
fp = None
form=self.form form = self.form
other=self.other other = self.other
taintedform=self.taintedform taintedform = self.taintedform
meth=None meth = None
fs=ZopeFieldStorage(fp=fp,environ=environ,keep_blank_values=1) fs = ZopeFieldStorage(fp=fp,environ=environ,keep_blank_values=1)
if not hasattr(fs,'list') or fs.list is None: if not hasattr(fs,'list') or fs.list is None:
if environ.has_key('HTTP_SOAPACTION'): if environ.has_key('HTTP_SOAPACTION'):
# Stash XML request for interpretation by a SOAP-aware view # Stash XML request for interpretation by a SOAP-aware view
...@@ -440,26 +490,27 @@ class HTTPRequest(BaseRequest): ...@@ -440,26 +490,27 @@ class HTTPRequest(BaseRequest):
method == 'POST'): method == 'POST'):
# Ye haaa, XML-RPC! # Ye haaa, XML-RPC!
global xmlrpc global xmlrpc
if xmlrpc is None: import xmlrpc if xmlrpc is None:
from ZPublisher import xmlrpc
meth, self.args = xmlrpc.parse_input(fs.value) meth, self.args = xmlrpc.parse_input(fs.value)
response=xmlrpc.response(response) response = xmlrpc.response(response)
other['RESPONSE']=self.response=response other['RESPONSE'] = self.response = response
self.maybe_webdav_client = 0 self.maybe_webdav_client = 0
else: else:
self._file=fs.file self._file = fs.file
else: else:
fslist=fs.list fslist = fs.list
tuple_items={} tuple_items = {}
lt=type([]) lt = type([])
CGI_name=isCGI_NAME CGI_name = isCGI_NAME
defaults={} defaults = {}
tainteddefaults={} tainteddefaults = {}
converter=None converter = None
for item in fslist: for item in fslist:
isFileUpload = 0 isFileUpload = 0
key=item.name key = item.name
if (hasattr(item,'file') and hasattr(item,'filename') if (hasattr(item,'file') and hasattr(item,'filename')
and hasattr(item,'headers')): and hasattr(item,'headers')):
if (item.file and if (item.file and
...@@ -467,12 +518,12 @@ class HTTPRequest(BaseRequest): ...@@ -467,12 +518,12 @@ class HTTPRequest(BaseRequest):
# RFC 1867 says that all fields get a content-type. # RFC 1867 says that all fields get a content-type.
# or 'content-type' in map(lower, item.headers.keys()) # or 'content-type' in map(lower, item.headers.keys())
)): )):
item=FileUpload(item) item = FileUpload(item)
isFileUpload = 1 isFileUpload = 1
else: else:
item=item.value item = item.value
flags=0 flags = 0
character_encoding = '' character_encoding = ''
# Variables for potentially unsafe values. # Variables for potentially unsafe values.
tainted = None tainted = None
...@@ -487,55 +538,64 @@ class HTTPRequest(BaseRequest): ...@@ -487,55 +538,64 @@ class HTTPRequest(BaseRequest):
# a re search. # a re search.
l=key.rfind(':') l = key.rfind(':')
if l >= 0: if l >= 0:
mo = search_type(key,l) mo = search_type(key,l)
if mo: l=mo.start(0) if mo:
else: l=-1 l = mo.start(0)
else:
l = -1
while l >= 0: while l >= 0:
type_name=key[l+1:] type_name = key[l+1:]
key=key[:l] key = key[:l]
c=get_converter(type_name, None) c = get_converter(type_name, None)
if c is not None: if c is not None:
converter=c converter = c
converter_type = type_name converter_type = type_name
flags=flags|CONVERTED flags = flags | CONVERTED
elif type_name == 'list': elif type_name == 'list':
flags=flags|SEQUENCE flags = flags | SEQUENCE
elif type_name == 'tuple': elif type_name == 'tuple':
tuple_items[key]=1 tuple_items[key] = 1
flags=flags|SEQUENCE flags = flags | SEQUENCE
elif (type_name == 'method' or type_name == 'action'): elif (type_name == 'method' or type_name == 'action'):
if l: meth=key if l:
else: meth=item meth = key
else:
meth = item
elif (type_name == 'default_method' or type_name == \ elif (type_name == 'default_method' or type_name == \
'default_action'): 'default_action'):
if not meth: if not meth:
if l: meth=key if l:
else: meth=item meth = key
else:
meth = item
elif type_name == 'default': elif type_name == 'default':
flags=flags|DEFAULT flags = flags | DEFAULT
elif type_name == 'record': elif type_name == 'record':
flags=flags|RECORD flags = flags | RECORD
elif type_name == 'records': elif type_name == 'records':
flags=flags|RECORDS flags = flags | RECORDS
elif type_name == 'ignore_empty': elif type_name == 'ignore_empty':
if not item: flags=flags|EMPTY if not item:
flags = flags | EMPTY
elif has_codec(type_name): elif has_codec(type_name):
character_encoding = type_name character_encoding = type_name
l=key.rfind(':') l = key.rfind(':')
if l < 0: break if l < 0:
mo=search_type(key,l) break
if mo: l = mo.start(0) mo = search_type(key,l)
else: l = -1 if mo:
l = mo.start(0)
else:
l = -1
# Filter out special names from form: # Filter out special names from form:
if CGI_name(key) or key[:5]=='HTTP_': continue if CGI_name(key) or key[:5] == 'HTTP_':
continue
# If the key is tainted, mark it so as well. # If the key is tainted, mark it so as well.
tainted_key = key tainted_key = key
...@@ -545,12 +605,13 @@ class HTTPRequest(BaseRequest): ...@@ -545,12 +605,13 @@ class HTTPRequest(BaseRequest):
if flags: if flags:
# skip over empty fields # skip over empty fields
if flags&EMPTY: continue if flags & EMPTY:
continue
#Split the key and its attribute #Split the key and its attribute
if flags&REC: if flags & REC:
key=key.split(".") key = key.split(".")
key, attr=".".join(key[:-1]), key[-1] key, attr = ".".join(key[:-1]), key[-1]
# Update the tainted_key if necessary # Update the tainted_key if necessary
tainted_key = key tainted_key = key
...@@ -564,19 +625,21 @@ class HTTPRequest(BaseRequest): ...@@ -564,19 +625,21 @@ class HTTPRequest(BaseRequest):
escape(attr)) escape(attr))
# defer conversion # defer conversion
if flags&CONVERTED: if flags & CONVERTED:
try: try:
if character_encoding: if character_encoding:
# We have a string with a specified character encoding. # We have a string with a specified character
# This gets passed to the converter either as unicode, if it can # encoding. This gets passed to the converter
# handle it, or crunched back down to latin-1 if it can not. # either as unicode, if it can handle it, or
# crunched back down to latin-1 if it can not.
item = unicode(item,character_encoding) item = unicode(item,character_encoding)
if hasattr(converter,'convert_unicode'): if hasattr(converter,'convert_unicode'):
item = converter.convert_unicode(item) item = converter.convert_unicode(item)
else: else:
item = converter(item.encode(default_encoding)) item = converter(
item.encode(default_encoding))
else: else:
item=converter(item) item = converter(item)
# Flag potentially unsafe values # Flag potentially unsafe values
if converter_type in ('string', 'required', 'text', if converter_type in ('string', 'required', 'text',
...@@ -595,18 +658,18 @@ class HTTPRequest(BaseRequest): ...@@ -595,18 +658,18 @@ class HTTPRequest(BaseRequest):
tainted = None tainted = None
except: except:
if (not item and not (flags&DEFAULT) and if (not item and not (flags & DEFAULT) and
defaults.has_key(key)): defaults.has_key(key)):
item = defaults[key] item = defaults[key]
if flags&RECORD: if flags & RECORD:
item=getattr(item,attr) item = getattr(item,attr)
if flags&RECORDS: if flags & RECORDS:
item = getattr(item[-1], attr) item = getattr(item[-1], attr)
if tainteddefaults.has_key(tainted_key): if tainteddefaults.has_key(tainted_key):
tainted = tainteddefaults[tainted_key] tainted = tainteddefaults[tainted_key]
if flags&RECORD: if flags & RECORD:
tainted = getattr(tainted, attr) tainted = getattr(tainted, attr)
if flags&RECORDS: if flags & RECORDS:
tainted = getattr(tainted[-1], attr) tainted = getattr(tainted[-1], attr)
else: else:
raise raise
...@@ -621,7 +684,7 @@ class HTTPRequest(BaseRequest): ...@@ -621,7 +684,7 @@ class HTTPRequest(BaseRequest):
tainted = item tainted = item
#Determine which dictionary to use #Determine which dictionary to use
if flags&DEFAULT: if flags & DEFAULT:
mapping_object = defaults mapping_object = defaults
tainted_mapping = tainteddefaults tainted_mapping = tainteddefaults
else: else:
...@@ -630,7 +693,7 @@ class HTTPRequest(BaseRequest): ...@@ -630,7 +693,7 @@ class HTTPRequest(BaseRequest):
#Insert in dictionary #Insert in dictionary
if mapping_object.has_key(key): if mapping_object.has_key(key):
if flags&RECORDS: if flags & RECORDS:
#Get the list and the last record #Get the list and the last record
#in the list. reclist is mutable. #in the list. reclist is mutable.
reclist = mapping_object[key] reclist = mapping_object[key]
...@@ -645,10 +708,11 @@ class HTTPRequest(BaseRequest): ...@@ -645,10 +708,11 @@ class HTTPRequest(BaseRequest):
lastrecord = treclist[-1] lastrecord = treclist[-1]
if not hasattr(lastrecord, attr): if not hasattr(lastrecord, attr):
if flags&SEQUENCE: tainted = [tainted] if flags & SEQUENCE:
tainted = [tainted]
setattr(lastrecord, attr, tainted) setattr(lastrecord, attr, tainted)
else: else:
if flags&SEQUENCE: if flags & SEQUENCE:
getattr(lastrecord, getattr(lastrecord,
attr).append(tainted) attr).append(tainted)
else: else:
...@@ -665,10 +729,11 @@ class HTTPRequest(BaseRequest): ...@@ -665,10 +729,11 @@ class HTTPRequest(BaseRequest):
copyitem = item copyitem = item
if not hasattr(lastrecord, attr): if not hasattr(lastrecord, attr):
if flags&SEQUENCE: copyitem = [copyitem] if flags & SEQUENCE:
copyitem = [copyitem]
setattr(lastrecord, attr, copyitem) setattr(lastrecord, attr, copyitem)
else: else:
if flags&SEQUENCE: if flags & SEQUENCE:
getattr(lastrecord, getattr(lastrecord,
attr).append(copyitem) attr).append(copyitem)
else: else:
...@@ -679,10 +744,11 @@ class HTTPRequest(BaseRequest): ...@@ -679,10 +744,11 @@ class HTTPRequest(BaseRequest):
if not hasattr(x,attr): if not hasattr(x,attr):
#If the attribute does not #If the attribute does not
#exist, setit #exist, setit
if flags&SEQUENCE: item=[item] if flags & SEQUENCE:
item = [item]
setattr(x,attr,item) setattr(x,attr,item)
else: else:
if flags&SEQUENCE: if flags & SEQUENCE:
# If the attribute is a # If the attribute is a
# sequence, append the item # sequence, append the item
# to the existing attribute # to the existing attribute
...@@ -692,25 +758,25 @@ class HTTPRequest(BaseRequest): ...@@ -692,25 +758,25 @@ class HTTPRequest(BaseRequest):
else: else:
# Create a new record and add # Create a new record and add
# it to the list # it to the list
n=record() n = record()
setattr(n,attr,item) setattr(n,attr,item)
mapping_object[key].append(n) mapping_object[key].append(n)
elif flags&RECORD: elif flags & RECORD:
b=mapping_object[key] b = mapping_object[key]
if flags&SEQUENCE: if flags & SEQUENCE:
item=[item] item = [item]
if not hasattr(b,attr): if not hasattr(b, attr):
# if it does not have the # if it does not have the
# attribute, set it # attribute, set it
setattr(b,attr,item) setattr(b, attr, item)
else: else:
# it has the attribute so # it has the attribute so
# append the item to it # append the item to it
setattr(b,attr,getattr(b,attr)+item) setattr(b, attr, getattr(b, attr) + item)
else: else:
# it is not a sequence so # it is not a sequence so
# set the attribute # set the attribute
setattr(b,attr,item) setattr(b, attr, item)
# Store a tainted copy as well if necessary # Store a tainted copy as well if necessary
if tainted: if tainted:
...@@ -718,7 +784,7 @@ class HTTPRequest(BaseRequest): ...@@ -718,7 +784,7 @@ class HTTPRequest(BaseRequest):
tainted_mapping[tainted_key] = deepcopy( tainted_mapping[tainted_key] = deepcopy(
mapping_object[key]) mapping_object[key])
b = tainted_mapping[tainted_key] b = tainted_mapping[tainted_key]
if flags&SEQUENCE: if flags & SEQUENCE:
seq = getattr(b, attr, []) seq = getattr(b, attr, [])
seq.append(tainted) seq.append(tainted)
setattr(b, attr, seq) setattr(b, attr, seq)
...@@ -730,7 +796,7 @@ class HTTPRequest(BaseRequest): ...@@ -730,7 +796,7 @@ class HTTPRequest(BaseRequest):
# record, we need to make sure the whole record # record, we need to make sure the whole record
# is built. # is built.
b = tainted_mapping[tainted_key] b = tainted_mapping[tainted_key]
if flags&SEQUENCE: if flags & SEQUENCE:
seq = getattr(b, attr, []) seq = getattr(b, attr, [])
seq.append(item) seq.append(item)
setattr(b, attr, seq) setattr(b, attr, seq)
...@@ -739,7 +805,7 @@ class HTTPRequest(BaseRequest): ...@@ -739,7 +805,7 @@ class HTTPRequest(BaseRequest):
else: else:
# it is not a record or list of records # it is not a record or list of records
found=mapping_object[key] found = mapping_object[key]
if tainted: if tainted:
# Store a tainted version if necessary # Store a tainted version if necessary
...@@ -765,45 +831,51 @@ class HTTPRequest(BaseRequest): ...@@ -765,45 +831,51 @@ class HTTPRequest(BaseRequest):
if type(found) is lt: if type(found) is lt:
found.append(item) found.append(item)
else: else:
found=[found,item] found = [found,item]
mapping_object[key]=found mapping_object[key] = found
else: else:
# The dictionary does not have the key # The dictionary does not have the key
if flags&RECORDS: if flags & RECORDS:
# Create a new record, set its attribute # Create a new record, set its attribute
# and put it in the dictionary as a list # and put it in the dictionary as a list
a = record() a = record()
if flags&SEQUENCE: item=[item] if flags & SEQUENCE:
item = [item]
setattr(a,attr,item) setattr(a,attr,item)
mapping_object[key]=[a] mapping_object[key] = [a]
if tainted: if tainted:
# Store a tainted copy if necessary # Store a tainted copy if necessary
a = record() a = record()
if flags&SEQUENCE: tainted = [tainted] if flags & SEQUENCE:
tainted = [tainted]
setattr(a, attr, tainted) setattr(a, attr, tainted)
tainted_mapping[tainted_key] = [a] tainted_mapping[tainted_key] = [a]
elif flags&RECORD: elif flags & RECORD:
# Create a new record, set its attribute # Create a new record, set its attribute
# and put it in the dictionary # and put it in the dictionary
if flags&SEQUENCE: item=[item] if flags & SEQUENCE:
r = mapping_object[key]=record() item = [item]
r = mapping_object[key] = record()
setattr(r,attr,item) setattr(r,attr,item)
if tainted: if tainted:
# Store a tainted copy if necessary # Store a tainted copy if necessary
if flags&SEQUENCE: tainted = [tainted] if flags & SEQUENCE:
tainted = [tainted]
r = tainted_mapping[tainted_key] = record() r = tainted_mapping[tainted_key] = record()
setattr(r, attr, tainted) setattr(r, attr, tainted)
else: else:
# it is not a record or list of records # it is not a record or list of records
if flags&SEQUENCE: item=[item] if flags & SEQUENCE:
mapping_object[key]=item item = [item]
mapping_object[key] = item
if tainted: if tainted:
# Store a tainted copy if necessary # Store a tainted copy if necessary
if flags&SEQUENCE: tainted = [tainted] if flags & SEQUENCE:
tainted = [tainted]
tainted_mapping[tainted_key] = tainted tainted_mapping[tainted_key] = tainted
else: else:
...@@ -818,7 +890,7 @@ class HTTPRequest(BaseRequest): ...@@ -818,7 +890,7 @@ class HTTPRequest(BaseRequest):
#Insert in dictionary #Insert in dictionary
if mapping_object.has_key(key): if mapping_object.has_key(key):
# it is not a record or list of records # it is not a record or list of records
found=mapping_object[key] found = mapping_object[key]
if tainted: if tainted:
# Store a tainted version if necessary # Store a tainted version if necessary
...@@ -846,10 +918,10 @@ class HTTPRequest(BaseRequest): ...@@ -846,10 +918,10 @@ class HTTPRequest(BaseRequest):
if type(found) is lt: if type(found) is lt:
found.append(item) found.append(item)
else: else:
found=[found,item] found = [found,item]
mapping_object[key]=found mapping_object[key] = found
else: else:
mapping_object[key]=item mapping_object[key] = item
if tainted: if tainted:
taintedform[tainted_key] = tainted taintedform[tainted_key] = tainted
...@@ -857,12 +929,13 @@ class HTTPRequest(BaseRequest): ...@@ -857,12 +929,13 @@ class HTTPRequest(BaseRequest):
if defaults: if defaults:
for key, value in defaults.items(): for key, value in defaults.items():
tainted_key = key tainted_key = key
if '<' in key: tainted_key = TaintedString(key) if '<' in key:
tainted_key = TaintedString(key)
if not form.has_key(key): if not form.has_key(key):
# if the form does not have the key, # if the form does not have the key,
# set the default # set the default
form[key]=value form[key] = value
if tainteddefaults.has_key(tainted_key): if tainteddefaults.has_key(tainted_key):
taintedform[tainted_key] = \ taintedform[tainted_key] = \
...@@ -936,7 +1009,8 @@ class HTTPRequest(BaseRequest): ...@@ -936,7 +1009,8 @@ class HTTPRequest(BaseRequest):
for k, v in \ for k, v in \
defitem.__dict__.items(): defitem.__dict__.items():
for origitem in l: for origitem in l:
if not hasattr(origitem, k): if not hasattr(
origitem, k):
missesdefault = 1 missesdefault = 1
raise NestedLoopExit raise NestedLoopExit
except NestedLoopExit: except NestedLoopExit:
...@@ -949,9 +1023,11 @@ class HTTPRequest(BaseRequest): ...@@ -949,9 +1023,11 @@ class HTTPRequest(BaseRequest):
tainted = deepcopy(l) tainted = deepcopy(l)
for defitem in tdefault: for defitem in tdefault:
if isinstance(defitem, record): if isinstance(defitem, record):
for k, v in defitem.__dict__.items(): for k, v in (
defitem.__dict__.items()):
for origitem in tainted: for origitem in tainted:
if not hasattr(origitem, k): if not hasattr(
origitem, k):
setattr(origitem, k, v) setattr(origitem, k, v)
else: else:
if not defitem in tainted: if not defitem in tainted:
...@@ -993,26 +1069,27 @@ class HTTPRequest(BaseRequest): ...@@ -993,26 +1069,27 @@ class HTTPRequest(BaseRequest):
if tuple_items: if tuple_items:
for key in tuple_items.keys(): for key in tuple_items.keys():
# Split the key and get the attr # Split the key and get the attr
k=key.split( ".") k = key.split( ".")
k,attr='.'.join(k[:-1]), k[-1] k,attr = '.'.join(k[:-1]), k[-1]
a = attr a = attr
new = '' new = ''
# remove any type_names in the attr # remove any type_names in the attr
while not a=='': while not a =='':
a=a.split( ":") a = a.split( ":")
a,new=':'.join(a[:-1]), a[-1] a,new = ':'.join(a[:-1]), a[-1]
attr = new attr = new
if form.has_key(k): if form.has_key(k):
# If the form has the split key get its value # If the form has the split key get its value
tainted_split_key = k tainted_split_key = k
if '<' in k: tainted_split_key = TaintedString(k) if '<' in k:
tainted_split_key = TaintedString(k)
item =form[k] item =form[k]
if isinstance(item, record): if isinstance(item, record):
# if the value is mapped to a record, check if it # if the value is mapped to a record, check if it
# has the attribute, if it has it, convert it to # has the attribute, if it has it, convert it to
# a tuple and set it # a tuple and set it
if hasattr(item,attr): if hasattr(item,attr):
value=tuple(getattr(item,attr)) value = tuple(getattr(item,attr))
setattr(item,attr,value) setattr(item,attr,value)
else: else:
# It is mapped to a list of records # It is mapped to a list of records
...@@ -1021,7 +1098,7 @@ class HTTPRequest(BaseRequest): ...@@ -1021,7 +1098,7 @@ class HTTPRequest(BaseRequest):
if hasattr(x, attr): if hasattr(x, attr):
# If the record has the attribute # If the record has the attribute
# convert it to a tuple and set it # convert it to a tuple and set it
value=tuple(getattr(x,attr)) value = tuple(getattr(x,attr))
setattr(x,attr,value) setattr(x,attr,value)
# Do the same for the tainted counterpart # Do the same for the tainted counterpart
...@@ -1039,13 +1116,14 @@ class HTTPRequest(BaseRequest): ...@@ -1039,13 +1116,14 @@ class HTTPRequest(BaseRequest):
else: else:
# the form does not have the split key # the form does not have the split key
tainted_key = key tainted_key = key
if '<' in key: tainted_key = TaintedString(key) if '<' in key:
tainted_key = TaintedString(key)
if form.has_key(key): if form.has_key(key):
# if it has the original key, get the item # if it has the original key, get the item
# convert it to a tuple # convert it to a tuple
item=form[key] item = form[key]
item=tuple(form[key]) item = tuple(form[key])
form[key]=item form[key] = item
if taintedform.has_key(tainted_key): if taintedform.has_key(tainted_key):
tainted = tuple(taintedform[tainted_key]) tainted = tuple(taintedform[tainted_key])
...@@ -1053,11 +1131,13 @@ class HTTPRequest(BaseRequest): ...@@ -1053,11 +1131,13 @@ class HTTPRequest(BaseRequest):
if meth: if meth:
if environ.has_key('PATH_INFO'): if environ.has_key('PATH_INFO'):
path=environ['PATH_INFO'] path = environ['PATH_INFO']
while path[-1:]=='/': path=path[:-1] while path[-1:] == '/':
else: path='' path = path[:-1]
other['PATH_INFO']=path="%s/%s" % (path,meth) else:
self._hacked_path=1 path = ''
other['PATH_INFO'] = path = "%s/%s" % (path,meth)
self._hacked_path = 1
def resolve_url(self, url): def resolve_url(self, url):
# Attempt to resolve a url into an object in the Zope # Attempt to resolve a url into an object in the Zope
...@@ -1071,21 +1151,25 @@ class HTTPRequest(BaseRequest): ...@@ -1071,21 +1151,25 @@ class HTTPRequest(BaseRequest):
# be raised. # be raised.
if url.find(self.script) != 0: if url.find(self.script) != 0:
raise ValueError, 'Different namespace.' raise ValueError, 'Different namespace.'
path=url[len(self.script):] path = url[len(self.script):]
while path and path[0]=='/': path=path[1:] while path and path[0] == '/':
while path and path[-1]=='/': path=path[:-1] path = path[1:]
req=self.clone() while path and path[-1] == '/':
rsp=req.response path = path[:-1]
req['PATH_INFO']=path req = self.clone()
object=None rsp = req.response
req['PATH_INFO'] = path
object = None
# Try to traverse to get an object. Note that we call # Try to traverse to get an object. Note that we call
# the exception method on the response, but we don't # the exception method on the response, but we don't
# want to actually abort the current transaction # want to actually abort the current transaction
# (which is usually the default when the exception # (which is usually the default when the exception
# method is called on the response). # method is called on the response).
try: object=req.traverse(path) try:
except: rsp.exception() object = req.traverse(path)
except:
rsp.exception()
if object is None: if object is None:
req.close() req.close()
raise rsp.errmsg, sys.exc_info()[1] raise rsp.errmsg, sys.exc_info()[1]
...@@ -1097,43 +1181,45 @@ class HTTPRequest(BaseRequest): ...@@ -1097,43 +1181,45 @@ class HTTPRequest(BaseRequest):
# the given url, and not some kind of default object. # the given url, and not some kind of default object.
if hasattr(object, 'id'): if hasattr(object, 'id'):
if callable(object.id): if callable(object.id):
name=object.id() name = object.id()
else: name=object.id else:
name = object.id
elif hasattr(object, '__name__'): elif hasattr(object, '__name__'):
name=object.__name__ name = object.__name__
else: name='' else:
name = ''
if name != os.path.split(path)[-1]: if name != os.path.split(path)[-1]:
object=req.PARENTS[0] object = req.PARENTS[0]
req.close() req.close()
return object return object
def clone(self): def clone(self):
# Return a clone of the current request object # Return a clone of the current request object
# that may be used to perform object traversal. # that may be used to perform object traversal.
environ=self.environ.copy() environ = self.environ.copy()
environ['REQUEST_METHOD']='GET' environ['REQUEST_METHOD'] = 'GET'
if self._auth: environ['HTTP_AUTHORIZATION']=self._auth if self._auth:
clone=HTTPRequest(None, environ, HTTPResponse(), clean=1) environ['HTTP_AUTHORIZATION'] = self._auth
clone['PARENTS']=[self['PARENTS'][-1]] clone = HTTPRequest(None, environ, HTTPResponse(), clean=1)
clone['PARENTS'] = [self['PARENTS'][-1]]
return clone return clone
def getHeader(self, name, default=None, literal=False): def getHeader(self, name, default = None, literal = False):
"""Return the named HTTP header, or an optional default """Return the named HTTP header, or an optional default
argument or None if the header is not found. Note that argument or None if the header is not found. Note that
both original and CGI-ified header names are recognized, both original and CGI-ified header names are recognized,
e.g. 'Content-Type', 'CONTENT_TYPE' and 'HTTP_CONTENT_TYPE' e.g. 'Content-Type', 'CONTENT_TYPE' and 'HTTP_CONTENT_TYPE'
should all return the Content-Type header, if available. should all return the Content-Type header, if available.
""" """
environ=self.environ environ = self.environ
if not literal: if not literal:
name = name.replace('-', '_').upper() name = name.replace('-', '_').upper()
val=environ.get(name, None) val = environ.get(name, None)
if val is not None: if val is not None:
return val return val
if name[:5] != 'HTTP_': if name[:5] != 'HTTP_':
name='HTTP_%s' % name name = 'HTTP_%s' % name
return environ.get(name, default) return environ.get(name, default)
get_header = getHeader # BBB get_header = getHeader # BBB
...@@ -1150,12 +1236,13 @@ class HTTPRequest(BaseRequest): ...@@ -1150,12 +1236,13 @@ class HTTPRequest(BaseRequest):
other variables, form data, and then cookies. other variables, form data, and then cookies.
""" #" """ #"
other=self.other other = self.other
if other.has_key(key): if other.has_key(key):
if key=='REQUEST': return self if key == 'REQUEST':
return self
return other[key] return other[key]
if key[:1]=='U': if key[:1] == 'U':
match = URLmatch(key) match = URLmatch(key)
if match is not None: if match is not None:
pathonly, n = match.groups() pathonly, n = match.groups()
...@@ -1175,14 +1262,15 @@ class HTTPRequest(BaseRequest): ...@@ -1175,14 +1262,15 @@ class HTTPRequest(BaseRequest):
return URL return URL
if isCGI_NAME(key) or key[:5] == 'HTTP_': if isCGI_NAME(key) or key[:5] == 'HTTP_':
environ=self.environ environ = self.environ
if environ.has_key(key) and (not hide_key(key)): if environ.has_key(key) and (not hide_key(key)):
return environ[key] return environ[key]
return '' return ''
if key=='REQUEST': return self if key == 'REQUEST':
return self
if key[:1]=='B': if key[:1] == 'B':
match = BASEmatch(key) match = BASEmatch(key)
if match is not None: if match is not None:
pathonly, n = match.groups() pathonly, n = match.groups()
...@@ -1207,26 +1295,28 @@ class HTTPRequest(BaseRequest): ...@@ -1207,26 +1295,28 @@ class HTTPRequest(BaseRequest):
self._urls = self._urls + (key,) self._urls = self._urls + (key,)
return URL return URL
if key=='BODY' and self._file is not None: if key == 'BODY' and self._file is not None:
p=self._file.tell() p = self._file.tell()
self._file.seek(0) self._file.seek(0)
v=self._file.read() v = self._file.read()
self._file.seek(p) self._file.seek(p)
self.other[key]=v self.other[key] = v
return v return v
if key=='BODYFILE' and self._file is not None: if key == 'BODYFILE' and self._file is not None:
v=self._file v = self._file
self.other[key]=v self.other[key] = v
return v return v
v=self.common.get(key, _marker) v = self.common.get(key, _marker)
if v is not _marker: return v if v is not _marker:
return v
if self._lazies: if self._lazies:
v = self._lazies.get(key, _marker) v = self._lazies.get(key, _marker)
if v is not _marker: if v is not _marker:
if callable(v): v = v() if callable(v):
v = v()
self[key] = v # Promote lazy value self[key] = v # Promote lazy value
del self._lazies[key] del self._lazies[key]
return v return v
...@@ -1287,9 +1377,12 @@ class HTTPRequest(BaseRequest): ...@@ -1287,9 +1377,12 @@ class HTTPRequest(BaseRequest):
self._lazies[key] = callable self._lazies[key] = callable
def has_key(self, key, returnTaints=0): def has_key(self, key, returnTaints=0):
try: self.__getitem__(key, returnTaints=returnTaints) try:
except: return 0 self.__getitem__(key, returnTaints=returnTaints)
else: return 1 except:
return 0
else:
return 1
def keys(self, returnTaints=0): def keys(self, returnTaints=0):
keys = {} keys = {}
...@@ -1302,100 +1395,115 @@ class HTTPRequest(BaseRequest): ...@@ -1302,100 +1395,115 @@ class HTTPRequest(BaseRequest):
# Cache URLN and BASEN in self.other. # Cache URLN and BASEN in self.other.
# This relies on a side effect of has_key. # This relies on a side effect of has_key.
n=0 n = 0
while 1: while 1:
n=n+1 n = n + 1
key = "URL%s" % n key = "URL%s" % n
if not self.has_key(key): break if not self.has_key(key):
break
n=0 n = 0
while 1: while 1:
n=n+1 n = n + 1
key = "BASE%s" % n key = "BASE%s" % n
if not self.has_key(key): break if not self.has_key(key):
break
keys.update(self.other) keys.update(self.other)
keys.update(self.cookies) keys.update(self.cookies)
if returnTaints: keys.update(self.taintedcookies) if returnTaints:
keys.update(self.taintedcookies)
keys.update(self.form) keys.update(self.form)
if returnTaints: keys.update(self.taintedform) if returnTaints:
keys.update(self.taintedform)
keys=keys.keys() keys = keys.keys()
keys.sort() keys.sort()
return keys return keys
def __str__(self): def __str__(self):
result="<h3>form</h3><table>" result = "<h3>form</h3><table>"
row='<tr valign="top" align="left"><th>%s</th><td>%s</td></tr>' row = '<tr valign="top" align="left"><th>%s</th><td>%s</td></tr>'
for k,v in _filterPasswordFields(self.form.items()): for k,v in _filterPasswordFields(self.form.items()):
result=result + row % (escape(k), escape(repr(v))) result = result + row % (escape(k), escape(repr(v)))
result=result+"</table><h3>cookies</h3><table>" result = result + "</table><h3>cookies</h3><table>"
for k,v in _filterPasswordFields(self.cookies.items()): for k,v in _filterPasswordFields(self.cookies.items()):
result=result + row % (escape(k), escape(repr(v))) result = result + row % (escape(k), escape(repr(v)))
result=result+"</table><h3>lazy items</h3><table>" result = result + "</table><h3>lazy items</h3><table>"
for k,v in _filterPasswordFields(self._lazies.items()): for k,v in _filterPasswordFields(self._lazies.items()):
result=result + row % (escape(k), escape(repr(v))) result = result + row % (escape(k), escape(repr(v)))
result=result+"</table><h3>other</h3><table>" result = result + "</table><h3>other</h3><table>"
for k,v in _filterPasswordFields(self.other.items()): for k,v in _filterPasswordFields(self.other.items()):
if k in ('PARENTS','RESPONSE'): continue if k in ('PARENTS','RESPONSE'):
result=result + row % (escape(k), escape(repr(v))) continue
result = result + row % (escape(k), escape(repr(v)))
for n in "0123456789": for n in "0123456789":
key = "URL%s"%n key = "URL%s"%n
try: result=result + row % (key, escape(self[key])) try:
except KeyError: pass result = result + row % (key, escape(self[key]))
except KeyError:
pass
for n in "0123456789": for n in "0123456789":
key = "BASE%s"%n key = "BASE%s"%n
try: result=result + row % (key, escape(self[key])) try:
except KeyError: pass result = result + row % (key, escape(self[key]))
except KeyError:
pass
result=result+"</table><h3>environ</h3><table>" result = result + "</table><h3>environ</h3><table>"
for k,v in self.environ.items(): for k,v in self.environ.items():
if not hide_key(k): if not hide_key(k):
result=result + row % (escape(k), escape(repr(v))) result = result + row % (escape(k), escape(repr(v)))
return result+"</table>" return result + "</table>"
def __repr__(self): def __repr__(self):
return "<%s, URL=%s>" % (self.__class__.__name__, self.get('URL')) return "<%s, URL=%s>" % (self.__class__.__name__, self.get('URL'))
def text(self): def text(self):
result="FORM\n\n" result = "FORM\n\n"
row='%-20s %s\n' row = '%-20s %s\n'
for k,v in self.form.items(): for k, v in self.form.items():
result=result + row % (k, repr(v)) result = result + row % (k, repr(v))
result=result+"\nCOOKIES\n\n" result = result + "\nCOOKIES\n\n"
for k,v in self.cookies.items(): for k, v in self.cookies.items():
result=result + row % (k, repr(v)) result = result + row % (k, repr(v))
result=result+"\nLAZY ITEMS\n\n" result = result + "\nLAZY ITEMS\n\n"
for k,v in self._lazies.items(): for k, v in self._lazies.items():
result=result + row % (k, repr(v)) result = result + row % (k, repr(v))
result=result+"\nOTHER\n\n" result = result + "\nOTHER\n\n"
for k,v in self.other.items(): for k, v in self.other.items():
if k in ('PARENTS','RESPONSE'): continue if k in ('PARENTS','RESPONSE'):
result=result + row % (k, repr(v)) continue
result = result + row % (k, repr(v))
for n in "0123456789": for n in "0123456789":
key = "URL%s"%n key = "URL%s"%n
try: result=result + row % (key, self[key]) try:
except KeyError: pass result = result + row % (key, self[key])
except KeyError:
pass
for n in "0123456789": for n in "0123456789":
key = "BASE%s"%n key = "BASE%s"%n
try: result=result + row % (key, self[key]) try:
except KeyError: pass result = result + row % (key, self[key])
except KeyError:
pass
result=result+"\nENVIRON\n\n" result = result + "\nENVIRON\n\n"
for k,v in self.environ.items(): for k,v in self.environ.items():
if not hide_key(k): if not hide_key(k):
result=result + row % (k, v) result = result + row % (k, v)
return result return result
def _authUserPW(self): def _authUserPW(self):
global base64 global base64
auth=self._auth auth = self._auth
if auth: if auth:
if auth[:6].lower() == 'basic ': if auth[:6].lower() == 'basic ':
if base64 is None: import base64 if base64 is None:
import base64
[name,password] = \ [name,password] = \
base64.decodestring(auth.split()[-1]).split(':', 1) base64.decodestring(auth.split()[-1]).split(':', 1)
return name, password return name, password
...@@ -1442,23 +1550,24 @@ def has_codec(x): ...@@ -1442,23 +1550,24 @@ def has_codec(x):
return 1 return 1
base64=None
def sane_environment(env): def sane_environment(env):
# return an environment mapping which has been cleaned of # return an environment mapping which has been cleaned of
# funny business such as REDIRECT_ prefixes added by Apache # funny business such as REDIRECT_ prefixes added by Apache
# or HTTP_CGI_AUTHORIZATION hacks. # or HTTP_CGI_AUTHORIZATION hacks.
dict={} dict = {}
for key, val in env.items(): for key, val in env.items():
while key[:9]=='REDIRECT_': while key[:9] == 'REDIRECT_':
key=key[9:] key = key[9:]
dict[key]=val dict[key] = val
if dict.has_key('HTTP_CGI_AUTHORIZATION'): if dict.has_key('HTTP_CGI_AUTHORIZATION'):
dict['HTTP_AUTHORIZATION']=dict['HTTP_CGI_AUTHORIZATION'] dict['HTTP_AUTHORIZATION'] = dict['HTTP_CGI_AUTHORIZATION']
try: del dict['HTTP_CGI_AUTHORIZATION'] try:
except: pass del dict['HTTP_CGI_AUTHORIZATION']
except:
pass
return dict return dict
class ZopeFieldStorage(FieldStorage): class ZopeFieldStorage(FieldStorage):
def make_file(self, binary=None): def make_file(self, binary=None):
...@@ -1518,22 +1627,25 @@ class FileUpload: ...@@ -1518,22 +1627,25 @@ class FileUpload:
return self return self
parse_cookie_lock=allocate_lock() parse_cookie_lock = allocate_lock()
QPARMRE= re.compile(
'([\x00- ]*([^\x00- ;,="]+)="([^"]*)"([\x00- ]*[;,])?[\x00- ]*)')
PARMRE = re.compile(
'([\x00- ]*([^\x00- ;,="]+)=([^;,"]*)([\x00- ]*[;,])?[\x00- ]*)')
PARAMLESSRE = re.compile(
'([\x00- ]*([^\x00- ;,="]+)[\x00- ]*[;,][\x00- ]*)')
def parse_cookie(text, def parse_cookie(text,
result=None, result=None,
qparmre=re.compile( qparmre=QPARMRE,
'([\x00- ]*([^\x00- ;,="]+)="([^"]*)"([\x00- ]*[;,])?[\x00- ]*)'), parmre=PARMRE,
parmre=re.compile( paramlessre=PARAMLESSRE,
'([\x00- ]*([^\x00- ;,="]+)=([^;,"]*)([\x00- ]*[;,])?[\x00- ]*)'),
paramlessre=re.compile(
'([\x00- ]*([^\x00- ;,="]+)[\x00- ]*[;,][\x00- ]*)'),
acquire=parse_cookie_lock.acquire, acquire=parse_cookie_lock.acquire,
release=parse_cookie_lock.release, release=parse_cookie_lock.release,
): ):
if result is None: result={} if result is None:
already_have=result.has_key result = {}
already_have = result.has_key
acquire() acquire()
try: try:
...@@ -1542,21 +1654,18 @@ def parse_cookie(text, ...@@ -1542,21 +1654,18 @@ def parse_cookie(text,
if mo_q: if mo_q:
# Match quoted correct cookies # Match quoted correct cookies
l = len(mo_q.group(1))
l = len(mo_q.group(1)) name = mo_q.group(2)
name = mo_q.group(2)
value = mo_q.group(3) value = mo_q.group(3)
else: else:
# Match evil MSIE cookies ;) # Match evil MSIE cookies ;)
mo_p = parmre.match(text) mo_p = parmre.match(text)
if mo_p: if mo_p:
l = len(mo_p.group(1)) l = len(mo_p.group(1))
name = mo_p.group(2) name = mo_p.group(2)
value = mo_p.group(3) value = mo_p.group(3)
else: else:
# Broken Cookie without = nor value. # Broken Cookie without = nor value.
broken_p = paramlessre.match(text) broken_p = paramlessre.match(text)
...@@ -1564,13 +1673,13 @@ def parse_cookie(text, ...@@ -1564,13 +1673,13 @@ def parse_cookie(text,
l = len(broken_p.group(1)) l = len(broken_p.group(1))
name = broken_p.group(2) name = broken_p.group(2)
value = '' value = ''
else: else:
return result return result
finally:
release()
finally: release() if not already_have(name):
result[name] = value
if not already_have(name): result[name]=value
return apply(parse_cookie,(text[l:],result)) return apply(parse_cookie,(text[l:],result))
...@@ -1578,11 +1687,20 @@ def parse_cookie(text, ...@@ -1578,11 +1687,20 @@ def parse_cookie(text,
class record: class record:
# Allow access to record methods and values from DTML # Allow access to record methods and values from DTML
__allow_access_to_unprotected_subobjects__=1 __allow_access_to_unprotected_subobjects__ = 1
_guarded_writes = 1 _guarded_writes = 1
def __getattr__(self, key, default=None): def __getattr__(self, key, default=None):
if key in ('get', 'keys', 'items', 'values', 'copy', 'has_key', '__contains__', '__iter__', '__len__'): if key in ('get',
'keys',
'items',
'values',
'copy',
'has_key',
'__contains__',
'__iter__',
'__len__',
):
return getattr(self.__dict__, key) return getattr(self.__dict__, key)
raise AttributeError, key raise AttributeError, key
...@@ -1607,15 +1725,6 @@ class record: ...@@ -1607,15 +1725,6 @@ class record:
cmp(self.__dict__.items(), other.__dict__.items())) cmp(self.__dict__.items(), other.__dict__.items()))
# Flags
SEQUENCE=1
DEFAULT=2
RECORD=4
RECORDS=8
REC=RECORD|RECORDS
EMPTY=16
CONVERTED=32
# Collector #777: filter out request fields which contain 'passw' # Collector #777: filter out request fields which contain 'passw'
def _filterPasswordFields(items): def _filterPasswordFields(items):
...@@ -1629,16 +1738,3 @@ def _filterPasswordFields(items): ...@@ -1629,16 +1738,3 @@ def _filterPasswordFields(items):
result.append((k, v)) result.append((k, v))
return result return result
# The trusted_proxies configuration setting contains a sequence
# of front-end proxies that are trusted to supply an accurate
# X_FORWARDED_FOR header. If REMOTE_ADDR is one of the values in this list
# and it has set an X_FORWARDED_FOR header, ZPublisher copies REMOTE_ADDR
# into X_FORWARDED_BY, and the last element of the X_FORWARDED_FOR list
# into REMOTE_ADDR. X_FORWARDED_FOR is left unchanged.
# The ZConfig machinery may sets this attribute on initialization
# if any trusted-proxies are defined in the configuration file.
trusted_proxies = []
...@@ -725,7 +725,8 @@ class HTTPResponse(BaseResponse): ...@@ -725,7 +725,8 @@ class HTTPResponse(BaseResponse):
t, v, tb = sys.exc_info() t, v, tb = sys.exc_info()
if t == 'Unauthorized' or t == Unauthorized or ( if t == 'Unauthorized' or t == Unauthorized or (
isinstance(t, (type, types.ClassType)) and issubclass(t, Unauthorized)): isinstance(t, (type, types.ClassType)) and
issubclass(t, Unauthorized)):
t = 'Unauthorized' t = 'Unauthorized'
self._unauthorized() self._unauthorized()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment