Monday, 19 November 2007

Config files in RPM files

see this very helpful description of RPM, %config, and (noreplace) by Jon Warbrick

all about when files are stored with extension .rpmnew or .rpmsave, and when the current file is actually replaced with the new file

Saturday, 17 November 2007

Kolab Groupware Calendaring

January 2004
See my kolab groupware calendaring pages

I wrote this documentation while trying to setup a working groupware calendaring solution. It is basically a log of this process, including the problems that I came across, and how I solved it, often with help from helpful people from the associated projects. I hope this text can help other people who will have the same problems. Some portions of this text are tailored for the server environment (SLS) of OM, the organisation that I work for.

Free Visual C++ Toolkit

copy nmake.exe from .net SDK into bin directory

use the shortcut to start a cmd box with the environment variables set

Blog about it

Manual from Microsoft about nmake.exe

review from a linux point of view:

If you have a Visual C++ 6 IDE, just copy over the bin, lib, and include directory, and compiling works. Debugging does not.

Some CSV functions for VBA

feel free to use!
Function getCountCSV(ByVal list As String) As String
Dim number As Integer
number = 0
While Len(list) <> 0
Call getNextCSV(list)
number = number + 1
getCountCSV = number
End Function

Function getNextCSV(list As String) As String
Dim commaPosition As Integer
commaPosition = InStr(list, ",")
If (commaPosition = 0) Then commaPosition = InStr(list, ";")
If (commaPosition <> 0) Then
getNextCSV = Trim$(Mid$(list, 1, commaPosition - 1))
list = Trim$(Mid$(list, commaPosition + 1, Len(list) - commaPosition))
getNextCSV = Trim$(list)
list = vbNullString
End If
End Function

Function getCSVValue(list As String, index As Integer) As String
' list is the text with comma separated values
' index is starting from 0
' returns the value at the given position in the list
Dim counter As Integer
Dim element As String
Dim listcsv As String
counter = 0
listcsv = list
element = getNextCSV(listcsv)
While (counter <> 0)
element = getNextCSV(listcsv)
counter = counter + 1
getCSVValue = element
End Function

BsDiff for Windows and .net

This program is based on the excellent unix tool bsdiff from Colin Percival.

I made some adjustments, so that it would compile in C++ mode in Dev-C++ IDE (mingw compiler), using the libbzip2 package.

This version is based on bsdiff 4.1. The difference between 4.1 and 4.2 is only in the patch program, instead of using lseek and read he now uses pread, which I find this text about it:
Another thing to take note of is that Linux 2.2 introduces the pread() and pwrite() system calls. These allow a process to read and write from a specified position in a file. This is similar, but not identical, to using the lseek() system call followed by an ordinary read() or write() system call. In particular, concurrent access to a file (required for asynchronous I/O (AIO) support) requires the pread() and pwrite() system calls.

In the windows version, I had to adjust the code anyway, because I am not using pipes, but keep the file open for reading. I guess the bug of the official bsdiff had to do with the concurrent access of the several forks of the program to the file. That does not happen in the windows version at all, the file is opened only once.

For questions, write to Timotheus Pokorra.

Here are the sources (including the .dev files for Dev-C++):
Here are the 2 executables:
The code is licensed under the BSD Protection License (see the original LICENSE file in bsdiff-4.1.tar.gz).

See also Andreas John's bsdiff for Visual C++.

May 2007: I have ported the program to, and with small modifications (make it a proper dll) you can use it even with C# programs. If anyone is interested in the code, I will be happy to share it. Drop me an email...
June 2007: Ok, someone has dropped me an email, and here is the version, with all required dlls. also read the readme.txt included in the archive, and the documentation in bsdiff.pas. If you have questions, ask!


SQL2Diagram: A sourceforge project that I am involved in; we use that program at work to keep track of our database structure, consisting of 250+ tables in several modules.

It basically parses the SQL Create Table statements and generates both HTML documentation and diagrams in XML format that can be displayed with the program Dia.

Installing Java Stored Procedures on PostgreSQL 8.0 (Win)

February 2005

look at the page PL Java Website.
change the file C:\Program Files\PostgreSQL\8.0\data\postgresql.conf:
dynamic_library_path = '$libdir;C:/Program Files/PostgreSQL/8.0/pljava'
custom_variable_classes = 'pljava'
pljava.classpath = 'C:/Program Files/PostgreSQL/8.0/pljava/pljava.jar'
Set the classpath:
set CLASSPATH=%CLASSPATH%;deploy.jar;..\jdbc\postgresql-8.0.309.jdbc2.jar;pljava.jar
change into directory "Program Files\PostgreSQL\8.0\pljava" and execute
java org.postgresql.pljava.deploy.Deployer -install -database mydatabase -user somesuperuser -password mypasswd
I got the error:
java.sql.SQLException: ERROR: could not load library "C:/Programme/PostgreSQL/8.0/lib/libpljava.dll": dynamic load error
This page helped me a lot: Debugging PostgreSQL.
runas /user:postgres cmd.exe
postmaster -d 5 -D ../data/
I started postmaster in one command line box, and then psql in another DOS box. That told me that jvm.dll could not be found. Finally I realised, that the path needs to be set before the postmaster is started.

Use patched files in RPMs

see Packaging software with RPM

diff -uNr the_package/the_file \
the_package/ > the_file.patch

copy the patch file to /usr/src/redhat/SOURCES

The spec file has those lines:

After Sources:
Patch0: the_file.patch

After %setup, before %build
%patch -p1
To get your new version from the original file:
patch slapd.conf.template \
../../slapd.conf.template.patch \

Package a Perl module

First check if somebody did already the job, e.g. on RPMS (SRPMS) or just for RPMS: RPMPan or this search site: Linux Software Directory .

You need to install perl-Archive-Tar-1.08-2.noarch.rpm and perl-RPM-Specfile-1.17-1.noarch.rpm.
A description of the module perl-RPM-Specfile can be found on cpan.
Download this perl script, called It is described as followed: "Grab a module from CPAN and sock it into an RPM using cpanflute2"
Call it this way:
perl \
perl \

That will create
If you install it with
rpm -i /usr/src/redhat/SRPMS/perl-Net-Netmask-1.9011-1.src.rpm
you can build the rpm from it with
rpmbuild -ba /usr/src/redhat/SPECS/perl-Net-Netmask.spec
to see what an rpm provides: rpm -qlp --provides perl-LDAP-0.31-4.noarch.rpm

The file list conversion from OpenPKG

One idea could be, to download the file from the OpenPKG CVS and save it to /usr/bin/rpmtool; you need to change the first line of that file to #!/bin/bash
Also add at the top of the spec file:
%define l_rpmtool /usr/bin/rpmtool
The other idea is, to install the OpenPKG source rpm of the package concerned:
/kolab/bin/openpkg rpm -i kolab-webadmin-0.4.0-20050318.src.rpm
In the /kolab/RPM/SRC/kolab-webadmin/kolab-webadmin.spec
insert after the l_rpmtool line:
cp files /usr/src/redhat/SOURCES/kolab-webadmin.files

Rebuild the package, which will create the kolab-webadmin.files:
/kolab/libexec/openpkg/rpmbuild -ba /kolab/RPM/SRC/kolab-webadmin/kolab-webadmin.spec

Perhaps need to change the paths, e.g. for perl:
in vi:

You need to put it into an archive:
cd /usr/src/redhat/SOURCES/
tar cvf kolab-webadmin.files.tar kolab-webadmin.files

In the fedora spec file, /usr/src/redhat/SPECS/kolab-webadmin.spec, you would add in the sources:
Source1: kolab-webadmin.files.tar

In the %prep section, insert:
%setup1 -D -T -b 1 -n kolab-webadmin-%{version}
As the parameter for -n, give the name of a directory that is created for the main tar file anyway.

In the %install section, remove the rpmtool lines; instead, you change the %files line:
%files -f ../kolab-webadmin.files

Converting OpenPKG spec file to Fedora

have a look at Building Packages with OpenPKG
See /usr/local/kolabopenpkg/etc/openpkg/rpmmacros to know what the macros (e.g. %l_musr) mean.

To get the spec file, install the OpenPKG source package:
/kolab/bin/openpkg rpm -i kolab-webadmin-0.4.0-20050318.src.rpm
Copy the /kolab/RPM/SRC/kolab-webadmin/kolab-webadmin.spec to /usr/src/redhat/SPECS;
Copy the other files (e.g. .tar.gz archives) to /usr/src/redhat/SOURCES

One special thing is that the required packages in OpenPKG don't only include the package name and required version number, but often also options that were included when configuring and building the package.
For example, cyrus-sasl::with_ldap would require that the cyrus-sasl::with_ldap is advertised in the Provides: tag in the spec file.
A common approach is not to advertise all compiling options, but to know the packages and test them thoroughly.

Remove the line:
Class: JUNK

To understand some of the macros, in the form %{something}, have a look at /usr/lib/rpm/macros and /usr/local/kolab/etc/openpkg/rpmmacros.

Insert these lines near the top:
%define l_prefix /kolab
%define l_make %{__make}
%define l_mflags -m
# m actually is ignored, compatibility
Replace all occurances of "apache" with "httpd" in your spec file.

It seems, the spaces before the %setup -q are not correct. Remove them!

Lines like %{l_shtool} install: just remove all the %{l_shtool}; install should work fine;
remove also the %{l_value -s -a} (though I am not sure what those characters stand for)

Quick RPM lookaround

April 2005:
That is how I learnt about RPM packaging of software for Fedora Linux.
My goal was to create Fedora packages for Kolab, which is packaged with OpenPKG.

Links to RPM introductions

Basic Idea of SRPMS

rpm -i some-package-0.0.1.src.rpm
will put some tar file(s) and patches in /usr/src/redhat/SOURCES; and will put the some-package.spec file in /usr/src/redhat/SPECS
to build the src.rpm and the rpm, run
rpmbuild -ba /usr/src/redhat/SPECS/some-package.spec
That will create the files /usr/src/redhat/SRPMS/some-package.src.rpm and /usr/src/redhat/RPMS/i386/some-package.rpm.

Find IP address of a Pocket Print Server (e.g. DP-301P+)

on the linux console, type:
i=1; \
while [ $i != 254 ]; do \
ping -c 1 192.168.1.$i; \
i=`expr $i + 1`; \
arp -a
That should give a list of all computers on that subnet The MAC address should tell you the IP address of the print server.

VPN between 2 networks with same IP address scheme (Windows)

Problem is, the routing does not work. Solution is: On DOS command prompt, type
route add MASK
...1.84 is the number of the computer you want to contact in the other network, ...1.160 is the client IP address of the VPN network connection.
To prevent your traffic into the Internet to go through the VPN, use:
route change mask metric 20
(.250 is the local network gateway into the internet)
If it gives the error: "The route addition failed: The parameter is incorrect." or "Hinzuf├╝gen der Route fehlgeschlagen: Falscher Parameter.", try using another local IP address. I found, the local IP address should not be too distant from the VPN client IP address.

Another annoying error I had, was that after some time of a working connection, I could not reconnect the VPN:
Error 619 came up, german: "Fehler 619 Ein unbekannter Fehler ist aufgetreten" nach "Benutzername und Passwort werden verifiziert".
My solution was, to set my LAN connection on a new IP address. Other people solved it by reinstalling their NIC card.


Install gimp 2.0 and gaim 0.79 on Windows, problems with GTK 2.4:
according to the gimpwin-users list, do this:
Install Gaim's GTK+- 2.2.4, then Gaim, then uninstall Gaim's GTK+-, and install GTK+- 2.4.1 and Gimp. Gaim should still work with GTK+- 2.4.1.
You also need to copy the file Program Files\Common Files\GTK\2.0\bin\zlib1.dll to zlib-1.dll.

Download websites with dynamically generated content (question mark in URL)

You should use the Windows version of wget, because that converts the ? nicely to the @ character.
wget --recursive \
--level=5 --relative --tries=1 --convert-links

Using WinMerge to compare CVS branches

I often have trouble with CVS merge, and so end up comparing the files manually. The problem is that the CVS Revision and Log tags should not show up as a difference. I wanted something similar to "Ignore whitespaces".

For the revision tag, the regular expression filter in WinMerge works fine: WinMerge, Tools, Filters, LineFilters: $Revision\: .*$
For the CVS commit history log, I have implemented a prediffer Plugin similar to Plugins\src_VCPP\IgnoreCommentsC from the source code of WinMerge.

The source code for the prediffer plugin is here:


This is specifically designed for Delphi code. It should be easy to adapt to different languages.

Backup/Restore a harddisk image onto a samba network drive

Use SystemRescueCd:

for resizing partitions, creating/deleting partitions:

mount -t smbfs \
-o username=myusername,password=mypassword \
//<ip-address of linux server>/homes \

for storing/restoring of images of partitions:


Reports with Symfony

I wondered what the easiest way was to create reports.
I looked into PM Report 4.1 by Zeke Walker, but did not think it would be what I needed.

So this is what I did:
edit the Peer class of your table, and add a function that will return the data that you will need in the report:
static function getAllRowsWithBlabla()
$con = Propel::getConnection(self::DATABASE_NAME);
$sql = 'SELECT * FROM '.self::TABLE_NAME.' WHERE a=1 ORDER BY nachname, vorname';
$stmt = $con->prepareStatement($sql);
$rs = $stmt->executeQuery(ResultSet::FETCHMODE_NUM);
return BasePatePeer::populateObjects($rs);

Then in apps/myapp/modules/mytable/actions/actions.class.php add an action for the report:
public function executeReportVereinsmitglieder()
$this->items = MyTablePeer::getAllRowsWithBlabla();

Finally, create a success page:
<?php use_helper('Text', 'Date') ?>

<div id="datecreated">Date created:
<?php echo format_date(time(), 'd', 'de');?></div>

<div id="doprint"><a href="javascript:window.print()">
Print this report</a></div>

<h2>My blabla report</h2>

<?php $first = true; ?>

<?php foreach($items as $item): ?>

if ($item->getSomeCondition())
if ($first)
$first = false;
echo ', ';
echo $item->getMyValue();


<?php endforeach ?>

To disable some items for printing, I changed the css styles
in file apps/myapp/templates/layout.php:
<style type="text/css">
@media print {
/* ... format definitions for printing ... */
#navigation { display:none; }
#title { display:none }
#doprint { display:none }

Symfony I18N


I have changed the default_culture in myapp/config/i18n.yml

Based on this blog entry with german translations I have created my own version:
save it as apps/mybackend/

Symfony Project

I enjoy using the symfony Web PHP Framework for a database/web application.

To make it run on a Debian Virtual Private Server:
add to file /etc/apt/sources.list this line:
deb debian/
Then install the required packages:
apt-get install php-pear php5-symfony php5-mysql php5-xsl
See the "My First Project"-Tutorial for initialising your project.

HTML2Wiki, Wiki2HTML

Integration of phpNuke and MediaWiki (Authentication)

The goal is, that users are only registered on phpNuke, and can use the same username on MediaWiki, without logging in twice.

Readme.txt, Download, Auth_phpnuke.php, authphpnuke.php, modules/MediaWiki/index.php.