[Zope] ZPublisher.Config and ZPublisher.Plumbing
Phillip J. Eby
pje@telecommunity.com
Mon, 08 Feb 1999 15:22:54 -0500
--=====================_918523374==_
Content-Type: text/plain; charset="us-ascii"
At 10:55 AM 2/8/99 -0500, Phillip J. Eby wrote:
>
>My newer FastCGI code is more a matter of changing to use Robin Dunn's
>"fcgi" module in place of DC's "fcgiapp" so that it can be run
>multithreaded, and creating a class framework for standalone publishers
>that takes care of most of the messy plumbing overhead. I'm factoring the
>code into (proposed) ZPublisher.Config and ZPublisher.Plumbing. I hope to
>have some working code to present today.
Well, here they are:
ZPublisher.Config - configuration and publishing defaults for Zope
ZPublisher.Plumbing - Zope "plumbing" base class w/subclasses for CGI &
FastCGI
Zopestart - A script for starting Zope under CGI or FastCGI
I have been running Zope under an earlier FastCGI attempt for the last
couple of weeks; and have been running this version for a few hours today.
To use these files, you'll need to stick Plumbing.py and Config.py into the
lib/python/ZPublisher directory of your Zope installation, and Zopestart
someplace it can be executed by your CGI back-end. You can edit it to
override "INSTANCE_HOME" or you can pass it INSTANCE_HOME in the
environment. You will need a FastCGI-supporting server or a cgi-fcgi
script to use it.
It should be possible to create subclasses to handle PCGI and direct HTTP,
but may not be worthwhile in favor of using ZServer.
--=====================_918523374==_
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="Publish.py"
############################################################################=
##
#
# Zope Public License (ZPL) Version 0.9.5
# ---------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Any use, including use of the Zope software to operate a website,
# must either comply with the terms described below under
# "Attribution" or alternatively secure a separate license from
# Digital Creations. Digital Creations will not unreasonably
# deny such a separate license in the event that the request
# explains in detail a valid reason for withholding attribution.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# Attribution
#
# Individuals or organizations using this software as a web site must
# provide attribution by placing the accompanying "button" and a link
# to the accompanying "credits page" on the website's main entry
# point. In cases where this placement of attribution is not
# feasible, a separate arrangment must be concluded with Digital
# Creations. Those using the software for purposes other than web
# sites must provide a corresponding attribution in locations that
# include a copyright using a manner best suited to the application
# environment. Where attribution is not possible, or is considered
# to be onerous for some other reason, a request should be made to
# Digital Creations to waive this requirement in writing. As stated
# above, for valid requests, Digital Creations will not unreasonably
# deny such requests.
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#=
############################################################################=
##
__doc__=3D"""Python Object Publisher -- Publish Python objects on web=
servers
$Id: Publish.py,v 1.114 1998/12/11 20:53:46 jim Exp=
$"""
__version__=3D'$Revision: 1.114 $'[11:-2]
import sys, os, string, cgi, regex
from string import lower, atoi, rfind, split, strip, join, upper, find
from Response import Response
from urllib import quote, unquote
from cgi import FieldStorage
from Request import Request, isCGI_NAME
from Converters import type_converters
# Waaaa, I wish I didn't have to work this hard.
try: from thread import allocate_lock
except:
class allocate_lock:
def acquire(*args): pass
def release(*args):=
pass
ListType=3Dtype([])
StringType=3Dtype('')
UNSPECIFIED_ROLES=3D''
try:
from ExtensionClass import Base
class RequestContainer(Base):
def __init__(self,**kw):
for k,v in kw.items(): self.__dict__[k]=3Dv
def manage_property_types(self):
return type_converters.keys()
except:
class RequestContainer:
def __init__(self,**kw):
for k,v in kw.items(): self.__dict__[k]=3Dv
class ModulePublisher:
HTTP_AUTHORIZATION=3DNone
_hacked_path=3DNone
def __init__(self,
stdin=3Dsys.stdin, stdout=3Dsys.stdout, stderr=3Dsys.stderr=
,
environ=3Dos.environ):
self.environ=3Denviron
fp=3DNone
try:
if environ['REQUEST_METHOD'] !=3D 'GET': fp=3Dstdin
except: pass
if environ.has_key('HTTP_AUTHORIZATION'):
self.HTTP_AUTHORIZATION=3Denviron['HTTP_AUTHORIZATION']
try: del environ['HTTP_AUTHORIZATION']
except: pass
elif environ.has_key('HTTP_CGI_AUTHORIZATION'):
self.HTTP_AUTHORIZATION=3Denviron['HTTP_CGI_AUTHORIZATION']
try: del environ['HTTP_CGI_AUTHORIZATION']
except: pass
form=3D{}
form_has=3Dform.has_key
other=3D{}
fs=3DFieldStorage(fp=3Dfp,environ=3Denviron,keep_blank_values=3D1)
if not hasattr(fs,'list') or fs.list is None:
form['BODY']=3Dother['BODY']=3Dfs.value
else:
meth=3DNone
fslist=3Dfs.list
tuple_items=3D{}
type_re=3Dregex.compile(':[a-zA-Z][a-zA-Z0-9_]+')
type_search=3Dtype_re.search
lt=3Dtype([])
CGI_name=3DisCGI_NAME
for item in fslist:
key=3Dunquote(item.name)
if (hasattr(item,'file') and hasattr(item,'filename')
and hasattr(item,'headers')):
if (item.file and
(item.filename is not None or
'content-type' in map(lower,
item.headers.keys()))):
item=3DFileUpload(item)
else:
item=3Ditem.value
seqf=3DNone
l=3Dtype_search(key)
while l >=3D 0:
type_name=3Dtype_re.group(0)[1:]
key=3Dkey[:l]+key[l+len(type_name)+1:]
if type_name =3D=3D 'list':
seqf=3Dlist
elif type_name =3D=3D 'tuple':
seqf=3Dtuple
tuple_items[key]=3D1
elif type_name =3D=3D 'method':
if l: meth=3Dkey
else: meth=3Ditem
elif type_name =3D=3D 'default_method':
if not meth:
if l: meth=3Dkey
else: meth=3Ditem
else:
item=3Dtype_converters[type_name](item)
l=3Dtype_search(key)
# Filter out special names from form:
if CGI_name(key) or key[:5]=3D=3D'HTTP_': continue
if form_has(key):
found=3Dform[key]
if type(found) is lt: found.append(item)
else:
found=3D[found,item]
form[key]=3Dfound
other[key]=3Dfound
else:
if seqf: item=3D[item]
form[key]=3Ditem
other[key]=3Ditem
for key in tuple_items.keys():
item=3Dtuple(form[key])
form[key]=3Ditem
other[key]=3Ditem
if meth:
if environ.has_key('PATH_INFO'):
path=3Denviron['PATH_INFO']
while path[-1:]=3D=3D'/': path=3Dpath[:-1]
else: path=3D''
other['PATH_INFO']=3Dpath=3D"%s/%s" % (path,meth)
self._hacked_path=3D1
# Cookie values should *not* be appended to existing form
# vars with the same name - they are more like default values
# for names not otherwise specified in the form.
cookies=3D{}
if environ.has_key('HTTP_COOKIE'):
parse_cookie(self.environ['HTTP_COOKIE'],cookies)
for k,item in cookies.items():
if not other.has_key(k):
other[k]=3Ditem
request=3Dself.request=3DRequest(environ,other,stdin)
request.form=3Dform
if cookies is not None: request.cookies=3Dcookies
self.response=3Dresponse=3DResponse(stdout=3Dstdout, stderr=3Dstderr=
)
request['RESPONSE']=3Dresponse
self.stdin=3Dstdin
self.stdout=3Dstdout
self.stderr=3Dstderr
self.base=3Drequest.base
self.script=3Drequest.script
def html(self,title,body):
return ("<html>\n"
"<head>\n<title>%s</title>\n</head>\n"
"<body>\n%s\n</body>\n"
"</html>\n" % (title,body))
def notFoundError(self,entry=3D'who knows!'):
raise 'NotFound',self.html(
"Resource not found",
"Sorry, the requested document does not exist.<p>"
"\n<!--\n%s\n-->" % entry)
forbiddenError=3DnotFoundError # If a resource is forbidden,
# why reveal that it exists?
def debugError(self,entry):
raise 'NotFound',self.html(
"Debugging Notice",
"Bobo has encountered a problem publishing your object.<p>"
"\n%s" % entry)
def badRequestError(self,name):
if regex.match('^[A-Z_0-9]+$',name) >=3D 0:
raise 'InternalError', self.html(
"Internal Error",
"Sorry, an internal error occurred in this resource.")
raise 'BadRequest',self.html(
"Invalid request",
"The parameter, <em>%s</em>, was omitted from the request."
"<!--%s-->"
% (name,self.request))
def unauthorized(self, realm,debug_mode=3DNone):
if not (self.request.has_key('REMOTE_USER') and
self.request['REMOTE_USER']):
self.response['WWW-authenticate']=3D'basic realm=3D"%s"' %=
realm
m=3D"<strong>You are not authorized to access this=
resource.</strong>"
if debug_mode:
if self.HTTP_AUTHORIZATION:
m=3Dm+'\nUsername and password are not correct.'
else:
m=3Dm+'\nNo Authorization header found.'
raise 'Unauthorized', m
def forbiddenError(self,object=3DNone):
raise 'NotFound',self.html(
"Resource not found",
"Sorry, the requested document does not exist.<p>"
"<!--%s-->" % object)
def get_request_data(self,request_params):
try: request_params=3Drequest_params()
except: pass
for key in request_params.keys():
self.request[key]=3Drequest_params[key]
def publish(self, module_name, after_list, published=3D'web_objects',
imported_modules=3D{}, module_dicts=3D{},debug=3D0):
request=3Dself.request
request_get=3Drequest.get
response=3Dself.response
# First check for "cancel" redirect:
cancel=3D''
if request_get('SUBMIT','')=3D=3D'cancel':
cancel=3Drequest_get('CANCEL_ACTION','')
if cancel: raise 'Redirect', cancel
(bobo_before, bobo_after, request_params,
inherited_groups, groups, roles,
object, doc, published, realm, module_name,
debug_mode)=3D get_module_info(module_name)
after_list[0]=3Dbobo_after
if bobo_before is not None: bobo_before();
if request_params: self.get_request_data(request_params)
# Get a nice clean path list:
path=3Dstrip(request_get('PATH_INFO'))
__traceback_info__=3Dpath
if path[:1] !=3D '/': path=3D'/'+path
if path[-1:] !=3D '/': path=3Dpath+'/'
if find(path,'/.') >=3D 0:
path=3Djoin(split(path,'/./'),'/')
l=3Dfind(path,'/../',1)
while l > 0:
p1=3Dpath[:l]
path=3Dpath[:rfind(p1,'/')+1]+path[l+4:]
l=3Dfind(path,'/../',1)
path=3Dpath[1:-1]
path=3Dsplit(path,'/')
while path and not path[0]: path =3D path[1:]
method=3Dupper(request_get('REQUEST_METHOD'))
if method=3D=3D'GET' or method=3D=3D'POST': method=3D'index_html'
URL=3Dself.script
# if the top object has a __bobo_traverse__ method, then use it
# to possibly traverse to an alternate top-level object.
if hasattr(object,'__bobo_traverse__'):
request['URL']=3DURL
try: object=3Dobject.__bobo_traverse__(request)
except: pass
# Get default object if no path was specified:
if not path:
entry_name=3Dmethod
try:
if hasattr(object,entry_name):
response.setBase(URL)
path=3D[entry_name]
else:
try:
if object.has_key(entry_name):
path=3D[entry_name]
except: pass
except: pass
if not path: path =3D ['help']
# Traverse the URL to find the object:
request['PARENTS']=3Dparents=3D[]
if hasattr(object, '__of__'):
# Try to bind the top-level object to the request
object=3Dobject.__of__(RequestContainer(REQUEST=3Drequest))
steps=3D[]
while path:
entry_name,path=3Dpath[0], path[1:]
URL=3D"%s/%s" % (URL,quote(entry_name))
got=3D0
if entry_name:
if entry_name[:1]=3D=3D'_':
if debug_mode:
self.debugError("Object name begins with an=
underscore at: %s" % URL)
else: self.forbiddenError(entry_name)
if hasattr(object,'__bobo_traverse__'):
request['URL']=3DURL
subobject=3Dobject.__bobo_traverse__(request,entry_name)
if type(subobject) is type(()) and len(subobject) > 1:
while len(subobject) > 2:
parents.append(subobject[0])
subobject=3Dsubobject[1:]
object, subobject =3D subobject
else:
try:
subobject=3Dgetattr(object,entry_name)
except AttributeError:
got=3D1
try: subobject=3Dobject[entry_name]
except (KeyError, IndexError,
TypeError, AttributeError):
if entry_name=3D=3D'.': subobject=3Dobject
elif entry_name=3D=3D'..' and parents:
subobject=3Dparents[-1]
elif debug_mode:
self.debugError(
"Cannot locate object at: %s" %URL)
else: self.notFoundError(URL)
if subobject is object and entry_name=3D=3D'.':
URL=3DURL[:rfind(URL,'/')]
else:
try:
try: doc=3Dsubobject.__doc__
except: doc=3Dgetattr(object, entry_name+'__doc__')
if not doc: raise AttributeError, entry_name
except:
if debug_mode:
self.debugError("Missing doc string at: %s" %=
URL)
else: self.notFoundError("%s" % (URL))
if hasattr(subobject,'__roles__'):
roles=3Dsubobject.__roles__
else:
if not got:
roleshack=3Dentry_name+'__roles__'
if hasattr(object, roleshack):
roles=3Dgetattr(object, roleshack)
# Promote subobject to object
parents.append(object)
object=3Dsubobject
steps.append(entry_name)
# Check for method:
if not path:
if hasattr(object,method) and entry_name !=3D method:
response.setBase(URL)
path=3D[method]
else:
if (hasattr(object, '__call__') and
hasattr(object.__call__,'__roles__')):
roles=3Dobject.__call__.__roles__
if self._hacked_path:
i=3Drfind(URL,'/')
if i > 0: response.setBase(URL[:i])
if entry_name !=3D method and method !=3D 'index_html':
if debug_mode:
self.debugError("Method %s not found at: %s" %=
(method,URL))
else: self.notFoundError(method)
request.steps=3Dsteps
parents.reverse()
# Do authorization checks
user=3DNone
i=3D0
if roles is not None:
last_parent_index=3Dlen(parents)
if hasattr(object, '__allow_groups__'):
groups=3Dobject.__allow_groups__
inext=3D0
else:
inext=3DNone
for i in range(last_parent_index):
if hasattr(parents[i],'__allow_groups__'):
groups=3Dparents[i].__allow_groups__
inext=3Di+1
break
if inext is not None:
i=3Dinext
if hasattr(groups, 'validate'): v=3Dgroups.validate
else: v=3Dold_validation
auth=3Dself.HTTP_AUTHORIZATION
if v is old_validation and roles is UNSPECIFIED_ROLES:
# No roles, so if we have a named group, get roles from
# group keys
if hasattr(groups,'keys'): roles=3Dgroups.keys()
else:
try: groups=3Dgroups()
except: pass
try: roles=3Dgroups.keys()
except: pass
if groups is None:
# Public group, hack structures to get it to=
validate
roles=3DNone
auth=3D''
if v is old_validation:
user=3Dold_validation(groups, request, auth, roles)
elif roles is UNSPECIFIED_ROLES: user=3Dv(request, auth)
else: user=3Dv(request, auth, roles)
=20 while user is None and i < last_parent_index:
parent=3Dparents[i]
i=3Di+1
if hasattr(parent, '__allow_groups__'):
groups=3Dparent.__allow_groups__
else: continue
if hasattr(groups,'validate'): v=3Dgroups.validate
else: v=3Dold_validation
if v is old_validation:
user=3Dold_validation(groups, request, auth, roles)
elif roles is UNSPECIFIED_ROLES: user=3Dv(request,=
auth)
else: user=3Dv(request, auth, roles)
if user is None and roles !=3D UNSPECIFIED_ROLES:
self.unauthorized(realm,debug_mode)
steps=3Djoin(steps[:-i],'/')
if user is not None:
request['AUTHENTICATED_USER']=3Duser
request['AUTHENTICATION_PATH']=3Dsteps
# Attempt to start a transaction:
try: transaction=3Dget_transaction()
except: transaction=3DNone
if transaction is not None:
info=3D"\t" + request_get('PATH_INFO')
auth_user=3Drequest_get('AUTHENTICATED_USER',None)
if auth_user is not None:
info=3D("%s %s" % (steps,auth_user))+info
transaction.begin(info)
# Now get object meta-data to decide if and how it should be
# called:
object_as_function=3Dobject
# First, assume we have a method:
if hasattr(object_as_function,'im_func'):
f=3Dobject_as_function.im_func
c=3Df.func_code
defaults=3Df.func_defaults
argument_names=3Dc.co_varnames[1:c.co_argcount]
else:
# Rather than sniff for FunctionType, assume its a
# function and fall back to returning the object itself: =
if hasattr(object_as_function,'func_defaults'):
defaults=3Dobject_as_function.func_defaults
c=3Dobject_as_function.func_code
argument_names=3Dc.co_varnames[:c.co_argcount]
# Make sure we don't have a class that smells like a func
if hasattr(object_as_function, '__bases__'):
self.forbiddenError(entry_name)
else: return response.setBody(object)
request['URL']=3DURL
request['PARENT_URL']=3DURL[:rfind(URL,'/')]
args=3D[]
nrequired=3Dlen(argument_names) - (len(defaults or []))
for name_index in range(len(argument_names)):
argument_name=3Dargument_names[name_index]
v=3Drequest_get(argument_name, args)
if v is args:
if argument_name=3D=3D'self': args.append(parents[0])
elif name_index < nrequired:
self.badRequestError(argument_name)
else: args.append(defaults[name_index-nrequired])
else: args.append(v)
args=3Dtuple(args)
if debug: result=3Dself.call_object(object,args)
else: result=3Dapply(object,args)
if result and result is not response: response.setBody(result)
if transaction: transaction.commit()
return response
def call_object(self,object,args):
result=3Dapply(object,args) # Type s<cr> to step into published=
object.
return result
_l=3Dallocate_lock()
def get_module_info(module_name, modules=3D{},
acquire=3D_l.acquire,
release=3D_l.release,
):
if modules.has_key(module_name): return modules[module_name]
if module_name[-4:]=3D=3D'.cgi': module_name=3Dmodule_name[:-4]
acquire()
tb=3DNone
try:
try:
module=3D__import__(module_name, globals(), globals(),=
('__doc__',))
realm=3Dmodule_name
# Let the app specify a realm
if hasattr(module,'__bobo_realm__'):
realm=3Dmodule.__bobo_realm__
elif os.environ.has_key('Z_REALM'):
realm=3Dos.environ['Z_REALM']
elif os.environ.has_key('BOBO_REALM'):
realm=3Dos.environ['BOBO_REALM']
else: realm=3Dmodule_name
# Check for debug mode
if hasattr(module,'__bobo_debug_mode__'):
debug_mode=3Dnot not module.__bobo_debug_mode__
elif (os.environ.has_key('Z_DEBUG_MODE') or
os.environ.has_key('BOBO_DEBUG_MODE')):
if os.environ.has_key('Z_DEBUG_MODE'):
debug_mode=3Dlower(os.environ['Z_DEBUG_MODE'])
else:
debug_mode=3Dlower(os.environ['BOBO_DEBUG_MODE'])
if debug_mode=3D=3D'y' or debug_mode=3D=3D'yes':
debug_mode=3D1
else:
try: debug_mode=3Datoi(debug_mode)
except: debug_mode=3DNone
else: debug_mode=3DNone
# Check whether tracebacks should be hidden:
if hasattr(module,'__bobo_hide_tracebacks__'):
hide_tracebacks=3Dnot not module.__bobo_hide_tracebacks__
elif os.environ.has_key('BOBO_HIDE_TRACEBACKS'):
hide_tracebacks=3Dlower(os.environ['BOBO_HIDE_TRACEBACKS'])
if hide_tracebacks=3D=3D'y' or hide_tracebacks=3D=3D'yes':
hide_tracebacks=3D1
else:
try: hide_tracebacks=3Datoi(hide_tracebacks)
except: hide_tracebacks=3DNone
else: hide_tracebacks=3D1
# Reset response handling of tracebacks, if necessary:
if debug_mode or not hide_tracebacks:
def hack_response():
import Response
Response._tbopen =3D '<PRE>'
Response._tbclose =3D '</PRE>'
hack_response()
if hasattr(module,'__bobo_before__'):
bobo_before=3Dmodule.__bobo_before__
else: bobo_before=3DNone
if hasattr(module,'__bobo_after__'):=
bobo_after=3Dmodule.__bobo_after__
else: bobo_after=3DNone
# Get request data from outermost environment:
if hasattr(module,'__request_data__'):
request_params=3Dmodule.__request_data__
else: request_params=3DNone
# Get initial group data:
inherited_groups=3D[]
if hasattr(module,'__allow_groups__'):
groups=3Dmodule.__allow_groups__
inherited_groups.append(groups)
else: groups=3DNone
web_objects=3DNone
roles=3DUNSPECIFIED_ROLES
if hasattr(module,'bobo_application'):
object=3Dmodule.bobo_application
if hasattr(object,'__allow_groups__'):
groups=3Dobject.__allow_groups__
inherited_groups.append(groups)
else: groups=3DNone
if hasattr(object,'__roles__'): roles=3Dobject.__roles__
else:
if hasattr(module,'web_objects'):
web_objects=3Dmodule.web_objects
object=3Dweb_objects
else: object=3Dmodule
published=3Dweb_objects
try: doc=3Dmodule.__doc__
except:
if web_objects is not None: doc=3D' '
else: doc=3DNone
info=3D (bobo_before, bobo_after, request_params,
inherited_groups, groups, roles,
object, doc, published, realm, module_name,
debug_mode)
modules[module_name]=3Dmodules[module_name+'.cgi']=3Dinfo
return info
except:
if hasattr(sys, 'exc_info'): t,v,tb=3Dsys.exc_info()
else: t, v, tb =3D sys.exc_type, sys.exc_value, sys.exc_traceback
v=3Dstr(v)
raise ImportError, (t, v), tb
finally:
tb=3DNone
release()
def str_field(v):
if type(v) is ListType:
return map(str_field,v)
if hasattr(v,'__class__') and v.__class__ is FieldStorage:
v=3Dv.value
elif type(v) is not StringType:
if hasattr(v,'file') and v.file: v=3Dv.file
elif hasattr(v,'value'): v=3Dv.value
return v
class FileUpload:
'''\
File upload objects
File upload objects are used to represent file-uploaded data.
File upload objects can be used just like files.
In addition, they have a 'headers' attribute that is a dictionary
containing the file-upload headers, and a 'filename' attribute
containing the name of the uploaded file.
'''
def __init__(self, aFieldStorage):
file=3DaFieldStorage.file
if hasattr(file, '__methods__'): methods=3Dfile.__methods__
else: methods=3D ['close', 'fileno', 'flush', 'isatty',
'read', 'readline', 'readlines', 'seek',
'tell', 'truncate', 'write', 'writelines']
d=3Dself.__dict__
for m in methods:
if hasattr(file,m): d[m]=3Dgetattr(file,m)
self.headers=3DaFieldStorage.headers
self.filename=3DaFieldStorage.filename
parse_cookie_lock=3Dallocate_lock()
def parse_cookie(text,
result=3DNone,
qparmre=3Dregex.compile(
'\([\0- ]*'
'\([^\0- ;,=3D\"]+\)=3D"\([^"]*\)\"'
'\([\0- ]*[;,]\)?[\0- ]*\)'
),
parmre=3Dregex.compile(
'\([\0- ]*'
'\([^\0- ;,=3D\"]+\)=3D\([^\0;-=3D\"]*\)'
'\([\0- ]*[;,]\)?[\0- ]*\)'
),
acquire=3Dparse_cookie_lock.acquire,
release=3Dparse_cookie_lock.release,
):
if result is None: result=3D{}
already_have=3Dresult.has_key
acquire()
try:
if qparmre.match(text) >=3D 0:
# Match quoted correct cookies
name=3Dqparmre.group(2)
value=3Dqparmre.group(3)
l=3Dlen(qparmre.group(1))
elif parmre.match(text) >=3D 0:
# Match evil MSIE cookies ;)
name=3Dparmre.group(2)
value=3Dparmre.group(3)
l=3Dlen(parmre.group(1))
else:
if not text or not strip(text): return result
raise "InvalidParameter", text
finally: release()
if not already_have(name): result[name]=3Dvalue
return apply(parse_cookie,(text[l:],result))
base64=3DNone
def old_validation(groups, request, HTTP_AUTHORIZATION,
roles=3DUNSPECIFIED_ROLES):
global base64
if base64 is None: import base64
if HTTP_AUTHORIZATION:
if lower(HTTP_AUTHORIZATION[:6]) !=3D 'basic ':
if roles is None: return ''
return None
[name,password] =3D split(
base64.decodestring(
split(HTTP_AUTHORIZATION)[-1]), ':')
elif request.environ.has_key('REMOTE_USER'):
name=3Drequest.environ['REMOTE_USER']
password=3DNone
else:
if roles is None: return ''
return None
if roles is None: return name
keys=3DNone
try:
keys=3Dgroups.keys
except:
try:
groups=3Dgroups() # Maybe it was a method defining a group
keys=3Dgroups.keys
except: pass
if keys is not None:
# OK, we have a named group, so apply the roles to the named
# group.
if roles is UNSPECIFIED_ROLES: roles=3Dkeys()
g=3D[]
for role in roles:
if groups.has_key(role): g.append(groups[role])
groups=3Dg
for d in groups:
if d.has_key(name) and (d[name]=3D=3Dpassword or password is None):
return name
if keys is None:
# Not a named group, so don't go further
raise 'Forbidden', (
"""<strong>You are not authorized to access this resource""")
return None
def publish_module(module_name,
stdin=3Dsys.stdin, stdout=3Dsys.stdout,=
stderr=3Dsys.stderr,
environ=3Dos.environ, debug=3D0):
must_die=3D0
status=3D200
after_list=3D[None]
request=3DNone
try:
try:
try:
response=3DResponse(stdout=3Dstdout, stderr=3Dstderr)
publisher =3D ModulePublisher(
stdin=3Dstdin, stdout=3Dstdout, stderr=3Dstderr,
environ=3Denviron)
response =3D publisher.response
request=3Dpublisher.request
finally:
pass
response =3D publisher.publish(module_name,after_list,
debug=3Ddebug)
except SystemExit, v:
if hasattr(sys, 'exc_info'): must_die=3Dsys.exc_info()
else: must_die =3D SystemExit, v, sys.exc_traceback
response.exception(must_die)
except ImportError, v:
if type(v) is type(()) and len(v)=3D=3D3: must_die=3Dv
elif hasattr(sys, 'exc_info'): must_die=3Dsys.exc_info()
else: must_die =3D SystemExit, v, sys.exc_traceback
response.exception(1, v)
except:
response.exception()
status=3Dresponse.getStatus()
if response:
response=3Dstr(response)
if response: stdout.write(response)
# The module defined a post-access function, call it
if after_list[0] is not None: after_list[0]()
finally:
if request is not None: request.other=3D{}
if must_die: raise must_die[0], must_die[1], must_die[2]
sys.exc_type, sys.exc_value, sys.exc_traceback =3D None, None, None
return status
--=====================_918523374==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="Config.py"
import __main__, os, sys
class ZConfig:
"""ZPublisher Configuration Object"""
def __init__(self):
d=self.__dict__
for k,v in os.environ.items(): d[k]=v
d.update(__main__.__dict__)
def __getattr__(self,attr):
if hasattr(self.__dict__,attr): return getattr(self.__dict__,attr)
else: return self[attr]
def get(self,*args): return apply(self.__dict__.get,args)
__getitem__ = get
def default(self,item,val): setattr(self,item,self.get(item,val))
me = sys.argv[0] # The original executable
ZConfig = ZConfig()
ZConfig.default('PUBLISHED_MODULE',os.path.splitext(os.path.basename(me))[0])
ZConfig.default('INCLUDE_PATHS',[])
using_symlinks = 0
while me and os.stat(me) != os.lstat(me): me = os.readlink(me); using_symlinks = 1
if using_symlinks: ZConfig.default('MODULE_HOME',os.path.dirname(me))
if ZConfig.INCLUDE_PATHS:
sys.path[0:0]=filter(lambda p,pp=sys.path: p not in pp, ZConfig.INCLUDE_PATHS)
if ZConfig.MODULE_HOME:
cdir=os.path.join(ZConfig.MODULE_HOME,'Components')
sys.path[0:0]=[ZConfig.MODULE_HOME,cdir,os.path.join(cdir,sys.platform)]
try: import thread
except: ZConfig.USE_THREADS = 0 # Don't have threads? Can't use 'em
else: ZConfig.default('USE_THREADS',1) # Do have 'em, don't have to use 'em
ZConfig.default('SINGLE_THREAD_PUBLISHER',1) # Either way, assume the safe thing.
ZConfig.default('MAX_REQUESTS',-1) # Infinite number of requests
ZConfig.default('MAX_LIFETIME',0) # Infinite lifetime
ZConfig.default('IDLE_TIMEOUT',0) # Infinite idle timeout
ZConfig.default('IIS_HACK', string.find(ZConfig.get('SERVER_SOFTWARE',''),'Microsoft-IIS') != -1)
--=====================_918523374==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="Zopestart"
#!/u/idsuser/Python151/bin/python
import os,sys
PUBLISHED_MODULE = "Main"
SOFTWARE_HOME = os.environ["SOFTWARE_HOME"] = "%s/lib/python" % os.path.dirname(sys.argv[0])
INCLUDE_PATHS = [SOFTWARE_HOME]
PROCESS_LOCK_FILE = "%s/var/Zope.lock" % os.environ["INSTANCE_HOME"]
USE_THREADS = 0
sys.path[0:0]=INCLUDE_PATHS
import ZPublisher.Plumbing
--=====================_918523374==_--