Getting CGI to read from a different STDIN source

B

Bill Gerba

Hi,

I've run into a problem with CGI.pm. I want to use my own generic
code to actually capture the raw POST data from a form submission and
store the whole thing to a file. After I've caught the entire POST
stream, I then want to load all of the data from the file back into
STDIN and create a new CGI object that will read the data in there and
parse it out for me. Attached is the code that I'm using, and I'm
submitting from a very simple HTML form with a few text boxes and
select widgets (Perl 5.6.1 and Apache on Linux, if it's important).

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use CGI;

# First, grab the HTTP POST stream and dump it into a file.
my ($TMP,$DATA);
open($TMP,">","posted_data.txt");
while (read STDIN, $DATA, 1024) {
print $TMP $DATA;
}
close $TMP;

# Next, open the file into STDIN so CGI.pm can read it
open(STDIN,"posted_data.txt") or die "can't open temp file: $!";
$| = 1;

# Print out the data from the HTTP POST as CGI sees it.
my $cc = new CGI;
my %v = $cc->Vars;
print $cc->header();
print Dumper(\%v);


When I run this, it saves the file correctly (all of the data and
headers are there), but I get a cryptic error message: "Filehandle
STDOUT opened only for input at test.cgi line 22."

AFAIK, I'm not doing anything at all to STDOUT, and CGI doesn't seem
to think that there's anything in STDIN at all. But if I don't make
the CGI object and just do a while (<STDIN>) { print; } I get all of
my data out fine. What am I doing wrong, and how can I get CGI to see
the data in STDIN?

TIA,

Bill
 
B

Bob Walton

Bill Gerba wrote:

....
I've run into a problem with CGI.pm. I want to use my own generic
code to actually capture the raw POST data from a form submission and
store the whole thing to a file. After I've caught the entire POST


Check out the CGI docs under the section "CREATING A NEW QUERY OBJECT
FROM AN INPUT FILE". That will let you do what you want, as in the
marked-up code below. BTW, I duplicated your problem with your code
under Windoze 98SE, except it didn't give any error message about STDOUT.

stream, I then want to load all of the data from the file back into
STDIN and create a new CGI object that will read the data in there and
parse it out for me. Attached is the code that I'm using, and I'm
submitting from a very simple HTML form with a few text boxes and
select widgets (Perl 5.6.1 and Apache on Linux, if it's important).

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use CGI;

# First, grab the HTTP POST stream and dump it into a file.
my ($TMP,$DATA);
open($TMP,">","posted_data.txt");

----------------------------------^
Missing or die ... clause.

while (read STDIN, $DATA, 1024) {
print $TMP $DATA;
}
close $TMP;

# Next, open the file into STDIN so CGI.pm can read it
open(STDIN,"posted_data.txt") or die "can't open temp file: $!";

open(IN, "posted_data.txt") or ...

#I didn't try it using STDIN as a filehandle, but it just
#seems nice not to mess with STDIN.


Line not needed.
 
B

Bill Gerba

Well, my problems continue. According to the docs, when you create a
CGI object using new CGI($FH), the file (or list, or hash, or
whatever) can ONLY contain data in either key=value format or a URI
encoding scheme. However, in the example below, I'm slurping all of
STDIN into a file, which includes things like the HTTP headers.
Consequently, when I run the script below, CGI dumps everything into
one huge variable full of crap.

Is it possible to take this entire file and have CGI successfully
parse it out?

A related question is: what's the difference between my $IN filehandle
and the original STDIN when the data is posted to the CGI script? Is
Apache stripping out the headers or something?

Also, it's worth noting that I'm trying this with a
multipart/form-data HTTP file upload, so there could be different (or
multiple) content-length headers in the POSTed data.

Here's the code:

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use CGI;

# First, grab the HTTP POST stream and dump it into a file.
my ($TMP,$DATA);
open($TMP,">","posted_data.txt") or die "can't open posted_data file:
$!";
while (read STDIN, $DATA, 1024) {
print $TMP $DATA;
}
close $TMP;

# Make a CGI object taking data from a filehandle $IN
my $IN;
open($IN,"posted_data.txt") or die "can't open temp file: $!";

# Print out the data from the HTTP POST as CGI sees it.
my $cc = new CGI($IN);
my %v = $cc->Vars;
print $cc->header();
print Dumper(\%v);

exit(0);


If you want to try this yourself, here's the HTML form that I'm using
to submit to the CGI:


<HTML>
<HEAD>
<TITLE>FireCast ClientCenter : Upload Files</TITLE>
</HEAD>
<BODY>
<form enctype="multipart/form-data" action="/cgi-bin/uptest.pl"
method="POST">

<table border=0 align="left" cellpadding=3>
<tr><td><input type="file" name="upfile1"></td></tr>
<tr><td><input type="file" name="upfile2"></td></tr>
<tr>
<td colspan=2 align="center">
<input type="hidden" name="sessionid" value="1234">
<input type='hidden' name='mode' value='upload'>
<input type="submit" value="Upload">
</td>
</tr>
</table>
</form>
</BODY>
</HTML>



Thanks again!
 
B

Brian McCauley

Well, my problems continue. According to the docs, when you create a
CGI object using new CGI($FH), the file (or list, or hash, or
whatever) can ONLY contain data in either key=value format or a URI
encoding scheme. However, in the example below, I'm slurping all of
STDIN into a file, which includes things like the HTTP headers.
Consequently, when I run the script below, CGI dumps everything into
one huge variable full of crap.

Is it possible to take this entire file and have CGI successfully
parse it out?

You could just open the file as STDIN
A related question is: what's the difference between my $IN filehandle
and the original STDIN when the data is posted to the CGI script?

The orginal STDIN is the speical standard input file handle.
my $IN;
open($IN,"posted_data.txt") or die "can't open temp file: $!";

# Print out the data from the HTTP POST as CGI sees it.
my $cc = new CGI($IN);

How about

# Untested
open(STDIN,"posted_data.txt") or die "can't open temp file: $!";
my $cc = new CGI;

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
B

Bill Gerba

Brian McCauley said:
You could just open the file as STDIN
....

How about

# Untested
open(STDIN,"posted_data.txt") or die "can't open temp file: $!";
my $cc = new CGI;

This was the first thing I tried. In my first post I noted that when
I do this I not only get an empty CGI object, but I also get a
peculiar message about STDOUT being opened for output only.
 
N

nobull

This was the first thing I tried. In my first post I noted that when
I do this I not only get an empty CGI object, but I also get a
peculiar message about STDOUT being opened for output only.

Sorry I missed the start of this thread originally.

I've gone back a copied the test script from the OP onto my web
server. I made only one small change - I added a chdir("/tmp")
because my httpd is not configured to set CGIs' CWD to a writable
directory. It worked perfectly.

Are you sure that your httpd _is_ configured to set CGIs' CWD to a
writable directory?

Are you sure you are using CGI at all (and not something like mod_perl
+ Apache::Registry)?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top