[Zope] ANN: Serving PHP/Perl from Zope update
Bill Welch
bill@carbonecho.com
Wed, 6 Sep 2000 14:56:09 +0000 (GMT)
I had to dig a level deeper to support phorum (www.phorum.org), a PHP
message board app. Here's my update to handle cookies, redirection, POST
variables, and relative links. I'm new to python, so if I've done anything
awkwardly, please let me know the more elegant way.
First, a patch to Client.py - first part doesn't die on redirects and
returns (instead of raising 'Redirect') so cookies and base can be set,
second part opens a hole to pass headers into Client (for cookies)
224c224
< if ec==200: return (headers,response)
---
> if ec==200 or ec==302: return (headers,response)
342,344c342,344
< def call(url,username=None, password=None, **kw):
<
< return apply(Function(url,username=username, password=password), (), kw)
---
> def call(url,username=None, password=None, headers={}, **kw):
> F = apply(Function, (url, (), None, username, password, None), headers)
> return apply(F, (), kw)
Then there's the rewrite of the code in the how-to. Here's the whole thing
(I use just one .py)
site = 'http://www.carbonecho.com/zforum'
from string import join
def DirectToPHP( self ):
if self.REQUEST.path:
# Build up a list of what is contained in self.REQUEST.path since
# you are going to redirect the user to /PHPContent/index_html. Start
# by adding the way you can access the PHP tree outside of Zope
originalRequestPath = [site]
# keep the original path to override base when serving
origPath = []
# is the user asking for a php script?
if self.REQUEST.path[0][-4:] == '.php': # I use .php, not .php3
# pop paths of REQUEST.path until its empty
while self.REQUEST.path:
# Remember the path components before you pop them
# hang on to passed in path to set as base when served
originalRequestPath.append( self.REQUEST.path[-1] )
origPath.append( self.REQUEST.path[-1] )
self.REQUEST.path.pop()
# Create a full url to pass to index_html
phpScript = join( originalRequestPath, '/' )
origScript = join( origPath, '/' )
# Is there a query string being passed to the script also?
if self.REQUEST.environ.has_key('QUERY_STRING'):
phpScript = phpScript + '?' + self.REQUEST.environ['QUERY_STRING']
origScript = origScript + '?' + self.REQUEST.environ['QUERY_STRING']
# self.REQUEST.path is now empty so the user is going to be
# directed to /forum/index_html. That method needs to
# know what the original request is, so pass it a REQUEST
# variable
self.REQUEST.set('phpScript', phpScript)
self.REQUEST.set('origScript', origScript)
# you also may want to redirect image requests to the PHP tree
elif self.REQUEST.path[0][-3:] in ['gif', 'png', 'jpg']:
originalRequestPath = [site]
while self.REQUEST.path:
originalRequestPath.append(self.REQUEST.path[-1])
self.REQUEST.path.pop()
# This is an image, so give it to a DTMLMethod that will
# just serve up images
self.REQUEST.path.append('ServeImage')
self.REQUEST.set('imagePath', join(originalRequestPath, '/'))
from ZPublisher import Client
from string import split
def ServePHP(self, username=None, password=None):
req = self.REQUEST
if req.environ.has_key('HTTP_COOKIE'):
headers = {'Cookie' : req.environ['HTTP_COOKIE']}
else:
headers = {}
if req.environ['REQUEST_METHOD'] == 'POST':
rTuple = apply(Client.call, (req['phpScript'], username, password, headers), req.form)
else:
rTuple = Client.call(req['phpScript'], username, password, headers)
resp = req['RESPONSE']
for cookie in rTuple[0].getallmatchingheaders('Set-Cookie'):
cookie = cookie[:-1]
apply(resp.setHeader, split(cookie, ':', 1))
# not a particularly strong test, maybe Client should pass back status
if rTuple[0].has_key('location'):
# override base so that relative references work
resp.base = rTuple[0]['location']
raise 'Redirect', resp.base
#override base so that relative references work
resp.base = 'http://www.carbonecho.com/forum/' + req['origScript']
return rTuple[1]
from ZPublisher import Client
def ServeImage(self):
return Client.call(self.REQUEST['imagePath'])[1]