Contributed by 
Russell Biggs	(Rusty)	<r-biggs@ti.com>

   The following examples are of course PERL code, found to work
 with the NET::LDAP modules.

   To get into the same state of mind that I was in when I built
 and successfully tested each of these, you need to read the following 
 Reference point.


 + + + + + + + + + 
 Reference Point:

 I'm building a series of scripts that work independantly
 (example: WEB cgi) and so I want to build a common set of LDAP utilities
 that I can use via a 'require' statement in all the other files.

 example:  'require ldaputils.pl'

 I set up my subroutines found in this file such that the each routine
 handles the data passed to it, makes the appropriate LDAP call, checks and 
 records any errors, then returns the result if any.

 I leave the creation of the data and/or data scructures to the calling
 programs.... and of course this is where the difficulty arrises. :) 

 + + + + + + + + +

# each of the following example sections will contain code 
# showing the creation of the data scructure then a bit of code
# showing the subroutine.

#######################################
#######################################
#
#  
   use Net::LDAP qw(:all);

#
#  for obvious reason's you'll have to change these
#  two call to fit your needs.
#

  $ldap = Net::LDAP->new("$myhost") or die "$@";
  $mesg = $ldap->bind("$admin",
                        password => "$passwd",
                        version => 3 );


#######################################
#######################################
#######################################
#
#   Displaying Search results 
#

  my @Attrs = ();
  my $result = LDAPsearch($ldap,"sn=*",\@Attrs);


     #------------
     # as_struct  method
     #
        my $href = $result->as_struct; 

        # get an array of the DN names 
        my @arrayOfDNs  = keys %$href ;        # use DN hashes

        # process each DN using it as a key
        foreach (@arrayOfDNs) {
           print $_,"\n";
           my $valref = $$href{$_};

           # get an array of the attribute names
           # passed for this one DN.
           my @arrayOfAttrs = sort keys %$valref; #use Attr hashes

           my $attrName;	
           foreach $attrName (@arrayOfAttrs) {

	     # skip any binary data: yuck!
             next if ( $attrName =~ /;binary$/ );

             # get the attribute value (pointer) using the 
    	     # attribute name as the hash
             my $attrVal =  @$valref{$attrName} ;
                print "\t $attrName: @$attrVal \n";
             }
           print "#-------------------------------\n";
 	   # End of that DN
         }
      #
      #  end of as_struct method
      #--------


      #------------
      # walk through method
      #
        my $entr ;
        foreach $entr ( @entries )
           {
            print "DN: ",$entr->dn,"\n";
            #my @attrs = sort $entr->attributes;

            my $attr;
           foreach $attr ( sort $entr->attributes ){
                next if ( $attr =~ /;binary$/ );    #skip binary we can't handle
                print "  $attr : ",$entr->get($attr),"\n";
                }
            

            #print "@attrs\n";
                print "#-------------------------------\n";
           }

      #
      # end of walk through method
      #------------



#######################################
#######################################
#######################################
#
#   Modify
#

#  for each of the modifies below you'll need to supply 
#  a full DN (Distinguished Name) for the $dn variable.
#   example:
#    cn=Jo TIer+IDnumber=a0123456,ou=person,o=ti,c=us
#
#   I would recommend doing a search (listed above)
#   then use the dn returned to populate the $dn variable.
 

#######################################
#
#   MODIFY using a HASH
#

   my %ReplaceHash = ( keyword => "x", proxy => "x" );

   my $result = LDAPmodify($ldap,$dn, \%ReplaceHash );

   sub LDAPmodify 
   {
     my ($ldap,$dn,$whatToChange ) = @_ ;
     my $result = $ldap->modify($dn,
                               replace => { %$whatToChange }
                               );
       return ($result );
   }
   
   
#######################################
#
#   MODIFY using a ARRAY List
#

    my @ReplaceArrayList = [  'keyword', "xxxxxxxxxx" ,
                               'proxy' , "yyyyyyyyyy"   ];

    my $result = LDAPmodify($ldap,$dn, \@ReplaceArrayList );

    sub LDAPmodify 
      {
      my ($ldap,$dn,$whatToChange ) = @_ ;
      my $result = $ldap->modify($dn,
                       changes => [
                       replace => @$whatToChange
                       ]
                       );
       return ($result );
      }


#######################################
#
#   MODIFY using a ARRAY 
#

    my @ReplaceArray	= (  'keyword', "xxxxxxxxxx" ,
                              'proxy' , "yyyyyyyyyy"   );

    my $result = LDAPmodify($ldap,$dn, \@ReplaceArray );

    sub LDAPmodify 
      {
      my ($ldap,$dn,$whatToChange ) = @_ ;
      my $result = $ldap->modify($dn,
                       changes => [
                       replace => [ @$whatToChange ]
                       ]
                       );
       return ($result );
      }


#######################################
#
#   MODIFY an existing record using 'Changes'
#    (or combination of add/delete/replace)
#


        my @whatToChange ;
        my @ReplaceArray ;
        my @DeleteArray ;
        my @AddArray ;

        push @AddArray, 'cn',"me myself";
        push @ReplaceArray, 'sn','!@#$%^&*()__+Hello THere';
        push @ReplaceArray, 'cn',"me myself I";
        push @DeleteArray, 'cn',"me myself";




        if ( $#ReplaceArray > 0 ) {
            push @whatToChange, 'replace' ;
            push @whatToChange, \@ReplaceArray  ;
           }
        if ( $#DeleteArray > 0 ) {
            push @whatToChange, 'delete' ;
            push @whatToChange, \@DeleteArray  ;
           }
        if ( $#AddArray > 0 ) {
            push @whatToChange, 'add' ;
            push @whatToChange, \@AddArray  ;
           }

        $result = LDAPmodify($ldap,$dn, \@whatToChange );


    sub LDAPmodify
    {
       my ($ldap,$dn,$whatToChange) = @_ ;

       my $result = $ldap->modify($dn,
                        changes => [
                        @$whatToChange
                        ]
                        );
     return ($result );
    }




#######################################
#######################################
#######################################
#
#  RDN CHANGE
#

   my $newRDN = "cn=Jo TIer+IDnumber=a0123456";

   my $result = LDAPrdnChange($ldap,$dn,$newRDN,"archive");


   sub LDAPrdnChange
   {
    my ($ldap,$dn,$whatToChange,$action) = @_ ;
    
      my $branch ;

      #
      # if the archive action is selected, move this
      # entry to another place in the directory.
      #
      if ( $action =~ /archive/i )  {
         $branch = "ou=newbranch,o=ti,c=us";
         }

      #
      # use the 'deleteoldrdn' to keep from getting
      # multivalues in the NAMING attribute.
      # in most cases that would be the 'CN' attribute
      #
      my $result = $ldap->moddn($dn,
                newrdn => $whatToChange,
                deleteoldrdn => '1',
                newsuperior => $branch
                );

     return ($result );

   }



#######################################
#######################################
#######################################
#
#   CREATE A NEW RECORD
#

  my $DNbranch = "ou=bailiwick, o=ti, c=us";

  #
  # check with your Directory Schema or Administrator
  # for the correct objectClass... I'm sure it'll be different
  #
  my $CreateArray = [
	     objectClass => ["top","person","organizationalPerson"],
                      cn => "RESERVED",
                IDNumber => "xg000000",
                      sn => "RESERVED",
               mailAlias => "xg000000"
                ];

  #
  # "I" want my new dn to look like this
  #   " cn=RESERVED+IDNumber=xg000000,ou=bailiwick, o=ti, c=us  "
  #
  # NOTE: this DN is not standard naming but is unique to my needs
  #

   my $NewDN =  "@$CreateArray[2]=".
                "@$CreateArray[3]+".
                "@$CreateArray[4]=".
                "@$CreateArray[5],".
                $DNbranch;

  LDAPentryCreate($ldap,$NewDN,$CreateArray);

    #
    # CreateArray is a reference to an anonymous array
    # you have to dereference it in the  subroutine it's 
    # passed to.
    #

  sub LDAPentryCreate
  {

   my ($ldap,$dn,$whatToCreate) = @_ ;
   my $result = $ldap->add( $dn, attrs => [  @$whatToCreate ] );
   return ($result );

  }



#######################################
#######################################
#######################################
#
#   Getting ERROR information 
#
#
#

  use Net::LDAP::Util qw( ldap_error_name
                          ldap_error_text) ;

  if ( $result->code ) {
        #
        # if we've got an error... record it
        #
        LDAPerror("Searching",$result);
        }



  sub LDAPerror
  {
    my ($from,$mesg) = @_;
    print "Return code: ",$mesg->code ;
    print "\tMessage: ", ldap_error_name($mesg->code);
    print " :",        ldap_error_text($mesg->code);
    print "MessageID: ",$mesg->mesg_id;
    print "\tDN: ",$mesg->dn;

      	#---
  	# Programmer note:
  	#
  	#  "$mesg->error"  DOESN'T work!!!
  	#
  	#print "\tMessage: ", $mesg->error;
  	#-----

   }


