diff -r 96f567261e87 -r 6a6c18cddf46 acl.pm --- a/acl.pm Tue Dec 13 13:01:23 2011 +0100 +++ b/acl.pm Tue Dec 13 13:39:03 2011 +0100 @@ -18,7 +18,7 @@ use Term::ReadKey; my $Cf; -my ( $ldap, $ubase, $abase ); +my ( $ldap, $ubase, $abase ); my ( $imap, $acl_password, $nspat ); END { $imap and $imap = undef; } @@ -80,22 +80,23 @@ $imap = Mail::IMAPTalk->new( Server => $Cf->imap_server, Port => $Cf->imap_port - ) - or die "Can't connect to IMAP Server '", $Cf->imap_server, - "', Port '", $Cf->imap_port, "': ", $@; + ) + or die "Can't connect to IMAP Server '", $Cf->imap_server, + "', Port '", $Cf->imap_port, "': ", $@; $imap->login( $Cf->acl_admin, $acl_password ) or die $@; - die "IMAP Server does not advertise acl support" unless $imap->capability->{acl}; + die "IMAP Server does not advertise acl support" + unless $imap->capability->{acl}; # requires an imap connection my $ns = $imap->namespace() or die "No public namespaces available: $@"; $nspat = []; - for (@{$ns->[2]}) { - (my $n = $_->[0]) =~ s/$_->[1]$//; - push @{$nspat}, [qr/\Q$n\E($_->[1]|$)/, $_->[1]]; + for ( @{ $ns->[2] } ) { + ( my $n = $_->[0] ) =~ s/$_->[1]$//; + push @{$nspat}, [ qr/\Q$n\E($_->[1]|$)/, $_->[1] ]; } - if ( $Cf->add ) { _modify() } - elsif ( $Cf->delete ) { $Cf->acl('delete') ; _modify() } + if ( $Cf->add ) { _modify() } + elsif ( $Cf->delete ) { $Cf->acl('delete'); _modify() } elsif ( $Cf->list ) { _list() } elsif ( $Cf->modify ) { _modify() } else { die "Need action (--add|--delete|--list|--modify)\n" } @@ -110,23 +111,27 @@ @ARGV or die "Need user(s)\n"; $Cf->folder ~~ [] and die "Need folders(s)\n"; $Cf->acl or die "Need acl\n"; - $Cf->recursive and $Cf->create and die "Use either --recursive or --create but not both\n"; + $Cf->recursive + and $Cf->create + and die "Use either --recursive or --create but not both\n"; my $r = $ldap->search( base => $ubase, filter => "(|" . join( "", map { "(uid=$_)" } @ARGV ) . ")" ); die $r->error if $r->code; - unless ($r->count) { - prompt('No matching user found in ldap. Continue? (y/N)', "n\n") =~ /y/i or exit 0; + unless ( $r->count ) { + prompt( 'No matching user found in ldap. Continue? (y/N)', "n\n" ) =~ + /y/i + or exit 0; @users = @ARGV; } - while (my $e = ($r->shift_entry or shift @users)) { + while ( my $e = ( $r->shift_entry or shift @users ) ) { - my ($user, $dn); + my ( $user, $dn ); - if (ref $e eq 'Net::LDAP::Entry') { + if ( ref $e eq 'Net::LDAP::Entry' ) { $user = $e->get_value("uid"); $dn = $e->dn; } else { @@ -138,23 +143,27 @@ verbose "$user:\n"; verbose "\t$dn...\n"; - for my $folder (@{$Cf->folder}) { - - $imap->create($folder) or die "Can't create folder '$folder': $@" if $Cf->create; + for my $folder ( @{ $Cf->folder } ) { - for my $f (@{acl_folders($folder)}) { + $imap->create($folder) + or die "Can't create folder '$folder': $@" + if $Cf->create; - if ($Cf->acl eq 'delete') { - $imap->deleteacl($f, $user) or die "Can't delete acl: $@"; + for my $f ( @{ acl_folders($folder) } ) { + + if ( $Cf->acl eq 'delete' ) { + $imap->deleteacl( $f, $user ) or die "Can't delete acl: $@"; verbose "\t$f: none\n"; } else { - $imap->setacl($f, $user, $Cf->acl) or die "Can't set acl: $@"; + $imap->setacl( $f, $user, $Cf->acl ) + or die "Can't set acl: $@"; verbose "\t$f: " . $Cf->acl . "\n"; } } } + # Fix: iusMailOptions wurde erst später eingeführt, bei Bedarf also hinzufügen #if (!grep /^iusMailOptions$/, @{$e->get("objectClass")}) { #$e->add(objectClass => "iusMailOptions"); @@ -178,28 +187,31 @@ die "option acl_admin required\n" unless $Cf->acl_admin; - if ($Cf->aclgroups) { + if ( $Cf->aclgroups ) { - warn "--folder option ignored when listing groups" unless $Cf->folder ~~ []; + warn "--folder option ignored when listing groups" + unless $Cf->folder ~~ []; list_groups(@ARGV); } elsif (@ARGV) { -# my $uid = $ARGV[0]; -# # searching by more than use user may be too expensive -# die "Searching by more than one user not supported" unless @ARGV == 1 or $uid =~ /\*/; + # my $uid = $ARGV[0]; + # # searching by more than use user may be too expensive + # die "Searching by more than one user not supported" unless @ARGV == 1 or $uid =~ /\*/; #list_by_user($_) for @ARGV; - warn "--folder option ignored when listing by user" unless $Cf->folder ~~ []; - list_by_user($imap, @ARGV); + warn "--folder option ignored when listing by user" + unless $Cf->folder ~~ []; + list_by_user( $imap, @ARGV ); - } elsif (not $Cf->folder ~~ []) { + } elsif ( not $Cf->folder ~~ [] ) { - list_by_folder($_) for @{$Cf->folder}; + list_by_folder($_) for @{ $Cf->folder }; } else { - die "Need either user or --folder. If you really want to search all users then supply the pattern '*'."; + die + "Need either user or --folder. If you really want to search all users then supply the pattern '*'."; } @@ -210,33 +222,35 @@ @_ = ('*') unless @_; my @ag = split ',', $Cf->imap_aclgroups; my $ag_att = AT_ACLGROUPS; - my $filter = "(&($ag_att=*)" - . "(|" . join( "", map { "(uid=$_)" } @_ ) . "))"; + my $filter = + "(&($ag_att=*)" . "(|" . join( "", map { "(uid=$_)" } @_ ) . "))"; my $r = $ldap->search( - attrs => ['uid', AT_ACLGROUPS], + attrs => [ 'uid', AT_ACLGROUPS ], filter => $filter, base => $ubase, ); die $r->error if $r->code; - unless ($r->count) { - print ("No aclgroups found in ldap\n"); + unless ( $r->count ) { + print("No aclgroups found in ldap\n"); exit 0; } my $users; - while (my $e = ($r->shift_entry)) { + while ( my $e = ( $r->shift_entry ) ) { my $uid = $e->get_value('uid'); my @ag_cur = split ',', $e->get_value($ag_att); for (@ag) { - $users->{$_} = defined $users->{$_} - ? [@{$users->{$_}}, $uid] - : [ $uid ] - if $_ ~~ @ag_cur + $users->{$_} = + defined $users->{$_} + ? [ @{ $users->{$_} }, $uid ] + : [$uid] + if $_ ~~ @ag_cur; } } - print "$_:\n\t", join("\n\t", @{$users->{$_}}), "\n\n" for keys %{$users}; + print "$_:\n\t", join( "\n\t", @{ $users->{$_} } ), "\n\n" + for keys %{$users}; } @@ -244,6 +258,7 @@ my $imap = shift; my $filter = "(|" . join( "", map { "(uid=$_)" } @_ ) . ")"; + #my $filter = "(uid=$uid)"; my $r = $ldap->search( filter => $filter, @@ -251,18 +266,18 @@ ); die $r->error if $r->code; my @users; - unless ($r->count) { + unless ( $r->count ) { verbose("No matching users found in ldap.\n"); @users = @_; } - while (my $e = ($r->shift_entry or shift @users)) { + while ( my $e = ( $r->shift_entry or shift @users ) ) { - my ($uid, $cn, $mr); - if (ref $e eq 'Net::LDAP::Entry') { - $uid = $e->get_value("uid"); - $cn = join( ", ", $e->get_value("cn") ); - $mr = $e->get_value(AT_PRIMARYADDRESS) || ""; # ?? + my ( $uid, $cn, $mr ); + if ( ref $e eq 'Net::LDAP::Entry' ) { + $uid = $e->get_value("uid"); + $cn = join( ", ", $e->get_value("cn") ); + $mr = $e->get_value(AT_PRIMARYADDRESS) || ""; # ?? } else { $uid = $e; $cn = '[cn not available]'; @@ -275,7 +290,9 @@ #print " INTERNAL"; #} - die "IMAP Server does not advertise acl support" unless $imap->capability->{acl}; + die "IMAP Server does not advertise acl support" + unless $imap->capability->{acl}; + # namespace() result looks like this # [ # [ # list of private namespace(s) @@ -300,16 +317,17 @@ # ] my $hasacl; my $ns = $imap->namespace() or die "No public namespaces available: $@"; + # uns interessieren nur 'public' namespaces - for my $n (@{$ns->[2]}) { + for my $n ( @{ $ns->[2] } ) { my $folders = imap_rlist( '', $n->[0], $n->[1] ); for my $f ( @{$folders} ) { #next if '\\Noselect' ~~ $f->[0]; - my $perms = $imap->getacl( $f ) or die "Can't getacl '$f': $@"; - my ($u, $p); - while ($u = shift @{$perms} and $p = shift @{$perms}) { + my $perms = $imap->getacl($f) or die "Can't getacl '$f': $@"; + my ( $u, $p ); + while ( $u = shift @{$perms} and $p = shift @{$perms} ) { next unless $u eq $uid; $hasacl = 1; print "\t$f: $u [$p]\n"; @@ -319,7 +337,8 @@ } - print "\tno acl found on listable folders in shared namespaces\n" unless $hasacl; + print "\tno acl found on listable folders in shared namespaces\n" + unless $hasacl; print "\n"; } @@ -330,18 +349,18 @@ my ($folder) = @_; - for my $f ( @{acl_folders($folder)} ) { + for my $f ( @{ acl_folders($folder) } ) { my $hasacl; print "$f\n"; - my $perms = $imap->getacl( $f ) or die $@; - my ($u, $p); - while ($u = shift @{$perms} and $p = shift @{$perms}) { + my $perms = $imap->getacl($f) or die $@; + my ( $u, $p ); + while ( $u = shift @{$perms} and $p = shift @{$perms} ) { # '#user' will be listed when we have a global acl for 'user' - my $gl = $u =~ /^#/ ? ' [global acl]' : ''; - my $gr = $u =~ /^\$/ ? ' [group acl]' : ''; + my $gl = $u =~ /^#/ ? ' [global acl]' : ''; + my $gr = $u =~ /^\$/ ? ' [group acl]' : ''; $hasacl = 1; print "\t$u [$p]$gr$gl\n"; } @@ -382,11 +401,14 @@ sub imap_list($$) { - my ($ref, $folder) = @_; + my ( $ref, $folder ) = @_; - my $list = $imap->list($ref, $folder) or die "Can't list('$ref', '$folder'): $@"; + my $list = $imap->list( $ref, $folder ) + or die "Can't list('$ref', '$folder'): $@"; + # single folder sieht wie folgt aus: [[flag1, flag2, ...], separator, foldername] ref $list and return [ map $_->[2], @{$list} ]; + # assuming empty result list otherwise return []; @@ -394,11 +416,11 @@ sub imap_rlist($$$) { - my ($ref, $folder, $sep) = @_; + my ( $ref, $folder, $sep ) = @_; $folder =~ s/$sep+$//; - my $list = imap_list($ref, $folder); - push @{$list}, @{imap_list($ref, "$folder$sep*")} if $Cf->recursive; + my $list = imap_list( $ref, $folder ); + push @{$list}, @{ imap_list( $ref, "$folder$sep*" ) } if $Cf->recursive; return $list; } @@ -407,10 +429,11 @@ my ($f) = @_; my $folders; - for my $np (@{$nspat}) { + for my $np ( @{$nspat} ) { + # don't modify $f! - (my $ft = $f) =~ s/$np->[1]$//; - return imap_rlist('', $f, $np->[1]) if ($ft =~ /$np->[0]/); + ( my $ft = $f ) =~ s/$np->[1]$//; + return imap_rlist( '', $f, $np->[1] ) if ( $ft =~ /$np->[0]/ ); } die "Foldername '$f' must begin with the name of a shared namespace\n"; @@ -418,11 +441,13 @@ } sub prompt($$) { - my ($prompt, $default) = @_; - print $prompt, substr($default, 0, 1), "\b"; - ReadMode 4; my $r = ReadKey(0); ReadMode 0; - if ($r eq "\n") { $r = $default } - else { $r .= substr($default, 1) } + my ( $prompt, $default ) = @_; + print $prompt, substr( $default, 0, 1 ), "\b"; + ReadMode 4; + my $r = ReadKey(0); + ReadMode 0; + if ( $r eq "\n" ) { $r = $default } + else { $r .= substr( $default, 1 ) } print $r; return $r; }