// How to create an easily maintainable DokuWiki template

Creating templates for most web applications is not really a hard task. But if you plan to share your work with the public you face a little problem every now and then, namely when there's a new version of the application available: you have to track down what has changed since the last release to be able to update your template accordingly. Sure, not everyone has the time to follow the development of an application close enough to notice every small change which affects his work. IMHO that could be the cause why some of the available DokuWiki templates are a little outdated and likely not 100% compatible with the latest release. However, I would like to show a way to take advantage of DokuWiki's stylesheet handling and to keep the effort needed to keep such a template up-to-date at a minimum (we're all lazy people, right ;-)).

Creating a new template

The easiest way to create a new template is the Starter template by Anika Henke.1) Just download and extract it. Rename the folder, place it below <dokuwiki>/lib/tpl/templates and select it in the DokuWiki configuration manager.

The idea: taking advantage of DokuWiki's CSS handling

DokuWiki provides an advanced CSS handling system which uses a PHP .ini file named style.ini, which is part of the template. It is used to determine which files are getting loaded for a certain display mode. So lets have a look at the style.ini provided by the Starter template. Right now we're interested in the first section of the file:

css/basic.css             = screen
css/structure.css         = screen
css/design.css            = screen
css/content.css           = screen
css/_imgdetail.css        = screen
css/_media_popup.css      = screen
css/_media_fullscreen.css = screen
css/_fileuploader.css     = screen
css/_tabs.css             = screen
css/_links.css            = screen
css/_toc.css              = screen
css/_footnotes.css        = screen
css/_search.css           = screen
css/_recent.css           = screen
css/_diff.css             = screen
css/_edit.css             = screen
css/_modal.css            = screen
css/_forms.css            = screen
css/_admin.css            = screen
css/includes.css          = screen
css/rtl.css               = rtl
css/print.css             = print

The above describes which .css file gets loaded for a certain display mode. “screen” is the normal display mode when you watch the page in a browser, “rtl” is loaded for right-to-left languages, and “print” obviously when you like to print a wiki page.2) For more information regarding the loading order of stylesheets refer to the docs.

So here is the key part:

We're not gonna edit any of the .css files we copied over from the Starter template!

We just add our own .css files for each mode at <dokuwiki>/lib/tpl/template/<mytemplate>/css instead and modify the style.ini so they get loaded after the original ones:

css/_imgdetail.css        = screen
css/_media_popup.css      = screen
css/_media_fullscreen.css = screen
css/_fileuploader.css     = screen
css/_tabs.css             = screen
css/_links.css            = screen
css/_toc.css              = screen
css/_footnotes.css        = screen
css/_search.css           = screen
css/_recent.css           = screen
css/_diff.css             = screen
css/_edit.css             = screen
css/_modal.css            = screen
css/_forms.css            = screen
css/_admin.css            = screen
css/mytemplate_screen.css = screen
css/rtl.css                = rtl
css/mytemplate_rtl.css     = rtl
css/print.css              = print
css/mytemplate_print.css   = print

Instead of editing any of the .css files we copied over from the Starter template we add our CSS rules to the files we just created and make use of a key CSS feature: the so-called cascade.3) Expressed in simplified terms, CSS rules simply override previous rules affecting the same element.4) And in some cases where the specificity of your rule is not enough, you may use !important5) or an own class to solve such problems.

So we just override any Starter template CSS rule we like to change in our own mytemplate_screen.css, mytemplate_rtl.css and mytemplate_print.css. Developing a stylesheet this way is a little bit more advanced than if you just edit the existing .css files. But it has an advantage as you'll see later. Additionally, you may noticed that I removed some original Starter template files which are not starting with an underscore (basic.css, structure.css, design.css, content.css and includes.css). The reason for this is simple: only the files starting with an underscore plus rtl.css and print.css are the important core styles, the rest is supposed to be adjusted. Therefore use them as starting point for your own mytemplate_screen.css.

Another thing you may like to consider while modifying DokuWiki's CSS is that it is best to access the elements the same way as done in the Starter template CSS files and prepend most ids or classes with .dokuwiki. And have a look at the color placeholders. If you happen to edit the main.php of your template to add or edit something you shouldn't remove the <div class="dokuwiki"> as it will break the whole stylesheet!

To get a clue about which rules to overwrite, it may help you to look at the CSS files of my templates prsnl10 and mnml-blog:

As you may have noticed, this approach has one drawback. The size of the final stylesheet delivered to the browser will be bigger than if you just edit the existing .css files. This should be around ~2kB till 15kB (uncompressed), depending on the things you are changing. Since the whole CSS gets compressed and is usually delivered only once and then cached I don't think it's that much of a problem.6) And it is not “unclean” or something like that because the Wiki's data is not affected and a template is not triggering any dependencies for your data in general.

Keeping It Up-To-Date

If you follow the approach given above, keeping your template up-to-date after a new DokuWiki release is a task that can be done very quickly! The only thing you have to do is to run a diff against all .css files you copied from the Starter template against the original ones (or have a look at the Commits, e.g. if you are not familiar with tools like diff). Checking the Starter template changelog is also a good idea. If there have been changes, just copy the changed .css files of the Starter template to your template folder overriding the old ones, and, only if needed, add some extra rules to your custom .css files to adjust everything to your needs. The best place to check if everything is OK is the syntax page included in every DokuWiki release.7) It is also recommendable to have a look at the .php files provided by the Starter template to determine if there are any changes needed for new features. The official Developers Changelog may help you to support new features, too.

Some additional notes

That's it! At least this approach works pretty well for me ;-). Of course this only covers CSS issues but it assures that things don't get totally messed up. If you've added new functionality to a template you surely have to put more time into testing/debuging things. But if you create a different look for DokuWiki and like to share it, this is one way to keep things easy over time. Keeping things maintained is normally much harder than creating something new, therefore the additional work when starting a new template should pay off quickly. The approach is even powerful enough to make things like vector8) or this blog's template mnml-blog possible without getting to much trouble when a new DokuWiki version was released.

In the past, the best way to start an own template was to copy DokuWiki's default template. The reason is simple: there was no such useful thing as the Starter template. Therefore all of my existing templates were based on the default template CSS. But things changed a bit. First of all, DokuWiki will get a new default template called “dokuwiki” in the near future. Therefore I asked on the mailing list if it is better to use the “Starter” template CSS or wait for the new “dokuwiki” template CSS as technical base for the development approach described in this text. And the answer is clear: use the Starter template as the new default template is based on Starter, too. Therefore I switched all of my templates over from the old default template CSS to the Starter template CSS as technical base.9) I'm sure a comparable situation won't happen again. Relying on the default template simply was less future-proof than relying on the now existing Starter template which is just existing to make template developing easier.

Update 2011-12-03: I updated parts of the article to fit the newest changes and Anika's recommendations.

This post is based on a text created by Michael Klier. He decided to shut down his blog. The unmodified text was originally posted on August, 16th 2007 and is licensed under the Creative Commons BY-NC-SA License and accordingly this text also is. I just took his post and changed the needed things to fit the facts of 2011.

Anika is an important and reliable part of the DokuWiki development and also responsible for the coming DokuWiki default template called “dokuwiki”.
You can have a look at it by using your browser's print preview.
The first “C” in CSS, you know.
In fact, the priority scheme is a little bit more complicated but this should not matter in general. If you want to know more about, have a look at the weblinks at the end of this text.
Usage example: p { font-size:1em !important; }
I am sure there are other opinions on that topic though
Tip: open two tabs in Firefox (one for the old, one for the new version) and use Ctrl+Page↑ / Ctrl+Page↓ to quickly switch between them for a comparison. Use the headline navigation (e.g. :wiki:syntax#tables) to jump to the exactly same point in both versions.
which merges DokuWiki and MediaWiki CSS
This sounds harder than it really is…

// Admin tip: use a CNAME DNS RR as alias for services like DynDNS.com

Dynamic DNS services like DynDNS are very useful, e.g. for LAN access via VPN in combination with non-static IP addresses. But the dynamic DNS hostname is normally a subdomain of the service (e.g. example.dyndns.org) which is often hard to remember. And this name is tying yourself up to the service you are using because a change may be really annoying (you have to change documentation, inform users and stuff).

I'm always wondering why most admins don't use a simple trick to solve all these problems: Use a sub-domain of your own domain (e.g. vpn) and set a CNAME RR for it. Let it simply point to your dynamic DNS hostname:

vpn.example.com.   CNAME  example.dyndns.org.

That's all, you are be able to use vpn.example.com from now on. A sub-domain of your main address should be much easier to remember and you can switch to another dynamic DNS service whenever you want. Without any noticeable difference for a common user.

// GnuPG on Android with APG and K-9 Mail

I'm using a separate10) email address for my Android 2.2 based mobile phone. This makes it possible for close friends and my family to write me when I'm on the road. For free and without the need for crappy SMS phone GUIs. Additionally, it is very handy to mail yourself a grocery list or a quick note before leaving the house. ;-) However: All unencrypted11) mails for your phone are clear for the telco provider and others to see. But there are comfortable applications to change this.

Quick and superficial guide about the needed actions:

  1. Install the needed applications on your phone (click on the app names for QR Codes containing an Android Market search query):
  2. Generate a new key pair for your phone. IMHO, it is a bad idea to place your main private key on an unencrypted mobile device. The risk of theft/loosing it is too high. I created the new key pair on my PC (even it would be possible on Android) because I prefer some kind of key hierarchy :lang_de: and a keyboard makes the creation more comfortable. Additionally, it is not a bad idea to have a backup copy of the new key on your PC.
  3. Export you new key pair into .asc files:
    gpg -ao ~/privkey.asc --export-secret-key KEY-ID
    gpg -ao ~/pubkey.asc --export KEY-ID

    If you don't like the terminal, use Enigmail or another GPG GUI for the export. It is also a good idea to export the public keys of the persons you want to write encrypted mails from your phone. Even APG provides the possibility to use keyservers, it makes no fun to search and import dozens of keys using that way.

  4. Copy the .asc files on your phone (e.g. via USB), the location does not matter (you can delete these files after the import was done).
  5. On your phone:
    1. Open APG→click Menu button→“Manage Public Keys”. The screen changes→click Menu button→“Import Key”. The program is asking where the .asc file containing your public key to import is located. Click on the file browser icon and run the action with “ASTRO”. Browse to the file and click on it. Check “Delete After Import” and click OK.
    2. Open APG→click Menu button→“Manage Private Keys”. The screen changes→click Menu button→“Import Key”. The program is asking where the .asc file to containing your private key to import is located. Click on the file browser icon and run the action with “ASTRO”. Browse to the file and click on it. Check “Delete After Import” and click OK.
    3. Open K-9-Mail→click Menu button→“More”→“Accounts”. The sceen changes→Click and hold on your account→“Advanced”→Cryptography→Select “APG” as the OpenPGP Provider. And check “Auto-sign” if it makes sense for you.

That's all. But you should know that K-9 Mail brings no support for PGP/MIME right now. This means you have to tell your friends to write Inline-PGP encoded mails, not PGP/MIME mails. But this should be default in most environments. If not: Enigmail provides a non-global select box for this setting at the “Per-Recipient Rules” menu.

I don't want all of my emails on my mobile
Only an insignificant amount of unencrypted mails are hitting my mailbox. It was a lot of work LOL but nearly everybody who writes mails to me is using GnuPG. Even my Mom. No excuses for not using it!

// Happy new year

The year is nearly over and it is time to wish all of you a happy new year 2011. :-)

Happy new year!
Picture source: Wikimedia Commons

// Winter

Before 2010 is over and all snow melted away, a few winter snapshots taken at the neighboring place four days ago.

// Protect your email address with reCAPTCHA

reCAPTCHA is a well known service and used by many websites. But a little know feature is their email address protection service. Just enter your mail address, click on “Protect It!” and everyone who wants to see your address has to solve a CAPTCHA before it will be shown. You will get a common link12) and HTML source code where only a part of your mail address is replaced:13)

Examples, created with the address foobar@example.com:

  • http://www.google.com/recaptcha/mailhide/d?k=01rhhtdpw4VPtj-ejfKMpwEw==&c=VGXKsGQ8aXgpBQISADqLu1SFbEYkjlSIeDbzeRHbKL4=

    Simply copy & paste the URL or use something like “Click to see my address” when you are able to create links with custom text.

  • foo<a href="http://www.google.com/recaptcha/mailhide/d?k=01rhhtdpw4VPtj-ejfKMpwEw==&amp;c=VGXKsGQ8aXgpBQISADqLu1SFbEYkjlSIeDbzeRHbKL4=" onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k\07501rhhtdpw4VPtj-ejfKMpwEw\75\75\46c\75VGXKsGQ8aXgpBQISADqLu1SFbEYkjlSIeDbzeRHbKL4\075', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;" title="Reveal this e-mail address">...</a>@example.com

    This will produce something like “foo...@example.com”.

Actually an old hat, but I just saw tons of plain email addresses in a forum. The smarter ones replaced @/. with [a]/[dot]. While this is better then nothing, most bots should be intelligent enough to parse such replacements. reCAPTCHA FTW.

perfect for IM, forums and stuff
perfect for websites and everywhere you are allowed to use (X)HTML

// LaTeX-Tutorial: Warum man es will. Wie man anfängt. Was man braucht.

Aufgrund der globalen Verbreitung und der bereits Jahrzehnte langen Existenz von (La)TeX finden sich extrem viele Informationen zum Thema. Als Anfänger ertrinkt man in der Informationsflut, eine thematische oder qualitative Selektion ist ohne Vorwissen sehr schwer: So manche Quelle ist von schlechter Qualität, andere sind hochwertig aber erschöpfend. Anderes ist… abgespact.

Ich liste daher im Folgenden (hoffentlich) nützliche Informationen, die ich als LaTeX-Einsteiger zusammengetragen habe. Vielleicht wird es für dem Ein oder Anderen hiermit leichter gemacht, zu wissen was man wofür braucht, welche Werkzeuge empfehlenswert sind und wo man gute Informationen dazu findet.

// Keep your Firefox fast and slim: use different profiles for different tasks

You know the problem: tons of add-ons are bloating your Firefox. Including slower rendering speed and start-up. This is especially true if you are a web developer because there are many useful but heavy extensions you never need if you are not working on a project. Different profiles and starters/shortcuts may help you out. It works for me14) and I'm sharing my approach here (maybe it is useful for someone else).

I really love my Firefox again. You don't need to switch to Chrome/Opera to get a fast browser.

// Quick Locale Switcher: Handle multiple locales and dictionaries in Firefox and Thunderbird

Quick Locale Switcher is an extension for Firefox and Thunderbird, providing a function to toggle between different locales to optionally switch:

  • The used dictionary (active by default)
  • Accept-Language-Header (active by default)
  • The GUI (inactive by default)

See the following for installation notes:

Don't forget to install additional dictionaries to get spell-checking support for the languages you want to use:

If there is more than one dictionary for your language, I recommend the ones based on Hunspell.

The add-on is especially helpful when you are writing mails and text in different languages. You probably missed quick access to the correct dictionary/spell-checker but Quick Locale Switcher is a clever solution to solve this problem.

// How to start with Bash

Writing Bash scripts is fundamental to automate and understand many tasks on common Unix-like environments. If you are new to Bash (or even Unix-like systems) you'll have it a lot easier if you take a weekend to learn some fundamental principles before starting to script your stuff. No matter how experienced you are in programming, everything you'll find regarding Bash is much easier to follow and understand if you know some things before.

High quality online readings

IMHO, the following resources are good starting points:

  1. Linux Shell Scripting Tutorial (LSST) :!:Extremely good resource, especially for beginners.
  2. Bash FAQ – Many answers to frequently asked questions.
  3. The official GNU bash manual – Reference work. If you are generally familiar with Bash/*ix or simply search for a specific thing: look at the manual. Nearly everything should be documented there.

Things you should understand before you write serious scripts

To make it much easier for yourself, make sure you understand15) the following (the resources mentioned above will help you):

  1. Streams and redirection
    Standard Input (stdin, 0), Standard Output (stdout, 1) and Standard Error (stderr, 2). It is really fundamental to understand the stream concept. How streams are working. And how to manipulate, redirect and merge them. This is particularly important before writing much code or libraries. Otherwise you may have to change many things over and over again to make your scripts are interacting smoothly with the system (→ error logging etc.).
    Example of things you should be able to do blindfolded:
    • merge foobar's stderr (2) into foobar's stdout (1):
      foobar 2>&1
    • If you redirect foobar's stdout (1) into a file now, all error messages will also be written into the file because stderr (2) is merged into stdout (1):
      foobar > ~./logfile.log 2>&1
    • If you understand the two steps above, it is clear what the following does:
      echo "message" 1>&2

      Explanation: echo prints something to stdout (1). 1>&2 merges stdout into stderr. Therefore “message” will be printed as error to stderr(2) instead of creating simple standard output – this is the way to go if you want to print a simple error message. You also need redirections if you want to use sudo.

  2. Exit codes
    This is particularly important before writing much code to make sure your scripts are interacting smoothly with other applications.
  3. Pipes and Filters
  4. Subshells and the so called Subshell Problematic
  5. Background processes
    E.g. how to start them (→ &).
  6. Globbing and the Internal Field Separator (IFS)
    Make sure you be able to change and restore the IFS. And know how to use find and why you need it.
  7. Regular Expressions and useful tools
    The sed, cut, grep and find commands are available on nearly every system and are very helpful when you need to edit, find, manipulate or create files and data.
  8. Learn how to detect if you are root
    if [ "$(id -u)" != "0" ]
        echo "This script needs root privileges!" 1>&2
        exit 1
  9. Learn how to define functions
  10. Here Documents
    See the Here Documents at the LSST for details.

Last but not least: find a project

You'll learn the most if your scripts are doing real jobs. Create a backup script. Or try to configure your whole desktop by script to make things comfortable on freshly installed systems.

at least: know when you will need them and where you can look it up. Or better: be able to do the things blindfolded.

// VPN KIT (former Uni Karlsruhe): use it with Ubuntu Linux

Connecting to university VPNs is always… fun. This is also true for the KIT VPN, especially because there is so much outdated information out there. E.g. there is no more Cisco compatible endpoint16) but tons of vpnc tutorials! You have to use the Juniper Networks software jnc now.


However… it worked after all. The IT guys were friendly enough to put helpful information at the online help. :-) But to make it even easier, here are a my hints to get the KIT University Karlsruhe VPN connection running:

  1. Make sure you got a working Java RE. I used sun-java6-jre, therefore I don't know if it runs with OpenJDK.
  2. If you are running a 64bit Ubuntu,17) you need some 32bit wrapper libraries for jnc:
    sudo apt-get install libc6-i386 lib32z1 lib32nss-mdns
  3. Open a terminal, download and untar the jnc archive the KIT VPN help provides for Linux:
    cd ~
    wget https://www.scc.kit.edu/scc/sw/juniper/7.0/linux_vpn_7.0.tar.gz
  4. Extract the archive and remove it afterwards:
    tar -xzf linux_vpn_7.0.tar.gz
    rm linux_vpn_7.0.tar.gz
  5. There should be a juniper_linux directory within your home dir now. Change into it and run the included vpn-install.sh script:
    cd ~/juniper_linux

    Simply follow the instructions (e.g. you have to enter your RZ username).

  6. Make sure jnc is executable:
    sudo chmod a+xr /usr/local/bin/jnc
  7. You can remove the temporary juniper_linux directory now:
    rm -rf ~/juniper_linux

    That's it.


To establish the connection, open a terminal and type jnc -n kit. The program should start and prompt you for your account's password. Example output:

user@computer:~$ jnc -n kit
Server certificate verified and CN is vpn.kit.edu. Saving in /home/user/.juniper_networks/network_connect/config/vpn.kit.edu.der.
Connecting to vpn.kit.edu : 443.
Waiting for ncsvc for 3 seconds... done
ncsvc is running, but tunnel is not established yet. Waiting for 3 seconds... done.
ncsvc is running in background (PID: 2448):
tunnel interface tun0, addr:

You can use jnc stop to close the VPN connection. Example output:

user@computer:~$ jnc stop
ncsvc is running, sending signal... terminated.

2011-10-25: Updated the installation instructions, there is a new VPN software version (7.0).

This means the Cisco compatible vpnc does not work!
You can check this by opening a terminal: If uname -m prints out x86_64, you are running a 64bit Ubuntu

// HMAC-SHA-1 for PHP

Hash-based Message Authentication Codes (HMAC)18) are very useful. Especially HMAC-SHA-1 is used by more and more webservices (e.g. Amazon S3) to verify if a request comes from a valid user (by using a shared secret/key + submitting the result of HMAC-SHA-1($request)). The easiest way to generate them – hash_hmac() – is only available for PHP > 5.1.2 and I saw many system where the function is not available. I even saw people installing the whole PEAR system just to get PEAR::Crypt_HMAC running. :-O

If you need a simple function for creating SHA-1 based HMACs, you may be interested in the following:

 * Returns the HMAC-SHA-1 of a string
 * @param string The data to hash.
 * @param string The key to use. Use ASCII only for best compatibility.
 *        Otherwise, you have to take care about using the same encoding in
 *        every case.
 * @param bool (optional) TRUE leads to PHP warnings if a non-ASCII-string was
 *        submitted as key. FALSE will suppress this check. Default is TRUE.
 * @return string The HMAC-SHA1 of the data.
 * @author Andreas Haerter
 * @link http://en.wikipedia.org/wiki/HMAC
 * @link http://tools.ietf.org/html/rfc2104
 * @link http://blog.andreas-haerter.com/2010/09/30/hmac-sha-1-php
 * @license GPLv2 (http://www.gnu.org/licenses/gpl2.html)
 * @license New/3-clause BSD (http://opensource.org/licenses/bsd-license.php)
function hmac_sha1($str, $key, $warn_nonasciikey = true)
	//check: key consists of ASCII chars only?
	//this should prevent unexpected (=not equal results) when mixing this
	//implementation and base64_encode(hash_hmac("sha1", $str, $key, true))
	//regarding different encodings etc.
	if (!empty($warn_nonasciikey)
	    //search for any bytes which are outside the ASCII range...
	    //note: the regex is *REALLY* fast. Even a "quickcheck" with ctype_alnum()
	    //      won't make the things faster but slower on *common* input!
	    && preg_match('/(?:[^\x00-\x7F])/u', $key) === 1) {  //ATTENTION: single quotes are needed here! Otherwise, PCRE is not able to find the ending delimiter!
		//inform developers
		              __FUNCTION__.":non-ASCII key may lead to unexpected results when switching encodings!",
	//use PHP's built in functionality if available (~20% faster than the
	//following script implementation)
	if (function_exists("hash_hmac")) {
		return base64_encode(hash_hmac("sha1", $str, $key, true));
	//create the secret based on the given key
	$key_lenght = strlen($key);
	//key is longer than 64 bytes, use the hash of it
	if ($key_lenght > 64) {
		$key        = sha1($key);
		$key_length = 40;
	//pad secret with 0x0 to get a 64 byte secret?
	if ($key_lenght < 64) {
		$secret = $key.str_repeat(chr(0), (64 - $key_lenght));
	} else {
		//64 bytes long, we can use the key directly
		$secret = $key;
	//hash and return it
	return base64_encode(sha1(//create the string we have to hash
	                          ($secret^str_repeat(chr(0x5c), 64)). //pad the key for inner digest
	                          sha1(//create substring we have to hash
	                               ($secret^str_repeat(chr(0x36), 64)). //pad the key for outer digest
	                               //we need RAW output!
	                          //we need RAW output!
echo hmac_sha1("this is the data to hash", "my secret key, ASCII only for best compatibility");

The source code of this function is dual-licensed under GPLv2 and New/3-clause BSD. Have fun. :-)

see RFC2104 for details

// LeechBlock - Firefox Add-on to (temporarily) block time-wasting websites

LeechBlock is a simple productivity tool. It is a Firefox extension to block time-wasting sites, distracting yourself e.g. from working effectively. All you need to do is specify which sites to block and when to block them.

See LeechBlock for installation instructions. Perfect to focus your attention when working on boring things. :-)

I'm no native speaker (English)
Please let me know if you find any errors (I want to improve my English skills). Thank you!
QR Code: URL of current page
QR Code: URL of current page start (generated for current page)