KontoCheck ist eine Bibliothek zum Test deutscher Bankkonten, kann aber auch zum Umrechnen der Kontonummern und BLZ in IBAN und BIC benutzt werden.

Es gab ein neues Update der Bankdatei, deren Inhalt jetzt für den Zeitraum 03. Juni 2019 bis 08. Dezember 2019 gilt. In unserer Bankdatei sind immer die zwei neuesten Bankdaten von der Bundesbank enthalten. Quelle: Deutsche Bundesbank, BLZ Download.

Entsprechend habe ich die Debian und CentOS Pakete aktualisiert:


Auch der Online Dienst https://kontocheck.solidcharity.com/ wurde auf die neue Version aktualisiert. Hier können sowohl manuell Umwandlungen von Kontonummer/BLZ auf IBAN/BIC durchgeführt werden, als auch über einen WebService Abfragen gestellt werden, die mit XML beantwortet werden.

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

In 2014, I migrated the OpenPetra forum from phpBB to Discourse. The reason was that Discourse had a fresh look on the way how forums can be done, it had a nice design, and easy and modern user interface. Here is the post about the details: https://www.pokorra.de/2014/09/migrate-phpbb-forum-to-discourse-using-the-ubuntu-packages-from-packager-io/

Unfortunately, the requirements of Discourse for RAM is quite high, and you cannot just install it inside a shared hosting environment, because it is recommended to be run inside a docker container. It uses technology that I just don’t know very much, with Ruby on Rails and Redis etc.

Then I discovered Flarum, which is written in PHP, but looks as nice and feels as modern as Discourse. It does not have exotic requirements, it just works. It is helpful to have an SSH account, to install the dependencies with composer, but that is available at Hostsharing for my shared hosting anyway.
Flarum is still work in progress, and officially in Beta testing. But you can run your forums in production with the latest Beta already, if you know what you are doing.

So now the issue is, how to migrate your forum from Discourse to Flarum.

At TBits.net, we worked on a migration tool, based on the scripts https://github.com/robrotheram/phpbb_to_flarumhttps://github.com/viruxe/phpbb_to_flarum, and https://github.com/Reflic/phpbb_to_flarum.

We did not cover all aspects, but only those issues we needed for our OpenPetra forum.

Things we covered were:

  • Format text properly, code, lists, http links, etc.
  • convert categories to tags
  • keep the users email addresses

We did not cover:

  • migration of uploaded content
  • we did not convert the user passwords (each user must use the resend password functionality of Flarum)
  • and probably more…

So this blog post has the goal to make our script public, and to encourage you to use it and improve it! Pull Requests are welcome, or just fork it and use it as you like!

We started to host the script first at https://github.com/Crusader99/discourse_to_flarum, then at https://github.com/The-CJ/discourse-flarum, and now the official home for the script is:


Of course, in your real life scenario, you will have a database already. But for contributing to this script, we might need a test database, for reproducing specific situations. See my other post for details how to create a test database with dummy data for Discourse!

Setting up Flarum is quite easy if you can access your webspace with SSH and you can run Composer. See the german instructions how to install Flarum inside your Hostsharing account.

If you are working with a virtual machine and CentOS7, this Ansible script might be useful:

You can run the playbook like this (assuming your test server or container has the IP, and you can access it as root via SSH and via HTTP):

ansible-playbook flarum.yml -u root -e working_host=

For running the script discourse_to_flarum.php, you also need a PostgreSQL database inside that container. This Ansible playbook will setup PostgreSQL, and will load the Discourse Backup into the PostgreSQL database. It will also install pgadmin and phpMyAdmin, which helps with debugging of the conversion routines.
You can run the playbook like this:

ansible-playbook migration.yml -u root -e working_host=

After this, you can access phpMyAdmin on the url, the user is flarum and the password is flarum. You can access phpPgAdmin on the url, the user is discourse, and the password is discourse.
And on, your Flarum forum is running.

Now you can actually run the conversion script:

cd /root/flarummigration
composer update
cp migrate-example.yaml migrate.yaml
# perhaps you need to modify the database credentials in migrate.yaml if you have your own setup
# if your prefix is not fl_ for the flarum tables
sed -i "s/fl_//g" migrate.yaml
php discourse_to_flarum.php

to reset the flarum database for a rerun:

zcat ../flarum.sql.gz | mysql -u flarum flarum -p
# vi discourse_flarum.php, or vi migrate.yaml
php discourse_to_flarum.php

Here are two screenshots of the sample posts in Discourse and in Flarum after the migration (mind you, some of the BBCodes also don’t work in Discourse…)




So there is probably still quite some work to do. Pull requests are welcome!

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

Migrating from KnowledgeTree to SeedDMS   September 24th, 2018

For many years, I had an installation of KnowledgeTree for our small charity “Nazareth Kinderheim Kenia e.V.”.

Unfortunately, it has not been maintained anymore for many years, and the replacement of PHP5 with PHP7 forced me to do something.

I finally settled for SeedDMS as a replacement, and I really like it!

See instructions how to install SeedDMS in a shared hosting environment, at Hostsharing: https://wiki.hostsharing.net/index.php?title=SeedDMS_installieren (in German).

To export the files from KnowledgeTree, I made the decision, that I would ignore deleted files, and would not need the history of files, so only the latest version of each file. That made the migration much easier.

I found a Python script by Ben E. C. Boyter at https://boyter.org/2015/09/exporting-documents-knowledgetree-3-7-0-2/ which was a good start. I found only two issues with it: it would restore even deleted or archived files, and it would restore a random version of a file, not the latest version. So I fixed the Python script, and you can see it here as a gist: https://gist.github.com/tpokorra/71526bc60ced2649dba2c528d5cd2259

There is an import function in SeedDMS, where you can import from a directory on the server, which minimizes the used bandwidth. Alternatively, you can use WebDAV to import a lot of files at the same time.


Tags: , , ,
Posted in Hosting | Comments Closed

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: https://docs.kolab.org/architecture-and-design/kolab-wap-api.html

There is also a PHP class, that I could have used: https://cgit.kolab.org/webadmin/tree/lib/kolab_client_api.php. 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.info, 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: https://github.com/TBits/KolabScripts/tree/KolabWinterfell/kolab-webadmin-api-client

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. https://cgit.kolab.org/webadmin/tree/lib/kolab_api_controller.php#n181

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 https://github.com/AbcAeffchen/Sephpa 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 .../mysql.db.inc 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 TBits.net, 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: https://github.com/TBits/partialPasswordShamirsSecret. 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 http://www.aypwip.org/webnote/. That got quite messy, with too many notes moving around all the time.


There is a short description of the Kanban method: http://kanboard.net/documentation/what-is-kanban

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 TBits.net, 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: https://github.com/tpokorra/kanboard-import-trello forked from https://github.com/matueranet/kanboard-import-trello

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 http://kontocheck.sourceforge.net/konto_check.php?fix_nav=1&ausgabe=5&sub=4).
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. https://kontocheck.solidcharity.com/index.php?kto=648489890&blz=50010517 returns an xml file like this:

<ort>Frankfurt am Main</ort>

The packages are built on the Suse Open Build Service: https://build.opensuse.org/package/show/home:tpokorra:kontocheck/kontocheck
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: http://software.opensuse.org/download/package?project=home:tpokorra:kontocheck&package=kontocheck

I am providing now a server for development of OpenPetra, with X2Go desktop remoting.
See more details at https://sourceforge.net/apps/mediawiki/openpetraorg/index.php?title=Hosted_development_workstation

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 http://jb.solidcharity.com"
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 https://gist.github.com/tpokorra/5984248#file-zenity-sh)

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

The php script looks like this:

see https://gist.github.com/tpokorra/5984248#file-_jiffybox-php
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