[packaging] 8 commits - bin/kolabpasswd.in bin/kolab_smtpdpolicy.in ChangeLog debian/changelog debian/patches DEVELOPMENT kolab.mk lib/Kolab lib/Kolab.pm Makefile.PL MANIFEST META.yml sbin/kolab_bootstrap.in sbin/kolabconf.in sbin/kolab_imappartitions.in

Jeroen van Meeuwen vanmeeuwen at kolabsys.com
Sun Mar 20 20:43:51 CET 2011


 ChangeLog                                   |  130 ++++
 DEVELOPMENT                                 |   82 ++
 MANIFEST                                    |    3 
 META.yml                                    |   14 
 Makefile.PL                                 |  109 +--
 bin/kolab_smtpdpolicy.in                    |    2 
 bin/kolabpasswd.in                          |   16 
 debian/changelog                            |    6 
 debian/patches/10-invoke-rc.diff            |   76 --
 debian/patches/30-bootstrap.diff            |   52 -
 debian/patches/40-disable-amavis.diff       |    8 
 debian/patches/90-slapd-runtime-config.diff |   52 -
 debian/patches/series                       |    3 
 kolab.mk                                    |   31 -
 lib/Kolab.pm                                |    8 
 lib/Kolab/Conf.pm                           |  790 ++++++++++------------------
 lib/Kolab/Cyrus.pm                          |   13 
 lib/Kolab/LDAP.pm                           |   52 +
 lib/Kolab/LDAP/Backend.pm                   |    2 
 lib/Kolab/LDAP/Backend/ad.pm                |    2 
 lib/Kolab/LDAP/Backend/slurpd.pm            |    2 
 lib/Kolab/Util.pm                           |    2 
 sbin/kolab_bootstrap.in                     |   79 ++
 sbin/kolab_imappartitions.in                |   58 ++
 sbin/kolabconf.in                           |   17 
 25 files changed, 760 insertions(+), 849 deletions(-)

New commits:
commit 33eb077291570b1b93678f89eab90b7a80301754
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 20:22:14 2011 +0100

    Refresh patches

diff --git a/debian/patches/90-slapd-runtime-config.diff b/debian/patches/90-slapd-runtime-config.diff
index f3e0eeb..e11828f 100644
--- a/debian/patches/90-slapd-runtime-config.diff
+++ b/debian/patches/90-slapd-runtime-config.diff
@@ -7,45 +7,12 @@ Author: Mathieu Parent <math.parent at gmail.com>
 
 Upstream status: https://issues.kolab.org/issue3000
 
-Index: libkolab-perl-2.2.4-20100624/lib/Kolab/Conf.pm
+Index: libkolab-perl/sbin/kolab_bootstrap.in
 ===================================================================
---- libkolab-perl-2.2.4-20100624.orig/lib/Kolab/Conf.pm	2010-09-13 21:18:54.000000000 +0200
-+++ libkolab-perl-2.2.4-20100624/lib/Kolab/Conf.pm	2010-09-14 08:28:22.000000000 +0200
-@@ -295,7 +295,7 @@
-                 $haschanged{'saslauthd'} = 1;
-             } elsif ($cfg =~ /apache/) {
-                 $haschanged{'apache'} = 1;
--            } elsif ($cfg =~ /openldap/) {
-+            } elsif ($cfg =~ /openldap/ || $cfg =~ /slapd/) {
-                 $haschanged{'slapd'} = 1;
-             } elsif ($cfg =~ /(imapd|cyrus)/) {
-                 $haschanged{'imapd'} = 1;
-@@ -854,8 +854,17 @@
- sub reload
- {
-     if ($haschanged{'slapd'}) {
--        &Kolab::log('K', 'Restarting OpenLDAP...');
--        system("invoke-rc.d slapd restart &");
-+        &Kolab::log('K', 'Stopping OpenLDAP...');
-+        system("invoke-rc.d slapd stop");
-+        &Kolab::log('K', 'Deleting old slapd config...');
-+        system("rm -rf $Kolab::config{'ldapserver_confdir'}/slapd.d");
-+        &Kolab::log('K', 'Converting slapd config... (most errors here can be ignored)');
-+        system("mkdir $Kolab::config{'ldapserver_confdir'}/slapd.d");
-+        system("slaptest -f $Kolab::config{'ldapserver_confdir'}/slapd.conf -F $Kolab::config{'ldapserver_confdir'}/slapd.d");
-+        system("chown -R openldap $Kolab::config{'ldapserver_confdir'}/slapd.d");
-+        system("chgrp -R openldap $Kolab::config{'ldapserver_confdir'}/slapd.d");
-+        &Kolab::log('K', 'Starting OpenLDAP...');
-+        system("invoke-rc.d slapd start");
-     }
- 
-     if ($haschanged{'saslauthd'}) {
-Index: libkolab-perl-2.2.4-20100624/sbin/kolab_bootstrap.in
-===================================================================
---- libkolab-perl-2.2.4-20100624.orig/sbin/kolab_bootstrap.in	2010-09-14 08:13:09.000000000 +0200
-+++ libkolab-perl-2.2.4-20100624/sbin/kolab_bootstrap.in	2010-09-14 08:27:09.000000000 +0200
-@@ -489,6 +489,14 @@
-       Kolab::Conf::bootstrapConfig();
+--- libkolab-perl.orig/sbin/kolab_bootstrap.in	2011-03-20 20:11:34.000000000 +0100
++++ libkolab-perl/sbin/kolab_bootstrap.in	2011-03-20 20:22:03.000000000 +0100
+@@ -521,13 +521,21 @@
+         );
        $Kolab::config{"bootstrap_config"} = 'false';
  
 +      print "Deleting old slapd config...\n";
@@ -56,13 +23,12 @@ Index: libkolab-perl-2.2.4-20100624/sbin/kolab_bootstrap.in
 +      system("chown -R openldap $Kolab::config{'ldapserver_confdir'}/slapd.d");
 +      system("chgrp -R openldap $Kolab::config{'ldapserver_confdir'}/slapd.d");
 +
-       #ldap server should access to certificate key
-       system("adduser --quiet $Kolab::config{'ldapserver_rusr'} $Kolab::config{'pki_grp'}");
- 
-@@ -497,7 +505,7 @@
+       # now we must startup slapd
+       print "temporarily starting slapd\n";
        $ldap_uri = "ldap://127.0.0.1:389/";
        # ensure that the database has correct permissions
-       system("chown $Kolab::config{'ldapserver_rusr'}:$Kolab::config{'ldapserver_grp'} $Kolab::config{'ldapserver_dir'}/*");
+       @files = <$Kolab::config{'ldapserver_dir'}/*>;
+       system("chown $Kolab::config{'ldapserver_rusr'}:$Kolab::config{'ldapserver_grp'} $Kolab::config{'ldapserver_dir'}/*") if (@files);
 -      (system("/usr/sbin/slapd -h ldap://127.0.0.1:389/ -f $Kolab::config{'ldapserver_confdir'}/slapd.conf -u $Kolab::config{'ldapserver_rusr'} -g $Kolab::config{'ldapserver_grp'}") == 0 ) || die( "Could not start temporary slapd: $!" );
 +      (system("/usr/sbin/slapd -h ldap://127.0.0.1:389/ -F $Kolab::config{'ldapserver_confdir'}/slapd.d -u $Kolab::config{'ldapserver_rusr'} -g $Kolab::config{'ldapserver_grp'}") == 0 ) || die( "Could not start temporary slapd: $!" );
        print ("Waiting for OpenLDAP to start\n");
diff --git a/debian/patches/series b/debian/patches/series
index 6d8a835..10634a1 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,7 +1,4 @@
 10-invoke-rc.diff
 30-bootstrap.diff
-40-disable-amavis.diff
-60-fix-build.diff
-70-reload-cyrus-conf.diff
 90-slapd-runtime-config.diff
 92-sieve-port-4190.diff


commit 5fee9611a26d4c4025ae6a1dbd2e6750ab3e8fca
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 20:08:31 2011 +0100

    Update 40-disable-amavis

diff --git a/debian/patches/40-disable-amavis.diff b/debian/patches/40-disable-amavis.diff
old mode 100755
new mode 100644
index 6e514b5..594e648
--- a/debian/patches/40-disable-amavis.diff
+++ b/debian/patches/40-disable-amavis.diff
@@ -4,11 +4,11 @@ Author: Mathieu Parent <math.parent at gmail.com>
 
 Upstream status: Specific to Debian
 
-Index: b/sbin/kolab_bootstrap.in
+Index: libkolab-perl/sbin/kolab_bootstrap.in
 ===================================================================
---- a/sbin/kolab_bootstrap.in
-+++ b/sbin/kolab_bootstrap.in
-@@ -498,7 +498,7 @@
+--- libkolab-perl.orig/sbin/kolab_bootstrap.in	2011-03-20 20:07:29.000000000 +0100
++++ libkolab-perl/sbin/kolab_bootstrap.in	2011-03-20 20:07:55.000000000 +0100
+@@ -561,7 +561,7 @@
          'postfix-mynetworks' => $mynetworkinterfaces,
          #'postfix-relayhost' => "",
          #'postfix-transport' => "",


commit 484594896b1ec50ed2bd36b4ff6cee97e807e4ec
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 20:07:38 2011 +0100

    Update 30-bootstrap  patch

diff --git a/debian/patches/30-bootstrap.diff b/debian/patches/30-bootstrap.diff
old mode 100755
new mode 100644
index e2de376..3c8a116
--- a/debian/patches/30-bootstrap.diff
+++ b/debian/patches/30-bootstrap.diff
@@ -4,27 +4,18 @@ Author: Noèl Köthe <noel at debian.org>
 
 Upstream status: Parts can be or have been included
 
-Index: b/sbin/kolab_bootstrap.in
+Index: libkolab-perl/sbin/kolab_bootstrap.in
 ===================================================================
---- a/sbin/kolab_bootstrap.in
-+++ b/sbin/kolab_bootstrap.in
-@@ -221,7 +221,7 @@
+--- libkolab-perl.orig/sbin/kolab_bootstrap.in	2011-03-20 20:04:55.000000000 +0100
++++ libkolab-perl/sbin/kolab_bootstrap.in	2011-03-20 20:07:29.000000000 +0100
+@@ -376,6 +376,18 @@
  
- print ("Excellent all required Ports are available!\n");
- 
--system("$Kolab::config{'sbindir'}/slapcat >/dev/null 2>&1");
-+system("su  --shell /bin/sh --command $Kolab::config{'sbindir'}/slapcat >/dev/null 2>&1");
- if ($?==0) {
-   print ("\nFound existing configuration\n");
-   print "\nBootstrapping Kolab will overwrite old configuration\n";
-@@ -320,6 +320,18 @@
-   print "Proceeding with master server setup\n\n";
- }
+ $Kolab::config{"is_master"} = $is_master;
  
 +# enable saslauthd by default
-+copy("/etc/default/saslauthd", "/etc/default/saslauthd.orig") || die "could not read /etc/default/saslauthd.orig";
++copy("/etc/default/saslauthd", "/etc/default/saslauthd.orig") || die "could not copy /etc/default/saslauthd to .orig";
 +my $saslauthd_orig = IO::File->new("/etc/default/saslauthd.orig", "r") || die "could not read /etc/default/saslauthd.orig";
-+my $saslauthd = IO::File->new("/etc/default/saslauthd", "w") || die "could not read /etc/default/saslauthd";
++my $saslauthd = IO::File->new("/etc/default/saslauthd", "w") || die "could not write /etc/default/saslauthd";
 +foreach (<$saslauthd_orig>) {
 +  s/^(# )?START=.*$/START=yes/g;
 +  s/^MECHANISMS="pam"/MECHANISMS="ldap"/g;
@@ -36,7 +27,7 @@ Index: b/sbin/kolab_bootstrap.in
  if ( $is_master eq "true" ) {
    ##### Master server setup
    getopt('f');
-@@ -408,6 +420,9 @@
+@@ -465,6 +477,9 @@
      }
    };
  
@@ -46,33 +37,16 @@ Index: b/sbin/kolab_bootstrap.in
    my $confname = "$Kolab::config{'sasl_smtpconffile'}";
    copy("@CONFIG_DIR@/templates/smtpd.conf.template", $confname) || die "could not write to $confname";
  
-@@ -441,12 +456,15 @@
-       Kolab::Conf::bootstrapConfig();
-       $Kolab::config{"bootstrap_config"} = 'false';
- 
-+      #ldap server should access to certificate key
-+      system("adduser --quiet $Kolab::config{'ldapserver_rusr'} $Kolab::config{'pki_grp'}");
-+
-       # now we must startup slapd
-       print "temporarily starting slapd\n";
-       $ldap_uri = "ldap://127.0.0.1:389/";
+@@ -512,7 +527,7 @@
        # ensure that the database has correct permissions
-       system("chown $Kolab::config{'ldapserver_rusr'}:$Kolab::config{'ldapserver_grp'} $Kolab::config{'ldapserver_dir'}/*");
+       @files = <$Kolab::config{'ldapserver_dir'}/*>;
+       system("chown $Kolab::config{'ldapserver_rusr'}:$Kolab::config{'ldapserver_grp'} $Kolab::config{'ldapserver_dir'}/*") if (@files);
 -      (system("$Kolab::config{'libexecdir'}/openldap/slapd -h ldap://127.0.0.1:389/ -f $Kolab::config{'ldapserver_confdir'}/slapd.conf -u $Kolab::config{'ldapserver_rusr'} -g $Kolab::config{'ldapserver_grp'}") == 0 ) || die( "Could not start temporary slapd: $!" );
 +      (system("/usr/sbin/slapd -h ldap://127.0.0.1:389/ -f $Kolab::config{'ldapserver_confdir'}/slapd.conf -u $Kolab::config{'ldapserver_rusr'} -g $Kolab::config{'ldapserver_grp'}") == 0 ) || die( "Could not start temporary slapd: $!" );
        print ("Waiting for OpenLDAP to start\n");
        sleep 10;
  
-@@ -781,7 +799,7 @@
-   chmod 0600, $kolab_config;
-   kolab_chown "$Kolab::config{'kolab_musr'}","$Kolab::config{'kolab_mgrp'}",$kolab_config;
- 
--  if ($kolab_config{'directory_mode'} ne "syncrepl" ) {
-+  if ($Kolab::config{'directory_mode'} ne "syncrepl" ) {
-     print << 'EOS';
- Now the master server needs to be stopped briefly while the contents of the LDAP database
- is copied over to this slave. Please make sure that this slave is entered into the list
-@@ -878,6 +896,9 @@
+@@ -949,6 +964,9 @@
    chmod 0600, $kolab_config;
  }
  
@@ -81,4 +55,4 @@ Index: b/sbin/kolab_bootstrap.in
 +
  #system("@CONFIG_DIR@/kolab_sslcert.sh $fqdn");
  print "kolab is now ready to run!\n";
- print "please restart all the daemons\n";
+ print "please restart all daemons\n";


commit 06c507772e9c7bbe51aa38bde2a1ef73ae41e9d2
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 20:01:28 2011 +0100

    Further update 10-invoke-rc

diff --git a/debian/patches/10-invoke-rc.diff b/debian/patches/10-invoke-rc.diff
old mode 100755
new mode 100644
index 302c62e..f7a5f6c
--- a/debian/patches/10-invoke-rc.diff
+++ b/debian/patches/10-invoke-rc.diff
@@ -4,11 +4,11 @@
 ## DP: Debian specific invocation of services
 
 @DPATCH@
-Index: b/sbin/kolab_bootstrap.in
+Index: libkolab-perl/sbin/kolab_bootstrap.in
 ===================================================================
---- a/sbin/kolab_bootstrap.in
-+++ b/sbin/kolab_bootstrap.in
-@@ -112,7 +112,7 @@
+--- libkolab-perl.orig/sbin/kolab_bootstrap.in	2011-03-20 19:56:29.000000000 +0100
++++ libkolab-perl/sbin/kolab_bootstrap.in	2011-03-20 20:01:06.000000000 +0100
+@@ -118,7 +118,7 @@
      print ("Error: Found $name running on Port $port\n");
      print ("Check your installation!\n");
      print ("You must stop the service $name before running Kolab\n");
@@ -17,41 +17,41 @@ Index: b/sbin/kolab_bootstrap.in
      exit 1;
    }
  }
-@@ -645,7 +645,7 @@
+@@ -678,7 +678,7 @@
  
     if ($ldap_uri =~ /127\.0\.0\.1/ || $ldap_uri =~ /localhost/) {
        print "\nkill temporary slapd\n\n";
--      system("$Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} stop");
+-      system("$Kolab::config{'KOLABRC'} rc openldap stop");
 +      system("invoke-rc.d slapd stop");
        sleep 1; # actually race should be impossible
        system("killall -9 slapd >/dev/null 2>&1");
     }
-@@ -698,7 +698,7 @@
+@@ -731,7 +731,7 @@
    ##### Slave server setup
  
    print "stop running slapd (if any)\n";
--  kolab_system("$Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} stop");
+-  kolab_system("$Kolab::config{'KOLABRC'} rc openldap stop");
 +  kolab_system("invoke-rc.d slapd stop");
  
    # Make sure that no rogue demons are running
    tryConnect( '127.0.0.1', 389 ) && die "A process is already listening to port 389 (ldap)\n"
-@@ -822,9 +822,9 @@
+@@ -856,9 +856,9 @@
  is copied over to this slave. Please make sure that this slave is entered into the list
  of kolabhosts on the master before proceeding.
  EOS
--    kolab_system("ssh -C $master_host \'$Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} stop".
+-    kolab_system("ssh -C $master_host \'$Kolab::config{'KOLABRC'} rc openldap stop".
 +    kolab_system("ssh -C $master_host \'invoke-rc.d slapd stop".
                   " && $Kolab::config{'TAR'} -C $Kolab::config{'ldapserver_statedir'} -pcf - openldap-data".
--                 " && $Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} start\'".
+-                 " && $Kolab::config{'KOLABRC'} rc openldap start\'".
 +                 " && invoke-rc.d slapd start\'".
                   " | $Kolab::config{'TAR'} -C $Kolab::config{'ldapserver_statedir'} -pxf -");
    }
  
-@@ -916,6 +916,6 @@
+@@ -951,6 +951,6 @@
  
  #system("@CONFIG_DIR@/kolab_sslcert.sh $fqdn");
  print "kolab is now ready to run!\n";
 -print "please run '$Kolab::config{'KOLABRC'} rc all start'\n";
-+print "please restart all the daemons\n";
- print ("Use login=manager and passwd=" . Encode::decode_utf8($bind_pw) . " when you log into\n");
++print "please restart all daemons\n";
+ print ("Use login=manager and passwd=$bind_pw when you log into\n");
  print ("the webinterface https://$fqdn$Kolab::config{'kolab_wui'} !\n");


commit 06ddae6f68d8e466eaa4a6b81bdf740c6051b148
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 19:57:26 2011 +0100

    Remove old snippet from patch 10-invoke-rc

diff --git a/debian/patches/10-invoke-rc.diff b/debian/patches/10-invoke-rc.diff
index 38f2aee..302c62e 100755
--- a/debian/patches/10-invoke-rc.diff
+++ b/debian/patches/10-invoke-rc.diff
@@ -4,54 +4,6 @@
 ## DP: Debian specific invocation of services
 
 @DPATCH@
-Index: b/lib/Kolab/Conf.pm
-===================================================================
---- a/lib/Kolab/Conf.pm
-+++ b/lib/Kolab/Conf.pm
-@@ -855,38 +855,28 @@
- {
-     if ($haschanged{'slapd'}) {
-         &Kolab::log('K', 'Restarting OpenLDAP...');
--        system("$Kolab::config{'KOLABRC'} rc openldap restart &");
-+        system("invoke-rc.d slapd restart &");
-     }
- 
-     if ($haschanged{'saslauthd'}) {
-         &Kolab::log('K', 'Restarting SASLAuthd...');
--        system("$Kolab::config{'KOLABRC'} rc sasl stop; sleep 1; $Kolab::config{sbindir}/saslauthd -a ldap -n 5");
-+        system("invoke-rc.d saslauthd restart");
-     }
- 
-     if ($haschanged{'apache'}) {
-         &Kolab::log('K', 'Reloading Apache...');
--        system("$Kolab::config{sbindir}/apachectl graceful");
-+        system("invoke-rc.d apache2 graceful");
-     }
- 
-     if ($haschanged{'postfix'}) {
-         &Kolab::log('K', 'Reloading Postfix...');
--        system("$Kolab::config{sbindir}/postfix reload");
-+        system("invoke-rc.d postfix reload");
-     }
- 
-     if ($haschanged{'imapd'}) {
-         &Kolab::log('K', 'Restarting imapd...');
- 	# Would it be enough with a reload here? /steffen
--        system("$Kolab::config{'KOLABRC'} rc imapd restart");
--    }
--
--    if ($haschanged{'amavisd'}) {
--        &Kolab::log('K', 'Restarting amavisd...');
--        system("$Kolab::config{'KOLABRC'} rc amavisd restart");
--    }
--
--    if ($haschanged{'clamav'}) {
--        &Kolab::log('K', 'Restarting clamav...');
--        system("$Kolab::config{'KOLABRC'} rc clamav restart");
-+        system("invoke-rc.d kolab-cyrus restart");
-     }
- 
-     %Kolab::Conf::haschanged = ();
 Index: b/sbin/kolab_bootstrap.in
 ===================================================================
 --- a/sbin/kolab_bootstrap.in


commit 5f4dac62ab467105529552b278f32c2faf18ac05
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 19:55:04 2011 +0100

    New version

diff --git a/debian/changelog b/debian/changelog
index 86e413f..7deaaa9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+libkolab-perl (1:2.3+git-1) unstable; urgency=low
+
+  * New upstream version
+
+ -- Jeroen van Meeuwen <vanmeeuwen at kolabsys.com>  Sun, 20 Mar 2011 11:11:11 +1111
+
 libkolab-perl (1:2.2.4-20100624-3) unstable; urgency=low
 
   * Fix "during bootstrap is controled port 2000 instead of 4190 for


commit c7503178d944b21e6a880c3361a45fdf2cc3ebd6
Merge: 253ec8a... c80a55e...
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 19:53:52 2011 +0100

    Merge commit 'upstream/2.3+git'



commit c80a55e87702b22cfb1ecf0964d438ce838b2ec4
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Sun Mar 20 19:53:51 2011 +0100

    Imported Upstream version 2.3+git

diff --git a/ChangeLog b/ChangeLog
index 1870e58..bc8da55 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,73 @@
-2010-06-04  Gunnar Wrobel <wrobel at pardus.de>
+2010-07-17  Gunnar Wrobel  <p at rdus.de>
 
-	* lib/Kolab/Cyrus.pm: kolab/issue4237 (additional event.default
-	folder created by kolabd (rt#6038))
+	* lib/Kolab/LDAP.pm:
+
+	kolab/issue977 (Kolab suppresses ldap error messages)
+	kolab/issue978 (incorrect $ldap->abandon; call)
+
+2010-06-28  Gunnar Wrobel  <p at rdus.de>
+
+	* lib/Kolab/LDAP.pm:
+
+	Removed hack for kolab/issue3472 (web client user prefs not
+	deleted when user gets deleted)
+
+2010-06-27  Gunnar Wrobel  <p at rdus.de>
+
+	* lib/Kolab/LDAP.pm (deleteObject):
+
+	Support a hooks directory that allows to extend the deletion of
+	users.
+
+	kolab/issue3472 (web client user prefs not deleted when user gets
+	deleted)
+
+2010-04-27  Thomas Arendsen Hein  <thomas at intevation.de>
+
+	* sbin/kolab_bootstrap.in: Check for availability of submission port,
+	see kolab/issue4311 (Activate port 587 for email submission)
+
+2010-03-30  Gunnar Wrobel  <p at rdus.de>
+
+	* lib/Kolab/LDAP.pm (createObject): kolab/issue4275 (LDAP.pm quota error)
+
+2010-03-23  Gunnar Wrobel  <p at rdus.de>
+
+	* lib/Kolab/Cyrus.pm (createCalendar): kolab/issue4237 (additional
+	event.default folder created by kolabd (rt#6038))
+
+2010-03-11  Gunnar Wrobel  <p at rdus.de>
+
+	* bin/kolabpasswd.in: kolab/issue919 (kolab server has
+	problems with some characters in passwords (rt#5558))
+
+2010-03-05  Gunnar Wrobel  <p at rdus.de>
+
+	* sbin/kolab_bootstrap.in: kolab/issue919 (kolab server has
+	problems with some characters in passwords (rt#5558))
+
+2009-02-11  Mathieu Parent <math.parent at gmail.com>
+
+	* lib/Kolab/Conf.pm:
+	  solve kolab/issue4024 (Lots of tmp files in kolab's configuration
+	  directory), introduced 2009-12-13. 
+
+2010-01-01 Richard Bos <richard at radoeka.nl>
+
+	* sbin/kolab_bootstrap.in: solve kolab/issue4009: kolab_bootstrap contains
+	  dangerous code, could remove wrong files
+
+2009-12-30 Richard Bos <richard at radoeka.nl>
+
+	* sbin/kolab_bootstrap.in: assign the variable Kolab::config{"is_master"}
+	  to prevent warnings during the execution of kolabconf.
+	  Verify if files that are to be moved or chown'ed exist.  If not
+	  skip the operation.  
+
+2009-12-28 Richard Bos <richard at radoeka.nl>
+
+	* sbin/kolab_bootstrap.in: removed the suffix ".in" in the call to
+	  Kolab::Conf::rebuildTemplates
 
 2009-12-16  Sascha Wilde  <wilde at intevation.de>
 
@@ -17,6 +83,31 @@
 	* sbin/kolab_bootstrap.in: kolab/issue919 (kolab server has
 	problems with some characters in passwords)
 
+2009-12-13  Mathieu Parent <math.parent at gmail.com>
+
+	* lib/Kolab/Conf.pm, sbin/kolab_bootstrap.in:
+	  Added arguments to rebuildTemplates(): dorunonchange and templates.
+	  Use those in kolab_bootstrap (in replacement of bootstrapConfig()).
+
+2009-12-13  Mathieu Parent <math.parent at gmail.com>
+
+	* lib/Kolab/Conf.pm: Touch configuration only when there is a change.
+	  This avoid postfix complaining about "database X.db is older than 
+	  source file X".
+	  Additionnay, renamed %templatehaschanged to %confighaschanged.
+
+2009-12-13  Mathieu Parent <math.parent at gmail.com>
+
+	* lib/Kolab/Conf.pm, sbin/kolabconf.in: $Kolab::do_reload is now an
+	  argument to Kolab::Conf::rebuildTemplates().
+
+2009-12-13  Mathieu Parent <math.parent at gmail.com>
+
+	* lib/Kolab/Conf.pm, sbin/kolabconf.in: new @@@print@@@ macro
+	  available for: getLDAPReplicas(), getLDAPAccess(),
+	  getCyrusGroups(), getPostfixMap(map). This removed the use of
+	  %special_templates, %haschanged, Kolab::Conf::reload()
+
 2009-12-07  Gunnar Wrobel <wrobel at pardus.de>
 
 	* lib/Kolab/LDAP.pm (createObject): kolab/issue1448 (Users might
@@ -32,7 +123,7 @@
 	kolab/issue1340 (RFC: restrict users to sending mail only to
 	internal recipients)
 
-	Only the first stub yeat reacts solely to "-" (Denying all
+	Only the first stub that reacts solely to "-" (Denying all
 	recipients).
 
 2009-11-24  Gunnar Wrobel <wrobel at pardus.de>
@@ -62,15 +153,46 @@
 	causes OpenLDAP restarts)
 	* lib/Kolab.pm: bump version number
 
+2009-05-07 Richard Bos <richard at radoeka.nl>
+
+	* sbin/kolab_bootstrap.in: Change $Kolab::config{'LDAPD'} to just
+	  openldap, see kolab/issue3604
+
+2009-05-07  Thomas Arendsen Hein  <thomas at intevation.de>
+
+	* lib/Kolab/Conf.pm: Removed special handling of imapd (except for
+	imapd.group.template)
+
+2009-05-05  Thomas Arendsen Hein  <thomas at intevation.de>
+
+	* lib/Kolab/Conf.pm: Execute duplicate RUNONCHANGE commands only once.
+	Part of kolab/issue1679 ([kolabconf] Update template META mechanism to
+	support service restarts)
+
 2009-04-16  Gunnar Wrobel  <p at rdus.de>
 
 	* lib/Kolab/LDAP.pm (deleteObject): Workaround for kolab/issue3472.
 
+2009-03-17  Thomas Arendsen Hein  <thomas at intevation.de>
+
+	* lib/Kolab/Conf.pm: Removed special handling of saslauthd.
+	* lib/Kolab/Conf.pm: Removed special handling of apache, amavisd and
+	clamav and remove duplicate "change detected" debug message.
+	* lib/Kolab/Conf.pm: Expand $map in debug message.
+	* lib/Kolab/Conf.pm: Removed postfix reload and postmap calls.
+
 2009-03-16  Thomas Arendsen Hein  <thomas at intevation.de>
 
 	* lib/Kolab/LDAP.pm: Creating the Calendar folder caused an
 	KOLAB_ERROR to be logged, changed to KOLAB_DEBUG.
 
+2009-03-16  Thomas Arendsen Hein  <thomas at intevation.de>
+
+	* sbin/kolab_imappartitions.in, MANIFEST, Makefile.PL, sbin/.cvsignore:
+	Added script to list imap partitions.
+	* lib/Kolab/Cyrus.pm, lib/Kolab/LDAP.pm: Select random imap partition
+	from output of kolab_imappartitions script if available.
+
 2009-03-04  Thomas Arendsen Hein  <thomas at intevation.de>
 
 	* lib/Kolab/Conf.pm: Add retry (every minute for 10 times, then every
diff --git a/DEVELOPMENT b/DEVELOPMENT
new file mode 100644
index 0000000..52d30b9
--- /dev/null
+++ b/DEVELOPMENT
@@ -0,0 +1,82 @@
+Development notes
+=================
+
+The perl-kolab package is a standard perl package and a Kolab Server
+core component. It is meant to be handled with the Makefile.PL
+script. You will receive a standard "Makefile" by running "perl
+Makefile.PL".
+
+The Kolab Server packages were usually not released as source
+packages. This should be changed with this new package layout. The
+"dist" target will produce a perl-kolab-*.tar.gz package that can be
+distributed as source package. The same run will produce a
+perl-kolab-*.src.rpm package that is suited for installation on an
+OpenPKG system.
+
+
+Version numbering
+=================
+
+The package version will be set in
+
+  lib/Kolab.pm
+
+e.g.
+
+  our $KOLAB_BASE_VERSION = "2.2.beta1";
+  my $KOLAB_CVS = 1;
+
+Release versions
+----------------
+
+Released packages should have the same core version as the server
+release. As a part of Kolab Server 2.2.0 the version number should be
+2.2.0. Pre-release candidates receive the suffix "betaX" or "rcX"
+(e.g. 2.2.beta1).
+
+Before tagging the next release the version number needs to be increased
+to the new Kolab Server version (e.g. 2.2.0) and the CVS switch needs to
+be set to 0:
+
+  our $KOLAB_BASE_VERSION = "2.2.0";
+  my $KOLAB_CVS = 0;
+
+After updating $KOLAB_BASE_VERSION and $KOLAB_CVS you can commit these
+changes and tag the release.
+
+Now you can create source tarballs and RPMs which will look like:
+
+  perl-kolab-2.2.0.tar.gz
+  perl-kolab-2.2.0-20070819.src.rpm
+
+Don't forget to change $KOLAB_CVS back to 1 again and commit, so later
+CVS snapshots will be named correctly.
+
+Snapshots
+---------
+
+Make sure lib/Kolab.pm contains the following line:
+
+  my $KOLAB_CVS = 1;
+
+The release number will then receive the suffix "+cvs" and the current
+date will be appended.
+
+Source tarballs and RPMs will then look like this:
+
+  perl-kolab-2.2.0+cvs20070810.tar.gz
+  perl-kolab-2.2.0+cvs-20070810.src.rpm
+
+
+Change log
+==========
+
+The change log for the package is provided in "ChangeLog". Please keep
+this file up-to-date if you change the source code of this package.
+
+
+Contributors
+============
+
+The developers of this package are listed in "AUTHORS". Please keep
+this file up-to-date if you change the source code of this package.
diff --git a/MANIFEST b/MANIFEST
index 4eb3c78..8958eae 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -7,6 +7,7 @@ bin/kolabquotareport.in
 bin/kolabquotawarn.in
 bin/kolab_smtpdpolicy.in
 sbin/kolab_bootstrap.in
+sbin/kolab_imappartitions.in
 sbin/kolabcheckperm.in
 sbin/kolabconf.in
 sbin/kolabd.in
@@ -22,7 +23,5 @@ lib/Kolab/LDAP/Backend/syncrepl.pm
 lib/Kolab/LDAP/Backend/fds.pm
 lib/Kolab/Util.pm
 Makefile.PL
-kolab.mk
 MANIFEST
 README
-META.yml                                 Module meta-data (added by MakeMaker)
diff --git a/META.yml b/META.yml
deleted file mode 100644
index 27a2a79..0000000
--- a/META.yml
+++ /dev/null
@@ -1,14 +0,0 @@
---- #YAML:1.0
-name:                perl-kolab
-version:             2.2.4
-abstract:            perl-kolab provides a basic set of perl modules required for the
-Kolab Groupware server.
-license:             ~
-author:              
-    - Stuart Bingë and others (see AUTHORS file)
-generated_by:        ExtUtils::MakeMaker version 6.42
-distribution_type:   module
-requires:     
-meta-spec:
-    url:     http://module-build.sourceforge.net/META-spec-v1.3.html
-    version: 1.3
diff --git a/Makefile.PL b/Makefile.PL
index 5592b8f..b8bb632 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -50,36 +50,6 @@ EOH
 exit 0;
 }
 
-# Add the dist_openpkg target to the dist target
-sub MY::dist {
-    package MY;   # To help SUPER work right
-    my $self = shift;
-    my @m;
-    
-    push(@m, $self->SUPER::dist(@_));
-    
-    my $dist = join "", @m;
-
-    $dist =~ s/(tardist.*)/clean_tardist $1 dist_openpkg/;
-     
-    return $dist;
-}
-
-# Remove additional files
-sub MY::veryclean {
-    package MY;   # To help SUPER work right
-    my $self = shift;
-    my @m;
-    
-    push(@m, $self->SUPER::clean(@_));
-    
-    my $clean = join "", @m;
-
-    $clean =~ s/(clean.*)/$1 clean_openpkg clean_scripts/;
-     
-    return $clean;
-}
-
 # Install sbin files
 sub MY::install {
     package MY;   # To help SUPER work right
@@ -96,17 +66,7 @@ sub MY::install {
 }
 
 sub MY::postamble {
-    if (-e "../kolab.mk")
-    {
-	copy("../kolab.mk", "./") or die "Could not copy ../kolab.mk";
-    }
-    my $add = "include kolab.mk
-
-PACKAGE = \$(shell [ -r \"perl-kolab.spec\" ] && grep '%define[ ]*V_package' perl-kolab.spec | sed -e 's/.*V_package\\s*\\([a-z\\_-]*\\).*/\\1/')
-VERSION = \$(shell perl -I lib -e 'use Kolab;print \$\$Kolab::KOLAB_VERSION;')
-RELEASE = \$(shell perl -I lib -e 'use Kolab;print \$\$Kolab::KOLAB_RELEASE;')
-SOURCE_TAG = \$(shell perl -I lib -e 'use Kolab;print \$\$Kolab::VERSION;')
-
+    my $add = "
 bin/%: bin/%.in
 	cat \$< | sed -e 's#\@CONFIG_DIR@#$CONFIG#g' > \$@
 
@@ -116,7 +76,7 @@ sbin/%: sbin/%.in
 	rm \$@.tmp
 	\$(FIXIN) \$@
 
-SBIN_TARGETS=sbin/kolabconf sbin/kolab_bootstrap sbin/kolabd sbin/kolabcheckperm
+SBIN_TARGETS=sbin/kolabconf sbin/kolab_bootstrap sbin/kolab_imappartitions sbin/kolabd sbin/kolabcheckperm
 
 install_sbin: \$(SBIN_TARGETS)
 	mkdir -p \$(DESTDIR)/$INSTALLSBIN
@@ -131,35 +91,23 @@ install_etc:
 	  cp \$\$ETC \$(DESTDIR)/$INSTALLETC;        \\
 	done
 
-ifeq \"x\$(PLATTAG)\" \"x\"
-	PLATTAG = \$(shell \$(RPM) -q --qf=\"%{ARCH}-%{OS}\" openpkg)-\$(KOLABDIR:/%=%)
-endif
-
-clean_tardist:
-	rm -rf *.tar.gz
-
-clean_all: clean_tardist veryclean
-	rm -rf \$(KOLABRPMTMP)/\$(PACKAGE)
-	rm -rf *.src.rpm
-	rm -rf *~
-
-dist_openpkg: perl-kolab.spec \$(PACKAGE)-\$(VERSION)-\$(RELEASE).src.rpm
-	cp \$(PACKAGE)-\$(VERSION)-\$(RELEASE).src.rpm ../stage/
-
-\$(KOLABRPMPKG)/\$(PACKAGE)-\$(VERSION)-\$(RELEASE).\$(PLATTAG).rpm \$(PACKAGE)-\$(VERSION)-\$(RELEASE).src.rpm: \$(PACKAGE).spec
-	test -d \$(KOLABRPMSRC)/\$(PACKAGE) || mkdir \$(KOLABRPMSRC)/\$(PACKAGE)
-	cp \$(PACKAGE).spec \$(PACKAGE).spec.tmp
-	sed -i -e 's/\@VERSION\@/\$(VERSION)/' \$(PACKAGE).spec.tmp
-	sed -i -e 's/\@RELEASE\@/\$(RELEASE)/' \$(PACKAGE).spec.tmp
-	sed -i -e 's/\@SOURCE_TAG\@/\$(SOURCE_TAG)/' \$(PACKAGE).spec.tmp
-	mv \$(PACKAGE).spec.tmp \$(KOLABRPMSRC)/\$(PACKAGE)/\$(PACKAGE).spec
-	mv \$(PACKAGE)-\$(SOURCE_TAG).tar.gz \$(KOLABRPMSRC)/\$(PACKAGE)
-	cd \$(KOLABRPMSRC)/\$(PACKAGE) && \$(RPM) -ba \$(PACKAGE).spec
-	cp -p \$(KOLABRPMPKG)/\$(PACKAGE)-\$(VERSION)-\$(RELEASE).src.rpm .
-
-.PHONY: install-kolab
-install-kolab: \$(KOLABRPMPKG)/\$(PACKAGE)-\$(VERSION)-\$(RELEASE).\$(PLATTAG).rpm
-	\$(RPM) -Uhv --force \$(KOLABRPMPKG)/\$(PACKAGE)-\$(VERSION)-\$(RELEASE).\$(PLATTAG).rpm
+# Upload location for the fileserver. Configure the kolab filesserver
+# in your ssh config at ~/.ssh/config. E.g.:
+#
+# Host=kolabfiles
+# User=wrobel
+# Hostname=files.kolab.org
+#
+FILESERVER = kolabfiles
+
+# Short name for uploading the snapshot.
+.PHONY:snapshot
+snapshot: .sent-\$(DISTVNAME).tar\$(SUFFIX)
+
+# Indicator to avoid uploading the same package twice.
+.sent-\$(DISTVNAME).tar\$(SUFFIX): \$(DISTVNAME).tar\$(SUFFIX)
+	echo \"put \$(DISTVNAME).tar\$(SUFFIX)\" | sftp \$(FILESERVER)
+	touch .sent-\$(DISTVNAME).tar\$(SUFFIX)
 ";
 
     return $add;
@@ -186,15 +134,16 @@ WriteMakefile(
                            'bin/kolabpasswd',
                            'bin/kolabquotawarn'],
     MAN1PODS          => {
-                           'bin/kolab_smtpdpolicy' => 'blib/man1/kolab_smtpdpolicy.1p',
-                           'bin/kolabquotareport'  => 'blib/man1/kolabquotareport.1p',
-                           'bin/kolabdcachetool'   => 'blib/man1/kolabdcachetool.1p',
-                           'bin/kolabpasswd'       => 'blib/man1/kolabpasswd.1p',
-                           'bin/kolabquotawarn'    => 'blib/man1/kolabquotawarn.1p',
-                           'sbin/kolab_bootstrap'  => 'blib/man1/kolab_bootstrap.1p',
-                           'sbin/kolabcheckperm'   => 'blib/man1/kolabcheckperm.1p',
-                           'sbin/kolabconf'        => 'blib/man1/kolabconf.1p',
-                           'sbin/kolabd'           => 'blib/man1/kolabd.1p',
+                           'bin/kolab_smtpdpolicy'     => 'blib/man1/kolab_smtpdpolicy.1p',
+                           'bin/kolabquotareport'      => 'blib/man1/kolabquotareport.1p',
+                           'bin/kolabdcachetool'       => 'blib/man1/kolabdcachetool.1p',
+                           'bin/kolabpasswd'           => 'blib/man1/kolabpasswd.1p',
+                           'bin/kolabquotawarn'        => 'blib/man1/kolabquotawarn.1p',
+                           'sbin/kolab_bootstrap'      => 'blib/man1/kolab_bootstrap.1p',
+                           'sbin/kolab_imappartitions' => 'blib/man1/kolab_imappartitions.1p',
+                           'sbin/kolabcheckperm'       => 'blib/man1/kolabcheckperm.1p',
+                           'sbin/kolabconf'            => 'blib/man1/kolabconf.1p',
+                           'sbin/kolabd'               => 'blib/man1/kolabd.1p',
                          },
     $installscript    => $INSTALLSCRIPT,
     ABSTRACT          => 
diff --git a/bin/kolab_smtpdpolicy.in b/bin/kolab_smtpdpolicy.in
index 09b0063..54e1fe0 100644
--- a/bin/kolab_smtpdpolicy.in
+++ b/bin/kolab_smtpdpolicy.in
@@ -108,7 +108,7 @@ Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 
 =cut
 
-##  $Revision: 1.2.2.3 $
+##  $Revision$
 
 use strict;
 use Fcntl;
diff --git a/bin/kolabpasswd.in b/bin/kolabpasswd.in
index e04abcb..38b88b0 100644
--- a/bin/kolabpasswd.in
+++ b/bin/kolabpasswd.in
@@ -12,7 +12,7 @@ B<kolabpasswd>
 
 The kolabpasswd script is used for changing the manager password on a Kolab Server.
 In multi-location Kolab setups the script must be run on each individual host 
-seperately.
+separately.
 
 After changing the manager password it is highly recommended to restart 
 the Kolab server.
@@ -45,6 +45,12 @@ Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 
 =cut
 
+use Encode;
+use I18N::Langinfo qw(langinfo YESSTR CODESET);
+my $local_codeset = langinfo(CODESET());
+
+binmode(STDIN, ":encoding($local_codeset)");
+
 use Term::ReadKey;
 use IO::File;
 use File::Temp;
@@ -118,6 +124,7 @@ my $kolabconfname = "@CONFIG_DIR@/kolab.conf";
 my %config = readConfig($kolabconfname);
 my $kolabconf = IO::File->new('@CONFIG_DIR@/kolab.conf','r')
                 || die "kolabpasswd: Fatal Error: could not open kolab config at $kolabconfname";
+binmode($kolabconf, ":encoding(UTF-8)");
 
 my $account = 'manager';
 my $account_dn = $config{'bind_dn'};
@@ -140,8 +147,6 @@ do {
   ReadMode 'noecho';
   my $old_password = ReadLine 0; chomp $old_password;
 
-  $old_password = Encode::encode_utf8($old_password);
-
   $mesg = $ldap->bind( $account_dn, password => $old_password ) || die "\nkolabpasswd: Failed to bind to LDAP server";
   if( $mesg->code ) { print "\nError: ".$mesg->error.". Please try again\n"; }
 } while ( $mesg->code );
@@ -157,15 +162,14 @@ print "\n";
 ReadMode 'normal';
 ($new_password eq $new_password2) || die "Sorry, passwords do not match.\n";
 
-$new_password = Encode::encode_utf8($new_password);
-
 my $bind_pw_hash;
 
 # create temporary config file
 my $tmp = new File::Temp( TEMPLATE => 'tempXXXXX', DIR => '@CONFIG_DIR@', UNLINK => 0, SUFFIX => '.conf')
      || die "Error: could not create temporary file under @CONFIG_DIR@";
+binmode($tmp, ":encoding(UTF-8)");
 $tmpfilename = $tmp->filename;
-$bind_pw_hash = hashPassword2($new_password);
+$bind_pw_hash = hashPassword($new_password);
 
 # copy and replace old config to temporary file
 foreach ($kolabconf->getlines()) {
diff --git a/kolab.mk b/kolab.mk
deleted file mode 100644
index 3ccfca7..0000000
--- a/kolab.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Set KOLABDIR to the base directory of the OpenPKG/Kolab installation:
-KOLABDIR = $(shell openpkg rpm -q --qf '%{INSTALLPREFIX}\n' openpkg)
-
-ifeq ($(KOLABDIR),)
-  $(error Could not determine KOLABDIR!)
-endif
-
-ifeq ($(RPM),)
-  RPM = $(KOLABDIR)/bin/openpkg rpm
-endif
-ifeq ($(KOLABRPMSRC),)
-  KOLABRPMSRC = $(KOLABDIR)/RPM/SRC
-endif
-ifeq ($(KOLABRPMPKG),)
-  KOLABRPMPKG = $(KOLABDIR)/RPM/PKG
-endif
-ifeq ($(KOLABRPMTMP),)
-  KOLABRPMTMP = $(KOLABDIR)/RPM/TMP
-endif
-ifeq ($(CURSRCDIR),)
-  CURSRCDIR = $(CURDIR)
-endif
-ifeq ($(KOLABPKGURI),)
-  KOLABPKGURI = http://files.kolab.org/server/release/kolab-server-2.2.0/sources/
-endif
-ifeq ($(OPENPKGURI),)
-  OPENPKGURI = http://files.kolab.org/server/development-2.2/openpkg-orig-srpms/
-endif
-ifeq ($(PLATTAG),)
-  PLATTAG = $(shell $(RPM) -q --qf="%{ARCH}-%{OS}" openpkg)-$(KOLABDIR:/%=%)
-endif
diff --git a/lib/Kolab.pm b/lib/Kolab.pm
index 351c0fd..a12846d 100644
--- a/lib/Kolab.pm
+++ b/lib/Kolab.pm
@@ -22,7 +22,7 @@ package Kolab;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.29.2.2 $
+##  $Revision$
 
 use 5.008;
 use strict;
@@ -59,15 +59,15 @@ our @EXPORT = qw(
 );
 
 # The Kolab version number for the perl-kolab package
-our $KOLAB_BASE_VERSION = "2.2.4";
+our $KOLAB_BASE_VERSION = "2.3";
 
 # Are current releases cvs based or is this a real release?
-my $KOLAB_CVS = 0;
+my $KOLAB_CVS = 1;
 
 our $KOLAB_RELEASE = sprintf "%0004d%02d%02d", ((gmtime)[5] + 1900), ((gmtime)[4] + 1), (gmtime)[3];
 
 if ($KOLAB_CVS) {
-    our $KOLAB_VERSION = $KOLAB_BASE_VERSION . "+cvs";
+    our $KOLAB_VERSION = $KOLAB_BASE_VERSION . "+git";
     our $VERSION = $KOLAB_VERSION . $KOLAB_RELEASE;
 } else {
     our $KOLAB_VERSION = $KOLAB_BASE_VERSION;
diff --git a/lib/Kolab/Conf.pm b/lib/Kolab/Conf.pm
index d123137..8ca62ca 100644
--- a/lib/Kolab/Conf.pm
+++ b/lib/Kolab/Conf.pm
@@ -22,7 +22,7 @@ package Kolab::Conf;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.4.2.1 $
+##  $Revision$
 
 use 5.008;
 use strict;
@@ -42,11 +42,8 @@ our @ISA = qw(Exporter);
 
 our %EXPORT_TAGS = (
     'all' => [ qw(
-        &buildPostfixTransportMap
-        &buildCyrusGroups
-        &buildLDAPReplicas
         &rebuildTemplates
-	&checkPermissions
+        &checkPermissions
     ) ]
     );
 
@@ -59,8 +56,7 @@ our @EXPORT = qw(
 my %templates = ();
 my %ownership = ();
 my %permissions = ();
-my %templatehaschanged = ();
-my %haschanged = ();
+my %confighaschanged = ();
 my %commentchar = ();
 
 sub fixup {
@@ -73,13 +69,13 @@ sub fixup {
     my $gid = (getgrnam($group))[2];
     Kolab::log('T', sprintf("Changing permissions of %s to 0%o", $file, $perm ), KOLAB_DEBUG );
     if( chmod($perm, $file) != 1 ) {
-	Kolab::log('T', "Unable to change permissions of `$file' to ".sprintf("0%o",$perm) . ": $!", KOLAB_ERROR);
-	exit(1);
+        Kolab::log('T', "Unable to change permissions of `$file' to ".sprintf("0%o",$perm) . ": $!", KOLAB_ERROR);
+        exit(1);
     }
     Kolab::log('T', "Changing owner of $file to $owner:$group ($uid:$gid)", KOLAB_DEBUG );
     if( chown($uid,$gid,$file) != 1 ) {
-	Kolab::log('T', "Unable to change ownership of `$file' to $uid:$gid: $!", KOLAB_ERROR);
-	exit(1);
+        Kolab::log('T', "Unable to change ownership of `$file' to $uid:$gid: $!", KOLAB_ERROR);
+        exit(1);
     }
 }
 
@@ -93,7 +89,6 @@ sub printWarning {
     $cc = "#" if (!defined $cc);
 
     # Different warnings during bootstrapping and regular configuration
-# $Kolab::config{"bootstrap_config"} = "true";
     if ((defined $Kolab::config{"bootstrap_config"}) &&
         ($Kolab::config{"bootstrap_config"} eq "true")) {
 
@@ -125,62 +120,37 @@ sub build {
     my $perm = shift;
     my $cchr = shift;  # comment character
 
-    my $oldcfg = $cfg . '.old';
     my $templatedir = $Kolab::config{"templatedir"};
 
-    my %special_templates = (
-	"$templatedir/transport.template"      => 1,
-	"$templatedir/virtual.template"        => 1,
-	"$templatedir/imapd.group.template"    => 1,
-	"$templatedir/slapd.access.template"   => 1,
-	"$templatedir/slapd.replicas.template" => 1
-	);
-
-    my $oldmask = umask 077;
-    #creating the config file is changing it
-    if (! -f $cfg) { 
-        $templatehaschanged{$tmpl} = 1;
-        Kolab::log('T', "`$cfg' creation detected", KOLAB_DEBUG );
-    }
-    copy($cfg, $oldcfg);
-    #chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $oldcfg);
-    # To avoid warnings, the backup files must be owned by root
-    chown(0, 0, $oldcfg);
-    umask $oldmask;
-    #chmod(0600, $oldcfg) if ($oldcfg =~ /openldap/);
-
     Kolab::log('T', "Creating new configuration file `$cfg' from template `$tmpl'", KOLAB_DEBUG );
-    #print STDERR "Creating new configuration file `$cfg' from template `$tmpl'\n";
 
     my $template;
     if (!($template = IO::File->new($tmpl, 'r'))) {
         Kolab::log('T', "Unable to open template file `$tmpl': $!", KOLAB_ERROR);
-	# Error, fail gracefully
-	return;
+        # Error, fail gracefully
+        return;
     }
     my $config;
     if (!($config = new File::Temp( TEMPLATE => 'tmpXXXXX',
-				    DIR => $Kolab::config{"kolabdir"},
-				    SUFFIX => '.kolabtmp',
-				    UNLINK => 0 ))) {
+                                    DIR => $Kolab::config{"kolabdir"},
+                                    SUFFIX => '.kolabtmp',
+                                    UNLINK => 0 ))) {
         Kolab::log('T', "Unable to open configuration file `$cfg': $!", KOLAB_ERROR);
         exit(1);
     }
 
-    #Kolab::log('T', "Using temporary file '".$config->filename."'", KOLAB_DEBUG );
-
     my $skip = 0;
     my $keep = 0;
     while (<$template>) {
-    	#Eat the meta data sections
-	if (/^KOLAB_META_START$/) {
-	    my $found_end;
-	    while (!$found_end) {	
-		$_ = <$template>;
-		$found_end = /^KOLAB_META_END$/;
-	    }
-	    $_ = <$template>;
-	}
+        #Eat the meta data sections
+        if (/^KOLAB_META_START$/) {
+            my $found_end;
+            while (!$found_end) {
+            $_ = <$template>;
+            $found_end = /^KOLAB_META_END$/;
+            }
+            $_ = <$template>;
+        }
 
         if (/\@{3}if\s+exists\(\s*(\S+?)\s*\)\@{3}/) {
             # @@@if exists(/full/path/to/file)@@@
@@ -199,168 +169,150 @@ sub build {
             # its value set to either 'false' or 'true'
             if ($Kolab::config{$1} && lc($Kolab::config{$1}) ne "false" ) {
                 # Keep text
-		$keep = 1;
+                $keep = 1;
             } else {
                 # Skip text
                 $skip++;
-		$keep = 0;
+                $keep = 0;
             }
             s/\@{3}if (\S+?)\@{3}\n?//;
-	} elsif (/\@{3}else\@{3}/) {
-	    if( $keep == 0 ) {
-		# Now keep
-		$keep = 1;
-		$skip--;
-	    } else {
-		# Now skip
-		$keep = 0;
-                $skip++;
-	    }
-            s/\@{3}else\@{3}\n?//;
+        } elsif (/\@{3}else\@{3}/) {
+            # @@@else@@@
+            if( $keep == 0 ) {
+            # Now keep
+            $keep = 1;
+            $skip--;
+            } else {
+            # Now skip
+            $keep = 0;
+                    $skip++;
+            }
+                s/\@{3}else\@{3}\n?//;
 
         } elsif (/\@{3}endif\@{3}/) {
+            # @@@endif@@@
             ($skip > 0) && $skip--;
             s/\@{3}endif\@{3}\n?//;
 
-        } elsif (/\@{3}warning\@{3}/) { 
-
+        } elsif (/\@{3}warning\@{3}/) {
+            # @@@warning@@@
             printWarning($config, $tmpl, $cchr);
 
+        } elsif (/\@{3}print\s+([^\s()]+?)\s*\(([^,]+)?\)\@{3}/) {
+            # @@@print func([arg])@@@
+            my $val;
+            if ($1 eq 'getLDAPReplicas') {$val = getLDAPReplicas();}
+            elsif ($1 eq 'getLDAPAccess') {$val = getLDAPAccess();}
+            elsif ($1 eq 'getCyrusGroups') {$val = getCyrusGroups();}
+            elsif ($1 eq 'getPostfixMap') {$val = getPostfixMap($2);}
+            else {Kolab::log('T', "Unknown printable value `$1'", KOLAB_WARN);}
+            s/\@{3}print\s+(\S+?)\@{3}//;
+            ($skip == 0) && print $config $val;
         } else {
             while (/\@{3}([^\s\@]+?)(\|(.+?)\((.*)\))?\@{3}/) {
-		my $attr = $1;
-		my $fct  = $3;
-		my $args = $4;
-		#print STDERR "attr=\"$attr\", fct=\"$fct\", args=\"$args\"\n";
-		if ($Kolab::config{$attr}) {
-		    my $val = "";
-		    if( !$fct ) {
-			if (ref $Kolab::config{$attr} eq "ARRAY") {
-			    $val = $Kolab::config{$attr}->[0];
-			} else {
-			    $val = $Kolab::config{$attr};
-			}
-		    } else {
-			# Modifier functions
-		      SWITCH: {
-			  # Join function 
-			  $fct eq 'join' && do {
-			      if (ref $Kolab::config{$attr} eq "ARRAY") {
-				  my @vals = @{$Kolab::config{$attr}} ;
-				  # We want to make sure subdomain.domain.tld comes before domain.tld
-				  my @length_sorted_vals = sort {length $b cmp length $a} @vals;
-				  $val = join ($args, @length_sorted_vals) ;
-			      } else {
-				  $val = $Kolab::config{$attr};
-			      }
-			      last SWITCH;
-			  };
-			  # Quote function
-			  $fct eq 'quote' && do {
-			      # slapd.conf compatible quoting
-			      $val = $Kolab::config{$attr};
-			      $val =~ s/"/\"/g;
-			      $val = '"'.$val.'"';
-			      last SWITCH;
-			  }
-			}
-		    }
-		    s/\@{3}([^\s\@]+?)(\|.+?)?\@{3}/$val/;
-		    last if ( $val eq "\@\@\@$attr\@\@\@" ); # prevent endless loop
-		} else {
-		    # Only warn the user in case we are not skipping the section
-		    ($skip == 0) && Kolab::log('T', "No configuration variable corresponding to `$1' exists", KOLAB_WARN);
-		    s/\@{3}([^\s\@]+?)\@{3}//;
-		}
-	    }
-	    ($skip == 0) && print $config $_;
-	}
+                # @@@attr@@@
+                # @@@attr|function(args)@@@
+                my $attr = $1;
+                my $fct  = $3;
+                my $args = $4;
+                #print STDERR "attr=\"$attr\", fct=\"$fct\", args=\"$args\"\n";
+                if ($Kolab::config{$attr}) {
+                    my $val = "";
+                    if( !$fct ) {
+                        if (ref $Kolab::config{$attr} eq "ARRAY") {
+                            $val = $Kolab::config{$attr}->[0];
+                        } else {
+                            $val = $Kolab::config{$attr};
+                        }
+                    } else {
+                        # Modifier functions
+                        SWITCH: {
+                            # Join function 
+                            $fct eq 'join' && do {
+                                if (ref $Kolab::config{$attr} eq "ARRAY") {
+                                my @vals = @{$Kolab::config{$attr}} ;
+                                # We want to make sure subdomain.domain.tld comes before domain.tld
+                                my @length_sorted_vals = sort {length $b cmp length $a} @vals;
+                                $val = join ($args, @length_sorted_vals) ;
+                                } else {
+                                $val = $Kolab::config{$attr};
+                                }
+                                last SWITCH;
+                            };
+                            # Quote function
+                            $fct eq 'quote' && do {
+                                # slapd.conf compatible quoting
+                                $val = $Kolab::config{$attr};
+                                $val =~ s/"/\"/g;
+                                $val = '"'.$val.'"';
+                                last SWITCH;
+                            }
+                        }
+                    }
+                    s/\@{3}([^\s\@]+?)(\|.+?)?\@{3}/$val/;
+                    last if ( $val eq "\@\@\@$attr\@\@\@" ); # prevent endless loop
+                } else {
+                    # Only warn the user in case we are not skipping the section
+                    ($skip == 0) && Kolab::log('T', "No configuration variable corresponding to `$1' exists", KOLAB_WARN);
+                    s/\@{3}([^\s\@]+?)\@{3}//;
+                }
+            }
+            ($skip == 0) && print $config $_;
+        }
     }
     
     $template->close;
     $config->close;
 
-    move($config->filename, $cfg) || Kolab::log('T', "Error moving configfile to $cfg, error: $!", KOLAB_ERROR );
-    fixup( $cfg, $owner, $perm );
-    #chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $cfg);
-    #chmod(0600, $cfg) if ($cfg =~ /openldap/);
 
-    if (-f $oldcfg && !defined $special_templates{$tmpl} ) {
-        my $rc = `diff -q $cfg $oldcfg`;
+    if (-f $cfg) {
+        my $cfgtemp = $config->filename;
+        my $rc = `diff -q $cfg $cfgtemp`;
         chomp($rc);
         if ($rc) {
-            if ($cfg =~ /postfix/) {
-                $haschanged{'postfix'} = 1;
-            } elsif ($cfg =~ /saslauthd/) {
-                $haschanged{'saslauthd'} = 1;
-            } elsif ($cfg =~ /apache/) {
-                $haschanged{'apache'} = 1;
-            } elsif ($cfg =~ /openldap/) {
-                $haschanged{'slapd'} = 1;
-            } elsif ($cfg =~ /imapd/) {
-                $haschanged{'imapd'} = 1;
-	    } elsif ($cfg =~ /amavisd/) {
-                $haschanged{'amavisd'} = 1;
-	    } elsif ($cfg =~ /clamav/) {
-                $haschanged{'clamav'} = 1;
-#} elsif ($cfg =~ /example/) {
-	    } else {
-		Kolab::log('T', "`$cfg' change detected ", KOLAB_DEBUG );
-	    }
-	    $templatehaschanged{$tmpl} = 1;
-
             Kolab::log('T', "`$cfg' change detected: $rc", KOLAB_DEBUG );
+            $confighaschanged{$tmpl} = 1;
+            #making backup
+            my $cfgbackup = $cfg . '.old';
+            my $oldmask = umask 077;
+            move($cfg, $cfgbackup) || Kolab::log('T', "Error backuping configfile to $cfgbackup, error: $!", KOLAB_ERROR );
+            # To avoid warnings, the backup files must be owned by root
+            chown(0, 0, $cfgbackup);
+            umask $oldmask;
         }
+    } else {
+        Kolab::log('T', "`$cfg' creation detected", KOLAB_DEBUG );
+        $confighaschanged{$tmpl} = 1;
     }
 
-    Kolab::log('T', "Finished creating configuration file `$cfg'", KOLAB_DEBUG );
-}
-
-sub buildPostfixTransportMap
-{
-    buildPostfixMap( 'transport' );
-}
+    if($confighaschanged{$tmpl}) {
+        move($config->filename, $cfg) || Kolab::log('T', "Error moving configfile to $cfg, error: $!", KOLAB_ERROR );
+        fixup( $cfg, $owner, $perm );
+    } else {
+        unlink($config->filename);
+    }
 
-sub buildPostfixVirtualMap
-{
-    buildPostfixMap( 'virtual' );
+    Kolab::log('T', "Finished creating configuration file `$cfg'", KOLAB_DEBUG );
 }
 
-sub buildPostfixMap
+sub getPostfixMap
 {
     my $map = shift;
+    my $ret = '';
     Kolab::log('T', "Building Postfix $map map", KOLAB_DEBUG);
 
-    my $templatedir = $Kolab::config{"templatedir"};
-
-    my $keytemplate = "$templatedir/$map.template";
-    my $cfg = $templates{$keytemplate};
-    my $oldcfg = $cfg . '.old';
-
-    #my $oldmask = umask 077;
-    #copy($cfg, $oldcfg);
-    #chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $oldcfg);
-    #umask $oldmask;
-    #delete $templates{$keytemplate};
-
-    my $transport;
-    if (!($transport = IO::File->new($cfg, 'a'))) {
-        Kolab::log('T', "Unable to create Postfix $map map: $!", KOLAB_ERROR);
-        exit(1);
-    }
-
     my $ldap = Kolab::LDAP::create(
         $Kolab::config{'ldap_ip'},
         $Kolab::config{'ldap_port'},
         $Kolab::config{'bind_dn'},
         $Kolab::config{'bind_pw'}
-	);
+    );
 
     my $mesg = $ldap->search(
         base    => 'k=kolab,'.$Kolab::config{'base_dn'},
         scope   => 'base',
         filter  => '(objectclass=*)'
-	);
+    );
     if ($mesg->code) {
         Kolab::log('T', "Unable to locate Postfix $map map entries in LDAP", KOLAB_ERROR);
         exit(1);
@@ -373,7 +325,7 @@ sub buildPostfixMap
             foreach (@$routes) {
                 $_ = trim($_);
                 Kolab::log('T', "Adding entry `$_' to $map");
-                print $transport $_ . "\n";
+                $ret .= $_ . "\n";
             }
         }
     } else {
@@ -381,61 +333,27 @@ sub buildPostfixMap
     }
 
     Kolab::LDAP::destroy($ldap);
-    $transport->close;
-
-    # FIXME: bad way of doing things...
-    #system("chown root:root @emailserver_confdir@/*");
-    fixup( $cfg, $ownership{$cfg}, $permissions{$cfg});
-    system("$Kolab::config{'postmapping'}/$map");
-
-    if (-f $oldcfg) {
-        my $rc = `diff -q $cfg $oldcfg`;
-        chomp($rc);
-        if ($rc) {
-	    Kolab::log('T', "`$cfg' change detected: $rc", KOLAB_DEBUG);
-	    $haschanged{'postfix'} = 1;
-        }
-    } else {
-        $haschanged{'postfix'} = 1;
-    }
-
-    Kolab::log('T', 'Finished building Postfix $map map', KOLAB_DEBUG);
+    Kolab::log('T', "Finished building Postfix $map map", KOLAB_DEBUG);
+    return $ret;
 }
 
-sub buildCyrusGroups
+sub getCyrusGroups
 {
+    my $ret ='';
     Kolab::log('T', 'Building Cyrus groups', KOLAB_DEBUG);
 
-    my $templatedir = $Kolab::config{"templatedir"};
-
-    my $keytemplate = "$templatedir/imapd.group.template";
-    my $cfg = $templates{$keytemplate};
-    my $oldcfg = $cfg . '.old';
-    #delete $templates{$keytemplate};
-
-    #my $oldmask = umask 077;
-    #copy($cfg, $oldcfg);
-    #chown($Kolab::config{'kolab_uid'}, $Kolab::config{'kolab_gid'}, $oldcfg);
-    #umask $oldmask;
-
-    my $groupconf;
-    if (!($groupconf = IO::File->new($cfg, 'a'))) {
-        Kolab::log('T', "Unable to open configuration file `$cfg': $!", KOLAB_ERROR);
-        exit(1);
-    }
-
     my $ldap = Kolab::LDAP::create(
         $Kolab::config{'ldap_ip'},
         $Kolab::config{'ldap_port'},
         $Kolab::config{'bind_dn'},
         $Kolab::config{'bind_pw'}
-	);
+    );
 
     my $mesg = $ldap->search(
         base    => $Kolab::config{'base_dn'},
         scope   => 'sub',
         filter  => '(&(mail=*)(objectclass=kolabgroupofnames))'
-	);
+    );
     if ($mesg->code) {
         Kolab::log('T', 'Unable to locate Cyrus groups in LDAP', KOLAB_ERROR);
         exit(1);
@@ -446,22 +364,22 @@ sub buildCyrusGroups
     if ($mesg->code <= 0) {
         foreach $ldapobject ($mesg->entries) {
             #my $group = $ldapobject->get_value('cn') . '@'.join('.',reverse(@dn)) . ":*:$count:";
-	    my $group = lc($ldapobject->get_value('mail')).":*:$count:";
+            my $group = lc($ldapobject->get_value('mail')).":*:$count:";
             my $userlist = $ldapobject->get_value('member', asref => 1);
             foreach (@$userlist) {
-		my $uid = $_;
-		my $umesg = $ldap->search( base => $uid,
-					   scope => 'base', 
-					   filter => '(objectClass=*)' );
-		if ( $umesg && $umesg->code() <= 0 && $umesg->count() == 1 ) {
-		    my $mail;
-		    ($mail = $umesg->entry(0)->get_value('mail')) or
-			($mail = $umesg->entry(0)->get_value('uid'));
-		    $group .= lc($mail).',';		
-		}
-	    }
+                my $uid = $_;
+                my $umesg = $ldap->search( base => $uid,
+                    scope => 'base', 
+                    filter => '(objectClass=*)' );
+                if ( $umesg && $umesg->code() <= 0 && $umesg->count() == 1 ) {
+                    my $mail;
+                    ($mail = $umesg->entry(0)->get_value('mail')) or
+                    ($mail = $umesg->entry(0)->get_value('uid'));
+                    $group .= lc($mail).',';
+                }
+            }
             $group =~ s/,$//;
-            print $groupconf $group . "\n";
+            $ret .= $group . "\n";
             Kolab::log('T', "Adding cyrus group `$group'");
             $count++;
         }
@@ -469,33 +387,17 @@ sub buildCyrusGroups
         Kolab::log('T', 'No Cyrus groups found');
     }
 
-    $groupconf->close;
     Kolab::LDAP::destroy($ldap);
 
-    fixup( $cfg, $ownership{$cfg}, $permissions{$cfg});
-
     Kolab::log('T', 'Finished building Cyrus groups', KOLAB_DEBUG );
+    return $ret;
 }
 
-sub buildLDAPAccess
+sub getLDAPAccess
 {
+    my $ret = '';
     Kolab::log('T', 'Building LDAP access file', KOLAB_DEBUG);
 
-    my $templatedir = $Kolab::config{"templatedir"};
-
-    my $keytemplate = "$templatedir/slapd.access.template";
-    if( ! -f $keytemplate ) {
-        Kolab::log('T', "No LDAP access file `$keytemplate', skipping", KOLAB_DEBUG);
-        return;
-    }
-    my $cfg = $templates{$keytemplate};
-    my $oldcfg = $cfg . '.old';
-
-    my $access;
-    if (!($access = IO::File->new($cfg, 'a'))) {
-        Kolab::log('T', "Unable to open configuration file `$cfg': $!", KOLAB_ERROR);
-        exit(1);
-    }
 
 my $global_acl = <<'EOS';
 # Domain specific access
@@ -529,78 +431,47 @@ my $dom_acl3 = << 'EOS';
          by * search stop
 EOS
 
-	my $str;
+    my $str;
     my $domain;
     my @domains;
     if( ref($Kolab::config{'postfix-mydestination'}) eq 'ARRAY' ) {
-	@domains = @{$Kolab::config{'postfix-mydestination'}};
+        @domains = @{$Kolab::config{'postfix-mydestination'}};
     } else {
-	@domains =( $Kolab::config{'postfix-mydestination'} );
+        @domains =( $Kolab::config{'postfix-mydestination'} );
     }
 
     ($str = $dom_acl1) =~ s/\@{3}base_dn\@{3}/$Kolab::config{'base_dn'}/g;
-    print $access $str;
+    $ret .= $str;
 
     foreach $domain (@domains) {
-	($str = $dom_acl2) =~ s/\@{3}domain\@{3}/$domain/g;
-	$str =~ s/\@{3}base_dn\@{3}/$Kolab::config{'base_dn'}/g;	
-	print $access $str;
+        ($str = $dom_acl2) =~ s/\@{3}domain\@{3}/$domain/g;
+        $str =~ s/\@{3}base_dn\@{3}/$Kolab::config{'base_dn'}/g;
+        $ret .= $str;
     }
 
     ($str = $dom_acl3) =~ s/\@{3}base_dn\@{3}/$Kolab::config{'base_dn'}/g;
-    print $access $str;
+    $ret .= $str;
 
     foreach $domain (@domains) {
-	($str = $global_acl) =~ s/\@{3}domain\@{3}/$domain/g;
-	$str =~ s/\@{3}base_dn\@{3}/$Kolab::config{'base_dn'}/g;	
-	print $access $str;
-	Kolab::log('T', "Adding acl for domain '$str'");
-    }
-
-    $access->close;
-
-    if (-f $oldcfg) {
-        my $rc = `diff -q $cfg $oldcfg`;
-        chomp($rc);
-        if ($rc) {
-	    Kolab::log('T', "`$cfg' change detected: $rc", KOLAB_DEBUG);
-	    $haschanged{'slapd'} = 1;
-        }
-    } else {
-        $haschanged{'slapd'} = 1;
+        ($str = $global_acl) =~ s/\@{3}domain\@{3}/$domain/g;
+        $str =~ s/\@{3}base_dn\@{3}/$Kolab::config{'base_dn'}/g;
+        $ret .= $str;
+        Kolab::log('T', "Adding acl for domain '$str'");
     }
-
-    fixup( $cfg, $ownership{$cfg}, $permissions{$cfg});
-
-    Kolab::log('T', 'Finished building LDAP access file', KOLAB_DEBUG );
+    return $ret;
 }
 
-sub buildLDAPReplicas
+sub getLDAPReplicas
 {
+    my $ret = '';
     Kolab::log('T', 'Building LDAP replicas', KOLAB_DEBUG);
 
-    my $templatedir = $Kolab::config{"templatedir"};
-
-    my $keytemplate = "$templatedir/slapd.replicas.template";
-    if( ! -f $keytemplate ) {
-        Kolab::log('T', "No LDAP replicas `$keytemplate', skipping", KOLAB_DEBUG);
-        return;
-    }
-    my $cfg = $templates{$keytemplate};
-    my $oldcfg = $cfg . '.old';
-
-    my $repl;
-    if (!($repl = IO::File->new($cfg, 'a'))) {
-        Kolab::log('T', "Unable to open configuration file `$cfg': $!", KOLAB_ERROR);
-        exit(1);
-    }
-
     # directory_mode syncrepl is supported from openldap-2.3.x and beyond
     if ($Kolab::config{'directory_mode'} eq "syncrepl") {
 
       if ( $Kolab::config{'is_master'} eq "false" ) {
         # Output a syncrepl statement for database synchronisation
-        print $repl "syncrepl rid=0 \n"
+        $ret .=   "syncrepl rid=0 \n"
                  ."         provider=".$Kolab::config{"ldap_master_uri"}."\n"
                  ."         type=refreshAndPersist\n"
                  ."         retry=\"60 10 300 +\"\n"
@@ -614,65 +485,51 @@ sub buildLDAPReplicas
 
     } else {
 
-      if( $Kolab::config{'is_master'} eq "true" ) {
-  	# Master setup
-  	my @kh;
-  	if( ref $Kolab::config{'kolabhost'} eq 'ARRAY' ) {
-  	    @kh = @{$Kolab::config{'kolabhost'}};
-  	} else {
-  	    @kh = ( $Kolab::config{'kolabhost'} );
-  	}
-  	for my $h ( @kh ) {
-  	    next if lc($h) eq lc($Kolab::config{'fqdnhostname'});
-  	    print $repl "replica uri=ldaps://$h\n"
-  		."  binddn=\"".$Kolab::config{'bind_dn'}."\"\n"
-  		."  bindmethod=simple credentials=".$Kolab::config{'bind_pw'}."\n\n";
-  	}
-      } else {
-  	# Slave setup
-  	# Output an update dn statement instead
-  	print $repl "updatedn ".$Kolab::config{'bind_dn'}."\n";
-  	print $repl "updateref ".$Kolab::config{'ldap_master_uri'}."\n";
-      }
-    }
-
-    $repl->close;
-
-    fixup( $cfg, $ownership{$cfg}, $permissions{$cfg});
-
-    if (-f $oldcfg) {
-        my $rc = `diff -q $cfg $oldcfg`;
-        chomp($rc);
-        if ($rc) {
-	    Kolab::log('T', "`$cfg' change detected: $rc", KOLAB_DEBUG);
-	    $haschanged{'slapd'} = 1;
+        if( $Kolab::config{'is_master'} eq "true" ) {
+            # Master setup
+            my @kh;
+            if( ref $Kolab::config{'kolabhost'} eq 'ARRAY' ) {
+                @kh = @{$Kolab::config{'kolabhost'}};
+            } else {
+                @kh = ( $Kolab::config{'kolabhost'} );
+            }
+            for my $h ( @kh ) {
+                next if lc($h) eq lc($Kolab::config{'fqdnhostname'});
+                $ret .= "replica uri=ldaps://$h\n"
+                ."  binddn=\"".$Kolab::config{'bind_dn'}."\"\n"
+                ."  bindmethod=simple credentials=".$Kolab::config{'bind_pw'}."\n\n";
+            }
+        } else {
+            # Slave setup
+            # Output an update dn statement instead
+            $ret .= "updatedn ".$Kolab::config{'bind_dn'}."\n";
+            $ret .= "updateref ".$Kolab::config{'ldap_master_uri'}."\n";
         }
-    } else {
-        $haschanged{'slapd'} = 1;
     }
 
     Kolab::log('T', 'Finished building LDAP replicas', KOLAB_DEBUG);
+    return $ret;
 }
 
 sub replaceMetaVar
-{	
+{
     my $var = shift;
 
     while ($var =~ /\@{3}([^\s\@]+?)\@{3}/) {
-	my $attr = $1;
-	if ($Kolab::config{$attr}) {
-	    my $val = $Kolab::config{$attr};
-	    $var =~ s/\@{3}([^\s\@]+?)\@{3}/$val/;
-	} else {
-	    Kolab::log('T', "No configuration variable corresponding to `$1' exists", KOLAB_WARN);
-	}
+        my $attr = $1;
+        if ($Kolab::config{$attr}) {
+            my $val = $Kolab::config{$attr};
+            $var =~ s/\@{3}([^\s\@]+?)\@{3}/$val/;
+        } else {
+            Kolab::log('T', "No configuration variable corresponding to `$1' exists", KOLAB_WARN);
+        }
     }
     return $var;
 }
 
 
 sub loadMetaTemplates
-{	
+{
     my $templatedir = shift;
     my ($tref, $pref, $oref, $cmdref, $ccharref) = @_;
 
@@ -682,65 +539,69 @@ sub loadMetaTemplates
     closedir(DIR);
 
     foreach my $template (@metatemplates) {
-	my $runonchange = undef;
-	my $commentchar = undef;
-	#Open each file and check for the META
-	if (open (TEMPLATE, "$templatedir/$template" )) {
-	    my $line = <TEMPLATE>;
-	    if ($line =~ /^KOLAB_META_START$/) {
-		Kolab::log('T', 'Processing META template :'.$template, KOLAB_DEBUG );
-		my ($found_end, $target, $permissions, $ownership);
-		while (<TEMPLATE>) {
-		    $line = $_;
-		    
-		    if (!$found_end) {
-			$found_end = $line =~ /^KOLAB_META_END$/;
-			if (!$found_end && $line) {
-			    my ($key,$value) = split(/=/,$line);
-			    chomp($value);
-			    Kolab::log('T', 'META Key: '.$key.' Value: '.$value, KOLAB_DEBUG );
-			    if ($key =~ /^TARGET$/) {
-				$target = replaceMetaVar($value);
-				Kolab::log('T', 'META Target '.$target, KOLAB_DEBUG );
-			    } elsif ($key =~ /^PERMISSIONS$/) {
-				$permissions = replaceMetaVar($value);
-				Kolab::log('T', 'META Permissions '.$permissions, KOLAB_DEBUG );
-			    } elsif ($key =~ /^OWNERSHIP$/) {
-				$ownership = replaceMetaVar($value);
-				Kolab::log('T', 'META Ownership '.$ownership, KOLAB_DEBUG );
-			    } elsif ($key =~ /^RUNONCHANGE$/) {
-				$runonchange = replaceMetaVar($value);
-				Kolab::log('T', 'META Cmd to execute '.$runonchange, KOLAB_DEBUG );
-			    } elsif ($key =~ /^COMMENT_CHAR$/) {
-			      $commentchar = replaceMetaVar($value);
-			      Kolab::log('T', 'META CommentChar to use: '.$commentchar, KOLAB_DEBUG );
-			    } else {
-			        Kolab::log('T', 'incorrect META key "'.$key.'" in: '.$template, KOLAB_WARN );
-			    }
-			}
-		    }
-		}
-		if ($found_end && $target && $permissions && $ownership) {
-		    Kolab::log('T', 'All mandatory fields populated in '.$template, KOLAB_DEBUG );
-		    $$tref{$templatedir . "/" . $template} = $target;
-		    $$oref{$target} = $ownership;
-		    $permissions = oct($permissions);
-		    $$pref{$target} = $permissions;
-		    my $runcmdtemplate = $templatedir."/".$template;
-		    $$cmdref{$runcmdtemplate} = $runonchange if (defined $runonchange);
-		    $$ccharref{$target} = $commentchar if (defined $commentchar);
-		}
-		
-	    }
-	} else {
-	    Kolab::log('T', 'Could not open template file: '. $template, KOLAB_WARN);
-	}
+        my $runonchange = undef;
+        my $commentchar = undef;
+        #Open each file and check for the META
+        if (open (TEMPLATE, "$templatedir/$template" )) {
+            my $line = <TEMPLATE>;
+            if ($line =~ /^KOLAB_META_START$/) {
+                Kolab::log('T', 'Processing META template :'.$template, KOLAB_DEBUG );
+                my ($found_end, $target, $permissions, $ownership);
+                while (<TEMPLATE>) {
+                    $line = $_;
+                    
+                    if (!$found_end) {
+                        $found_end = $line =~ /^KOLAB_META_END$/;
+                        if (!$found_end && $line) {
+                            my ($key,$value) = split(/=/,$line);
+                            chomp($value);
+                            Kolab::log('T', 'META Key: '.$key.' Value: '.$value, KOLAB_DEBUG );
+                            if ($key =~ /^TARGET$/) {
+                                $target = replaceMetaVar($value);
+                                Kolab::log('T', 'META Target '.$target, KOLAB_DEBUG );
+                            } elsif ($key =~ /^PERMISSIONS$/) {
+                                $permissions = replaceMetaVar($value);
+                                Kolab::log('T', 'META Permissions '.$permissions, KOLAB_DEBUG );
+                            } elsif ($key =~ /^OWNERSHIP$/) {
+                                $ownership = replaceMetaVar($value);
+                                Kolab::log('T', 'META Ownership '.$ownership, KOLAB_DEBUG );
+                            } elsif ($key =~ /^RUNONCHANGE$/) {
+                                $runonchange = replaceMetaVar($value);
+                                Kolab::log('T', 'META Cmd to execute '.$runonchange, KOLAB_DEBUG );
+                            } elsif ($key =~ /^COMMENT_CHAR$/) {
+                                $commentchar = replaceMetaVar($value);
+                                Kolab::log('T', 'META CommentChar to use: '.$commentchar, KOLAB_DEBUG );
+                            } else {
+                                Kolab::log('T', 'incorrect META key "'.$key.'" in: '.$template, KOLAB_WARN );
+                            }
+                        }
+                    }
+                }
+                if ($found_end && $target && $permissions && $ownership) {
+                    Kolab::log('T', 'All mandatory fields populated in '.$template, KOLAB_DEBUG );
+                    $$tref{$templatedir . "/" . $template} = $target;
+                    $$oref{$target} = $ownership;
+                    $permissions = oct($permissions);
+                    $$pref{$target} = $permissions;
+                    my $runcmdtemplate = $templatedir."/".$template;
+                    $$cmdref{$runcmdtemplate} = $runonchange if (defined $runonchange);
+                    $$ccharref{$target} = $commentchar if (defined $commentchar);
+                }
+            }
+        } else {
+            Kolab::log('T', 'Could not open template file: '. $template, KOLAB_WARN);
+        }
     }
 
 }
 
 sub rebuildTemplates
 {
+    my %args = @_;
+    $args{doreload} = 1 if !exists $args{doreload};
+    $args{dorunonchange} = 1 if !exists $args{dorunonchange};
+    #$args{templates} = ALL if !exists $args{templates};
+
     my $key;
     my $value;
     my $section="";
@@ -753,65 +614,43 @@ sub rebuildTemplates
     Kolab::log('T', 'Loading meta-template data', KOLAB_DEBUG );
     loadMetaTemplates( $templatedir, \%templates, \%permissions, \%ownership, \%runonchange, \%commentchar );
 
+    # defaults to all templates
+    $args{templates} = [ keys %templates ] if !exists $args{templates};
     my $cfg;
     my $tpl;
-    foreach $tpl (keys %templates) {
+    foreach $tpl (@{$args{templates}}) {
         $cfg = $templates{$tpl};
-        #print STDOUT "Rebuilding $tpl => $cfg\n";
         build($tpl, $cfg, $ownership{$cfg}, $permissions{$cfg}, $commentchar{$cfg});
      }
 
-    buildPostfixTransportMap;
-    buildPostfixVirtualMap;
-    buildLDAPAccess;
-    buildLDAPReplicas;
-    buildCyrusGroups;
-
     Kolab::log('T', 'Finished regenerating configuration files', KOLAB_DEBUG );
 
-    foreach $key (keys %runonchange) {
-	if (defined $templatehaschanged{$key})
-	{
-	    Kolab::log('T', 'Actioning RUNONCHANGE for '.$key, KOLAB_DEBUG );
-	    my $cmd = $runonchange{$key};
-	    # $cmd can contain:
-	    # - /usr/sbin/postmap: should always be executed
-	    # - openpkg rc imapd restart (in openpkg distribution)
-	    # - kolabsrv rc post reload  (in other distributions)
-	    # The commands with ' rc ' may only be executed when reloading is not
-	    # prohibited by the user with the "-n" option.
-	    if ($Kolab::do_reload || $cmd !~ / rc \S+ re(start|load)/) {
-		Kolab::log('T', 'Executing command: '.$cmd, KOLAB_DEBUG );
-		system($cmd);
-	    } else {
-		Kolab::log('T', 'Reload not allowed, not executing command: '.$cmd, KOLAB_DEBUG );
-	    }
-	    system($cmd);
-	    Kolab::log('T', 'Executing command', KOLAB_DEBUG );
-	}
+    if(!$args{dorunonchange}) {
+        Kolab::log('T', 'RUNONCHANGE will not be executed, as requested.', KOLAB_DEBUG );
+        return;
     }
-}
 
-sub bootstrapConfig
-{
-    my $templatedir = $Kolab::config{"templatedir"};
-
-    # FIXME: it would be better if the templates can be given as an
-    # argument to this function.
-    my @templ = ("$templatedir/slapd.access.template",
-      "$templatedir/slapd.conf.template",
-      "$templatedir/slapd.replicas.template");
- 
-    my %runonchange;
-
-    loadMetaTemplates( $templatedir, \%templates, \%permissions, \%ownership, \%runonchange, \%commentchar );
-
-    my $cfg;
-    my $out;
-    foreach my $tpl (@templ) {
-      $cfg = $templates{$tpl};
-      # print STDOUT "Rebuilding $tpl => $cfg\n";
-      build($tpl, $cfg, $ownership{$cfg}, $permissions{$cfg}, $commentchar{$cfg});
+    my %cmds = ();
+    foreach $key (keys %runonchange) {
+        if (defined $confighaschanged{$key}) {
+            Kolab::log('T', 'Queueing RUNONCHANGE for '.$key, KOLAB_DEBUG );
+            $cmds{$runonchange{$key}} = 1;
+        }
+    }
+    my $cmd;
+    foreach $cmd (keys %cmds) {
+        # $cmd can contain:
+        # - /usr/sbin/postmap: should always be executed
+        # - openpkg rc imapd restart (in openpkg distribution)
+        # - kolabsrv rc post reload  (in other distributions)
+        # The commands with ' rc ' may only be executed when reloading is not
+        # prohibited by the user with the "-n" option.
+        if ($args{doreload} || $cmd !~ / rc \S+ re(start|load)/) {
+            Kolab::log('T', 'Executing command: '.$cmd, KOLAB_DEBUG );
+            system($cmd);
+        } else {
+            Kolab::log('T', 'Reload not allowed, not executing command: '.$cmd, KOLAB_DEBUG );
+        }
     }
 }
 
@@ -828,72 +667,29 @@ sub checkPermissions {
     my $ok = 1;
 
     foreach $key (keys %templates) {
-	my $tpl = $templates{$key};
-
-	if (-r $tpl) {
-	    my $st = stat($tpl);
-	    my $owner = getpwuid($st->uid).':'.getgrgid($st->gid);
-	    if( ( ($st->mode & 07777) != $permissions{$tpl}) ||
-		($owner ne $ownership{$tpl}) ) {
-		my $str = 'File '.$tpl.' has the wrong persmissions/owner. Found '
-		    .sprintf("%lo", $st->mode&07777).' '.$owner.', expected '
-		    .sprintf("%lo",$permissions{$tpl}).' '.$ownership{$tpl};
-		print( "$str\n" );
-		Kolab::log('T', $str, KOLAB_ERROR );
-		$ok = 0;
-	    }
-	} else {
-	    my $str = "File $tpl does not exist";
-	    print "$str\n";
-	    Kolab::log('T', "$str", KOLAB_ERROR );
-	}
+        my $tpl = $templates{$key};
+
+        if (-r $tpl) {
+            my $st = stat($tpl);
+            my $owner = getpwuid($st->uid).':'.getgrgid($st->gid);
+            if( ( ($st->mode & 07777) != $permissions{$tpl}) ||
+                    ($owner ne $ownership{$tpl}) ) {
+                my $str = 'File '.$tpl.' has the wrong persmissions/owner. Found '
+                    .sprintf("%lo", $st->mode&07777).' '.$owner.', expected '
+                    .sprintf("%lo",$permissions{$tpl}).' '.$ownership{$tpl};
+                print( "$str\n" );
+                Kolab::log('T', $str, KOLAB_ERROR );
+                $ok = 0;
+            }
+        } else {
+            my $str = "File $tpl does not exist";
+            print "$str\n";
+            Kolab::log('T', "$str", KOLAB_ERROR );
+        }
     }
     return $ok;
 }
 
-sub reload
-{
-    if ($haschanged{'slapd'}) {
-        &Kolab::log('K', 'Restarting OpenLDAP...');
-        system("$Kolab::config{'KOLABRC'} rc openldap restart &");
-    }
-
-    if ($haschanged{'saslauthd'}) {
-        &Kolab::log('K', 'Restarting SASLAuthd...');
-        system("$Kolab::config{'KOLABRC'} rc sasl stop; sleep 1; $Kolab::config{sbindir}/saslauthd -a ldap -n 5");
-    }
-
-    if ($haschanged{'apache'}) {
-        &Kolab::log('K', 'Reloading Apache...');
-        system("$Kolab::config{sbindir}/apachectl graceful");
-    }
-
-    if ($haschanged{'postfix'}) {
-        &Kolab::log('K', 'Reloading Postfix...');
-        system("$Kolab::config{sbindir}/postfix reload");
-    }
-
-    if ($haschanged{'imapd'}) {
-        &Kolab::log('K', 'Restarting imapd...');
-	# Would it be enough with a reload here? /steffen
-        system("$Kolab::config{'KOLABRC'} rc imapd restart");
-    }
-
-    if ($haschanged{'amavisd'}) {
-        &Kolab::log('K', 'Restarting amavisd...');
-        system("$Kolab::config{'KOLABRC'} rc amavisd restart");
-    }
-
-    if ($haschanged{'clamav'}) {
-        &Kolab::log('K', 'Restarting clamav...');
-        system("$Kolab::config{'KOLABRC'} rc clamav restart");
-    }
-
-    %Kolab::Conf::haschanged = ();
-
-    &Kolab::log('K', 'Reload finished');
-}
-
 1;
 __END__
 =head1 NAME
diff --git a/lib/Kolab/Cyrus.pm b/lib/Kolab/Cyrus.pm
index 6d1f16b..4973add 100644
--- a/lib/Kolab/Cyrus.pm
+++ b/lib/Kolab/Cyrus.pm
@@ -22,7 +22,7 @@ package Kolab::Cyrus;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.6.2.1 $
+##  $Revision$
 
 use 5.008;
 use strict;
@@ -97,12 +97,13 @@ sub createMailbox
     my $cyrus = shift;
     my $uid = shift;
     my $sf = shift || 0;
-    my $cyruid = &createUid($uid, $sf);
+    my $partition = shift || '';
 
+    my $cyruid = &createUid($uid, $sf);
     my $mailbox = ($cyrus->list($cyruid))[0];
     if ($uid && ($uid ne $Kolab::config{'cyrus_admin'}) && ($uid ne "freebusy") && ($uid ne "nobody") && !defined($mailbox)) {
-        Kolab::log('Y', "Creating mailbox `$cyruid'");
-        if (!$cyrus->create($cyruid)) {
+        Kolab::log('Y', "Creating mailbox `$cyruid' on ".($partition?"partition `$partition'":"default partition"));
+        if (!$cyrus->create($cyruid, $partition)) {
             Kolab::log('Y', "Unable to create mailbox `$cyruid', Error = `" . $cyrus->error . "'", KOLAB_WARN);
         }
     } else {
@@ -125,8 +126,8 @@ sub createCalendar
     foreach my $mailbox (@mailboxes) {
 	my $u = @{$mailbox}[0];
 	%info = $cyrus->info($u, ('/vendor/kolab/folder-type'));
-        my $key = '/mailbox/{' . $u . '}/vendor/kolab/folder-type';
-        if (exists($info{$key}) && $info{$key} eq 'event.default') {
+	my $key = '/mailbox/{' . $u . '}/vendor/kolab/folder-type';
+	if (exists($info{$key}) && $info{$key} eq 'event.default') {
 	    $calendar = $u;
 	}
     }
diff --git a/lib/Kolab/LDAP.pm b/lib/Kolab/LDAP.pm
index 20021a8..8756be0 100644
--- a/lib/Kolab/LDAP.pm
+++ b/lib/Kolab/LDAP.pm
@@ -22,7 +22,7 @@ package Kolab::LDAP;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.11.2.6 $
+##  $Revision$
 
 use 5.008;
 use strict;
@@ -321,7 +321,7 @@ sub create
         timeout => 20,
         async   => $as,
 	verify => 'none',
-	onerror => 'undef'
+	onerror => \&ldap_error
       );
     } else {
       $ldap = Net::LDAP->new(
@@ -330,7 +330,7 @@ sub create
         version => 3,
         timeout => 20,
         async   => $as,
-	onerror => 'undef'
+	onerror => \&ldap_error
       );
     }
     if (!$ldap) {
@@ -356,7 +356,6 @@ sub destroy
     my $ldap = shift;
 
     if (defined($ldap) && ($ldap->isa('Net::LDAP') || $ldap->isa('Net::LDAPS'))) {
-        $ldap->abandon;
         $ldap->unbind;
         $ldap->disconnect;
     }
@@ -525,9 +524,20 @@ sub createObject
             if ($sync) { $newuid_db{$guid} = $oldgyarduid; } else { uidcacheStore($guid, $oldgyarduid); }
         } else {
             Kolab::log('L', "Creating user `$uid' corresponding to GUID `$guid'", KOLAB_DEBUG);
+            my $partition = '';
+            my $imappartitions_script = $Kolab::config{'imappartitions_script'};
+            if ($imappartitions_script) {
+                my @partitions;
+                if (@partitions = `$imappartitions_script`) {
+                    $partition = $partitions[rand($#partitions + 1)];
+                    chomp $partition;
+                } else {
+                    Kolab::log('L', "Unable to run imappartitions_script `$imappartitions_script': $!", KOLAB_ERROR);
+                }
+            }
             # We have a object that we have no previous record of, so create everything
             if ($sync) { $newuid_db{$guid} = $uid; } else { uidcacheStore($guid, $uid); }
-            Kolab::Cyrus::createMailbox($cyrus, $uid, ($p eq 'sf' ? 1 : 0));
+            Kolab::Cyrus::createMailbox($cyrus, $uid, ($p eq 'sf' ? 1 : 0), $partition);
             if( $p eq 'sf' ){
                 my $foldertype = lc($object->get_value('kolabfoldertype'));
 
@@ -574,7 +584,7 @@ sub createObject
     if( $quota != $oldquota ) {
         Kolab::Cyrus::setQuota($cyrus, $uid, $quota*1024, ($p eq 'sf' ? 1 : 0));
         if( $quota == 0 ) {
-            quotaDelete{$guid};
+            quotaDelete($guid);
         } else {
             quotaStore($guid, $quota);
         }
@@ -708,16 +718,18 @@ sub deleteObject
 	}
     }
 
-    # FIXME
-    # This is a horrible fix for kolab/issue3472. kolabd is a simple
-    # deamon that should react to changes within LDAP. It should NOT
-    # however have any application knowledge. It would be better if
-    # each application that requires cleanup operations after user
-    # removal could add a script in a directory collecting such
-    # operations.
-    if (-e $Kolab::config{'webserver_document_root'} . '/client/storage/' . $uid . '.prefs' ) {
-	unlink($Kolab::config{'webserver_document_root'} . '/client/storage/' . $uid . '.prefs');
-        Kolab::log('L', "Deleted web client user preferences for user $uid.", KOLAB_DEBUG);
+    my $hooksdir = $Kolab::config{'kolab_hooksdir'} . '/delete';
+    opendir(DIR, $hooksdir) or Kolab::log('T', 'Given hook directory $hooksdir does not exist!', KOLAB_ERROR );
+    my @hooks = grep { /^hook-/ } readdir (DIR);
+    closedir(DIR);
+
+    foreach my $hook (@hooks) {
+	system($Kolab::config{'kolab_hooksdir'} . '/delete/' . $hook . " $uid");
+	if ($?==0) {
+	    Kolab::log('L', "Successfully ran hook $hook for user $uid.", KOLAB_DEBUG);
+	} else {
+	    Kolab::log('L', "Failed running hook $hook for user $uid.", KOLAB_ERROR);
+	}
     }
 
     if (!$uid) {
@@ -996,6 +1008,14 @@ sub make_salt {
     return join "", @tab[ map {rand 64} (1 .. $length) ];
 }
 
+sub ldap_error {
+    my $mesg = shift;
+    my $errstr = $mesg->dn || '';
+    $errstr .= ": " if $errstr;
+    $errstr .= $mesg->error if $mesg->error;
+    Kolab::log('L', $errstr, KOLAB_ERROR);
+}
+
 
 1;
 __END__
diff --git a/lib/Kolab/LDAP/Backend.pm b/lib/Kolab/LDAP/Backend.pm
index af22021..ba1c9d5 100644
--- a/lib/Kolab/LDAP/Backend.pm
+++ b/lib/Kolab/LDAP/Backend.pm
@@ -22,7 +22,7 @@ package Kolab::LDAP::Backend;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.1 $
+##  $Revision$
 
 use 5.008;
 use strict;
diff --git a/lib/Kolab/LDAP/Backend/ad.pm b/lib/Kolab/LDAP/Backend/ad.pm
index 0947664..668b67f 100644
--- a/lib/Kolab/LDAP/Backend/ad.pm
+++ b/lib/Kolab/LDAP/Backend/ad.pm
@@ -22,7 +22,7 @@ package Kolab::LDAP::Backend::ad;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.1 $
+##  $Revision$
 
 use 5.008;
 use strict;
diff --git a/lib/Kolab/LDAP/Backend/slurpd.pm b/lib/Kolab/LDAP/Backend/slurpd.pm
index b712fa8..8f7cb7a 100644
--- a/lib/Kolab/LDAP/Backend/slurpd.pm
+++ b/lib/Kolab/LDAP/Backend/slurpd.pm
@@ -22,7 +22,7 @@ package Kolab::LDAP::Backend::slurpd;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.3 $
+##  $Revision$
 
 use 5.008;
 use strict;
diff --git a/lib/Kolab/Util.pm b/lib/Kolab/Util.pm
index 4acc459..f115eeb 100644
--- a/lib/Kolab/Util.pm
+++ b/lib/Kolab/Util.pm
@@ -22,7 +22,7 @@ package Kolab::Util;
 ##  You can view the  GNU General Public License, online, at the GNU
 ##  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 ##
-##  $Revision: 1.1 $
+##  $Revision$
 
 use 5.008;
 use strict;
diff --git a/sbin/kolab_bootstrap.in b/sbin/kolab_bootstrap.in
index dc461cf..1c4532d 100644
--- a/sbin/kolab_bootstrap.in
+++ b/sbin/kolab_bootstrap.in
@@ -48,6 +48,12 @@ Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 use strict;
 use vars qw($opt_b $opt_f);
 
+use Encode;
+use I18N::Langinfo qw(langinfo YESSTR CODESET);
+my $local_codeset = langinfo(CODESET());
+
+binmode(STDIN, ":encoding($local_codeset)");
+
 use URI;
 use Socket;
 use IO::File;
@@ -65,13 +71,13 @@ use Time::Local;
 use Time::localtime;
 use Digest::SHA1;
 use MIME::Base64;
-use Encode;
 
 # Reload only kolab.globals into our configuration.
 Kolab::reloadConfig("@CONFIG_DIR@/kolab.globals", 1);
 
 my $kolab_config = "@CONFIG_DIR@/kolab.conf";
 my %kolab_config;
+my @files;
 
 ##### Utility Functions
 
@@ -243,6 +249,7 @@ checkPort("pop3 server", 110);
 checkPort("pop3s server", 995);
 checkPort("smtp server", 25);
 checkPort("smtps server", 465);
+checkPort("submission server", 587);
 checkPort("amavis server", 10024);
 checkPort("postfix reinjection from kolabfilter", 10025);
 checkPort("postfix reinjection from amavis", 10026);
@@ -286,14 +293,28 @@ if ($?==0) {
     system("mv \"@CONFIG_DIR@/ca\" $backupdir");
   }
 
-  system("cd \"@CONFIG_DIR@\"; mv *.pem $backupdir");
+  @files = <@CONFIG_DIR@/*.pem>;
+  system("cd \"@CONFIG_DIR@\"; mv *.pem $backupdir") if (@files);
 
   if (-f $kolab_config) {
     system("mv \"$kolab_config\" $backupdir");
   }
 
-  print "Cleaning up LDAP\n";
-  system("cd \"$Kolab::config{'ldapserver_dir'}\"; rm -f *");
+  # Potentially dangerous code, be defensive.  The "rm -f" command could remove
+  # the wrong files when the variable $Kolab::config{'ldapserver_dir'} is not
+  # assigned correctly.  See kolab/issue4009.  With the current implementation
+  # it is of course still possible to remove the wrong files, but this is a
+  # good trade off between defensive code and too much code.
+  if ((defined $Kolab::config{'ldapserver_dir'})
+    and ($Kolab::config{'ldapserver_dir'} ne "")
+    and ($Kolab::config{'ldapserver_dir'} ne "/")) {
+    print "Cleaning up LDAP\n";
+    system("rm -f \"$Kolab::config{'ldapserver_dir'}\"/*");
+  } else {
+    print "Error: variable ldapserver_dir incorrectly defined: ".
+      $Kolab::config{'ldapserver_dir'}."\n";
+    exit 1;
+  }
 
 } else {
   print "LDAP repository is empty - assuming fresh install\n";
@@ -309,7 +330,7 @@ my $fqdnhostname = $kolab_config{'fqdnhostname'} || die "could not read fqdnhost
 my $is_master = $kolab_config{'is_master'} || "true";
 my $bind_dn = $kolab_config{'bind_dn'} || die "could not read bind_dn from $kolab_config";
 my $bind_pw = $kolab_config{'bind_pw'} || die "could not read bind_pw from $kolab_config";
-my $bind_pw_hash = $kolab_config{'bind_pw_hash'} || hashPassword2( $bind_pw );
+my $bind_pw_hash = $kolab_config{'bind_pw_hash'} || hashPassword( $bind_pw );
 my $ldap_uri = $kolab_config{'ldap_uri'} || die "could not read ldap_uri from $kolab_config";
 my $base_dn = $kolab_config{'base_dn'} || die "could not read base_dn from $kolab_config";
 my $php_dn = $kolab_config{'php_dn'} || die "could not read php_dn from $kolab_config";
@@ -353,6 +374,8 @@ if ( $tmp2 eq "2" ) {
   print "Proceeding with master server setup\n\n";
 }
 
+$Kolab::config{"is_master"} = $is_master;
+
 if ( $is_master eq "true" ) {
   ##### Master server setup
   getopt('f');
@@ -385,9 +408,9 @@ if ( $is_master eq "true" ) {
     if ($bind_pw =~ /\@\@\@/) {
       $bind_pw = `$Kolab::config{'bindir'}/openssl rand -base64 12`;
       chomp $bind_pw;
-      $bind_pw = Encode::encode_utf8(getUserInput("Please choose a manager password", $bind_pw));
-      print " bind_pw : " . Encode::decode_utf8($bind_pw) . "\n";
-      $bind_pw_hash = hashPassword2($bind_pw);
+      $bind_pw = getUserInput("Please choose a manager password", $bind_pw);
+      print " bind_pw : $bind_pw\n";
+      $bind_pw_hash = hashPassword($bind_pw);
     }
 
     # Generate passwords
@@ -405,6 +428,7 @@ if ( $is_master eq "true" ) {
     }
 
     my $fd = IO::File->new($kolab_config, "w+") || die "could not open $kolab_config";
+    binmode($fd, ":encoding(UTF-8)");
     print $fd "fqdnhostname : $fqdn\n";
     print $fd "is_master : $is_master\n";
     print $fd "base_dn : $base_dn\n";
@@ -424,13 +448,13 @@ if ( $is_master eq "true" ) {
     chmod 0600, $kolab_config;
     kolab_chown "$Kolab::config{'kolab_musr'}","$Kolab::config{'kolab_mgrp'}", $kolab_config;
     print "IMPORTANT NOTE:\n";
-    print "use login=manager and passwd=" . Encode::decode_utf8($bind_pw) . " when you log into the webinterface!\n\n";
+    print "use login=manager and passwd=$bind_pw when you log into the webinterface!\n\n";
   }
 
   # Set up slapd to replicate to slave server's kolabds
   @kolabhosts = ( $fqdn );
   while(1) {
-    my $tmp = getUserInput("Enter fully qualified hostname of slave kolab server e.g. thishost.domain.tld [empty when done]");
+    my $tmp = getUserInput("Enter fully qualified hostname of slave kolab server e.g. thishost.domain.tld (empty when done)");
     if( $tmp ) {
       push @kolabhosts, $tmp;
       #$cfg .= "replica host=$tmp\n";
@@ -471,14 +495,23 @@ if ( $is_master eq "true" ) {
       # hence can't be used, these definitons are skipped when
       # bootstrap_config = true
       $Kolab::config{"bootstrap_config"} = 'true';
-      Kolab::Conf::bootstrapConfig();
+      my $templatedir = $Kolab::config{"templatedir"};
+      Kolab::Conf::rebuildTemplates(
+            dorunonchange =>0,
+            templates => [
+              "$templatedir/slapd.access.template",
+              "$templatedir/slapd.conf.template",
+              "$templatedir/slapd.replicas.template"
+            ],
+        );
       $Kolab::config{"bootstrap_config"} = 'false';
 
       # now we must startup slapd
       print "temporarily starting slapd\n";
       $ldap_uri = "ldap://127.0.0.1:389/";
       # ensure that the database has correct permissions
-      system("chown $Kolab::config{'ldapserver_rusr'}:$Kolab::config{'ldapserver_grp'} $Kolab::config{'ldapserver_dir'}/*");
+      @files = <$Kolab::config{'ldapserver_dir'}/*>;
+      system("chown $Kolab::config{'ldapserver_rusr'}:$Kolab::config{'ldapserver_grp'} $Kolab::config{'ldapserver_dir'}/*") if (@files);
       (system("$Kolab::config{'libexecdir'}/openldap/slapd -h ldap://127.0.0.1:389/ -f $Kolab::config{'ldapserver_confdir'}/slapd.conf -u $Kolab::config{'ldapserver_rusr'} -g $Kolab::config{'ldapserver_grp'}") == 0 ) || die( "Could not start temporary slapd: $!" );
       print ("Waiting for OpenLDAP to start\n");
       sleep 10;
@@ -589,7 +622,7 @@ if ( $is_master eq "true" ) {
       # create php read-only user
       $ldapobject = newOrExistingLDAPEntry( $ldap, "cn=nobody,cn=internal,$base_dn" );
       $ldapobject->replace('cn' => 'nobody', 'sn' => 'n/a n/a', 'uid' => 'nobody',
-                           'userPassword' => hashPassword2($php_pw),
+                           'userPassword' => hashPassword($php_pw),
                            'objectclass' => ['top','inetorgperson','kolabinetorgperson']);
       $ldapobject->dn("cn=nobody,cn=internal,$base_dn");
       $mesg = $ldapobject->update($ldap);
@@ -599,7 +632,7 @@ if ( $is_master eq "true" ) {
       # create calendar user
       $ldapobject = newOrExistingLDAPEntry( $ldap, "cn=$calendar_id@" . $domain . ",cn=internal,$base_dn" );
       $ldapobject->replace('cn' => $calendar_id . '@' . $domain, 'sn' => 'n/a n/a', 'uid' => $calendar_id . '@' . $domain,
-                           'userPassword' => hashPassword2($calendar_pw),
+                           'userPassword' => hashPassword($calendar_pw),
                            'objectclass' => ['top','inetorgperson','kolabinetorgperson']);
       $ldapobject->dn("cn=$calendar_id@" . $domain . ",cn=internal,$base_dn");
       $mesg = $ldapobject->update($ldap);
@@ -645,7 +678,7 @@ if ( $is_master eq "true" ) {
 
    if ($ldap_uri =~ /127\.0\.0\.1/ || $ldap_uri =~ /localhost/) {
       print "\nkill temporary slapd\n\n";
-      system("$Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} stop");
+      system("$Kolab::config{'KOLABRC'} rc openldap stop");
       sleep 1; # actually race should be impossible
       system("killall -9 slapd >/dev/null 2>&1");
    }
@@ -698,7 +731,7 @@ EOS
   ##### Slave server setup
 
   print "stop running slapd (if any)\n";
-  kolab_system("$Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} stop");
+  kolab_system("$Kolab::config{'KOLABRC'} rc openldap stop");
 
   # Make sure that no rogue demons are running
   tryConnect( '127.0.0.1', 389 ) && die "A process is already listening to port 389 (ldap)\n"
@@ -725,8 +758,8 @@ EOS
   print "proceeding with base DN $base_dn\n";
 
   $bind_dn = "cn=manager,cn=internal,$base_dn";
-  $bind_pw = Encode::encode_utf8(getUserInput("Manager password"));
-  $bind_pw_hash = hashPassword2($bind_pw);
+  $bind_pw = getUserInput("Manager password");
+  $bind_pw_hash = hashPassword($bind_pw);
 
   my $confname = "$Kolab::config{'sasl_smtpconffile'}";
   copy("@CONFIG_DIR@/templates/smtpd.conf.template", $confname) || die "could not write to $confname";
@@ -797,6 +830,7 @@ EOS
   (print "Error reading calendar password" && goto SLAVESTART) unless( $calendar_pw );
 
   my $fd = IO::File->new($kolab_config, "w+") || die "could not open $kolab_config";
+  binmode($fd, ":encoding(UTF-8)");
   print $fd "fqdnhostname : $fqdn\n";
   print $fd "is_master : $is_master\n";
   print $fd "base_dn : $base_dn\n";
@@ -816,15 +850,15 @@ EOS
   chmod 0600, $kolab_config;
   kolab_chown "$Kolab::config{'kolab_musr'}","$Kolab::config{'kolab_mgrp'}",$kolab_config;
 
-  if ($kolab_config{'directory_mode'} ne "syncrepl" ) {
+  if ($Kolab::config{'directory_mode'} ne "syncrepl" ) {
     print << 'EOS';
 Now the master server needs to be stopped briefly while the contents of the LDAP database
 is copied over to this slave. Please make sure that this slave is entered into the list
 of kolabhosts on the master before proceeding.
 EOS
-    kolab_system("ssh -C $master_host \'$Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} stop".
+    kolab_system("ssh -C $master_host \'$Kolab::config{'KOLABRC'} rc openldap stop".
                  " && $Kolab::config{'TAR'} -C $Kolab::config{'ldapserver_statedir'} -pcf - openldap-data".
-                 " && $Kolab::config{'KOLABRC'} rc $Kolab::config{'LDAPD'} start\'".
+                 " && $Kolab::config{'KOLABRC'} rc openldap start\'".
                  " | $Kolab::config{'TAR'} -C $Kolab::config{'ldapserver_statedir'} -pxf -");
   }
 
@@ -895,6 +929,7 @@ EOS
   kolab_system("$Kolab::config{'sbindir'}/kolabconf -n");
 
   $fd = IO::File->new($kolab_config, "w+") || die "could not open $kolab_config";
+  binmode($fd, ":encoding(UTF-8)");
   print $fd "fqdnhostname : $fqdn\n";
   print $fd "is_master : $is_master\n";
   print $fd "base_dn : $base_dn\n";
@@ -917,5 +952,5 @@ EOS
 #system("@CONFIG_DIR@/kolab_sslcert.sh $fqdn");
 print "kolab is now ready to run!\n";
 print "please run '$Kolab::config{'KOLABRC'} rc all start'\n";
-print ("Use login=manager and passwd=" . Encode::decode_utf8($bind_pw) . " when you log into\n");
+print ("Use login=manager and passwd=$bind_pw when you log into\n");
 print ("the webinterface https://$fqdn$Kolab::config{'kolab_wui'} !\n");
diff --git a/sbin/kolab_imappartitions.in b/sbin/kolab_imappartitions.in
new file mode 100644
index 0000000..f594fe7
--- /dev/null
+++ b/sbin/kolab_imappartitions.in
@@ -0,0 +1,58 @@
+#!perl
+
+=head1 NAME
+
+kolab_imappartitions - List all imap partition
+
+=head1 SYNOPSIS
+
+B<kolab_imappartitions>
+
+=head1 COPYRIGHT AND AUTHORS
+
+Copyright (c) 2009 Intevation GmbH
+
+Written by Thomas Arendsen Hein <thomas at intevation.de>
+
+=head1 LICENSE
+
+This  program is free  software; you can redistribute  it and/or
+modify it  under the terms of the GNU  General Public License as
+published by the  Free Software Foundation; either version 2, or
+(at your option) any later version.
+
+This program is  distributed in the hope that it will be useful,
+but WITHOUT  ANY WARRANTY; without even the  implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You can view the  GNU General Public License, online, at the GNU
+Project's homepage; see
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>.
+
+=cut
+
+use strict;
+use Kolab;
+use IO::File;
+
+Kolab::reloadConfig("@CONFIG_DIR@/kolab.globals");
+
+my $imap_conf = "$Kolab::config{'imap_confdir'}/imapd.conf";
+
+my $file;
+if (!($file = IO::File->new($imap_conf, 'r'))) {
+    Kolab::log('T', "Unable to open IMAP configuration file `$imap_conf': $!", KOLAB_ERROR);
+    # Error, use default partition
+    print "\n";
+    exit(1);
+}
+
+while (<$file>) {
+    if (/^\s*partition-(\w+):/) {
+        print "$1\n";
+    }
+}
+$file->close;
+
+exit(0);
diff --git a/sbin/kolabconf.in b/sbin/kolabconf.in
index bfe6127..62ea567 100644
--- a/sbin/kolabconf.in
+++ b/sbin/kolabconf.in
@@ -6,7 +6,7 @@ kolabconf - Kolab configuration tool
 
 =head1 SYNOPSIS
 
-B<kolab_bootstrap> [B<-d>] [B<-n>] [B<-h>]
+B<kolabconf> [B<-d>] [B<-n>] [B<-h>]
 
 =head1 OPTIONS AND ARGUMENTS
 
@@ -47,7 +47,7 @@ Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 
 =cut
 
-##  $Revision: 1.2.2.1 $
+##  $Revision$
 
 use 5.008;
 use strict;
@@ -93,9 +93,9 @@ if ($opt_d) {
     exit 0;
 }
 
-$Kolab::do_reload = 1;
+my $do_reload = 1;
 if($opt_n) {
-    $Kolab::do_reload = 0;
+    $do_reload = 0;
 }
 
 if( !$Kolab::reloadOk ) {
@@ -106,11 +106,6 @@ if( !$Kolab::reloadOk ) {
 }
 
 Kolab::log('KC', 'Rebuilding templates');
-Kolab::Conf::rebuildTemplates;
-Kolab::log('KC', 'Reloading kolab components');
-
-if( $Kolab::do_reload ) {
-    Kolab::Conf::reload;
-}
-
+Kolab::Conf::rebuildTemplates(doreload => $do_reload);
 Kolab::log('KC', 'Finished');
+




More information about the packaging-commits mailing list