# HG changeset patch # User Mahlon E. Smith # Date 1315350211 25200 # Node ID 057fefab56b040aa8e6242fddfefb5607b90fed1 # Parent 95dbffcc757b649574f4b40705afd7c4a336b69e Repair broken path behavior, remove unneeded #path_to_dn 'relative' flag. diff -r 95dbffcc757b -r 057fefab56b0 shelldap --- a/shelldap Sun Mar 06 20:51:08 2011 +0100 +++ b/shelldap Tue Sep 06 16:03:31 2011 -0700 @@ -195,16 +195,16 @@ =item B< cd> -Change DN. Translated to LDAP, this changes the current basedn. +Change directory. Translated to LDAP, this changes the current basedn. All commands after a 'cd' operate within the new basedn. - cd change to 'home' basedn - cd ~ same thing - cd - change to previous node - cd ou=People change to explicit path below current node - cd .. change to parent node - cd ..,..,ou=Groups change to node ou=Groups, which is a sibling - to the current node's parent node + cd change to 'home' basedn + cd ~ change to the binddn, or basedn if anonymously bound + cd - change to previous node + cd ou=People change to explicit path below current node + cd .. change to parent node + cd ../../ou=Groups change to node ou=Groups, which is a sibling + to the current node's grandparent Since LDAP doesn't actually limit what can be a container object, you can actually cd into any entry. Many commands then work on '.', meaning @@ -372,8 +372,8 @@ use Term::ReadKey; use Term::Shell; use Digest::MD5; -use Net::LDAP qw(LDAP_SUCCESS LDAP_SERVER_DOWN); -use Net::LDAP::Util qw(canonical_dn ldap_explode_dn); +use Net::LDAP qw/ LDAP_SUCCESS LDAP_SERVER_DOWN /; +use Net::LDAP::Util qw/ canonical_dn ldap_explode_dn /; use Net::LDAP::LDIF; use Data::Dumper; use File::Temp; @@ -733,51 +733,54 @@ return; } -# convert a given path to a DN: deal with '..', '.', '~' -# Synopsis: $dn = $self->path_to_dn($path, [relative => N]); +# convert a given path to a DN: deal with '..', '.' +# Synopsis: $dn = $self->path_to_dn( $path ); sub path_to_dn { - my $self = shift; - my $path = shift; - my %flags = @_; - my $base = $self->base(); - - # fail on wrong / missing parameter - return undef if (!defined($path)); - - # return configured base DN - return($conf->{basedn}) if ($path eq '~'); + my $self = shift; + my $path = shift; + my %flags = @_; + my $curbase = $self->base(); # return current base DN - return($base) if ($path eq '.'); + return $curbase if $path eq '.'; + + # support 'cd -' + return $self->{'previous_base'} if $path eq '-'; - if ($path =~ /^\.\./o) { # relative path + # support empty 'cd' or 'cd ~' going to root + return $conf->{'basedn'} if $path eq '~' || ! $path; + + # relative path, upwards + # + if ( $path =~ /^\.\./o ) { # support '..' (possibly iterated and as prefix to a DN) - my @base = @{ldap_explode_dn($base, casefold => 'none')}; + my @base = @{ ldap_explode_dn($curbase, casefold => 'none') }; # deal with leading .., - while ($path =~ /^\.\./) { - shift(@base) if (@base); + while ( $path =~ /^\.\./ ) { + shift( @base ) if @base; $path =~ s/^\.\.//; - last if ($path !~ /,\s*/); - $path =~ s/,\s*//; + last if $path !~ /[,\/]\s*/; + $path =~ s/[,\/]\s*//; } - # build a new absolute DN - $path .= ',' . canonical_dn(\@base, casefold => 'none') - if (@base); - } - elsif ($path =~ /,\s*~$/o) { # absolute path - $path =~ s/,\s*~$//; - $path.= ','.$conf->{basedn} - if ($conf->{basedn}); - } - else { # relative or absolute path - $path.= ','.$conf->{basedn} - if ($conf->{basedn} && $flags{relative}); + # append the new dn to the node if one was specified: + # cd ../../cn=somewhere vs + # cd ../../ + # + my $newbase_root = canonical_dn( \@base, casefold => 'none' ); + $path = $path ? $path . ',' . $newbase_root : $newbase_root; } - return($path); + # attach the base if it isn't already there (this takes care of + # deeper relative nodes and absolutes) + # + else { + $path = "$path," . $curbase unless $path =~ /$curbase/; + } + + return $path; } # given an array ref of shell-like globs, @@ -985,7 +988,7 @@ } else { # convert given path to DN - $dn = $self->path_to_dn($dn, relative => 1); + $dn = $self->path_to_dn( $dn ); $s = $self->search({ base => $dn, vals => 1, @@ -1009,18 +1012,10 @@ { my $self = shift; my $newbase = join ' ', @_; - - # support 'cd' going to root - $newbase ||= $conf->{'basedn'}; - - # support 'cd -' - if ( $newbase eq '-' ) { - $newbase = $self->{'previous_base'} || return; - } # convert given path to a DN - $newbase = $self->path_to_dn($newbase, relative => 1); - + $newbase = $self->path_to_dn( $newbase ); + unless ( $self->is_valid_dn( $newbase ) ) { print "No such object\n"; return; @@ -1067,7 +1062,7 @@ } # convert given source path to DN - $s_dn = $self->path_to_dn($s_dn, relative => 1); + $s_dn = $self->path_to_dn( $s_dn ); my $s = $self->search({ base => $s_dn, vals => 1 }); unless ( $s->{'code'} == LDAP_SUCCESS ) { @@ -1236,7 +1231,7 @@ } # convert given path to DN - $dn = $self->path_to_dn($dn, relative => 1); + $dn = $self->path_to_dn( $dn ); my $s = $self->search({ base => $dn, vals => 1 }); @@ -1398,8 +1393,9 @@ print "No search base specified.\n"; return; } + # convert base path to DN - $base = $self->path_to_dn($base, relative => 1); + $base = $self->path_to_dn( $base ); $self->debug("Filter parsed as: " . $filter->as_string() . "\n"); @@ -1574,7 +1570,7 @@ } # convert given path to DN - $dir = $self->path_to_dn($dir, relative => 1); + $dir = $self->path_to_dn( $dir ); # normalize name, if it is not yet a legal DN $dir = 'ou='.$dir if (!canonical_dn($dir)); @@ -1625,7 +1621,7 @@ } # convert given source path to DN - $s_dn = $self->path_to_dn($s_dn, relative => 1); + $s_dn = $self->path_to_dn( $s_dn ); unless ( $self->is_valid_dn( $s_dn ) ) { print "No such object\n"; @@ -1666,7 +1662,7 @@ } # convert given path to DN - $self->path_to_dn($dn, relative => 1); + $self->path_to_dn( $dn ); my $s = $self->search( { base => $dn, scope => 'base' } ); if ( $s->{'code'} ) {