csarid has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks!
I am able to use the following code from ldap.perl.org with user a filter to pull out a directory record. However, I am wondering if there is a more clean way to supress printing all the fields for the record found except for specific ones; such as, say "givenname" or "department" for instance. I could throw the result into an array and massage it from there but wanted to see if anyone had any suggestions on doing this through some better method. Basically, taking advantage of some obscure feature(at least obscure to me anyway). Something like calling an object and using it in the foreach loop which prints the "$value" variable.
Thanks very much,
csarid
use Net::LDAP; $ldap = Net::LDAP->new('ldap.acme.com') or die "$@"; $mesg = $ldap->search( base => "o=acme.com", scope => 'sub', filter => "sn=smith", ); # # At this point the user can get the returned data as an array # or as a stack. # In this example we will use an array # How many entries were returned from the search my $max = $mesg->count; for( my $index = 0 ; $index < $max ; $index++) { my $entry = $mesg->entry($index); my $dn = $entry->dn; # Obtain DN of this entry @attrs = $entry->attributes; # Obtain attributes for this entry. foreach my $var (@attrs) { #get a list of values for a given attribute $attr = $entry->get_value( $var, asref => 1 ); if ( defined($attr) ) { foreach my $value ( @$attr ) { print "$var: $value\n"; # Print each value for the attribut +e. } } + } }

Replies are listed 'Best First'.
Re: ldap search question
by salva (Canon) on Jul 21, 2009 at 06:16 UTC
    The LDAP protocol allows to specify a subset of attributes to retrieve in the search method.

    Net::LDAP supports that feature via the attrs parameter. For instance:

    $mesg = $ldap->search( base => "o=acme.com", scope => 'sub', filter => "sn=smith", attrs => [qw(sn givenName department)] );
Re: ldap search question
by spazm (Monk) on Jul 21, 2009 at 05:01 UTC
    Do you want to limit by $var ( element of @attrs) or by $value (element of @$attr)?

    Here is an example with 3 extra lines compare to yours that only prints givenname and department, assuming that those are of the latter form, limiting to values of $value

    # configuration: Put the fields you want here. my @fields_i_want_to_see= qw(givenname department); my %show_field = map { $_ => 1 } @fields_i_want_to_see; use Net::LDAP; $ldap = Net::LDAP->new('ldap.acme.com') or die "$@"; $mesg = $ldap->search( base => "o=acme.com", scope => 'sub', filter => "sn=smith", ); # # At this point the user can get the returned data # as an array or as a stack. # In this example we will use an array # How many entries were returned from the search my $max = $mesg->count; for( my $index = 0 ; $index < $max ; $index++) { my $entry = $mesg->entry($index); my $dn = $entry->dn; # Obtain DN of this entry @attrs = $entry->attributes; # Obtain attributes for this entry. foreach my $var (@attrs) { #get a list of values for a given attribute $attr = $entry->get_value( $var, asref => 1 ); if ( defined($attr) ) { foreach my $value ( @$attr ) { print "$var: $value\n" if $show_field{$var};# Print each val +ue for the attribute. } } + } }
      spazm,

      Thanks very much for the very useful lines you added. This is exactly what I was looking for, but did not know how to formulate. This is very clean and very efficient for my needs.

      Also, thanks to all who reaponded, I appreciate your answers as well.

      Thanks again for all the help everyone!

      Now that I can pull the givenname and department, if I were to want to pull a list of "sn" in my search criteria(such as "smith, jones, peters"), the print statement which checks if the values are one of "surname or department" would continously print all values for "smith, jones, and peters".

      I my case I would like to generate a list I can then be parsed pulling the "surname and deapartment" to do something with this.
      For example:

      currently it would print:
      "SmithY100JonesZ300PetersXL200"

      What I would like to be able to do is have an output like: "SmithY100:JonesZ300:PetersXL200"

      Being able to group the information for each name/department. I can throw this into a messy array, but I'm hoping there some suggestions I can learn from and do this more efficiently.

      # configuration: Put the fields you want here. my @fields_i_want_to_see= qw(givenname department); my %show_field = map { $_ => 1 } @fields_i_want_to_see; use Net::LDAP; $ldap = Net::LDAP->new('ldap.acme.com') or die "$@"; $mesg = $ldap->search( base => "o=acme.com", scope => 'sub', filter => "sn=smith", ); # # At this point the user can get the returned data # as an array or as a stack. # In this example we will use an array # How many entries were returned from the search my $max = $mesg->count; for( my $index = 0 ; $index < $max ; $index++) { my $entry = $mesg->entry($index); my $dn = $entry->dn; # Obtain DN of this entry @attrs = $entry->attributes; # Obtain attributes for this entry. foreach my $var (@attrs) { #get a list of values for a given attribute $attr = $entry->get_value( $var, asref => 1 ); if ( defined($attr) ) { foreach my $value ( @$attr ) { # I'd like to be able to check when the we're past the last +entry we're looking for, for each "smith, jones, and peters" + print "$var: $value\n" if $show_field{$var};# Print each val +ue for the attribute. } } + } }
Re: ldap search question
by NetWallah (Canon) on Jul 21, 2009 at 05:52 UTC
    I wrote some code for a similar purpose - this one provides a web-based form for query, and can be run as a CGI script.

         Potentia vobiscum ! (Si hoc legere scis nimium eruditionis habes)

Re: ldap search question
by nif (Sexton) on Jul 22, 2009 at 09:49 UTC
    I prefer using "as_struct" method to place all search results in one perl structure. Like this
    #!/usr/bin/perl -w use strict; use English; use Data::Dumper; use Net::LDAP; my $ldap = Net::LDAP->new("ldap://ldapserver.company.com") or die "$EV +AL_ERROR"; my $mesg = $ldap->search( base => "ou=people,dc=company,dc=com", scope => "sub", filter => "cn=oracle*", ); my $struct = $mesg->as_struct; print Dumper( $struct );
    So the output will be something like:
    $VAR1 = { 'uid=oracle8,ou=people,dc=fresenius,dc=de' => { 'gidnumber' => [ '4019' ], 'objectclass' => [ 'shadowAccount', 'posixAccount', 'account', 'top' ], 'loginshell' => [ '/bin/sh' ], 'uid' => [ 'oracle8' ], 'homedirectory' => [ '/home/oracle8' ], 'cn' => [ 'oracle8' ], 'uidnumber' => [ '3355' ], 'gecos' => [ 'Oracle8 user account' ] }, 'uid=oracle7,ou=people,dc=fresenius,dc=de' => { 'gidnumber' => [ '4019' ], 'objectclass' => [ 'shadowAccount', 'posixAccount', 'account', 'top' ], 'loginshell' => [ '/bin/sh' ], 'uid' => [ 'oracle7' ], 'homedirectory' => [ '/home/oracle7' ], 'cn' => [ 'oracle7' ], 'uidnumber' => [ '4022' ], 'gecos' => [ 'Oracle7 user account' ] }, 'uid=oracle,ou=people,dc=fresenius,dc=de' => { 'gidnumber' => [ '206' ], 'loginshell' => [ '/bin/bash' ], 'objectclass' => [ 'shadowAccount', 'posixAccount', 'account', 'top' ], 'uid' => [ 'oracle' ], 'homedirectory' => [ '/home/oracle' ], 'cn' => [ 'oracle' ], 'uidnumber' => [ '4267' ], 'gecos' => [ 'oracle db admin' ] } };
    Note that attribute values in this perl structure are always represented as ARRAY references, even though that most have only single value assigned.