#!/usr/bin/perl # # # Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # - Neither the name of Sun Microsystems nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ######################################################################### # # This script reads a LDIF with entries and drills down the levels. # Prints the entries of a particular level if -l option is provided, else # prints all the entries starting at Level 1. # Also available -b option to specify the base DN. Useful to print only a # sub tree. # # Prints only dn of the entry if -d option is used. # # Author: Srikanth Konjarla, Sun Microsystems # # Date: April 16, 2006 - First Cut # # Script comes with no warrarny and not supported. # Use this script at your own discretion. # sub usage { print "This script reads a LDIF with entries and drills down the levels.\n"; print "Prints the entries of a particular level if -l option is provided, else\n"; print "prints all the entries starting at Level 1.\n"; print "Also available -b option to specify the base DN. Useful to print only a\n"; print "specific branch. To exclude a branch from printing, use -B option\n"; print "\n"; print "Prints only dn of the entry if -d option is used\n"; print "\n"; print "usage: $0 [-lbBd] \n"; print "-b: Base DN to include\n"; print "-B: Base DN to exclude\n"; print "-d: Print dn lines only\n"; print "-l: Level of the tree.\n"; exit 1; } sub procline { my ($line) = $_[0]; if ($line =~ /^dn:/) { $line =~ s/\s+\,/,/g; $line =~ s/\,\s+/,/g; $line =~ s/\s+=/=/g; $line =~ s/=\s+/=/g; $dnkey = $line; } else { if ( ($line =~ /(.+?):\s(.+)$/) && defined($dnkey) ){ push @{$entry{$dnkey}}, $line; } } } use Getopt::Std; getopts("dB:b:l:") or die usage; usage unless @ARGV; #$rootsuffix = $opt_b; $rootsuffix = defined($opt_b) ? $opt_b : $opt_B; $rootsuffix =~ s/\s+\,/,/g; $rootsuffix =~ s/\,\s+/,/g; $rootsuffix =~ s/\s+=/=/g; $rootsuffix =~ s/=\s+/=/g; $level = $opt_l; # Read the file and build hash. while (<>) { chomp; s/\cM//; # Remove the ^M. next if (/^#/); # Ignore comments. if (/^$/) { if (defined($line)) { procline($line); } undef $line; undef $dnkey; } elsif (/^\s(.+)$/) { $line .= $1; } else { if (defined($line)) { procline($line); } $line = $_; } } @sortedlines = sort keys %entry; #print "$rootsuffix\n"; foreach $dn (@sortedlines) { # Check if -B option is used. if ($opt_B) { #next if ( $dn =~ /\Q$rootsuffix\E$/i ); next if ( $dn =~ /\Q$opt_B\E$/i ); } else { next unless ( $dn =~ /\Q$rootsuffix\E$/i ); } $dnorig = $dn; $dn =~ s/^dn: //g; $dn =~ s/\Q$rootsuffix\E/therootsuffix/gi; $components = split /\,/,$dn; # Build hash of DNs with branch level as key. if (defined($levels{$components})) { push @{$levels{$components}}, $dnorig; } else { $levels{$components} = [ $dnorig ]; } } # Check if "-l" option is set. # If yes, print only those entries # Otherwise, print everything. if ($opt_l) { print "#Level: $opt_l\n"; #print @{$levels{$opt_l}}; foreach $entrydn (@{$levels{$opt_l}}) { print "$entrydn\n"; unless ($opt_d) { foreach $attr (@{$entry{$entrydn}}) { print "$attr\n"; } print "\n"; } } $entrydn = undef; $attr = undef; } else { foreach $level (sort { $a <=> $b } keys %levels) { #foreach $level (keys %levels) { print "#Level: $level\n"; @sortedlevels = sort {length $a cmp length $b} @{$levels{$level}}; #@sortedlevels = @{$levels{$level}}; #print @sortedlevels; foreach $entrydn (@sortedlevels) { print "$entrydn\n"; unless ($opt_d) { foreach $attr (@{$entry{$entrydn}}) { print "$attr\n"; } print "\n"; } } } } =head1 NAME ldifpart =head1 DESCRIPTION This script reads a LDIF file and prints the levels of LDAP tree. =head1 USAGE ldifpart [-lbBd] Without any option it will print the entries at each level. A dn "ou=people,o=example.com" is considered as two level -b: Base DN to include. This would instruct the script to set this as level 1. -B: Base DN to exclude. This option would exclude all the entries at this level and below. -d: Print dn lines only. Prints only dn line instead of the whole entry. -l: Level of the tree. Print only this particular level of the tree. =head1 NOTES This script is intended to be used as a tool to manipulate big LDIF files. Also, to perform offline work on the LDIF data. =head1 AUTHOR Srikanth Konjarla, Sun Microsystems April 16, 2006 =cut