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

Hi all, I have to populate an array from an ldapsearch query but I'm doing something wrong and I can't work out what it is, if anyone can help out, I'd be grateful. The data for the ldapsearch is populated from a cgi.

#!/usr/bin/perl -w use CGI; $upload_dir = "/opt/apache/1.3.27/htdocs/cspireutils/files-ch"; $query = new CGI; $tstamp = `date '+%Y%d%m'`; #$username = $query->param("username"); #$password = $query->param("password"); $sid = $query->param("sid"); $email = $query->param("primaryemailradius"); $maildomain = $email; $altemail = $query->param("aliasemailradius"); $proftp = $query->param("proftp"); $dirsrv = "cn=directory manager"; chomp($email); $email =~ s/\@.*//g; my @fields = ("dn", "jrMailBoxId", "jrMailboxAliasStore", "jrPWPUID", +"jrPWPUserPrefs", "jrUserFriendlyID"); my @mailfields = ("jrMailId", "jrFullMailAliasList", "jrPrimaryMailId" +); open (MODLDIF, ">$upload_dir/$email-$tstamp") or die "Can't open $emai +l-$date for output"; open (MODDN, ">$upload_dir/$proftp-$tstamp") or die "Can't open $proft +p-$date for output"; print MODLDIF "$email\n"; @fields=~'/opt/apache/1.3.27/cgi-bin/cspireutils/ldapsearch -h 172.30. +58.243 -p 389 -D $dirsrv -w 'passwd' -b ou=subscribers,ou=u sers,ou=prague,ou=domains,ou=cz,ou=domains,o=chello cn=$sid dn jrMailB +oxId jrMailboxAliasStore jrPWPUID jrPWPUserPrefs jrUserFriendl yID'; print MODLDIF "@fields\n"; while (<>) { my %thisrecord = (); foreach my $field(@fields) { $thisrecord{$field} = ""; } s/\n^ //msg; chomp (); while (m/^([^:]*:?): (.*)/mg) { my ($field, $data) = ($1, $2); if (grep (/$field/, @fields)) { $thisrecord{$field} = $data; } } } print "$thisrecord{'jrUserFriendlyID'}"; if ($thisrecord{'jrUserFriendlyID'} = $email) { die " Error duplicate entry detected, please resolve manually" +; } else { print MODLDIF "$thisrecord{'dn'},ou=subscribers,ou=users,ou=pr +ague,ou=domains,ou=cz,ou=domains,o=chello \n"; print MODLDIF "changetype: modify\n"; print MODLDIF "replace : jrMailboxId\n"; print MODLDIF "jrMailbox: $maildomain\n"; print MODLDIF "-\n"; print MODLDIF "replace: jrPWPUID\n"; print MODLDIF "jrPWPUID: $proftp\n"; print MODLDIF "dn: $thisrecord{'jrMailboxAliasStore'},ou=OpenW +aveSupplement,ou=mail,ou=USCOs,ou=prague,ou=domains,ou=cz,ou=d omains,o=chello\n"; print MODLDIF "changetype: modify\n"; print MODLDIF "replace: jrPrimaryMailId\n"; print MODLDIF "jrPrimaryMailId: $email\n"; print MODLDIF "-\n"; print MODLDIF "replace: jrFullMailAliasList\n"; print MODLDIF "jrFullMailAliasList: $altemail\n"; print MODDN "%thisrecord{'jrPWPUID'},ouProFTPSupplement,ou=ftp +,ou=USCOs,ou=prague,ou=domains,ou=cz,ou=domains,o=chello\n"; print MODDN "jrPWPUID=$proftp\n"; } system ("ldapmodify -h 172.30.58.243 -p 389 -D $dirsrv -w 'passwd' -f +/opt/apache/1.3.27/htdocs/cspireutils/files-ch/$email-$tsta mp > /opt/apache/1.3.27/htdocs/cspireutils/files-ch/modify-$email-$tst +amp"); system ("ldapmodrdn -h 172.30.58.243 -p 389 -D $dirsrv -w 'passwd' -f +/opt/apache/1.3.27/htdocs/cspireutils/files-ch/$proftp-$tst amp >> /opt/apache/1.3.27/htdocs/cspireutils/files-ch/modify-$email-$t +stamp"); print <<ENDHTMLb; <HTML> <HEAD> <TITLE>Modifications submitted</TITLE> </HEAD> <BODY> <P></P> <P>The modification has been submitted for the Billing ID $sid</P> <P>Please take a look at</P> <A HREF="/cspireutils/files-ch/modify-$email-$tstamp">modification lo +g</A> </BODY> </HTML> ENDHTMLb exit;

The output from the array is:
dn jrMailBoxId jrMailboxAliasStore jrPWPUID jrPWPUserPrefs jrUserFrien +dlyID
I was expecting object fields of course :) And the output from the script in the apache logs is:
Applying pattern match (m//) to @array will act on scalar(@array) at / +opt/apache/1.3.27/cgi-bin/cspireutils/upload-ch.pl line 25. Applying pattern match (m//) to @array will act on scalar(@array) at / +opt/apache/1.3.27/cgi-bin/cspireutils/upload-ch.pl line 25. Use of uninitialized value in string at /opt/apache/1.3.27/cgi-bin/csp +ireutils/upload-ch.pl line 44.

Replies are listed 'Best First'.
Re: Populating the array, what am I doing wrong.
by andreas1234567 (Vicar) on Apr 25, 2008 at 10:35 UTC
    Use strict and warnings. Always.

    Your problem is most likely related to these lines:

    $ cat 682776.pl use strict; use warnings; my @fields=~'/opt/apache/1.3.27/cgi-bin/cspireutils/ldapsearch -h 172. +30.58.243 -p 389 .. __END__
    What exactly is it you want @fields to contain? Hints:
    • Quotes
    • Assignment operators vs regular expressions.
    --
    No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]
      Hi,
      I want the fields to hold the results of the ldapsearch for example :
      field dn cn=t43311 field jrMailboxId poohbear@woods.com field jrMailboxAliasStore 452125643 field jrPWPUID poohbear field jrPWPUserPrefs poohbear field jrUserFriendlyID poohbear

      As this information is used later in the script, the script is supposed to take the input from the cgi, which is the SID, the existing mail address and proftp information, the ldapsearch searches for the SID and is supposed to populate the array with the requested fields.

      If the jrFriendlyID is unique, it modifies the user object to have the input from the cgi for mail address and proftp.
Re: Populating the array, what am I doing wrong.
by jdporter (Paladin) on Apr 25, 2008 at 13:07 UTC

    Your code has lots of problems. For starters, the line

    @fields=~'/opt/apache/1.3.27/cgi-bin/cspireutils/ldapsearch -h 172.30 +.58.243 -p 389 -D $dirsrv -w 'passwd' -b ou=subscribers,ou=users,ou=p +rague,ou=domains,ou=cz,ou=domains,o=chello cn=$sid dn jrMailBoxId jrM +ailboxAliasStore jrPWPUID jrPWPUserPrefs jrUserFriendlyID';
    is completely bogus Perl. What in the world did you mean to be doing there?

    A few lines further down, it looks like you're reading from stdin with

    while (<>) {
    What data are you expecting to read from stdin? I.e. are you expecting to pipe the input from another program's output?

    This kind of touches on another bug, which is that you have declared %thisrecord inside that while loop, but you try to use it later in the program. This doesn't make sense, and merely moving the %thisrecord declaration outside the loop probably won't result in a correct program.

    And that relates to another bug: You try to use a field from the hash in a string, as "%thisrecord{'jrPWPUID'}... but that is incorrect; it should be "$thisrecord{'jrPWPUID'}... (Note the $, vice %.)

    A word spoken in Mind will reach its own level, in the objective world, by its own weight
      What in the world did you mean to be doing there? Well
      I was trying to populate the @fields with the selected objects from the ldapsearch

      The ldapsearch, if you do it outside of the script, returns with:
      cn=t43311,ou=subscribers,ou=users,ou=country,ou=domains,ou=cz,ou=chell +o jrMailBoxId=poohbear@woods.com jrMailboxAliasStore=5485113511 jrPWPUID=poohbear jrPWPUserPrefs=poohbear jrUserFriendlyID=poohbear

      but all that seems to get populated in the array is dn jrMailBoxId jrMailboxAliasStore jrPWPUID jrPWPUsersPrefs jrUserFriendlyID

        Ok, well you're going about that all wrong. To execute an external program and get its output into an array of lines, use qx():

        @fields = qx( /opt/apache/1.3.27/cgi-bin/cspireutils/ldapsearch -h 172 +.30.58.243 -p 389 -D $dirsrv -w 'passwd' -b ou=subscribers,ou=users,o +u=prague,ou=domains,ou=cz,ou=domains,o=chello cn=$sid dn jrMailBoxId +jrMailboxAliasStore jrPWPUID jrPWPUserPrefs jrUserFriendlyID );
        then you can easily iterate over the lines with foreach.

        Alternatively, you could use the while(<>) construct to read from a pipe connected to the output of an external program:

        open P, $command # as above or die "can't run $command - $!"; while (<P>)
        but note specially the use of an explicit filehandle inside the angle brackets. Omit that, and you'd be reading from stdin.

        If you assign to @fields as above, you'll be overwriting the array of values you orginally assigned to it. Is that what you intended?

        A word spoken in Mind will reach its own level, in the objective world, by its own weight
Re: Populating the array, what am I doing wrong.
by Narveson (Chaplain) on Apr 25, 2008 at 13:19 UTC

    You say

    while (<>) { my %thisrecord = (); # 11 lines of code to populate %thisrecord } print "$thisrecord{'jrUserFriendlyID'}";

    but the print statement is outside the scope of %thisrecord, so there's nothing to print.

    Enable warnings if you'd like to be informed of this state of affairs.

    Try writing a small program with output that shows you've successfully populated your hash with the data you're expecting to read. Change while (<>) to while (<DATA>) and put test data at the bottom of the program below a __DATA__ marker.