1

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

John D
  • 311
  • 2
  • 7
  • 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 Nov 20 '19 at 21:34
  • No it doesn't work if I use require "./formparser.lib". I can't see the stdout of CGI processes anywhere unfortunately – John D Nov 20 '19 at 22:02
  • (Meant stderr, but same idea anyway) – hobbs Nov 20 '19 at 22:16
  • Note that you shouldn't assume the current work directory is the same as the script's directory. See [this](https://stackoverflow.com/a/46550384/589924) – ikegami Nov 20 '19 at 23:07
  • I'm voting to close this question as off-topic because there's little we can do without an error message – ikegami Nov 21 '19 at 02:26
  • Is `formparser.lib` really so badly formatted? :-) – Dave Cross Nov 21 '19 at 13:28
  • I recommend switching from `formparser.lib` to `CGI.pm` (which is probably a standard part of the Perl installation on your system). It'll be like moving your development practices from 1995 to 2003. – Dave Cross Nov 21 '19 at 13:30
  • @ikegami Yes fair enough – John D Nov 21 '19 at 17:04
  • @DaveCross there’s one $ missing otherwise it’s straight from the book. The very old book – John D Nov 21 '19 at 17:23
  • If you can't get the errors to go to the log file then you could (temporarily) add `use CGI::Carp qw(fatalsToBrowser);` to the CGI program in order to send them to the browser. – Dave Cross Nov 22 '19 at 09:22

1 Answers1

1

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.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97