cd: flexible treatment of repeated '..', even as prefix
authorPeter Marschall <peter@adpm.de>
Sat, 05 Mar 2011 20:19:18 +0100
changeset 24 3a8ae9117981
parent 23 2ab2df609cc7
child 25 77fd303f1a28
cd: flexible treatment of repeated '..', even as prefix Treat '..' as any shell does: - while the path given starts with '..', strip away the first element of the current base DN - use ',' as separator - if anything remains in thep ath given, prepend it to the stripped down baseDN - use the result as the new base DN
shelldap
--- a/shelldap	Tue Sep 06 15:59:10 2011 -0700
+++ b/shelldap	Sat Mar 05 20:19:18 2011 +0100
@@ -195,14 +195,16 @@
 
 =item B<  cd>
 
-Change directory.  Translated to LDAP, this changes the current basedn.
+Change DN.  Translated to LDAP, this changes the current basedn.
 All commands after a 'cd' operate within the new basedn.
 
-    cd                cd to 'home' basedn
+    cd                change to 'home' basedn
     cd ~              same thing
-    cd -              cd to previous directory
-    cd ou=People      cd to explicit path
-    cd ..             cd to parent node
+    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
 
 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
@@ -347,9 +349,6 @@
 For now, it only makes sense to connect to a master if you plan on doing
 any writes.
 
-"cd ../ou=SomewhereElse" doesn't work, but "cd ../../" does.  This is
-weird, as both should probably work.
-
 =head1 BUGS / LIMITATIONS
 
 There is no support for editing binary data.  If you need to edit base64
@@ -368,7 +367,7 @@
 use Term::Shell;
 use Digest::MD5;
 use Net::LDAP qw(LDAP_SUCCESS LDAP_SERVER_DOWN);
-use Net::LDAP::Util qw(canonical_dn);
+use Net::LDAP::Util qw(canonical_dn ldap_explode_dn);
 use Net::LDAP::LDIF;
 use Data::Dumper;
 use File::Temp;
@@ -990,9 +989,21 @@
 		$newbase = $self->{'previous_base'} || return;
 	}
 
-	# support '..'
-	if ( $newbase =~ /\.\./ ) {
-		$self->parent_dn( \$newbase );
+	# support '..' (possibly iterated and as prefix to a DN)
+	if ( $newbase =~ /^\.\.,?/ ) {
+		my @curbase = @{ldap_explode_dn($self->base(), casefold => 'none')};
+
+		# deal with leading ..,
+		while ($newbase =~ /^\.\./) {
+			shift(@curbase)  if (@curbase);
+			$newbase =~ s/^\.\.//;
+			last  if ($newbase !~ /,\s*/);
+			$newbase =~ s/,\s*//;
+		}
+
+		# build a new absolute DN
+		$newbase .= ',' . canonical_dn(\@curbase, casefold => 'none')
+			if (@curbase);
 	}
 	else {
 		$self->rdn_to_dn( \$newbase );