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

So, I'm passing data from a form to a script to insert data into a database. Simple, yes, and I feel really stupid for having problems with this.. I'm using someone else's script (because I was instructed to, and because its supposed to "Work"). well, it doesn't. when you pass it the input from a checkbox, it only inserts the first element of the checkbox array into the database.. so I tried a few things.. one (the commented one) didn't work, and while the other doesn't error, it doesn't do what I wanted it to do.. I'd like to make this as dynamic as possible, that way, it doesn't matter what variable becomes a check box or multi-select in the future, it'll still work. here's what I have.. %INPUT is formed using the old fashioned
if ($ENV{'REQUEST_METHOD'} eq 'POST') read(STDIN, $buffer, $ENV{'CONTE +NT_LENGTH'}); why, I don't know, but I "should use this because its more portable". anyways here's the part that needs attention: foreach $thing (keys(%INPUT)) { if(ref($INPUT{$thing}) eq "ARRAY") { $INPUT{$thing} = join('^' +, $$INPUT{$thing}); } # if($#INPUT{$thing}) { $INPUT{$thing} = join('^', $$INPUT{$thin +g}); } }

any other ideas? or insight?

-brad.. tired, bored, and tired. :)

Replies are listed 'Best First'.
Re: CGI type question involving arrays..
by Adam (Vicar) on Sep 26, 2000 at 21:31 UTC
    use CGI.pm

    This will give you access to params without having to know if they came in on a post or a get and without having to monkey around with environment variables.

    As for your code snipit:

    foreach $thing (keys(%INPUT)) { if(ref($INPUT{$thing}) eq "ARRAY") { $INPUT{$thing} = join('^' +, $$INPUT{$thing}); } # if($#INPUT{$thing}) { $INPUT{$thing} = join('^', $$INPUT{$thin +g}); } }
    The line starting with a pound is a comment, but I suspect you knew that. (Its also wrong... you can't $# a hash.) So I'm going to drop it and just look at the other line. Thats trying to dereference an array, which you might want to do explicitly:
    foreach $thing ( keys %INPUT ) { if( ref( $INPUT{$thing} ) eq "ARRAY" ) { $INPUT{$thing} = join '^', @{$INPUT{$thing}} } } # You can also write the above like this: $INPUT{$_} = join '^', @{$INPUT{$_}} for grep {"ARRAY" eq ref $INPUT{$ +_}} keys %INPUT
Re: CGI type question involving arrays..
by kilinrax (Deacon) on Sep 26, 2000 at 21:39 UTC
    More portable, pah. Why not use CGI.pm?
    For example:
    #!/usr/bin/perl -w use strict; use CGI; my $query = new CGI; my @params = $query->param; foreach $param(@params) { $values = join '^', $query->param($param); # do what you want with the data here }
    Hope this helps;-)
      You forgot to add the -T switch to turn on taint checking. Since this person is using this data to add to a database, they're probably constructing SQL statements with it. Thus, without taint checking, a savvy cracker can have fun passing values that delete databases, change information they shouldn't, or other nasty things.

      See perlsec for details.

      Cheers,
      Ovid

      Join the Perlmonks Setiathome Group or just go the the link and check out our stats.

      I was told to "USE THIS CODE OR ELSE" by my manager.. heh..
      thanks for your help :)
Re: CGI type question involving arrays..
by swiftone (Curate) on Sep 26, 2000 at 22:21 UTC
    Well, I really recommend using CGI.pm, as everyone else has suggested, but I believe the problem with the code is: if(ref($INPUT{$thing}) eq "ARRAY") { $INPUT{$thing} = join('^', $$INPUT{$thing}); } Specifically: join('^', $$INPUT{$thing}) You've already determined that $INPUT{$thing} is an array reference, so the proper way to de-reference it is: @$INPUT{$thing} Or (more clearly) @{ $INPUT{$thing} } So your final solution is: if(ref($INPUT{$thing}) eq "ARRAY") { $INPUT{$thing} = join('^', @{$INPUT{$thing}}); }
RE: CGI type question involving arrays..
by little (Curate) on Sep 26, 2000 at 21:42 UTC
    Well, I guess you are running into trouble, cause there's one key but more values to it. So you better read the query string and stuff all remitted vars in separate array's or hashes first and then go down to single key-value pairs.
    But if you'd like to use CGI.pm, as suggested, you you could use something like @wanted = $query->param($remitted), where $remitted is the key.
    Do you think, your employer would allow you to tune up that script with cgi.pm ???
    Have a nice day
    Update
    Ok, as I see, others have been faster :-)
Re: CGI type question involving arrays..
by reyjrar (Hermit) on Sep 27, 2000 at 00:05 UTC
    Update: Thanks everyone!
    Basically, I redid the script using CGI.pm and showed my boss two versions, one that worked and one that didn't.. and he choose the one that worked :)
    hehe.. thanks again..

    -brad..
Re: CGI type question involving arrays..
by japhy (Canon) on Sep 26, 2000 at 23:07 UTC
    I'll be putting a tutorial online in the future about why it is NOT SMART to use cut-and-paste CGI query parsers, and demonstrate the proper way to parse CGI queries -- without just saying "use CGI;".

    I've looked at the source code to CGI.pm, and found what browsers mess up where, and I go through and actually SHOW what CGI queries look like. If you're interested in a free preview, check out the very upcoming node, japhy's CGI Tutorial Trailer.

    $_="goto+F.print+chop;\n=yhpaj";F1:eval
Re: CGI type question involving arrays..
by wardk (Deacon) on Sep 27, 2000 at 17:46 UTC
    #!/usr/bin/perl use CGI; $q = new CGI; @CheckBoxData = $q->param("checkboxName"); print "insert into table (colname) values ( \"@CheckBoxData\" )\n"; # or foreach $v ( @CheckBoxData ) { # process the value print " insert into table ( colname ) values (\"$v\" ) \n"; }