##################################################
# SPYCE - Python-based HTML Scripting
# Copyright (c) 2002 Rimon Barr.
#
# Refer to spyce.py
# CVS: $Id: request.py 1021 2006-08-04 01:10:53Z ellisj $
##################################################
from spyceModule import spyceModule
import spyce, cgi, string, urlparse, spyceUtil, sys
__doc__ = """Request module provides access to the browser request
information. """
def lowerize(d):
"""
returns a dict containing the list values of d, mapped to lower-case keys.
d may contain keys that differ only in case.
"""
lowered = {}
for key in d:
keyL = string.lower(key)
lowered[keyL] = lowered.get(keyL, []) + d[key]
return lowered
def extractValue(hash, key, default, single):
"""
Extract key's value from dictionary [of lists], if it exists.
If single, return value[0].
If key is none, return entire dictionary, or dictionary of first values if single.
Else if key is not found, return default.
"""
if key is None:
if single:
d = {}
for key in hash:
d[key] = hash[key][0]
return d
return hash
if key in hash:
if single:
return hash[key][0]
return hash[key]
if default == []: default = [] # workaround default-only-evaluated-once "feature"
return default
def filterDict(request, d, filters):
for f in filters:
f(request, d)
class request(spyceModule):
def start(self):
"Initialise module variables"
self._initted = False
if spyce.DEBUG_ERROR:
sys.stderr.write('GET variables: %s\n' % self.get())
sys.stderr.write('POST variables: %s\n' % self.post())
def uri(self, component=None):
"Return request URI, or URI component"
theuri = self._api.getRequest().env()['REQUEST_URI']
if not component:
return theuri
else:
component = string.lower(component)
if component == 'scheme': component = 0
elif component == 'location': component = 1
elif component == 'path': component = 2
elif component == 'parameters': component = 3
elif component == 'query': component = 4
elif component == 'fragment': component = 5
else: raise 'unknown uri component'
return urlparse.urlparse(theuri)[component]
def uri_scheme(self):
"Return request URI scheme, ie. http (usually)"
return urlparse.urlparse(self.uri())[0]
def uri_location(self):
"Return request URI scheme, ie. http (usually)"
return urlparse.urlparse(self.uri())[1]
def uri_path(self):
"Return request URI path component"
return urlparse.urlparse(self.uri())[2]
def method(self):
"Return request method: get/post/..."
return string.upper(self._api.getRequest().env()['REQUEST_METHOD'])
def query(self):
"Return request query string"
return self._api.getRequest().env()['QUERY_STRING']
def stack(self, i=None):
s = self._api.getStack()
if i is not None: s = s[i]
return s
def filename(self, relative=None):
"Return original Spyce filename"
myfile = self._api.getFilename()
if relative is None:
return myfile
else:
return os.path.realpath(os.path.join(os.path.dirname(myfile), relative))
def default(self, value, value2):
"Return value, or value2 if value is None"
if value is None: return value2
return value
def _getInit(self):
self._get = cgi.parse_qs(self.query(), 1)
def get(self, name=None, default=[], ignoreCase=0, single=False):
"Return GET parameter(s) list(s)"
self._init()
if ignoreCase:
if name: name = string.lower(name)
return extractValue(self._getL, name, default, single)
return extractValue(self._get, name, default, single)
def get1(self, name=None, default=None, ignoreCase=0):
"Return single GET parameter(s)"
return self.get(name, default, ignoreCase, True)
def _postInit(self):
if hasattr(self._api.getRequest(), 'spycepostinfo'):
# stream was already parsed (possibly this is an internal redirect)
(self._post, self._file) = self._api.getRequest().spycepostinfo
return
self._post = {}
self._file = {}
try: len = int(str(self.env('CONTENT_LENGTH')))
except: len=0
if self.method()=='POST' and len:
postfields = cgi.FieldStorage(fp=self._api.getRequest(), environ=self.env(), keep_blank_values=1)
for key in postfields.keys():
if type(postfields[key]) == type( [] ):
self._post[key] = map(lambda attr: attr.value, postfields[key])
elif not postfields[key].filename:
self._post[key] = [postfields[key].value]
else:
self._file[key] = postfields[key]
# save parsed information in request object to prevent reparsing (on redirection)
self._api.getRequest().spycepostinfo = (self._post, self._file)
def _init(self):
if self._initted:
return
# get raw parameters before filtering
# this allows sophisticated filters to take action based on the "big picture"
# not just individual key/values
self._getInit()
self._postInit()
filterDict(self, self._get, spyce.getServer().config.param_filters)
filterDict(self, self._post, spyce.getServer().config.param_filters)
filterDict(self, self._file, spyce.getServer().config.file_filters)
# generate lowercase dicts after filtering
self._getL = lowerize(self._get)
self._postL = lowerize(self._post)
self._fileL = {}
for key in self._file:
self._fileL[string.lower(key)] = self._file[key]
self._initted = True
def post(self, name=None, default=[], ignoreCase=False, single=False):
"Return POST parameter(s) list(s)"
self._postInit()
if ignoreCase:
if name: name = string.lower(name)
return extractValue(self._postL, name, default, single)
return extractValue(self._post, name, default, single)
def post1(self, name=None, default=None, ignoreCase=0):
"Return single POST parameter(s)"
return self.post(name, default, ignoreCase, True)
def file(self, name=None, ignoreCase=0):
"Return POSTed file(s)"
self._init()
if ignoreCase:
if name: name = string.lower(name)
return spyceUtil.extractValue(self._fileL, name)
else:
return spyceUtil.extractValue(self._file, name)
def env(self, name=None, default=None):
"Return other request (CGI) environment variables"
return self.default(self._api.getRequest().env(name), default)
def getHeader(self, type=None):
"Return browser HTTP header(s)"
return self._api.getRequest().getHeader(type)
# __setitem__ deliberately left out --
# if you really truly want to present a modified view of request parameters
# to yourself, use add[File|Param]Filter.
def __getitem__(self, key):
if type(key) == type(0):
spyce.DEBUG('returning raw for %s' % key)
return self.getpost().keys()[key]
else:
v = self.get1(key)
if v is not None: return v
v = self.post1(key)
if v is not None: return v
v = self.file(key)
spyce.DEBUG('getitem for %s is %s' % (key, v))
if v is not None: return v
def __repr__(self):
return ''
def _multidict(self, *args):
args = list(args)
args.reverse()
dict = {}
for d in args:
for k in d.keys():
dict[k] = d[k]
return dict
def getpost(self, name=None, default=None, ignoreCase=0):
"Return get() if not None, otherwise post() if not None, otherwise default"
if name is None:
self._init()
return self._multidict(self._get, self._post)
else:
value = self.get(name, None, ignoreCase)
if value is None: value = self.post(name, default, ignoreCase)
return value
def getpost1(self, name=None, default=None, ignoreCase=0):
"Return get1() if not None, otherwise post1() if not None, otherwise default"
if name is None:
self._init()
return self._multidict(self.get1(), self.post1())
else:
value = self.get1(name, None, ignoreCase)
if value is None: value = self.post1(name, default, ignoreCase)
return value
def postget(self, name=None, default=None, ignoreCase=0):
"Return post() if not None, otherwise get() if not None, otherwise default"
if name is None:
self._init()
return self._multidict(self._post, self._get)
else:
value = self.post(name, None, ignoreCase)
if value is None: value = self.get(name, default, ignoreCase)
return value
def postget1(self, name=None, default=None, ignoreCase=0):
"Return post1() if not None, otherwise get1() if not None, otherwise default"
if name is None:
self._init()
return self._multidict(self.post1(), self.get1())
else:
value = self.post1(name, None, ignoreCase)
if value is None: value = self.get1(name, default, ignoreCase)
return value
|