Thursday, January 29, 2009

Debugging Apache rewrite rules using a local environment

On a production site, I got an error when accessing Zope/Plone through Apache. Without Apache in front, it worked just fine. When reading Zope's instance log, it showed IndexError: string index out of range. Probably something to do with a rewrite rule. Apache rewrite rules with the VirtualHostMonster can be a mystery.

A colleague showed me how to set up a local environment for testing. This allows us to test a rewrite rule without risking downtime on the production environment.

Edit: See the Rewrite rule witch for a quick start with rewrite rules.

Modify your hosts file

  • Add test-rewrite to your /etc/hosts file

Set up apache

  • Install Apache locally, if you hadn't already. :)

  • Add an Apache config file test to /etc/apache2/sites-available, which looks like
    <VirtualHost *>

    ServerName test-rewrite

    RewriteEngine On

    # The rewrite rule under scrutiny
    # Assumes your Zope is running on port 8080
    RewriteRule ^/(.*)$1 [P,L,NC]

    RewriteLog /var/log/apache2/rewrite.log
    RewriteLogLevel 9

    CustomLog /var/log/apache2/test-rewriterule.log combined


  • Enable modules proxy, rewrite, proxy-http (using a2enmod)

  • In proxy.conf, set "Allow from all"

  • Enable the new config: a2ensite test

  • Modify /etc/apache2/sites-available/default so it begins with
    NameVirtualHost *
    <VirtualHost *>

Test it!

  • Run apache2ctl -t and apache2ctl -S

  • Run a tail -f on /var/log/apache2/rewrite.log

  • Tinker on your rewrite rule, and restart apache (/etc/init.d/apache2 restart) after modifications.

  • Go to http://test-rewrite and watch the log to see what happens

History: "compare to previous revision" shows nothing

That's because you have to tell the Plone difftool which fields to compare.

Go to the ZMI, portal_diff, select Document (or whatever your content type is), select the field ('text' most likely), Diff Type is 'Compound type for AT Types', and add.

Makefile for translating page templates using i18ndude

# Makefile for creating translation files (.pot and .po) in Plone products.
# Kees Hink , 2009.
# Place this inside the 'i18n' directory in you Product (which should be empty
# otherwise). Adjust the definitions, and run 'make'.
# A .pot file will be created. Edit it, and run 'make xx-translation' to create
# a translation file for language xx.
# I have chosen to not rebuild the .pot-file, but to merge it with a newly
# created temporary file. This assures the settings (author, e-mail, package
# etc.) are kept.

# Modify these to suit your product.
# The base name for your .pot and .po files.
# Beware of trailing whitespace!
FILENAMEBASE = yourproduct_here
TEMPORARY = temp.pot
# The i18n domain should match the i18n.domain="" statement in your .pt,
# .cpt, etc. files.
I18NDOMAIN = yourproduct
# Where to find the translatable strings.
# For a typical Plone 2.5 product, this will be skins/{product}_templates/
# For Plone 3, it will be browser/templates/ or just browser/
TEMPLATE_DIRECTORY = '../browser/templates'

# Update the main translations file.
# This is run by default when you run 'make'.
# Create temporary .pot file.
# We only search the browser/templates directory.
i18ndude rebuild-pot --pot ${TEMPORARY} \
# Check if the .pot file exists:
# - If it exists, create a backup.
# - If no, this must be the first run. Use a copy of the temporary .pot file
# as basis. Edit the .pot file after the first run.
if [ -e ${POTFILE} ]; \
then cp ${POTFILE} ${POTFILE}.backup; \
else cp ${TEMPORARY} ${POTFILE}; \
# Merge temporary into the .pot.
# Merging will print a warning 'Merge-Warning: Key is already in
# target-catalog' for each string that is in both the temporary and the real
# .pot file (almost all strings, in effect).
# You can safely ignore these warnings.
i18ndude merge --pot ${POTFILE} --merge ${TEMPORARY}

# Update a specific translation file.
# Call as 'make xx-translation', replace xx with your country code.
# Create backup, or else create initial file.
if [ ! -e ${FILENAMEBASE}-$*.po ]; \
then touch ${FILENAMEBASE}-$*.po;\
else cp ${FILENAMEBASE}-$*.po ${FILENAMEBASE}-$*.po.backup;\
# Sync translation strings in translation file with .pot
# This may delete translations. If you see something like '0 added, 531
# removed, consider re-examining the backup.
i18ndude sync --pot ${POTFILE} ${FILENAMEBASE}-$*.po

Wednesday, January 21, 2009

Apache2 VirtualHost doesn't work

I had a setup with 2 virtual hosts via SSL on the same server, but when trying to add a third i couldn't get it to work. Turns out using named virtual hosts is guaranteed not to work with SSL, and this was SSL. So why did it work for 2 virtual hosts before? This was because the domain names were pointing to different IP addresses. (One to the load balancer and one to one of the two balanced machines.)

Lesson learned: read the ouput of 'apache2ctl -S' carefully!

Sunday, January 18, 2009

Noorderslag 2009

Seen on saturday January 17th:

  • Marike Jager: Singer/songwriter. Don't remember any features.

  • Das Aldi Combo: Funk/soul with bass, drums, organ and trombone/sousaphone.

  • Giants of Husavik: Maybe that's just not my thing. Why were they clad like KKK?

  • The Fringe: Rap/hiphop. Well, that's really not my thing.

  • De Dijk: Winner of the Popprijs 2008. They played a short set, very slick as we know them. The songs from their new album 'Brussel' were the most interesting. Always a great live band.

  • Face Tomorrow: Rock. Energetic, good stuff. Wouldn't mind seeing more of them.

  • zZz: Drums + keyboards. Original! However, my ears were tired.

Great evening, when do you get a chance to see so many bands live? Nice crowd too.

Eurosonic 2009 (day 2)

Seen friday January 16th:

  • De Fuckups (De Walrus): Punk! Bass, drums, 2 guitars, singer.

  • The 69'ers (De Walrus): Drums/guitar duo. Well done, but lacked power or variation after a few songs.

  • Universe 217 (Huis de Beurs): Metal, which is not my area of interest. Interesting still.

  • Awkward I (Huis de Beurs): Acoustic multivocal songs with guitar(s), cello, organ, mandolin. Original songs, good show

Where does cups-pdf put my pdf file?

Cups-pdf is a great tool if you want to print files to pdf format. It installs very easily in Ubuntu (Intrepid): just do sudo apt-get install cups-pdf, and you will see a 'PDF' printer in your printers overview. It works like a charm, but where do the PDF files go?

You'll have to create a directory called 'PDF' in your home folder. It's strange that cups-pdf exits without error for cases where there's no PDF folder yet, but there you go. This bug is already known.

Friday, January 16, 2009

How to be careful when banking online

Many people would love to be careful, but don't know how. A few hints are explained here.
When banking online:

  • Don't have more than one browser window or tab open when banking.

  • When you're asked to type a password, always check that that request comes from the real site.

  • Consider downloading the NoScript plugin for Firefox

Eurosonic 2009 (day 1)

Seen Thursday January 15:

  • Them Holy Rollers (Pacific Bar): Good, but it should have been way louder.

  • Killteam (De Kar): Hard metal-ish stuff, and loud enough. Liked it.

  • Polarkreis 18 (Grand Theatre Main): 80's pop, bombastic and slightly gay, mostly due to the singer. Nice to see pros at work.

  • John & Jehn (Spieghel Down): Singer/songwriterish duo, didn't sound interesting.

  • Barbie Bangkok (Spieghel Up): Couldn't see a thing, place was full. Music sounded flavorless.

  • Triggerfinger (Vera): Trio.The evening's winner. A good mixture of the first two acts.

Thursday, January 15, 2009

Python password generator

Probably been done before, whatever.

(Update 2010-06-24: Maybe you want to use a command line program like pwgen)

from random import choice

default_number_of_passwords = 100
default_password_length = 8

def generate(length):
"""Make a password.

Password length is an argument. Which characters are used can be set below.
# Define character classes.
az = range(ord('a'),ord('z')+1)
AZ = range(ord('A'),ord('Z')+1)
zero_to_9 = range(ord('0'),ord('9')+1)
special = [ord(x) for x in '!@#$%^&*()-_=+[]{};:,.<>/?\|`~']
# Select character classes to use.
# Special characters may not be valid on the system where you want to use
# these passwords! They are therefore not used by default. Modify the string
# on the line below accordingly, and probably also the 'special' list
# above.
characters = az + AZ + zero_to_9
pw = ''
for i in range(length):
pw += chr(choice(characters))
return pw

def main_program(number_of_passwords=None,password_length=None):
if number_of_passwords is None:
number_of_passwords = default_number_of_passwords
if password_length is None:
password_length = default_password_length
for i in range(number_of_passwords):
print generate(password_length)

if '__main__' in __name__:

Monday, January 12, 2009

Nomination for Least Prolific Blogger

I hereby would like to nominate Wichert Akkerman for the Least Prolific Blogger Award. His last entry comes after a 16-month silence. And of course, when you don't blog often, people pay extra attention when you do!

Monday, January 5, 2009

Parcours NK Marathon op natuurijs

Hier de locatie: De Oostvaardersplassen. Rechtsboven Lelystad.

En hier het parcours, van de site van de KNSB: