Branch merge.
authorMahlon E. Smith <mahlon@laika.com>
Mon, 11 Aug 2014 11:25:33 -0700
changeset 71 b5adcd83b152
parent 70 feb78b7417ee (diff)
parent 66 5a0c99ca0c0d (current diff)
child 72 39e9f802eb40
Branch merge.
.hgtags
shelldap
--- a/.hgsigs	Mon Jun 23 08:17:18 2014 -0700
+++ b/.hgsigs	Mon Aug 11 11:25:33 2014 -0700
@@ -1,1 +1,2 @@
 5de7014b0e608e3e95ce8d48125b18d8d8ef3b2c 0 iD8DBQBRSPZ01bsjBDapbeMRAhQLAKCNbDa6gxBJTz2AsyV6A8trw+BrrQCcDUrEWbabfbuYBX3U3cLltIZGsys=
+b220dc77493703900627d6cb556728217fe40fe1 0 iD8DBQBT6Qk91bsjBDapbeMRAmXLAKCgAyR+SeXy1q91mAnyv3P0OM6rBwCfaVuVRsGEFd2e7uJiNpUvyIFqm2g=
--- a/.hgtags	Mon Jun 23 08:17:18 2014 -0700
+++ b/.hgtags	Mon Aug 11 11:25:33 2014 -0700
@@ -7,3 +7,4 @@
 0cc20d93ff50438fcb3fec864474b3cab492dd1a 1.0.1
 94b64bbf93cfdfaf0ee68c54cd60bd85865fcb47 1.0.2
 e1728adb2561a87a3ab10e57ae4b3140abf4b5cf 1.1.0
+1a480ba231b6ef7714a08151434b7773a1851936 1.2.0
--- a/CONTRIBUTORS	Mon Jun 23 08:17:18 2014 -0700
+++ b/CONTRIBUTORS	Mon Aug 11 11:25:33 2014 -0700
@@ -1,11 +1,13 @@
 Adam Spiers <adam@spiers.net>
 Alexander Perlis <aperlis@math.lsu.edu>
+Dennis Kaarsemaker <dennis.kaarsemaker@booking.com>
 Emile "iMil" Heitor <imil@home.imil.net>
 Gertjan Halkes <shelldap@ghalkes.nl>
 Giacomo Tenaglia <Giacomo.Tenaglia@cern.ch>
 Jonathan Rozes <jonathan@laika.com>
 Josef Wells <Josefwells@alumni.utexas.net>
 Landry Breuil <landry@cvs.openbsd.org>
+Lars Täuber <taeuber@bbaw.de>
 Michael Granger <ged@faeriemud.org>
 Michael Raitza <spacefrogg-devel@meterriblecrew.net>
 Mike Hix <m@hix.io>
@@ -14,3 +16,4 @@
 Rong-En Fan <rafan@FreeBSD.org>
 Salvatore Bonaccorso <carnil@debian.org>
 Yann Cezard <yann.cezard@univ-pau.fr>
+
--- a/shelldap	Mon Jun 23 08:17:18 2014 -0700
+++ b/shelldap	Mon Aug 11 11:25:33 2014 -0700
@@ -293,10 +293,12 @@
 =item B<delete>
 
 Remove an entry from the directory.  Globbing is supported.
-All deletes are sanity-prompted.
+All deletes are sanity-prompted.  The -v flag prints the entries out
+for review before delete.
 
     delete uid=mahlon
     delete uid=ma*
+    rm -v uid=mahlon,ou=People,dc=example,o=company l=office
 
 aliased to: rm
 
@@ -402,6 +404,8 @@
 Show current auth credentials.  Unless you specified a binddn, this
 will just show an anonymous bind.
 
+aliased to: id
+
 =back
 
 =head1 TODO
@@ -653,7 +657,7 @@
 	if ( $use_temp ) {
 		my ( undef, $fname ) =
 		  File::Temp::tempfile( 'shelldap_XXXXXXXX', SUFFIX => '.ldif', DIR => '/tmp', UNLINK => 1 );
-		$self->{'ldif'}	      = Net::LDAP::LDIF->new( $fname, 'w', sort => 1, wrap => $self->wrapsize );
+		$self->{'ldif'}	      = Net::LDAP::LDIF->new( $fname, 'w', sort => 1, wrap => 0 );
 		$self->{'ldif_fname'} = $fname;
 	}
 
@@ -1452,31 +1456,76 @@
 sub run_delete
 {
 	my $self = shift;
-	my @DNs  = @_;
-
-	unless ( scalar @DNs ) {
+	my @args  = @_;
+	my @matches;
+	my $s;
+	my $verbose;
+
+	unless ( scalar @args ) {
 		print "No dn specified.\n";
 		return;
 	}
 
-	my $filter;
-	unless ( $DNs[0] eq '*' ) {
-		$filter = $self->make_filter( \@DNs ) or return;
+	# Flags.
+	#
+	if ( $args[0] =~ /^\-v/ ) {
+		$verbose = 1;
+		shift @args;
 	}
-
-	my $s = $self->search({ scope => 'one', filter => $filter });
-	unless ( $s->{'code'} == LDAP_SUCCESS ) {
-		print "$s->{'message'}\n";
+	
+	# Separate real args from filter arguments.
+	#
+	foreach my $dn ( @args ) {
+		if ( $dn eq '*' ) {
+			$s = $self->search({ scope => 'one' });
+			map { push @matches, $_ } @{ $s->{'entries'} } if $s->{'code'} == LDAP_SUCCESS;
+		}
+
+		# Search by filter
+		#
+		else {
+
+			my $filter = $self->make_filter( [$dn] ) or next;
+			$s = $self->search({ scope => 'one', filter => $filter });
+			if ( scalar @{$s->{'entries'}} != 0 ) {
+				map { push @matches, $_ } @{ $s->{'entries'} } if $s->{'code'} == LDAP_SUCCESS;
+			}
+
+			# Search by exact DN.
+			#
+			else {
+				$dn = $self->path_to_dn( $dn );
+				$s = $self->search({ base => $dn, vals => 0 });
+				my $e = ${ $s->{'entries'} }[0];
+				push @matches, $e if $s->{'code'} == LDAP_SUCCESS;
+			}
+		}
+	}
+
+	# Unique the matchset for a consistent count, keyed by DN.
+	#
+	my @uniq_matches = keys %{{ map { $_->dn => 1 } @matches }};
+
+	my $mcount = scalar @uniq_matches;
+	if ( $mcount == 0 ) {
+		print "Nothing matched.\n";
 		return;
 	}
 
-	print "Are you sure? [Ny]: ";
+	if ( $verbose ) {
+		print "* $_\n" foreach @uniq_matches;
+	}
+
+	print "About to remove $mcount item(s).  Are you sure? [Ny]: ";
 	chomp( my $resp = <STDIN> );
 	return unless $resp =~ /^y/i;
-   
-	foreach my $e ( @{ $s->{'entries'} } ) {
+
+	my %seen;
+	foreach my $e ( @matches ) {
 		my $dn = $e->dn();
+		next if $seen{ $dn };
 		my $rv = $self->ldap->delete( $dn );
+		$seen{ $dn }++;
 		print "$dn: ", $rv->error(), "\n";
 	}
    
@@ -2202,7 +2251,7 @@
 use warnings;
 
 $0 = 'shelldap';
-my $VERSION = '1.1.1';
+my $VERSION = '1.2.0';
 
 use Getopt::Long;
 use YAML::Syck;