Integrate external content in Plone
Background
I have some content sitting on another server that I wanted to integrate into the rest of my plone site. This describes how to do it (in probably completely the wrong way, but it works for me!)...
WARNING this method fiddles with traversal and is slightly magic. It works for me on zope 2.5.1 and plone 1.0beta2 and Zope 2.7.0 and plone 2.0.4. Your mileage may vary... In particular, relative links inside your external document may not work correctly. As always, try it on a test Plone instance before putting it on a production site!
What to do
Put all of these files in your custom skin folder
- getBody.py - an external method, mounted as getBody:
import urllib import pre def getBody(self, REQUEST, url): page = urllib.urlopen(url) data = page.read() contents = page.info().getheader('Content-Type') page.close() REQUEST.RESPONSE.setHeader('Content-Type', contents) #check that it is an html document if pre.search('<(h|H)(t|T)(m|M)(l|L)',data): #find start of body conents #assumes <body *>tag is on one line (?) start = pre.search('<(b|B)(o|O)(d|D)(y|Y)[^>]*>',data).end() end = pre.search('</(b|B)(o|O)(d|D)(y|Y)',data).start() return {'data': data[start:end], 'Content-Type': contents} else: return {'data': data, 'Content-Type': contents}
This gets the external page, and if that page is an html document, strips it down to the body.
- external - a python script:
import string request = context.REQUEST extpath = request['ExternalPath'] exturl = context.link + extpath obj = context.getBody(context, request, exturl) if obj['Content-Type'] == 'text/html': return context.external_view(contents=(obj['data']), extpath=extpath) else: return obj['data']
This script marshalls whether to put the external page through a page template or not (so images come through in one piece)
- external_view - a page template:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US" metal:use-macro="here/main_template/macros/master"> <head metal:use-macro="here/header/macros/html_header"> <metal:block metal:fill-slot="base"> <base href="" tal:attributes="href string:${here/absolute_url}/${options/extpath}" /> </metal:block> </head> <body> <div metal:fill-slot="main"> <div tal:replace="structure options/contents"> replaced site contents </div> </div> </body> </html>
This is the page template that defines the look of the external conten. Note the fiddling with teh base fill-slot, this ensures that relative links in the external content work properly
- Next create a new plone folder to act as the root of the external content
Give the folder a string property named link, containing the url for the external site, ie http://somwhere/somefolder/
- create a python script in the folder called 'access_rule':
#use /_SUPPRESS_ACCESSRULE/manage to access this from string import split,join request = container.REQUEST #The stack of URL path items after here stack = request['TraversalRequestNameStack'] #make a copy of the remaining path to be used later extpath = stack[:] extpath.reverse() request.set('ExternalPath', join(extpath, '/')) #consume the rest of the stack so that external path items are ignored in traversal while stack: stack.pop() #add the path of objects in the title to the stack add_path = filter(None, split(script.title, '/')) add_path.reverse() stack.extend(add_path)
Set the script title to the path that should be appended during traversal, here /external
This bit can be dangerous and stop your Zope Management Interface from working
use http://url/to/folder/_SUPPRESS_ACCESSRULE/manage to remove it if you're having problems
finally set the access rule for the folder to access_rule (add Set Access Rule in the zope management interface)
Hopefully everything should now be working...
References
Laurence Rowe ( l at lrowe dot co dot uk )
