in reply to Odd difference between

You aren't respecting the protocol in your CGI program. All bets are off when you do that.

I'm gonna sound like a broken record but use CGI.pm. You aren't reading $ENV{CONTENT_LENGTH} bytes from STDIN on a POST. That's bound to upset somebody. CGI.pm will do this for you.

Also, check the return value of system calls!

-- Randal L. Schwartz, Perl hacker

Replies are listed 'Best First'.
Re: Odd difference between
by cLive ;-) (Prior) on May 04, 2001 at 11:27 UTC
    Er, I think Randal's misunderstood something, but since it's Randal, I'll just re-read your post...

    OK, I'm gonna go out on a limb here (expecting to be thrashed at any moment... :)

    As far as I can see, your forms/links do not pass any values to the server in the buffer or query string. All they do is serve one PDF file.

    If so, all you need in your script is:

    print "Content-type: application/pdf\n\n"; open(PAGE, "</home/username/pdf/ho99-6a.pdf") || die("Can't open file +- $!"); print while (<PAGE>); close(PAGE); exit(0);

    You would only need to read the query string / buffer if you actually sent any information.

    The only time I would think you might do this is if the document is stored outside the web root and you can't symlink to it.

    What would involve query_string / buffer would be if you sent a variable to the script. ie, the html was something like:

    <html> <body> <a href="/~newbie/cgi-bin/getpdf2.pl?document=ho99-6a.pdf">Click Here +for Test 1</a><p> <FORM METHOD="POST" ACTION="/~newbie/cgi-bin/getpdf2.pl"> <INPUT TYPE="hidden" NAME="document" VALUE="ho99-6a.pdf"> <INPUT TYPE="SUBMIT" VALUE=" Click here for test 2 "> </FORM> <p> <FORM METHOD="GET" ACTION="/~newbie/cgi-bin/getpdf2.pl"> <INPUT TYPE="hidden" NAME="document" VALUE="ho99-6a.pdf"> <INPUT TYPE="SUBMIT" VALUE=" Click here for test 3 "> </FORM> </body> </html>

    Please kick me. I must be missing something here?!?

    cLive ;-)

      "As far as I can see, your forms/links do not pass any values to the server in the buffer or query string. All they do is serve one PDF file."

      It's twue, it's really twue. (Lily VonShtup)

      The sample script was stripped to the absolute bare essentials. Since I was trying to fix a problem in *gag* authenticate.cgi */gag* and the customer did not want to pay for a total rewrite I started cutting down to the fundamental issue. The fundamental issue being: when a pdf file was feed back to a browser it worked fine with Netscape 4.7 or less and with MSIE 5 or less. But a pdf file feed back to a browser would not work with Netscape 6 and MSIE 5.5

      So I eliminated all subroutines, password monkey business, logging mumbo-jumbo, and everything else getting down to spitting out a pdf file based on a script just being called.

      "Please kick me. I must be missing something here?!?"

      No need. I kicked myself enough running around in circles trying to figure out what these new versions of Netscape were upto.

      Turns out just the Submit button was enough data in the stream to cause a problem.

      Near as I can tell when these new versions of Netscape and MSIE send a POST they go into a "waiting for a request to send data" mode.

      If anything other than a "request to read waiting data" comes back to the browser these new versions seem to eat the first string, figure out that the server is not going to ask for data, then start sending the rest of the incoming bytes to the "render the darn page" subroutines.

      I do believe the first string sent to a new browser after a POST is being dumped. Maybe out of spite for being left hanging around with perfectly good posted data. Maybe because the error recovery from an apparently broken CGI session is not the greatest. The older versions of the browsers managed to send the string on into the rendering subroutines. The newer versions don't seem to do that. Leastwise that is the apparent effect.

      The solution to this is to either use the GET method or: read(STDIN, $forminfo, $content_length, $offset);

      The offending script was using <STDIN> to snarf up the POST data. Apparently there is something happening in the newer browsers such that <STDIN> is not "doing the whole trick" -- at least not in this one form/script combination.

      If I replace the read with <STDIN> the script won't fully function for Netscape 6. And if I put the read() back in the script works fine. Or alternately I can switch the POST method to a GET method.

      I'm sure this isn't the whole story. But with the exception of a zillion and a half Matt's scripts still in use around the internet anyone using CGI.pm (which utilizes a proper read($fh, $$buff, $len, $offset);) should be fine.

      So while rewriting the script from scratch would have solved the problem by incorporating proper use of CGI.pm, I do think there is some value in understanding some of the nuances of what's happening in the innards.

      Claude

        I suspect that had you done the rewrite using CGI you would have been done sooner than you were staying with the broken hand-rolled approach.

        And you wouldn't have taken up anyone else's time.

        That is why people chant CGI. It is the good kind of lazy. Takes less work and you come up with answers that you know you can trust.

        The only case where I wouldn't recommend it that I know of is doing .csv downloads to IE 4.x (may be some OS or subversion issue as well there). Why? Because if the browser thinks it is a CGI script, it breaks horribly in loading Excel. (In fact it takes the path, that includes the directory "Temporary Internet Files", splits on the space, and feeds that as 3 files to Excel, none of which are there.)

        In that case I would cheat and store the argument list in $ENV{PATH_INFO}.

        Other than that bug I have not ever heard of any good reason to not do things right with CGI...

        OK, get your point. not gonna plead Randal now - just very drunk.

        What you're stressed about is browser incompatabilty. AFAIK, the best way to consistantly display stuff correctly is with GET method - either in a form, or as a query string (following ? in url link).

        My IE is set to check every time coz I'm always debugging scripts, but let's assume QS requests get cached (they do, don't they? check your /windows/temporary internet files directory...).

        Since over 90% of users use IE, only worry about that and you're 90% there (what a coincidence).

        Anyway, like I said - drunk and in need of sleep.

        cLive ;-)