Thursday, June 28, 2007

Plone workshop, London, August 2007

For anyone interested in learning how to develop Plone sites there's a 5-day Plone workshop in London on 13-17th August 2007.

There's a fairly steep initial learning curve when it comes to developing and extending Plone. Although there's a lot of support available in the form of mailing lists, chat rooms, books and documentation on the Plone website itself, it takes quite a while on your own to get your head around such a large content management system.

That's why this workshop sounds like it would be useful to anyone with not much prior knowledge of Plone but who wants to get up to speed quickly. At nearly £1000 it's a significant investment. but I reckon it's worth it for the time it's likely to save doing it by yourself.

Plone used by Friends of the Earth

Friends of the Earth International (FOEI) unveiled their new Plone site back in April and I'm just getting round to having a look at it now. Visually it's quite plain, a little bit too blocky and it feels very flat on the page to me. I'm not a visual designer, but I probably would have at least thrown the odd gradient in there to soften it a bit.

One of the good things about Plone is the speed at which a fully functional content-managed site can be deployed but I think more effort should be put into skinning the public appearance. If nothing else, this would at least show others that it can be done. See the British Postal Museum and Archive site for example.

Interestingly, the FOEI site uses PloneMultisite to deploy content from a single editing base to multiple sites. I'm not up to speed on exactly how this product works but it sounds like something that's worth further investigation.

Thursday, June 07, 2007

ReadSpeaker in action

Following on from my ReadSpeaker without nasty page reloads post, the nice way of implementing ReadSpeaker that we developed has now gone live on the British Postal Museum and Archive's website.

Comments and suggestions about how to make it better are welcomed.

Tuesday, May 29, 2007

Demand Led Standards-based Development

I think Peter-Paul Koch's recent article on A List Apart
Evangelizing Outside the Box: Web Standards and Large Companies – ought to make more of the power that clients have in steering the progress of web standards.

The main thrust of the article, that high profile employees of large companies could and should be highly vocal evangelists for web standards in order to add momentum to the movement in general, is totally valid and I certainly wouldn't argue against it. Such evangelism is bound to have an influence on a significant number of developers who are yet to recognise the benefits of web standards.

But the incentives to adopt the good practices of their peers may not be strong enough to enduce most late adopters to put in the work to make the jump to web standards. Why should they bother if they can maintain a viable business using the same methods as they've always used?

However, if their clients demand the use of web standards, these same developers will have to adapt their methods or risk going out of business.

So its down to the larger companies (and everyone else) to educate their clients about the benefits of web standards so that, eventually, there'll be no demand for non-standards based development and anyone who doesn't adapt will become extinct.

ReadSpeaker without nasty page reloads

Readspeaker's a great service that makes it easy for any website owners to provide audio versions of their content on the fly. This is clearly preferable to re-recording content manually every time a couple of words get changed and the quality of the synthesized voice is actually very natural and lifelike.

Every implemetation of ReadSpeaker that I've seen works by providing a link near the text which, when clicked, either forces a page reload so that an audio player can be embedded or - and this is my personal anti favourite - opens a new page containing only the audio player and shrinks the browser window to the size of the player. Take a look at the O'Reilly Radar (click on the 'listen' link) or any number of examples on ReadSpeaker's site to see what I mean.

While in most cases it's probably true that having a badly implemented audio version of a page is better than no audio version, it is possible to implement ReadSpeaker in a nice, elegant and accessible way.

The reason why it's difficult to find any examples is that the ReadSpeaker documentation doesn't make it very clear that it's possible. However, it is possible to retrieve the URL of the generated mp3 file.

This means that it's possible to pass the mp3 url to an audio player that's embedded in the page when it first loads. If this is implemented with a suitable Flash mp3 player, the mp3 won't be downloaded unless the user decides to play the audio.

The way to retrieve the un-encoded URL of the mp3 is to make the following call to ReadSpeaker (if you want the URL to be encoded, set the 'type' parameter to 101):


http://asp.readspeaker.net/cgi-bin/[CUSTOMER_NAME]rsone?customerid=[CUSTOMER_ID]&url=[URL_OF_PAGE_TO_READ]&type=100

where CUSTOMER_NAME and CUSTOMER_ID are supplied to you by ReadSpeaker when you open an account.

Your Flash player may be capable of using this URL as it is but if you need to pass the player an actual mp3 URL, you'll need to write a script to retrieve the URL of the mp3 up front.

Here's a Python script that I wrote for use with Plone but it should be easy to adapt to any other platform:


# Python script to retrieve the URL of an MP3 audio file from readspeaker.com.

# Import required functions
from urllib import urlopen, quote

def getReadSpeakerURL(customer_name, customer_id, page_to_read_url):
url_to_open = "http://asp.readspeaker.net/cgi-bin/%srsone?customerid=%s&url=%s&type=100" % (customer_name, customer_id, page_to_read_url)
mp3file = ''

try:
fp = urlopen(url_to_open) # this retrieves a page containing the url of the mp3 file
mp3file = fp.readline() # this retrieves the mp3 url itself

# check for errors
except IOError:
mp3file = ''

# return two versions of the mp3 url, one with the URL encoded and one without
return (mp3file, quote(mp3file))

Then place the following HTML into any pages that you want to be ReadSpeaker-ed (this example is written for Plone so uses Template Attribute Language (TAL) syntax. Sorry if you're not familiar with this but I hope you can still follow it):


<div class="readspeaker" define="customer_name string:[CUSTOMER_NAME]; customer_id string:[CUSTOMER_ID]; rs_url_array python: here.getReadSpeakerURL(customer_name, customer_id, here.absolute_url() + '?hidereadspeaker=1'); rs_url_unquoted python:rs_url_array[0]; rs_url_quoted python:rs_url_array[1];">
<h2>Hear this page read out loud</h2>
<object type="application/x-shockwave-flash" define="flashplayer string:/flash/emff_comments.swf?src=${rs_url_quoted}" attributes="data flashplayer" align="middle" height="28" width="200">
<param value="" name="movie" attributes="value flashplayer">
<p>To hear this page read aloud, get the Flash Player from <a href="www.adobe.com">Adobe's web site</a></p>
</object>
<p><a href="" attributes="href rs_url_unquoted">Download</a> - <a href="" attributes="href string:${here/portal_url}/help/index_html#readspeaker-help">Help</a></p>
</div>

This way you can have an accessible method of providing audio content without nasty page reloads.

Wednesday, May 23, 2007

Apache rewrite recipe for usable URLs

Here's a little mod_rewrite recipe for Apache that might be useful if you're developing a web app like StripMe which is a very simple service that takes a CSS file and returns a version of the file with all the comments and white space stripped out.

The location of the CSS file to be stripped is passed to the service in the query string of the URL. Normally, this URL would look something like this:
  • http://stripme.org/index.php?cssfile=http://mysite.com/style.css
We wanted to make the service easy to use by letting users pass the URL of their CSS files like this:
  • http://stripme.org/http://mysite.com/style.css
To do this, I ended up using the following rewrites in Apache:
  • RewriteCond %{REQUEST_URI} "http:\/\/"
  • RewriteRule "(.*)http:\/\/(.*)" "$1index.php?http:\/\/$2" [PT]
It's probably not the most elegant solution, but as long as there's a script in your root directory called index.php that knows what parameters to expect, it should work.

Please let me know if it doesn't work or if there's a nicer way of doing it.

Monday, May 21, 2007

One way to fix POSKeyErrors in Zope on Windows

I just spent much longer than should have been necessary trying to fix a Zope problem so I'm going to document it just in case anyone else has the same problem in the future.

The problem started with Zope raising a POSKeyError exception whenever a certain object was accessed in the Zope Management Interface (ZMI). The object could not be removed from Zope using the ZMI in any way.

Investigation revealed that this exception signifies corruption of the Zope Database (ZODB) due to an object that has become browkn in some way.

We have backups (of course), but this worried me because it happened on our development server and we do so much development that even restoring a half a day old backup means losing a significant amount of work. So I looked for a way of fixing the problem without restoring a backup.

Further investigation revealed that this can be achieved using 'zopectl debug' to interact directly with the ZODB in a Python shell and delete the broken object.

The next hurdle was that zopectl doesn't work on Windows and no prizes for guessing what we use.

The solution was to use PloneShell, which does the same thing as zopectl but also works on Windows.

The final solution once I had my interactive PloneShell shell running and attached to the ZODB, was to replace the corrupt object with a new object:
  • container._setOb(idOfBrokenObject, someNewObject)
then delete the broken object:
  • container._delObject(idOfBrokenObject)
and then commit the changes to the ZODB:
  • get_transaction().commit()

Sunday, May 20, 2007

Upscaling Zope with ZEO on Windows

If you're using Plone for production level business applications and you're not yet using Zope Enterprise Objects (ZEO) I'd highly recommend switching over at your earliest opportunity.

If you've got a single server system with multiple CPUs or you want to be able to balance the application load over two or more servers, ZEO is the way to go.

I've recently switched over our Windows-based installation of Zope 2.7 (with Plone 2.0.5). The performance gains are easily worth the effort and I found a couple of resources on the Plone site that made the whole process easy to implement (see links below)

The added bonus is that new servers can now be added easily to the configuration as demand on the server increases making it a great long term solution for a production environment.

Here are the documents I found useful:

Tuesday, May 15, 2007

Setting up Plone on Ubuntu Feisty Fawn

Recently I needed to set up Plone on an Ubuntu server. I wanted to run Plone behind Apache and I needed to be able to remotely administer the server on a Windows machine.

I don't have very much experience with linux so I was expecting all sorts of command line stumbling blocks but I was amazed at how easy everything was to set up, barring a couple of hiccups.

I thought I'd post a log of what I did to get the server working (mostly for my own benefit so I've got a permanent record in case I need to do it again). It's not massively detailed so don't expect a breakdown on how to install and configure things like the secure FTP client WinSCP.

I'm absolutely certain that there are better ways of doing it, and I welcome any comments about how I could have done things differently.

Install Log

On the windows machine
  • Download and install these useful remote administration tools:
    • Putty - For remote login to linux
    • WinSCP - For secure file transfer to and from linux
On the linux machine
  • Install Ubuntu desktop edition (I used a Pentium III, 1GHz CPU with 512MB RAM)
  • Install SSH server - sudo apt-get install openssh-server
  • Install Apache - sudo apt-get install apache2
  • Install Zope (see How to setup Plone from source for some pointers on this) - sudo apt-get install zope2.9 (if you leave off the 2.9 bit it will probably find the package containing the latest version)
  • Make a Zope instance - sudo /usr/lib/zope2.9/bin/mkzopeinstance.py
    • Provide the information requested:
      • Directory: /var/zope/instance001
      • Username: user
      • Password: pass
    • If necessary edit zope.conf to specify port number, etc (it may be necessary to use a terminal to change the owner of zope.conf before you can save the changes to files that you edit)
      • sudo chown user /var/zope/instance001/etc/zope.conf
    • and then back again when you have finished
      • sudo chown zope /var/zope/instance001/etc/zope.conf
  • Run zope - sudo /var/zope/instance001/bin/runzope (or, to run it in debug mode: sudo /var/zope/instance001/bin/runzope -X "debug-mode=on")
    • or:
    • sudo /var/zope/instance001/bin/zopectl start
      • sudo /var/zope/instance001/bin/zopectl stop
  • Install PIL - sudo apt-get install python-imaging
  • Download and install Plone 2.5.2 (you may have to change ownership on the Products folder before you can transfer the Plone files to the Products directory)
Apache setup - See HTTPD - Apache2 Web Server to see how Apache is configured in Ubuntu
  • to create a new virtual host, make a copy of the default site and then - sudo a2ensite site-name
  • To enable a module - sudo a2enmod module-name
  • Enable mod_proxy and mod_rewrite
    • sudo a2enmod proxy
    • sudo a2enmod proxy_http
    • sudo a2enmod rewrite
  • Edit proxy.conf to allow proxying (I could only do this by enabling proxying from the specific client I was accessing the site from but I need to find a better way as this opens up the server to general proxying which is bad)
    • Change 'Proxyrequests Off' to 'Proxyrequests On'
    • Add 'Allow from all' in tag
  • To restart apache:
    • sudo /etc/init.d/apache2 reload
    • or:
    • sudo /etc/init.d/apache2 force-reload
For accessing the ubuntu server using a remote windows environment:
  • On the Ubuntu machine, log in locally to the desktop and open System -> Adminstration -> Login Window
    • In the 'Remote' tab, select 'Same as Local' from the 'Style' drop down list
  • On the Windows machine, Install Cygwin and the X11 components
  • Edit [CYGWIN_INSTALL_DRIVE]:\cygwin\usr\X11R6\bin\startxdmcp.bat setting the IP address of the REMOTE_HOST to the IP address of the Ubuntu server
  • Launch [CYGWIN_INSTALL_DRIVE]:\cygwin\usr\X11R6\bin\startxdmcp.bat
    • Note - By default, this will only allow you to have one session running simultaneously but this can be configured in the Login Window settings in Ubuntu
  • For further help, see:

Thursday, February 08, 2007

Brighton coding dojo

I went along to the Brighton Coding Dojo for the first time today. I didn't really know what to expect so was nervous as a kitten and it turned out to be just as scary as I imagined. Well, almost.


Brighton coding dojo

Above: Coders going at it at the Brighton coding dojo


I'm not at all used to standing in front of a group of people and verbalising a programming problem while simultaneously trying to code the solution to the problem (and we were coding in Ruby using Eclipse, neither of which I had any experience of).

My usual methodology is to take my time, on my own, thinking about a problem, sometimes making notes and drawing diagrams and then coding in a not altogether best practice kind of way which gradually gets me to the end goal.

But that's exactly why I went - to learn about new techniques, improve my skills, share my (limited) knowledge - and it all took place in a relaxed, friendly kind of way (although someone did suggest that it seemed like a kind of geeky fight club).

So I'll definitely be going along to another dojo (if they'll have me).

Tuesday, January 30, 2007

I found it useful. You could too! - Firebug

Today's useful thing is the Firebug extension for Firefox.

If you're a web developer Firebug's an absolute must have. It's like a mechanic's pit for web pages. It lets you get right underneath and have a good tinker with all the elements that make up the page.

Any one of its features would make a great tool in its own right. Like being able to edit the html code of a page in the browser and see immediately what effect the changes are going to have without even refreshing the page. But it's does so much more than that. You can edit, monitor and debug all the html, css and javascript that makes up any page - including data returned by Ajax calls. Take a look at Jesse Newland's Firebug 1.0 screencast.

If it's not already in your developer's toolkit, add it.

One little hiccup: Firebug 1.0 has recently been released but a lot of users are experiencing a bug which prevents the styles from being displayed and can only be fixed by uninstalling Firefox and reinstalling it in a new directory. There's a discussion about this on the Firebug blog.

I haven't done this yet as I'm hoping a better fix will be found and released soon and I don't fancy reinstalling Firefox.

Screenshot showing a bug in Firebug 1.0

Above: Screenshot showing Firebug 1.0's styles bug in the right hand pane.

Despite this, I'd still recommend upgrading if you're still using version 0.4.

Previous post in this series: Enlarge TextArea

Monday, January 29, 2007

Collaboration with Google Docs

Following a recent heuristic evaluation, Yandle and myself put Google Docs collaboration capabilities to the test to write the report.


Photo of Danny in front of his computer while editing a Google Docs documment

Photo of Ben in front of his computer while editing a Google Docs documment

Above: Collaborating with silly faces.

We were working in the same room on separate workstations so we could easily communicate and in the beginning we were being really careful about making sure that we weren't working on the same part of the document at the same time in case one of us accidentally wiped out something that the other was working on.

However we quickly found that we didn't need to worry about this at all because the document was being autosaved so frequently. Every time it was saved the changes made by the other writer would be merged in seamlessly with our own changes. So in fact it was very rare for there to be any conflicts in what we were doing which gave us more time to shut up and get on with the task itself.

Even when there was a rare conflict and the most recent changes were lost, the amount of changes that had been made between autosaves were so few that it was very easy to recover from.

Additionally, if there had been a more serious loss of work, it would also probably have been easy to recover from as Google keeps multiple revisions of a document allowing you to go back and compare documents over time.

Possibly the most difficult part of working with Google Docs was learning to trust the system and remembering not to press Control-S to save the document every ten seconds in case the application crashed.

When one of the computers did crash there was no panic and we felt safe in the knowledge that, being an online application, the document wouldn't be lost even if the computer was dead forever.

I'd definitely recommend using Google Docs as a collaboration tool and even as a plain old non-collaborative word processor (although I'd like to test it out with a few more simultaneous collaborators in different rooms to see whether it would deserve such a glowing report under those conditions).

Wednesday, January 24, 2007

I found it useful. You could too!. (Pilot)

This is a pilot for a series of posts I'm calling "I found it useful. You could too!". The ratings will decide its future. Or if there's no ratings I'll decide cos I rule.

Today's useful thing was introduced to me by Yandle. It's a simple bookmarklet that just increases the height of all the text area fields in a form on a web page. As most text areas in web forms are way too short for what you want to put in them, I found it useful. You could too! (now do you see where the title comes from?)

To use it, just drag the link below into your bookmarks toolbar:

Enlarge textarea

Now find a page with text areas in a form, click on the bookmarklet and hey presto!

Jump on the snowwagon

Snow today in Brighton sent most of us into some kind of mental weather frenzy, including me. Use your eyes on these pics.

Photo of the view from my balcony on a snowy day


Photo of stairs covered in snow

Monday, January 22, 2007

Postage to the BBC

If you don't have your own blog (or even if you do) and you feel like airing an opinion or just chewing the fat with a chance of it being read out to millions of listeners worldwide, go and post an entry on the BBC Five Live radio's First Post site.

Yeah, it might just be a very cheap way for the BBC to get fresh content onto their site and keep it up in the search rankings but this is the BBC. It's not likely to be short of visitors, is it?