Getting CGI to read from a different STDIN source

Discussion in 'Perl Misc' started by Bill Gerba, Feb 8, 2004.

  1. Bill Gerba

    Bill Gerba Guest

    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
    Bill Gerba, Feb 8, 2004
    #1
    1. Advertising

  2. Bill Gerba

    Bob Walton Guest

    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.


    > $| = 1;


    Line not needed.


    >
    > # 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);
    >
    >
    > 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?

    ....
    > Bill
    >


    --
    Bob Walton
    Email: http://bwalton.com/cgi-bin/emailbob.pl
    Bob Walton, Feb 8, 2004
    #2
    1. Advertising

  3. Bill Gerba

    Ben Morrow Guest

    d wrote:
    > Bill Gerba wrote:
    > open(IN, "posted_data.txt") or ...


    open my $IN, "posted_data.txt" or die ...;

    > > my $cc = new CGI(\*IN);

    > ------------------^^^^^^


    my $cc = new CGI($IN);

    Ben

    --
    Musica Dei donum optimi, trahit homines, trahit deos. |
    Musica truces mollit animos, tristesque mentes erigit. |
    Musica vel ipsas arbores et horridas movet feras. |
    Ben Morrow, Feb 8, 2004
    #3
  4. Bill Gerba

    Bill Gerba Guest

    Brilliant, both of you. Thanks!
    Bill Gerba, Feb 9, 2004
    #4
  5. Bill Gerba

    Bill Gerba Guest

    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!
    Bill Gerba, Feb 13, 2004
    #5
  6. (Bill Gerba) writes:

    > 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\\
    Brian McCauley, Feb 13, 2004
    #6
  7. Bill Gerba

    Bill Gerba Guest

    Brian McCauley <> wrote in message news:<>...
    >
    > 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.
    Bill Gerba, Feb 14, 2004
    #7
  8. Bill Gerba

    Guest

    (Bill Gerba) wrote in message news:<>...
    > Brian McCauley <> wrote in message news:<>...
    > >
    > > 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.


    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)?
    , Feb 16, 2004
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Johnathan Doe

    peek at stdin, flush stdin

    Johnathan Doe, May 15, 2004, in forum: C Programming
    Replies:
    5
    Views:
    24,842
    Chatoyer
    May 17, 2013
  2. Charlie Zender

    Reading stdin once confuses second stdin read

    Charlie Zender, Jun 19, 2004, in forum: C Programming
    Replies:
    6
    Views:
    768
    Dan Pop
    Jun 21, 2004
  3. Replies:
    1
    Views:
    773
  4. Ben
    Replies:
    2
    Views:
    1,327
    jacob navia
    Aug 29, 2009
  5. Terry Cooper
    Replies:
    7
    Views:
    420
    Janos Sebok
    Jun 9, 2009
Loading...

Share This Page