193 cat uid=mahlon,ou=People,dc=example,o=company |
193 cat uid=mahlon,ou=People,dc=example,o=company |
194 cat uid=mahlon + userPassword |
194 cat uid=mahlon + userPassword |
195 |
195 |
196 =item B< cd> |
196 =item B< cd> |
197 |
197 |
198 Change DN. Translated to LDAP, this changes the current basedn. |
198 Change directory. Translated to LDAP, this changes the current basedn. |
199 All commands after a 'cd' operate within the new basedn. |
199 All commands after a 'cd' operate within the new basedn. |
200 |
200 |
201 cd change to 'home' basedn |
201 cd change to 'home' basedn |
202 cd ~ same thing |
202 cd ~ change to the binddn, or basedn if anonymously bound |
203 cd - change to previous node |
203 cd - change to previous node |
204 cd ou=People change to explicit path below current node |
204 cd ou=People change to explicit path below current node |
205 cd .. change to parent node |
205 cd .. change to parent node |
206 cd ..,..,ou=Groups change to node ou=Groups, which is a sibling |
206 cd ../../ou=Groups change to node ou=Groups, which is a sibling |
207 to the current node's parent node |
207 to the current node's grandparent |
208 |
208 |
209 Since LDAP doesn't actually limit what can be a container object, you |
209 Since LDAP doesn't actually limit what can be a container object, you |
210 can actually cd into any entry. Many commands then work on '.', meaning |
210 can actually cd into any entry. Many commands then work on '.', meaning |
211 "wherever I currently am." |
211 "wherever I currently am." |
212 |
212 |
731 |
731 |
732 $self->{'cwd_entries'} = $cache->{'entries'}; |
732 $self->{'cwd_entries'} = $cache->{'entries'}; |
733 return; |
733 return; |
734 } |
734 } |
735 |
735 |
736 # convert a given path to a DN: deal with '..', '.', '~' |
736 # convert a given path to a DN: deal with '..', '.' |
737 # Synopsis: $dn = $self->path_to_dn($path, [relative => N]); |
737 # Synopsis: $dn = $self->path_to_dn( $path ); |
738 sub path_to_dn |
738 sub path_to_dn |
739 { |
739 { |
740 my $self = shift; |
740 my $self = shift; |
741 my $path = shift; |
741 my $path = shift; |
742 my %flags = @_; |
742 my %flags = @_; |
743 my $base = $self->base(); |
743 my $curbase = $self->base(); |
744 |
|
745 # fail on wrong / missing parameter |
|
746 return undef if (!defined($path)); |
|
747 |
|
748 # return configured base DN |
|
749 return($conf->{basedn}) if ($path eq '~'); |
|
750 |
744 |
751 # return current base DN |
745 # return current base DN |
752 return($base) if ($path eq '.'); |
746 return $curbase if $path eq '.'; |
753 |
747 |
754 if ($path =~ /^\.\./o) { # relative path |
748 # support 'cd -' |
|
749 return $self->{'previous_base'} if $path eq '-'; |
|
750 |
|
751 # support empty 'cd' or 'cd ~' going to root |
|
752 return $conf->{'basedn'} if $path eq '~' || ! $path; |
|
753 |
|
754 # relative path, upwards |
|
755 # |
|
756 if ( $path =~ /^\.\./o ) { |
755 # support '..' (possibly iterated and as prefix to a DN) |
757 # support '..' (possibly iterated and as prefix to a DN) |
756 my @base = @{ldap_explode_dn($base, casefold => 'none')}; |
758 my @base = @{ ldap_explode_dn($curbase, casefold => 'none') }; |
757 |
759 |
758 # deal with leading .., |
760 # deal with leading .., |
759 while ($path =~ /^\.\./) { |
761 while ( $path =~ /^\.\./ ) { |
760 shift(@base) if (@base); |
762 shift( @base ) if @base; |
761 $path =~ s/^\.\.//; |
763 $path =~ s/^\.\.//; |
762 last if ($path !~ /,\s*/); |
764 last if $path !~ /[,\/]\s*/; |
763 $path =~ s/,\s*//; |
765 $path =~ s/[,\/]\s*//; |
764 } |
766 } |
765 |
767 |
766 # build a new absolute DN |
768 # append the new dn to the node if one was specified: |
767 $path .= ',' . canonical_dn(\@base, casefold => 'none') |
769 # cd ../../cn=somewhere vs |
768 if (@base); |
770 # cd ../../ |
769 } |
771 # |
770 elsif ($path =~ /,\s*~$/o) { # absolute path |
772 my $newbase_root = canonical_dn( \@base, casefold => 'none' ); |
771 $path =~ s/,\s*~$//; |
773 $path = $path ? $path . ',' . $newbase_root : $newbase_root; |
772 $path.= ','.$conf->{basedn} |
774 } |
773 if ($conf->{basedn}); |
775 |
774 } |
776 # attach the base if it isn't already there (this takes care of |
775 else { # relative or absolute path |
777 # deeper relative nodes and absolutes) |
776 $path.= ','.$conf->{basedn} |
778 # |
777 if ($conf->{basedn} && $flags{relative}); |
779 else { |
778 } |
780 $path = "$path," . $curbase unless $path =~ /$curbase/; |
779 |
781 } |
780 return($path); |
782 |
|
783 return $path; |
781 } |
784 } |
782 |
785 |
783 # given an array ref of shell-like globs, |
786 # given an array ref of shell-like globs, |
784 # make and return an LDAP filter object. |
787 # make and return an LDAP filter object. |
785 # |
788 # |
1007 |
1010 |
1008 sub run_cd |
1011 sub run_cd |
1009 { |
1012 { |
1010 my $self = shift; |
1013 my $self = shift; |
1011 my $newbase = join ' ', @_; |
1014 my $newbase = join ' ', @_; |
1012 |
|
1013 # support 'cd' going to root |
|
1014 $newbase ||= $conf->{'basedn'}; |
|
1015 |
|
1016 # support 'cd -' |
|
1017 if ( $newbase eq '-' ) { |
|
1018 $newbase = $self->{'previous_base'} || return; |
|
1019 } |
|
1020 |
1015 |
1021 # convert given path to a DN |
1016 # convert given path to a DN |
1022 $newbase = $self->path_to_dn($newbase, relative => 1); |
1017 $newbase = $self->path_to_dn( $newbase ); |
1023 |
1018 |
1024 unless ( $self->is_valid_dn( $newbase ) ) { |
1019 unless ( $self->is_valid_dn( $newbase ) ) { |
1025 print "No such object\n"; |
1020 print "No such object\n"; |
1026 return; |
1021 return; |
1027 } |
1022 } |
1028 |
1023 |
1065 print "No destination dn provided.\n"; |
1060 print "No destination dn provided.\n"; |
1066 return; |
1061 return; |
1067 } |
1062 } |
1068 |
1063 |
1069 # convert given source path to DN |
1064 # convert given source path to DN |
1070 $s_dn = $self->path_to_dn($s_dn, relative => 1); |
1065 $s_dn = $self->path_to_dn( $s_dn ); |
1071 |
1066 |
1072 my $s = $self->search({ base => $s_dn, vals => 1 }); |
1067 my $s = $self->search({ base => $s_dn, vals => 1 }); |
1073 unless ( $s->{'code'} == LDAP_SUCCESS ) { |
1068 unless ( $s->{'code'} == LDAP_SUCCESS ) { |
1074 print "No such object\n"; |
1069 print "No such object\n"; |
1075 return; |
1070 return; |
1572 print "No 'directory' provided.\n"; |
1568 print "No 'directory' provided.\n"; |
1573 return; |
1569 return; |
1574 } |
1570 } |
1575 |
1571 |
1576 # convert given path to DN |
1572 # convert given path to DN |
1577 $dir = $self->path_to_dn($dir, relative => 1); |
1573 $dir = $self->path_to_dn( $dir ); |
1578 |
1574 |
1579 # normalize name, if it is not yet a legal DN |
1575 # normalize name, if it is not yet a legal DN |
1580 $dir = 'ou='.$dir if (!canonical_dn($dir)); |
1576 $dir = 'ou='.$dir if (!canonical_dn($dir)); |
1581 |
1577 |
1582 # get RDN: naming attributes (lower-case) and their values |
1578 # get RDN: naming attributes (lower-case) and their values |
1664 print "Sorry, password changes not supported by LDAP server.\n"; |
1660 print "Sorry, password changes not supported by LDAP server.\n"; |
1665 return; |
1661 return; |
1666 } |
1662 } |
1667 |
1663 |
1668 # convert given path to DN |
1664 # convert given path to DN |
1669 $self->path_to_dn($dn, relative => 1); |
1665 $self->path_to_dn( $dn ); |
1670 |
1666 |
1671 my $s = $self->search( { base => $dn, scope => 'base' } ); |
1667 my $s = $self->search( { base => $dn, scope => 'base' } ); |
1672 if ( $s->{'code'} ) { |
1668 if ( $s->{'code'} ) { |
1673 print $s->{'message'}, "\n"; |
1669 print $s->{'message'}, "\n"; |
1674 return; |
1670 return; |