Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

perl-CGI module - post method

176 views
Skip to first unread message

Victor

unread,
Feb 8, 2005, 5:20:03 AM2/8/05
to beginn...@perl.org
I use the last version of perl-CGI.
When I transmit the variables using the get method it
works($cgi->param(<variable>) returns the correct value).
When I transmit the variables using the post method it I receive a empty
string(($cgi->param(<variable>) is empty).

If I try to receive the variables using post method, but without the
perl-CGI($ENV{CONTENT_LENGHT}...) - then it works.

Thank you.

Ovid

unread,
Feb 8, 2005, 11:15:48 AM2/8/05
to David Romero, beginn...@perl.org
--- David Romero <da...@vendingmexico.com> wrote:

> Victor wrote:
> > When I transmit the variables using the post method it I receive a
> > empty string(($cgi->param(<variable>) is empty).
> >
> The POST data can be read one time, if you create an cgi objet before
> these, the second object recibe empty data.
> Is posible than one of your use modules read the post data frist.
>
> Im fix the problem with the standatd pragma.
>
> use CGI qw/standad/;
> my $value = param("post_var");

It is true that you can only read the POST data once (without extreme
trickery, that is), but the fix would not be to use /:standard/.
Instead, if more than once instance of a CGI object is being
instantiated, the fix is to either remove the extraneous instantiations
or to call param() on the first instantiation which does have the POST
data.

As a more extreme method of debugging (just to verify that you're
sending the data the way you thought you were), you can always test to
ensure that you really *are* sending data via the POST method by
pointing your form to this script (typed on the fly so sorry if there
are typos):

#!/usr/bin/perl -wT
use strict;

print "Content-type: text/plain\n\n";

if ( "GET" eq $ENV{REQUEST_METHOD} ) {
print "Request method was GET.\n";
print $ENV{QUERY_STRING};
}
elsif ( "POST" eq $ENV{REQUEST_METHOD} ) {
print "Request method was POST.\n";
print "Content length was $ENV{CONTENT_LENGTH}\n";
my $buffer;
if (read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'})) {
print $buffer;
}
else {
print "Could not read STDIN";
}
}
else {
print "Don't know how to handle '$ENV{REQUEST_METHOD'";
}

I have more information about this at Lesson 2
(http://users.easystreet.com/ovid/cgi_course/lessons/lesson_two.html)
of my course.

Cheers,
Ovid

=====
If this message is a response to a question on a mailing list, please send
follow up questions to the list.

Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/

David Romero

unread,
Feb 8, 2005, 11:14:04 AM2/8/05
to beginn...@perl.org
David Romero wrote:

> The POST data can be read one time, if you create an cgi objet before
> these, the second object recibe empty data.
> Is posible than one of your use modules read the post data frist.
>
>
>
> Im fix the problem with the standatd pragma.
>
> use CGI qw/standad/;
> my $value = param("post_var");
>
>

sorry the correct syntaxis is
use CGI qw/:standard/;

David Romero

unread,
Feb 8, 2005, 11:02:34 AM2/8/05
to beginn...@perl.org
Victor wrote:

Scott R. Godin

unread,
Feb 8, 2005, 4:41:24 PM2/8/05
to beginn...@perl.org

it sounds more like he's doing

use CGI;

my $cgi = CGI->new();

since he clearly illustrates the use of the object-oriented syntax in
his example and in which case you want to get the params AFTER creating
the cgi-object

my %params = $cgi->Vars;

which ensures that you also get multi-value <select>s as separate
values. too.

--
Scott R. Godin
Laughing Dragon Services
www.webdragon.net

Ovid

unread,
Feb 8, 2005, 7:40:14 PM2/8/05
to beginn...@perl.org
--- "Scott R. Godin" <nos...@webdragon.net> wrote:

> his example and in which case you want to get the params AFTER
> creating
> the cgi-object
>
> my %params = $cgi->Vars;
>
> which ensures that you also get multi-value <select>s as separate
> values. too.

$cgi->Vars separates multiple values with a null byte, thus increasing
the risk of the person using this being vulnerable to a null-byte hack.
I would only use this if you're migrating from the Perl 4 cgi-lib.pl.


Also. having to do "@foo = split "\0",$params->{foo};" is not fun and
it's easy to get wrong.

If someone needs multiple values, they should just take advantage of
list context:

my $foo = $cgi->param('foo'); # single value
# versus
my @foo = $cgi->param('foo'); # multiple values

Tee

unread,
Feb 8, 2005, 10:04:44 PM2/8/05
to publiustemp-...@yahoo.com, Tee, beginn...@perl.org
Can you do: my %foo = $cgi->param("foo")

Else, how do you loop thru to put the array into %keys?

--Tee

> --
> To unsubscribe, e-mail: beginners-cg...@perl.org
> For additional commands, e-mail: beginners...@perl.org
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
>
>

Ovid

unread,
Feb 8, 2005, 10:35:59 PM2/8/05
to Tee, publiustemp-...@yahoo.com, Tee, beginn...@perl.org
--- Tee <trl...@insightbb.com> wrote:
> Can you do: my %foo = $cgi->param("foo")
>
> Else, how do you loop thru to put the array into %keys?

Sorry Tee, that won't work. Perl recognizes void, scalar, and list
contexts. There is no "hash" context. If you have a hash on the left
hand side of the equals sign (=), param() see you're in list context
and return a list.

One thing you can do (keeping in mind that $cgi->param returns the form
param names and not the values):

my %params = map { $_ => [$cgi->param($_)] } $cgi->param;

With this, every key will represent one items on the form and every
value will be an array ref containing the values for that form element.

Written as a foreach loop, the above is the exact equivalent of this:

my %params;
foreach my $param ($cgi->param) {
$params{$param} = $cgi->param($param);
}

Thus, if you have one value for the form element "username", you could
access it like this:

my $username = $form->{username}->[0];

If you have multiple values, you could access them like this:

my @color = @{ $form->{color} };

Since most forms have one value per element, though, most people would
choose something like this:

my %form = map { $_ => $cgi->param($_) } $cgi->param;

Of course, that loses data if any params have multiple values, but
again, most forms are not like that.

There are other ways to deal with this, but they are pretty safe and
straightforward.

Scott R. Godin

unread,
Feb 8, 2005, 9:01:52 PM2/8/05
to beginn...@perl.org
Ovid wrote:
> --- "Scott R. Godin" <nos...@webdragon.net> wrote:
>
>
>>his example and in which case you want to get the params AFTER
>>creating
>>the cgi-object
>>
>>my %params = $cgi->Vars;
>>
>>which ensures that you also get multi-value <select>s as separate
>>values. too.
>
>
> $cgi->Vars separates multiple values with a null byte, thus increasing
> the risk of the person using this being vulnerable to a null-byte hack.
> I would only use this if you're migrating from the Perl 4 cgi-lib.pl.
>
>
> Also. having to do "@foo = split "\0",$params->{foo};" is not fun and
> it's easy to get wrong.
>
> If someone needs multiple values, they should just take advantage of
> list context:
>
> my $foo = $cgi->param('foo'); # single value
> # versus
> my @foo = $cgi->param('foo'); # multiple values
>
> Cheers,
> Ovid


You raise a good point, m'friend, and one that I pondered for quite a
while before sending an RFE to Lincoln Stein regarding possibly adding a
pragma to indicate that you want the multi-value params as an anonymous
array within the hash, thereby avoiding the potential problems of the
poison null-byte.

along the lines of

%hash = $cgi->Vars();
@foo = @{ $hash{foo} };

From what I can see from the code it looks like the \0-packing is being
done artificially after the fact, and internally the object data IS
being stored within an arrayref in the object's structure, so this may
be a simple thing to implement. I don't know myself. I got brain-freeze
trying to follow the flow within CGI.pm :-)

We'll have to wait and see what Lincoln says, but I brainstormed a bit
and even came up with a sensible pragma name.. either -presplit or
:presplit.

Very very good point though, and one I'm going to drill on until I can't
forget it again.

Victor

unread,
Feb 9, 2005, 8:36:43 AM2/9/05
to beginn...@perl.org
I wrote tne initial question about the perl-CGI module and post method.
Thank you for your answers.

The problem is a little more comlicated, but I found a solution.
I belive it is a problem o incompatibility betwen perl-CGI and
something else on my system - possible Apache ASP(I can't say exactly
and I don't have any more time to investigate).

The solution:
In CGI.pm I replaced the line
"return $MOD_PERL ? $self->r->read($$buff, $len, $offset) :
read(\*STDIN, $$buff, $len, $offset);"
with
"read(\*STDIN, $$buff, $len, $offset);"
And it worked.

I have perl-CGI 3.05, apache2, Apache-asp 2.57, apache2-mod_perl,
apache2-mod_ssl

And the apache configuration for the working dorectory:
<VirtualHost xxx.xxx.xxx.xxx:443>
ErrorLog logs/ssl-error_log
TransferLog logs/ssl-access_log
SSLEngine on
SSLCertificateFile /etc/ssl/apache2/server.crt
SSLCertificateKeyFile /etc/ssl/apache2/server.key
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
RewriteEngine On
RewriteOptions inherit
DocumentRoot /var/www/html/freeside
ServerName xxxxxx
<Perl>
$MLDBM::RemoveTaint = 1;
</Perl>
PerlRequire Require.pm
<Directory /var/www/html/freeside>
<Files ~ (\.cgi)>
AddHandler perl-script .cgi
PerlHandler Apache::ASP
</Files>
PerlSetVar Global /usr/local/etc/freeside/asp-global/
PerlSetVar Debug 2
PerlSetVar Global /usr/local/etc/freeside/asp-global/
AuthName Freeside
AuthType Basic
AuthUserFile /usr/local/etc/freeside/htpasswd
require valid-user
</Directory>
</VirtualHost>


Scott R. Godin

unread,
Jul 18, 2005, 12:14:04 PM7/18/05
to beginn...@perl.org, publiustemp-...@yahoo.com

I finally got my tuits in order, unfroze my brain, and managed to grok
enough of the CGI.pm internals that I was able to implement at least a
partial solution to the problem.

It does require one download a separate module (which replaces three of
the CGI.pm AUTOLOAD methods), but short of Lincoln Stein implementing
this as a -presplit or -nopoison pragma, this solves the issue quite
nicely. :)

http://search.cpan.org/~sgodin/CGI-NoPoison-3.10/

Scott R. Godin

unread,
Jul 18, 2005, 12:13:24 PM7/18/05
to beginn...@perl.org, publiustemp-...@yahoo.com

I finally got my tuits in order, unfroze my brain, and managed to grok

0 new messages