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

All I want to do it is read some form data.!! I'm not a perl programmer so this is doing my head in. Anyway, I have the sub below:
# A simple HTTP request parser to emulate ASP request.xxx< # So you can do $request->{"clicked"} in place of Request("clicked") # Has problems with MIME or complex submits # sub getHTTPData { my $xx; my $buffer; my %vars; if($ENV{"REQUEST_METHOD"} eq "GET") { $buffer=$ENV{'QUERY_STRING'}; } else { read ( STDIN, $buffer, $ENV{"CONTENT_LENGTH"}); } foreach $pair (split(/&/, $buffer)) { $pair =~ tr/+//; ($name, $value) = split(/=/, $pair); $value =~ s/%(\w\w)/sprintf("%c", hex($1))/ge; # convert hex t +o ascii $value=~s/\+/ /g; $vars{$name}="$value"; } return \%vars; }
so that I can use $uid = $request->{"uid}";

Fair enough. I also want to be able to access all the items submitted in a form. So I tried to use this bit of code as well:

use CGI ':standard'; print "Content-type: text/html\n\n"; print "<body>"; foreach my $name ( param() ) { my @values = param ($name); print "<p><b>Key:</b> $name <b>Value(s):</b> @values"; }
That works fine. BUT if I use the following after the above code:
$request = getHTTPData(); print "<br> fromtime is ". $request->{"fromTime"};
I get nada! Only one way will work (whichever is used first on the page)... am i asking to much to be able to do the equivalent of:
for each fld in request.form # do stuff with the name and value next
Ideally something in the sub getHTTPData() would probably be best. Any suggestions? (and I thought Lotus Script/ Domino was opaque...). Thanks,
p.s. Is it possible to make variables on the fly from names/ values submitted from a form i.e. if there are fields name id, acc1, acc2 ..accn can I do something like this (in pseudo code)
foreach fld in formdata{ make a variable named $fld have a value of $value }
that I can then access later in the page?..;-)

Edit by tye: title, READMORE

Replies are listed 'Best First'.
Re: why is this so hard?
by gjb (Vicar) on Dec 20, 2002 at 12:22 UTC

    If this is a POST request, you can't expect the buffer to be read twice (once by getHTTPData and a second time by the CGI module or vice versa). So you can use either, and I'd prefer CGI if I were you.

    As to your second question: don't. It's bad mojo to use user supplied data as variable names since it is very insecure.

    Just my 2 cents, -gjb-

        If this is a POST request, you can't expect the buffer to be read twice (once by getHTTPData and a second time by the CGI module or vice versa). So you can use either, and I'd prefer CGI if I were you.

      I agree with gjb and other reply'ers - I also prefer to use CGI.pm to read "param"s. You can only read cgi parameters once :-)

        As to your second question: don't. It's bad mojo to use user supplied data as variable names since it is very insecure.

      Again, agreed. If you *have* to use user supplied data as variable names, then turn on "taint" mode - in fact, turn on "taint" mode anyway - it is very strict about what it will allow your cgi scripts to do. It will only allow you to do things that are safe, and it forces you to "untaint" data coming in to your script from outside - like all environment variables and all user supplied data.

      HTH.
Re: why is this so hard?
by davorg (Chancellor) on Dec 20, 2002 at 13:23 UTC

    Your code in getHTTPdata is broken. Although it will work in most cases, it fails to handle many of the "corner cases" that are common in CGI programming. See use CGI or die; for more details on that.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: why is this so hard?
by Aristotle (Chancellor) on Dec 20, 2002 at 15:46 UTC

    Please make sure to read Mark-Jason Dominus' archived newsposts, part one, two and three on Why it's stupid to 'use a variable as a variable name'. You really don't want to do that.

    If you automatically generate variables named after all the parameters in your code, you may end up only thinking you do so. What if someone saves the page with your <form>, edits it and sends a request that contains, f.ex, &/=& ? You will end up trampling over Perl's $/ variable and probably doing something you really didn't expect. (See perldoc perlvar to find out what that variable does..) And what if you have a variable called $filename that's not supposed to be changed from the outside and someone sends you a &filename=/etc/passwd?

    Just don't go there.

    What's wrong with saying param('uid') instead of $uid?

    Makeshifts last the longest.

Re: why is this so hard?
by fruiture (Curate) on Dec 20, 2002 at 13:23 UTC

    As gjb pointed out, POST data (stuff submitted via Request-body) is put into STDIN of a CGI program and the program reads that stuff _once_.

    Secondly, you should completely omit getHTTPData(), for it is what one might call a "Broken CGI Parser". use CGI or die;

    Third, creating variables from foreign data is a security hole. You must not mix the source of your program and the data your program deals with.

    If you really _need_ something like Request('...') you can write that function as wrapper around CGI::param().

    --
    http://fruiture.de
Re: why is this so hard?
by diotalevi (Canon) on Dec 20, 2002 at 15:01 UTC

    And LotusScript/Domino isn't opaque. They just have different strengths. If you want a nice LotusScript module for doing these tasks I'll send one to you. I'm not posting the code here so as to not annoy all the perly people with LotusScript *grin*. There are some e-mail addresses on my home node.