--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/account.pm.rej Fri Feb 21 11:56:39 2014 +0100
@@ -0,0 +1,530 @@
+--- account.pm Mon Mar 02 13:51:24 2009 +0000
++++ account.pm Thu Dec 15 16:08:16 2011 +0100
+@@ -118,257 +129,342 @@
+
+ verbose("\t$dn...");
+
+- $r = $ldap->search(base => $ubase, filter => "(uid=$user)");
++ $r = $ldap->search( base => $ubase, filter => "(uid=$user)" );
+ die $r->error if $r->code;
+ die "Multiple entries not expected" if $r->count > 1;
+
+ my $e;
+- if ($r->count) {
+- $e = $r->shift_entry;
++ if ( $r->count ) {
++ $e = $r->shift_entry;
+ } else {
+- $e = new Net::LDAP::Entry;
+- $e->dn($dn);
++ $e = new Net::LDAP::Entry;
++ $e->dn($dn);
+ }
+
+- if ($e->exists("mail") || $e->exists(AT_PRIMARYADDRESS) || $e->exists("userPassword")) {
+- verbose "exists\n";
++ if ( $e->exists("mail")
++ || $e->exists(AT_PRIMARYADDRESS)
++ || $e->exists("userPassword") )
++ {
++ verbose "exists\n";
+ } else {
+- FORCE:
++ FORCE:
+
+- # Bevor wir ans Werk gehen, noch ein paar Tests (mailPrimaryAddress und mail darf
+- # noch nicht vergeben sein)
+- foreach my $a ($mailPrimaryAddress, @$mailAddress) {
+- $a =~ s/!$// and next; # wenn ein ! am Ende steht, dann ist es so gewollt und wird
+- # nicht geprüft
+- $r = $ldap->search(filter => "(mail=$a)", base => $ubase);
+- die $r->error if $r->code;
+- die "$a ist schon vergeben\n" if $r->count;
+- }
++ # Bevor wir ans Werk gehen, noch ein paar Tests (mailPrimaryAddress und mail darf
++ # noch nicht vergeben sein)
++ foreach my $a ( $mailPrimaryAddress, @$mailAddress ) {
++ $a =~ s/!$//
++ and
++ next; # wenn ein ! am Ende steht, dann ist es so gewollt und wird
++ # nicht geprüft
++ $r = $ldap->search( filter => "(mail=$a)", base => $ubase );
++ die $r->error if $r->code;
++ die "$a ist schon vergeben\n" if $r->count;
++ }
+
+- $e->replace(objectClass => [uniq $e->get("objectClass"), qw/uidObject person/, OC_RECIPIENT]);
+- $e->replace(uid => [uniq $e->get("uid"), $user]);
++ $e->replace(
++ objectClass => [
++ uniq $e->get("objectClass"),
++ qw/uidObject person/,
++ OC_RECIPIENT
++ ]
++ );
++ $e->replace( uid => [ uniq $e->get("uid"), $user ] );
+
+- $e->add((AT_ADDRESS) => $mailAddress);
+- $e->add((AT_PRIMARYADDRESS) => $mailPrimaryAddress);
+- $e->add(userPassword => $pw);
+- $e->add((AT_GROUP) => $mailGroup) if @$mailGroup;
+- $e->add((AT_FORWARDINGADDRESS) => $mailForwardingAddress) if @$mailForwardingAddress;
++ $e->add( (AT_ADDRESS) => $mailAddress );
++ $e->add( (AT_PRIMARYADDRESS) => $mailPrimaryAddress );
++ $e->add( userPassword => "{plain}$pw" );
++ $e->add( (AT_GROUP) => $mailGroup ) if @$mailGroup;
++ $e->add( (AT_FORWARDINGADDRESS) => $mailForwardingAddress )
++ if @$mailForwardingAddress;
++ $e->add( (AT_QUOTA) => $Cf->imap_quota );
++ $e->add( (AT_ACLGROUPS) => $Cf->imap_aclgroups ) if $Cf->imap_aclgroups;
+
+- # $e->add(iusRestrictedMail => $Cf->internal) if $Cf->internal ne ":";
++ # $e->add(iusRestrictedMail => $Cf->internal) if $Cf->internal ne ":";
+
+- $e->exists("sn") or $e->add(sn => $sn);
+- $e->exists("cn") or $e->add(cn => $cn);
++ $e->exists("sn") or $e->add( sn => $sn );
++ $e->exists("cn") or $e->add( cn => $cn );
+
++ $r = $e->update($ldap);
++ die $r->error if $r->code;
+
+- $r = $e->update($ldap);
+- die $r->error if $r->code;
+-
+- verbose("ok");
+- verbose(" Password: $pw") if not $Cf->password or $Cf->password eq "{pwgen}";
++ verbose('ok');
++ verbose(" Password: $pw")
++ if not $Cf->password
++ or $Cf->password eq "{pwgen}";
+ }
+
+- if($Cf->mbox) {
+- verbose("\n\t$mbox...");
++ if ( $Cf->mbox ) {
+
+- if ($imap->list($mbox)) { verbose("exists") }
+- else {
+- $imap->create($mbox) and verbose("ok") or die $@;
+- $imap->setacl($mbox, $Cf->imap_admin => "lrswipcda") or die $@;
+- $imap->setquota($mbox, STORAGE => 1024 * $Cf->imap_quota) or die $@;
+- }
++ verbose("\n\t$mbox...");
++
++ if ( -d $mbox ) {
++
++ verbose('exists')
++
++ } elsif ( ( $imap->login( $user, $pw ) or die $@ )
++ and $imap->capability->{acl} )
++ {
++
++ # wenn wir acl verwenden,
++ # * dann triggert 'list' acl file (und damit maildir) erzeugung
++ # bei dovecot
++ # * müssen wir dem master nutzer ausdrücklich rechte gewähren
++ # (sofern wir das nicht eleganter über globale acl regeln können)
++ # (lra: sicht-, les- und administrierbar)
++ my $f = $imap->list( '', '*' ) or die $@;
++
++ #$imap->setacl( $f->[0]->[2], $Cf->imap_admin, 'lra' ) or die $@;
++ verbose('ok');
++
++ } else {
++
++ verbose('will be created automatically on first email delivery');
++
++ }
++
+ }
+
+-
+ verbose("\n");
+ }
+
+ sub _modify() {
+-# Auch hier gehen wir davon aus, daß die dn direkt aus dem User-Namen folgt:
+-# dn: uid=USER,...
++
++ # Auch hier gehen wir davon aus, daß die dn direkt aus dem User-Namen folgt:
++ # dn: uid=USER,...
+ my (@users) = @ARGV or die "Need username(s)\n";
+ my @dns;
+
+- my $r = $ldap->search(base => $ubase,
+- filter => "(|" . join("", map { "(uid=$_)" } @ARGV) . ")");
++ my $r = $ldap->search(
++ base => $ubase,
++ filter => "(|" . join( "", map { "(uid=$_)" } @ARGV ) . ")"
++ );
+ die $r->error if $r->code;
+ die "No entries found.\n" if $r->count == 0;
+
+- while (my $e = $r->shift_entry) {
+- my $r;
++ while ( my $e = $r->shift_entry ) {
++ my $r;
+
+- my $user = $e->get_value("uid");
+- my $dn = $e->dn;
+- my $mbox = "user/$user";
++ my $user = $e->get_value("uid");
++ my $dn = $e->dn;
+
+- my $modified = 0;
+- verbose "$user:";
++ my $modified = 0;
++ verbose "$user:";
+
+- verbose "\n\t$dn...";
++ verbose "\n\t$dn...";
+
+- # Fix: iusMailOptions wurde erst später eingeführt, bei Bedarf also hinzufügen
+- #if (!grep /^iusMailOptions$/, @{$e->get("objectClass")}) {
+- #$e->add(objectClass => "iusMailOptions");
+- #}
++ # Fix: iusMailOptions wurde erst später eingeführt, bei Bedarf also hinzufügen
++ #if (!grep /^iusMailOptions$/, @{$e->get("objectClass")}) {
++ #$e->add(objectClass => "iusMailOptions");
++ #}
+
+- if (my $cn = $Cf->fullname) {
+- # Aus dem Fullnamen leiten wir cn und sn ab.
+- my $sn = (reverse split " ", $cn)[0];
++ if ( my $cn = $Cf->fullname ) {
+
+- if ($cn =~ s/^\+//) {
+- $e->replace(
+- cn => [uniq $e->get("cn"), $cn],
+- sn => [uniq $e->get("sn"), $sn]);
+- } elsif ($cn =~ s/^-//) {
+- $e->delete(cn => [$cn], sn => [$sn]);
+- } else { $e->replace(cn => $cn, sn => $sn); }
+- $modified++;
+- }
++ # Aus dem Fullnamen leiten wir cn und sn ab.
++ my $sn = ( reverse split " ", $cn )[0];
+
+- if (defined $Cf->other) {
+- my @o = split /,/, $Cf->other;
+- grep { /^[+-]/ } @o or $e->delete(AT_ADDRESS);
++ if ( $cn =~ s/^\+// ) {
++ $e->replace(
++ cn => [ uniq $e->get("cn"), $cn ],
++ sn => [ uniq $e->get("sn"), $sn ]
++ );
++ } elsif ( $cn =~ s/^-// ) {
++ $e->delete( cn => [$cn], sn => [$sn] );
++ } else {
++ $e->replace( cn => $cn, sn => $sn );
++ }
++ $modified++;
++ }
+
+- foreach my $a (split /,/, $Cf->other) {
+- if ($a =~ s/^-//) {
+- $e->delete((AT_ADDRESS) => [$a])
+- } else {
+- $a =~ s/^\+//;
++ if ( defined $Cf->other ) {
++ my @o = split /,/, $Cf->other;
++ grep { /^[+-]/ } @o or $e->delete(AT_ADDRESS);
+
+- # Darf noch nicht woanders sein
+- $r = $ldap->search(base => $ubase, filter => "(mail=$a)");
+- die $r->error if $r->code;
+- die "$a ist schon vergeben\n" if $r->count;
++ foreach my $a ( split /,/, $Cf->other ) {
++ if ( $a =~ s/^-// ) {
++ $e->delete( (AT_ADDRESS) => [$a] );
++ } else {
++ $a =~ s/^\+//;
+
+- $e->add((AT_ADDRESS) => [$a])
+- }
+- }
+- $modified++;
+- }
++ # Darf noch nicht woanders sein
++ $r = $ldap->search( base => $ubase, filter => "(mail=$a)" );
++ die $r->error if $r->code;
++ die "$a ist schon vergeben\n" if $r->count;
+
+- if (defined $Cf->group) {
+- my @g = split /,/, $Cf->group;
+- grep { /^[+-]/ } @g or $e->delete(AT_GROUP)
+- if $e->get_value(AT_GROUP);
++ $e->add( (AT_ADDRESS) => [$a] );
++ }
++ }
++ $modified++;
++ }
+
+- foreach my $g (@g) {
+- if ($g =~ s/^-//) {
+- $e->delete((AT_GROUP) => [$g])
+- } else {
+- $g =~ s/^\+//;
+- $e->add((AT_GROUP) => [$g])
+- }
+- }
+- $modified++;
+- }
++ if ( defined $Cf->group ) {
++ my @g = split /,/, $Cf->group;
++ grep { /^[+-]/ } @g
++ or $e->delete(AT_GROUP)
++ if $e->get_value(AT_GROUP);
+
+- if (defined $Cf->forward) {
+- my @f = split /,/, $Cf->forward;
+- grep { /^[+-]/ } @f or $e->delete(AT_FORWARDINGADDRESS)
+- if $e->get_value(AT_FORWARDINGADDRESS);
++ foreach my $g (@g) {
++ if ( $g =~ s/^-// ) {
++ $e->delete( (AT_GROUP) => [$g] );
++ } else {
++ $g =~ s/^\+//;
++ $e->add( (AT_GROUP) => [$g] );
++ }
++ }
++ $modified++;
++ }
+
+- foreach my $f (@f) {
+- if ($f =~ s/^-//) {
+- $e->delete((AT_FORWARDINGADDRESS) => [$f]);
+- } else {
+- $f =~ s/^\+//;
+- $e->add((AT_FORWARDINGADDRESS) => [$f]);
+- }
+- }
+- $modified++;
+- }
++ if ( defined $Cf->forward ) {
++ my @f = split /,/, $Cf->forward;
++ grep { /^[+-]/ } @f
++ or $e->delete(AT_FORWARDINGADDRESS)
++ if $e->get_value(AT_FORWARDINGADDRESS);
+
+- if (my $a = $Cf->primary) {
+- $r = $ldap->search(base => $ubase,
+- # filter => "(|(mailPrimaryAddress=$a)(mail=$a))");
+- filter => "(mail=$a)");
+- die $r->error if $r->code;
+- die "$a ist schon vergeben\n" if $r->count;
+-
+- $e->replace((AT_PRIMARYADDRESS) => $Cf->primary);
+- $modified++;
+- }
++ foreach my $f (@f) {
++ if ( $f =~ s/^-// ) {
++ $e->delete( (AT_FORWARDINGADDRESS) => [$f] );
++ } else {
++ $f =~ s/^\+//;
++ $e->add( (AT_FORWARDINGADDRESS) => [$f] );
++ }
++ }
++ $modified++;
++ }
+
+- if (my $pw = _mkpw($Cf->password)) {
+- $e->replace(userPassword => $pw);
+- $modified++;
+- }
++ if ( defined $Cf->quota ) {
++ $e->replace( (AT_QUOTA) => $Cf->quota );
++ $modified++;
++ }
+
+- #if ($Cf->internal ne ":") {
+- #$e->replace(iusRestrictedMail => $Cf->internal ? "TRUE" : "FALSE");
+- #$modified++;
+- #}
++ if ( defined $Cf->aclgroups ) {
+
+- $e->dump if $Cf->debug;
++ my $ag = $Cf->aclgroups;
++ my $lag = $e->get_value(AT_ACLGROUPS);
++ # groups should be supplied with leading '$' for consistency with
++ # dovecots imap acl, but should not be saved in ldap with it!
++ $ag =~ s/(^|,[+-]?)\K\$//g;
+
+- if ($modified) {
+- $r = $e->update($ldap);
+- die $r->error.$r->code if $r->code;
+- }
++ if ( $ag =~ /(^|,\s*)[+-]/ ) {
++ my %x;
++ @x{ split /,/, $lag } = ();
++ for ( split /,/, $ag ) {
++ if (s/^-//) {
++ delete $x{$_};
++ } else {
++ s/^\+//;
++ $x{$_} = undef;
++ }
++ }
+
+- # FIXME: Wenn keine Mailbox existiert, gibt es hier ein Problem
+- if (defined $Cf->imap_quota) {
+- $imap->setquota($mbox, STORAGE => $Cf->imap_quota * 1024)
+- or die $@;
+- }
++ $ag = join ',', sort keys %x;
+
+- verbose "ok\n";
++ }
+
+- print "\n";
++ if ($ag) {
++ $e->replace( (AT_ACLGROUPS) => $ag );
++ } else {
++ $e->delete( AT_ACLGROUPS ) if $lag;
++ }
++ $modified++;
++ }
++
++ if ( my $a = $Cf->primary ) {
++ $r = $ldap->search(
++ base => $ubase,
++
++ # filter => "(|(mailPrimaryAddress=$a)(mail=$a))");
++ filter => "(mail=$a)"
++ );
++ die $r->error if $r->code;
++ die "$a ist schon vergeben\n" if $r->count;
++
++ $e->replace( (AT_PRIMARYADDRESS) => $Cf->primary );
++ $modified++;
++ }
++
++ if ( my $pw = _mkpw( $Cf->password ) ) {
++ $e->replace( userPassword => $pw );
++ $modified++;
++ }
++
++ #if ($Cf->internal ne ":") {
++ #$e->replace(iusRestrictedMail => $Cf->internal ? "TRUE" : "FALSE");
++ #$modified++;
++ #}
++
++ $e->dump if $Cf->debug;
++
++ if ($modified) {
++ $r = $e->update($ldap);
++ die $r->error . $r->code if $r->code;
++ }
++
++ verbose "ok\n";
++
++ print "\n";
+ }
+ }
+
+ sub _delete() {
+-# Wir gehen davon aus, daß es einen dn uid=USER,ou=.... gibt, den wir löschen können.
+-# Wir löschen den kompletten Container. Es kann natürlich sein, daß er noch jemand anders gehört.
+-# Dann ist das Pech. Um es besser zu haben, müßten wir für alles unsere eigenen
+-# Objektklassen haben...
+
+- if (!@ARGV) {
+- print "User: ";
+- chomp($_ = <>);
+- @ARGV = ($_);
++ # Wir gehen davon aus, daß es einen dn uid=USER,ou=.... gibt, den wir löschen können.
++ # Wir löschen den kompletten Container. Es kann natürlich sein, daß er noch jemand anders gehört.
++ # Dann ist das Pech. Um es besser zu haben, müßten wir für alles unsere eigenen
++ # Objektklassen haben...
++
++ if ( !@ARGV ) {
++ print "User: ";
++ chomp( $_ = <> );
++ @ARGV = ($_);
+ }
+
++ foreach (@ARGV) {
++ my $user = $_;
++ my $dn = "uid=$user,$ubase";
+
+- foreach (@ARGV) {
+- my $user = $_;
+- my $dn = "uid=$user,$ubase";
+- my $mbox = "user/$user";
++ verbose("$user:\n");
+
+- verbose("$user:\n");
++ # Nachsehen, ob es noch aliase gibt, in denen dieser Nutzer steht:
++ my $r = $ldap->search(
++ base => $abase,
++ filter => "(" . AT_FORWARDINGADDRESS . "=$_)",
++ attrs => [ "mail", AT_FORWARDINGADDRESS ]
++ );
++ while ( my $e = $r->shift_entry ) {
++ verbose("\tdeleting $user from alias "
++ . $e->get_value("mail")
++ . "..." );
++ $e->delete( (AT_FORWARDINGADDRESS) => [$user] );
+
+- # Nachsehen, ob es noch aliase gibt, in denen dieser Nutzer steht:
+- my $r = $ldap->search(base => $abase,
+- filter => "(".AT_FORWARDINGADDRESS."=$_)",
+- attrs => ["mail", AT_FORWARDINGADDRESS]);
+- while (my $e = $r->shift_entry) {
+- verbose("\tdeleting $user from alias ".$e->get_value("mail")."...");
+- $e->delete((AT_FORWARDINGADDRESS) => [$user]);
++ my $r = $e->update($ldap);
++ if ( $r->code == 0 ) { verbose("ok\n") }
++ else { die $r->error }
++ }
+
+- my $r = $e->update($ldap);
+- if ($r->code == 0) { verbose("ok\n") }
+- else { die $r->error }
+- }
++ verbose("\tdeleting $dn...");
++ $r = $ldap->delete($dn);
+
+- verbose("\tdeleting $dn...");
+- $r = $ldap->delete($dn);
++ if ( $r->code == LDAP_NO_SUCH_OBJECT ) {
++ verbose("doesn't exist");
++ } elsif ( $r->code == 0 ) {
++ verbose("ok");
++ } else {
++ die $r->error;
++ }
++ verbose("\n");
+
+- if ($r->code == LDAP_NO_SUCH_OBJECT) {
+- verbose("doesn't exist");
+- } elsif ($r->code == 0) {
+- verbose("ok");
+- } else {
+- die $r->error;
+- }
+- verbose("\n");
+-
+- if ($Cf->mbox) {
+- verbose("\tdeleting mbox $mbox...");
+- $imap->delete($mbox) and verbose("ok")
+- or verbose($imap->error);
+- }
++ if ( $Cf->mbox ) {
++ my $m = _mbox($user);
++ if ( not( defined $m and $m ) ) {
++ verbose("can't determine mbox location - not deleting it");
++ } else {
++ verbose("\tdeleting $m...");
++ verbose( ( remove_tree $m) ? 'ok' : " Can't remove '$m': $!" );
++ }
++ }
+
+- verbose("\n");
++ print
++ "Don't forget to remove acl entries for this user if any exist!\n";
++ verbose("\n");
+
+ }
+ }