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] _______________________________________________ Zope maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope-dev )