This How-to applies to: Any version.
This How-to is intended for: Server Administrators
The original content of this how-to can be found at this location.
A working example can be found at this location.
I can‘t just paste the code, since your setup will be different from mine. And beware for those who want elegance, this is not the epitome of pretty code. It is just a plain quick hack that took under 2 hours to implement. I have no doubt this How-To will take me at least double that length of time. Furthermore, my deepest respect to the ViewCVS team for an excellent product. I am sorry that I had to do what I did to get it to work how I wanted it to. I would send you a patch but I am far too scared. And last but not least, Plone and Zope, absolutely killer products from the minds of geniuses.
The nice thing about Plone, and I have only been using it for 4 days, is that everything looks the same. I think the Human Computer Interface Designers would call this something like uniformity and consistency , and for me as the end user it is just lovely.
That is all well, but what about prepackaged scripts that don‘t look like plone, how can you embed them in a Plone page? ViewCVS is one such script. It is used almost universally for displaying CVS contents with HTML over HTTP for example. Incredibly, and if you checked the link, you will see that even Sourceforge display a naked ViewCVS page with no formatting. Yuck!
Well, there are about 14,000 solutions to this problem, and I really should have approached it in one of the other ways (like importing the mod-python viewcvs modules and using them, or even calling the cgi scripts directly) but instead, I decided to use my existing Apache based viewcvs setup.
I shall force viewCVS requests to be passed to a Zope request-handler which will independently request the actual ViewCVS content and embed it in a plone page.:
USER -> APACHE -> REWRITE -> ZOPE -> VIEWCVS(APACHE) -> ZOPE -> USER
Well that is it. If you understand that, you are done with this how-to. If you need more information on some or all of the steps that it took (and remember doing it takes very little actual time) please read on.
The plan is to have all requests to the root /
on the server to be redirected to the Plone (Zope) server, while all requests to /local/
to be allowed to pass through to Apache. I understand this is a very common way of using Zope and Plone, and it certainly works fairly smoothly on my set up.
I am barely literate in Apache mod-rewrite, but the best I can do is to paste my example configuration and explain it. If you alreday have rewrite set up, you may need to review your config to see exactly what is going on.:
RewriteEngine OnRewriteRule ^/local - [L]RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/http/aa.homelinux.com:80/VirtualHostRoot/$1 [P]
The first line turns rewriting on. The second line tells the server to stop processing and pass through to the local server - [L]
any requests to /local
. And the third line rewrite all other requests to that weird url on the local machine. If you don‘t know what they all mean, don‘t worry, just know that localhost:8080
is the location of the Zope server, and aa.homelinux.com:80
is the location of the Apache Server. Leave the other words as they are. They are needed by the virtual host monster.
Do it now, install a virtual host monster in the root of your Zope installation. It is in the dropdown box on the right. You don‘t need to edit this in any way. And while you are at it, if you have changed any Apache settings, restart the server.
Currently, I have an alias for /local/cvs/
which points to my actual viewcvs directory using Apache2. If you haven‘t already set it up, a simple alias like this will usually do the job for making ViewCVS work with Apache:
Alias /local/cvs /usr/lib/cgi-bin/viewcvs.cgi
Where /local/cvs/
is the browseable url for ViewCVS on the Apache server, and /usr/lib/cgi-bin/viewcvs.cgi
is the actual location of ViewCVS on your filesystem. Before I put Plone in the mix, this is how the outside world would access ViewCVS.
When ViewCVS renders it‘s pages it sets up the url for the link and in our case it sets them up as:
<servername>/<script location>/<parameters>
In order that we can force ViewCVS to change its links to point to:
<servername>/<our Plone proxy>/<parameters>/
we must edit the code. The creation of the Plone proxy is discussed below. It is responsible for fetching actual ViewCVS pages and making them look Plone.
Editing your exact code may be different, my version is 1.0-dev from Debian Unstable. You need to find the main ViewCVS module, called /usr/lib/python2.3/site-packages/viewcvs/viewcvs.py
on my installation. At approximately line 403, in the method get_link(), I have changed:
url = self.script_name
to:
url = ‘/cvs/vcvsproxy‘
or the location of a page template in your Plone site, eg /Portal/vcvsproxy from where you want to serve the ViewCVS Content.
(further elements are added to this url by the method)
Thus, if original links had been created to:
<servername>/local/cvs/<parameters>
they would now point to:
<servername>/cvs/vcsproxy/<parameters>
Check the change has worked. Refresh a ViewCVS page, and click on a link. They should all be broken and point to a zope page that isn‘t there. If they are broken, examin the links. Are they of the correct type discussed above? I repeat, your installation may be different from everyone else‘s, so examine them carefully. If you are done, you should now move on to creating the Plone proxy, a dynamic piece of Plone content.
Did you remember to install a virual host monster in the root folder of your Zope?
You would expect that it is easy to make a random HTML page look like a Plone page from within a Plone site. You would be right, it is easy.
You have to:
Excuse me if you already know how to do this! Go to the drop down box on the left in the Zope Management Interface (usually at /manage on your Zope installation) and select "page template". You will be asked for an ID and set this to vcvsproxy
or the value that you entered above for the new ViewCVS URLs.
Ok, done! Check it worked. Browse your Plone site to the ID of your newly added page template, and you should see the defualt template in place.
Edit your newly created page template and in it‘s <html>
tag insert:
metal:use-macro="here/main_template/macros/master"
As you can probably see, this will make the page template use the default Plone template (here/main_template).
Ok, done! Check it worked. Browse the page again, and this time it should miraculously look like a Plone page.
There are a few ways which you can add content to this page and there are surely more that I will discover with time.
In the body of your page template you need to insert the tags:
<div metal:fill-slot="main"><span tal:replace="structure here/getcvs" /></div>
<div>
element indicates that we would like the content to fill the main slot, the main content area of the page: metal:fill-slot="main"
<span>
element indicates that it would like itself replaced by the output of here/foo with: tal:replace="structure here/getcvs"
. getcvs
is the name of the script or external method we shall be calling. This guarantees that the external method will return an HTML-formatted string which will be embedded at the requested position in the page. (Note: for an External Method, this is the ID of the method itself, not the module within which it is). We will concentrate on External methods since we will be using one later. You will need to:
Call it whatever you like with the extension .py (beware Windows users!). For our example we shall call it cvs.py
. Your installation may differ from mine - the location of the module. I put mine in /var/lib/zope/instance/default/Extensions
, and I am assured that this is a good place for it. It must be in the Extensions directory of your instance on your filesystem. You need one method at least in this module that takes an optional parameter (which we shall call self
but as a note for Python programmers, this is not an instance of the method) and which will return a string. We shall call our method getcvs
. At this stage we don‘t know what we are going to need in our module, we will just put in a test. Your module should look like this:
def getcvs(self):return "<h1>Hello Plone World</h1>"
In the dropdown box, select External Method. Enter the following options:
ID getcvsTITLE The ViewCVS FetcherMODULE NAME cvsFUNCTION NAME getcvs
And you are done. Remember this page, you need to reload the method every time you make a change of it just by uploading the file again. Check the script works, by browsing the URL of your vcvsproxy. It should return you a Plone looking page greeting you with the message Hello Plone World
entered above. If so you have the script working, so you can move on to actually making it useful.
You have a working external method (getcvs) that is called by a Plone-looking page-template (vcvsproxy) for its content. You external method may differ from mine. Mine is probably appalling code, but it almost works. The general idea is to:
Happy? Let‘s have a look at the code:
import urllib2def getcvs(self):# self is an object passed to us. You can query it with dir() if you# like, split the path requested, and grab the bit after ‘/vcvsproxy/‘p = self.REQUEST.PATH_INFO.split(‘vcvsproxy‘)[-1]# build the new actual URL to ViewCVSu = "http://localhost/local/cvs/%s?%s" % (p, self.REQUEST.QUERY_STRING)# urllib2 voodoo for clearing proxies that might be set upopener = urllib2.build_opener(urllib2.ProxyHandler({}))# open the URL without readingf = opener.open(u)o = ‘‘# check the content typeif f.info().has_key(‘Content-Type‘):ct = f.info()[‘Content-Type‘].split(‘/‘)[-1]# if it is htmlif ct.startswith(‘html‘):# read the data and return it with in a templateo = RT % f.read()else:# otherwise return a link to the file in a templateo = FT % ureturn oFT = """<h1>Please download the file here</h1><a href="%s">download</a>"""RT = """%s<a >How to embed ViewCVS in Plone</a>"""
Well, you won‘t believe it, but you are done!
Test your setup. Browsing vcvsproxy/ should give you the CVS root. If you would like to see an example of this working, please visit my CVS Repository.