1
votes

I'm trying to run a cgi script on Abyss web server on Windows 10, following a script from CGI & Perl by Mike MCCGrath.

There is a simple HTML form (colours html) that sends data to a CGI script called colours.cgi

The colours.html is

<!DOCTYPE html>
<html>
<head>
<title>Form template</title>
</head>
<body>
<form method="POST" action="http://localhost/colours.cgi">
1:
<input type="text" name="colour1" size="25">
2:
<input type="text" name="colour2" size="25">
3:
<input type="text" name="colour3" size="25">
<input type="submit" value="Send">
</body>
</html>

The colours.cgi script which requires a file called formparser.lib is as follows:

 require "formparser.lib";
    &parseform;
    print "Content-type: text/html\n\n <html>";
    print "You entered these colours:";
    print "$formdata{'colour1'}, ";
    print "$formdata{'colour2'}, ";
    print "$formdata{'colour3'}  </html>";

Finally the formparser.lib file is:

sub parseform {
 if ($ENV{'REQUEST_METHOD'} eq 'GET') {
 @pairs = split(/&/, $ENV{'QUERY_STRING'});
 }
 elsif ($ENV{'REQUEST_METHOD'} eq 'POST'){
 read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
 @pairs = split(/&/, $buffer);
 if ($ENV{'QUERY_STRING'}) {
 @getpairs = split(/&/, $ENV{'QUERY_STRING'});
 push (@pairs, @getpairs); }
 }
 else {
 print "Content-type:text/html\n\n";
 print "Unrecognized Request Method - User GET or POST";
 }

 foreach $pair (@pairs) {
 ($key, $value) = split (/=/, $pair);
 $key =~ tr/+/ /;
 $key =~ tr/%(..)/pack("c", hex($1))/eg;
 $value =~ tr/+/ /;
 $value =~ tr/%(..)/pack("c", hex($1))/eg;
 if ($formdata{$key}) {
 $formdata{$key} .= ", $value";
 }
 else {formdata{$key} = $value;}
 }
 }
 1;

So when colours.html opens, I have a form with 3 input fields, where i want to send the names of 3 colours to colours.cgi. However, when I submit I get Error 500.

I have mananged to get other CGI scripts running with the Abyss web server. I have configured the path to Strawberry Perl, and included associated extensions .pl, .cgi etc.

I'm thinking it is something to do with the 'requires lib' part of the script. Is there anything I need to be aware of when using require with lib files in a CGI script, in terms of server setup etc. The Abyss log says

CGI: [C:\strawberry\perl\bin\perl.exe colours.cgi ] URI: /colours.cgi   Broken pipe

many thanks John

1
Does it work if you change it to require "./formparser.lib" ? I think this is a .-in-@INC thing but I'm not certain. Also, doesn't your webserver log the stdout of CGI processes anywhere? It's pretty hard to debug when the actual error messages are hidden. - hobbs
No it doesn't work if I use require "./formparser.lib". I can't see the stdout of CGI processes anywhere unfortunately - John D
(Meant stderr, but same idea anyway) - hobbs
Note that you shouldn't assume the current work directory is the same as the script's directory. See this - ikegami
I'm voting to close this question as off-topic because there's little we can do without an error message - ikegami

1 Answers

1
votes

I copied your form parsing code into a file and asked perl to check the syntax:

$ perl -c formparser.lib
Bareword found where operator expected at formparser.lib line 20, near "tr/%(..)/pack("c", hex($1))/eg"
Bareword found where operator expected at formparser.lib line 22, near "tr/%(..)/pack("c", hex($1))/eg"
syntax error at formparser.lib line 20, near "tr/%(..)/pack("c", hex($1))/eg"
syntax error at formparser.lib line 22, near "tr/%(..)/pack("c", hex($1))/eg"

So there's a problem with these two lines.

Line 20:

$key =~ tr/%(..)/pack("c", hex($1))/eg;

Line 22:

$value =~ tr/%(..)/pack("c", hex($1))/eg;

I'm not sure which "very old book" you got this code from, but it's never going to work. [Update: Oh, yes I do - you mentioned it in your question.]

Perl has two operators that you can use to carry out substitutions - tr/// can be used to make simple "replace one character with another" substitutions and s/// can be used to make more complicated substitutions using regular expressions or using Perl code in the replacement text.

This code contains a perfect example of the simple substitution that tr/// would be used for:

$key =~ tr/+/ /;

In this code we replace a "+" with a space. That's simple enough and tr/// is the perfect approach to do this.

However, the other use of tr/// in this code is wrong.

$key =~ tr/%(..)/pack("c", hex($1))/eg;

This is trying to do something far more complex. It's trying to do this:

Find a percent sign followed by two characters. Capture those two following characters in $1. Interpret those characters as a hexadecimal number and convert that into the matching character. Then replace the original string (the percent followed by two characters) with the character that we've found. And do that for every percent sign followed by two characters you can find in the input string.

That's not something you can do with tr///. That needs s///.

So you need to replace:

$key =~ tr/%(..)/pack("c", hex($1))/eg;

With:

$key =~ s/%(..)/pack("c", hex($1))/eg;

And you need to make the same change on the $value line.

And I'd probably recommend burning the book that gave you this code too.