Recently I was in the situation where I needed to manage users in Kolab from PHP.

There is an API for the Kolab Webadmin, and it is documented here:

There is also a PHP class, that I could have used: But for some reason, I am using CURL.

It took me some time to figure out how to do the GET or POST calls for connecting to the API and call, user.delete, user.add and users.list.

Therefore, I have created a small PHP class, that shows how to do that.

You can find it here:

There is also a test.config.php and a test.php to show the usage of that class.

During development, I sometimes got the message: “Internal error”. This is from the class kolab_api_controller, eg.

Actually, it would help if that error was logged to /var/log/kolab-webadmin/errors with some detail:

else {
    Log::error("API controller: Internal Error, ".$service . "_" . $method. " Post: " .print_r($postdata,true). " Get: ".print_r($_GET,true));
    $this->output->error("Internal error", 500);
Tags: ,
Posted in Software Development | Comments Closed

German title: “Lastschriften in Überweisungen konvertieren”

We have had the situation that a SEPA direct debit was sent twice to the bank.

Now we need to credit our customers the amount again.

I did not find an open source script that reverses a direct debit, but I found which can write SEPA direct credit files.

Preparation on CentOS7:

yum install epel-release
yum install php-cli composer
composer require AbcAeffchen/Sephpa

Then get the index.php from below, modify the filename of the direct debit file, and the execution and creation date, and pipe the result:

php reverseSEPA.php > directcredit.xml

Here is the script:

Tags: ,
Posted in Software Development | Comments Closed

I have been using TimeSheetNG for years to record the working time for myself, so that I can keep track on where my time is going, and who I can charge for which hours 🙂

I am using version 1.5.2 of TimeSheetNG, with some small modifications to make it easier for me to enter the minutes of an hour.

My instance is running on a Hostsharing server, which was just upgraded to Debian Jessie. This meant that I got a php warning, that mysql_connect is deprecated, and I should be using mysqli instead:

Deprecated: mysql_pconnect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in .../ on line 10

So here is the patch that I applied to my TimeSheetNG 1.5.2, it should work for 1.5.3 as well:



Tags: , ,
Posted in Hosting, Software Development | Comments Closed

Recently at, we wanted to even better secure the authentication to a web application that we provide to our customers.

There are several options to extend authentication:

We decided for partial passwords: You have your username and your first password, you login with that, and if that worked, you are asked about some specific letters from your second password: Please give us the third and 5th character of your second password!

See this paper called “Give Me Letters 2, 3 and 6!”: Partial Password Implementations & Attacks that describes Partial Password implementations and attacks in a detailed study.

The next question is, how to store the information about the partial password: you cannot hash it, because you will have to verify single characters. The solution is to use a secret sharing scheme, as described in Partial Passwords – How. It uses the Shamir’s Secret Sharing algorithm.

I have now implemented this idea, processing partial passwords with Shamir’s secret sharing scheme, in PHP. You can find the code licensed under the MIT at: There is an example included.

The Wikipedia article on Lagrange polynomial has been helpful as well in properly implementing the algorithm in PHP.

Tags: , ,
Posted in Software Development | Comments Closed

How do you organize your TODO list?

Over the past months, I have tried to organize my TODO list better.

Often I kept emails unread in my Inbox: I thought, that I would know which emails I still have to answer. But I realized that this was very confusing, and there was no order at all.

One attempt was to use a virtual board with notes on it, based on That got quite messy, with too many notes moving around all the time.


There is a short description of the Kanban method:

Kanban was invented by Toyota. It can be used for organising your work. You can see your tasks visually, and can decide to focus on tasks by limiting the tasks that you currently work on.

Organising your tasks on boards and columns

I have a board per project: For example, one board for Kolab, one board for OpenPetra, one board for, and one board for daily things. I create my own columns on those boards.

For my daily board, these are the columns I use:

  • A column for incoming, things that you will need to sort later when you have time into the proper column.
  • Another column I have is for today: these are the things that are important now, and I want to finish them today.
  • Another column is called “week”: these are the things that I want to deal with this week.
  • Another column is “month”.
  • Another column is: “Long term goals”.

For the project specific boards, I have columns for subprojects, but also for daily, weekly and long-term tasks.


Trello is a free service. You can create several boards, and each board can have as many columns as you want. The UI is very nice, and it is easy to add new columns, to close tasks, to move tasks between boards.


Unfortunately, Trello is not free software, and you cannot install it on your own server. So I looked for an Open Source alternative, and I found Kanboard. It is written in PHP. Some elements of the user interface are still involving too many clicks for my taste, but it is open source, and I already got one pull request merged on Github…

Moving your data from Trello to Kanboard

I was able to improve an existing importer from Trello to Kanboard: forked from

With my improvements of the importer, all my comments and checklists on all cards got imported from Trello. Empty columns were ignored. The importer uses the JSON API of Trello to download the boards and cards.


Tags: ,
Posted in Software Development | Comments Closed

With the coming switch in Germany from Bank account number and banking sort code (BLZ) to IBAN and BIC, there are quite some tasks to accomplish.

One task is to convert the bank account numbers to the new IBAN number.
On the first look, you might think that it is simply concatenating the account number and BLZ, add a checksum digit, and you are done. Eg: kto=648489890 and blz=50010517 becomes IBAN DE12500105170648489890
But in fact there are currently 54 rules, explained on 171 pages (see Bundesbank IBAN_Regeln).

There is an Open Source library available under LGPL that does implement all these rules:

It can be used from several programming languages, among them C# and PHP (see
I have packaged it for PHP to offer it as a webservice for OpenPetra.
You can test it live here:
I have added an option to use it as a webservice.
Eg. returns an xml file like this:

<ort>Frankfurt am Main</ort>

The packages are built on the Suse Open Build Service:
At the moment I build it for CentOS5, CentOS6, and Debian 7. If you are interested in other distributions that are available on build.opensuse, let me know, I might add that.

Installation instructions for CentOS5, CentOS6 and Debian 7 see:

I am providing now a server for development of OpenPetra, with X2Go desktop remoting.
See more details at

To save costs, I am running the server on a jiffybox, which costs less when you freeze it.

So I am providing a php script that allows starting the machine, and to refresh it. After the last start or refresh, the machine will be stopped and frozen.

Now it would be good to remind the users once in an hour to do visit the refresh link.
I am using zenity to display the message.
This script will get all users logged in over X2Go, and display the message on their desktops:

message="Server will shutdown soon, please refresh if you still need it by visiting"
wall $message
for display in `ps xaf | grep x2goagent | grep -v grep | awk '{ print ( $(NF) ) }'`
  user=`ps xaf | grep x2goagent | grep -v grep | grep "$display$" | awk ' { print ( $(NF-5) ) }' | awk ' { print ( $3 ) }' FS='/'`
  echo "$user $display"
  su - $user -c "zenity --info --display=$display --text='$message'&"

(for better layout, see

The crontab looks like this, to run it every hour:
0 */1 * * * /root/

The php script looks like this:

The script is installed on a separate machine, that is always running.
The users can call jiffybox.php/?operation=refresh to start or refresh the machine.
The cronjob for stopping the machine looks like this:
*/15 * * * * cd ~/subs/jb; php jiffybox.php

Tags: , ,
Posted in Software Development | Comments Closed

Knowledge Tree and PHP 5.3.3   March 7th, 2011

We have got the latest PHP version on Hostsharing, and Knowledge Tree did not work anymore.

I got a long list of deprecated warnings, and the session would not even start, so not even a login screen is displayed.
Deprecated: Assigning the return value of new by reference is deprecated
Warning: The magic method __get() must have public visibility and cannot be static
Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent
The solution is to edit config/dmsDefaults.php, find the lines containing
error_reporting(E_ALL & ~E_NOTICE);
ini_set(‘display_errors’, ‘1’);
ini_set(‘display_startup_errors’, ‘1’);
Below that, add the following line:


Now Knowledge Tree will work again, and hopefully the next version of Knowledge Tree will have fixed all the deprecated PHP things.

Digest for phpBB Forum without plugin   November 13th, 2010

I am very glad for the hosted apps that Sourceforge provides. It is excellent to have only one login, and not to need to worry about updating the apps.

The problem with the phpBB forum is that the notification emails, when you watch a forum, do not include the message. On Sourceforge you are also not able to install a digest modification, eg.
Therefore I thought it would be good to have an external script, that regularly checks for new posts and sends an email with the contents.
In the end, it was not too hard.
This only works for a public forum, where all posts are accessible by non-registered users.
There is the page search.php (eg. that shows all new posts.
I store each post that has been sent as an email with the post number in a text file.
Then the script fetches the page of the new posts, and checks each post if it has been sent already.
The script sends HTML emails, and even quoting blocks appear quite alright in my email client (google mail).
The script is also able to parse the posts of a thread that spreads across several pages.
You also might find the functions interesting to get the HTML code and to parse for code between the beginning and the end tag.
Feel free to use the script and to modify it.

The advantage of KnowledgeTree is that it keeps versions of each document that you upload. Unfortunately, this does not seem to work in version, when uploading a new version of an existing file via WebDAV. The file is overwritten with the new version, but there is no version history.

There might be good reasons for that behaviour, which are explained in this issue?

Here is a solution that works for me, but of course, I do not know the interna of Knowledge Tree, therefore please use it at your own risk…
In file ktwebdav/lib/, find the lines:
// Modified – 25/10/07 – changed add to overwrite
// $oDocument =& KTDocumentUtil::add($oParentFolder, $name, $oUser, $aOptions);
$oDocument =& KTDocumentUtil::overwrite($oDocument, $name, $sTempFilename, $oUser, $aOptions);
It seems, with the add method a new file would be created, with a unique filename. So uploading a new version of test.txt would result in two files, test.txt would stay, and the new file would be test(1).txt. This is not really what you want.
To get real versioning, comment that line with “overwrite”, and add these lines:
$aOptions[‘newfilename’] = $name;
$oDocument =& KTDocumentUtil::checkin($oDocument, $sTempFilename, ‘WebDAV upload’, $oUser, $aOptions);
This should do the trick. You will only have one file in your folder, and when you click on “Version History” in your webinterface, you will see the old versions and the current version. The file you download via WebDAV is always the latest version. This makes sense to me…