student has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I am a student learning Perl and I have a question regarding redirection. My script works fine with the exception of the redirection. If I leave one field blank it shows the link of the page I want to display. If I leave two fields blank it shows two links to the page I want to display etc. Can anyone tell me what I am doing wrong? The book I am using is CGI/Perl by Diane Zak. This book doesn't explain things clearly. Any help would be appreciated. Attached is my script...
#!c:\phpdev\perl\bin\perl.exe print "Content-type: text/html\n\n"; use CGI qw(:standard -debug); #prevent Perl from creating undeclared variables use strict; #declare variables my ($Salesperson, $Sales, $Size, $Rate, $Percentage, @records, @errors +, $errors, $bonus); #assign input items to variables $Salesperson = param('Salesperson'); $Sales = param('Sales'); $Rate = param('Rate'); $Percentage = param('Percentage'); #determine size of @errors array $Size = @errors; #calculate bonus rates $bonus = $Rate * $Sales; if ($Salesperson eq "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } if ($Sales == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } if ($Rate == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } else { print "<HTML>\n"; print "<HEAD><TITLE>Patton Industries</TITLE><BASEFONT SIZE=5></HEAD>\ +n"; print "<H1>Bonus Calculation</H1>\n"; print "<BODY>\n"; print "Salesperson: $Salesperson<BR>\n"; printf "Your bonus is: \$%.2f<BR><BR>\n", $bonus; printf "You entered a sales amount of \$%.2f and a \n", $Sales; printf "bonus rate of %.1f%%.<BR>\n", $Rate * 100; print "</BODY>\n"; print "</HTML>\n"; print "</BODY></HTML>\n"; }

2004-11-11 Edited by Arunbear: Changed title from 'Redirection', as per Monastery guidelines

Replies are listed 'Best First'.
Re: HTTP headers and redirection
by jZed (Prior) on Nov 11, 2004 at 03:19 UTC
    Your problem is that you print a content-header at the top of the file. The location header must be the first header. Only print the content header for the HTML, don't print it for the redirect. Also you should use CGI.pm's header() and redirect() methods rather than doing them by hand.
      Not sure exactly what you mean... I edited my script like this and it's still not working. If I move my print "Content-type: text/html\n\n"; things will not work correctly. Also I have no idea how to use CGI.pm's header and redirect methods. This book doesn't go into depth nearly enough to complete these assignments. This is frustrating for me Any help? I am a novice. This is my first Perl Class. Thanks,
      #!c:\phpdev\perl\bin\perl.exe #c12ex3.cgi - Location Header print "Content-type: text/html\n\n"; use CGI qw(:standard -debug); #prevent Perl from creating undeclared variables use strict; #declare variables my ($Salesperson, $Sales, $Size, $Rate, $Percentage, @records, @errors +, $errors, $bonus); #assign input items to variables $Salesperson = param('Salesperson'); $Sales = param('Sales'); $Rate = param('Rate'); $Percentage = param('Percentage'); #calculate bonus rates $bonus = $Rate * $Sales; if ($Salesperson eq "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } elsif ($Sales == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } elsif ($Rate == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } else { print "<HTML>\n"; print "<HEAD><TITLE>Patton Industries</TITLE><BASEFONT SIZE=5></HEAD>\ +n"; print "<H1>Bonus Calculation</H1>\n"; print "<BODY>\n"; print "Salesperson: $Salesperson<BR>\n"; printf "Your bonus is: \$%.2f<BR><BR>\n", $bonus; printf "You entered a sales amount of \$%.2f and a \n", $Sales; printf "bonus rate of %.1f%%.<BR>\n", $Rate * 100; print "</BODY>\n"; print "</HTML>\n"; print "</BODY></HTML>\n"; }
Re: HTTP headers and redirection
by Kalaspuff (Beadle) on Nov 11, 2004 at 03:22 UTC
    The three if-statements you have makes it possible that all three applies;
    if ($Salesperson eq "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } if ($Sales == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } if ($Rate == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; }
    It is better if the two later (for $Sales and $Rate) is used with elsif instead of if. In that case the script won't process any further elsif or else if any of them applies.
      Thanks, But please see what I sent to jzed here and provide any input if you could >> Not sure exactly what you mean... I edited my script like this and it's still not working. If I move my print "Content-type: text/html\n\n"; things will not work correctly. Also I have no idea how to use CGI.pm's header and redirect methods. This book doesn't go into depth nearly enough to complete these assignments. This is frustrating for me Any help? I am a novice. This is my first Perl Class. Thanks,
      #!c:\phpdev\perl\bin\perl.exe #c12ex3.cgi - Location Header print "Content-type: text/html\n\n"; use CGI qw(:standard -debug); #prevent Perl from creating undeclared variables use strict; #declare variables my ($Salesperson, $Sales, $Size, $Rate, $Percentage, @records, @errors +, $errors, $bonus); #assign input items to variables $Salesperson = param('Salesperson'); $Sales = param('Sales'); $Rate = param('Rate'); $Percentage = param('Percentage'); #calculate bonus rates $bonus = $Rate * $Sales; if ($Salesperson eq "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } elsif ($Sales == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } elsif ($Rate == "") { print "Location: http://localhost/cgi-bin/c12ex3b.html\n\n"; } else { print "<HTML>\n"; print "<HEAD><TITLE>Patton Industries</TITLE><BASEFONT SIZE=5></HEAD>\ +n"; print "<H1>Bonus Calculation</H1>\n"; print "<BODY>\n"; print "Salesperson: $Salesperson<BR>\n"; printf "Your bonus is: \$%.2f<BR><BR>\n", $bonus; printf "You entered a sales amount of \$%.2f and a \n", $Sales; printf "bonus rate of %.1f%%.<BR>\n", $Rate * 100; print "</BODY>\n"; print "</HTML>\n"; print "</BODY></HTML>\n"; }
        Let me explain in short words. An HTTP transaction consists of two parts. The first part is the headers, that consist of special data to tell the client how to interpret the data. The second part is the body. Headers are series of name-value pairs seperated by new lines. The header section as a whole is ended by an empty new line. So for example:
        print "Content-type: text/html\n"; print "Location: foo\n\n"; print "This is the body"
        You print two headers: Content-type, and location, then you send "this is the body" as the body of the message. However, if you do this:
        print "Content-type: text/html\n\n"; print "Location: foo\n"; print "This is the body"
        You are only sending one header, the Content-type. The Location: foo line and the "this is the body" is all interpreter as part of the body of the response.
        As a side note: you mention two times your book doesn't contain enough information to solve your problem. Maybe you should try to get better documentation. The reference manual for CGI.pm should be accessible via man CGI (at least on unixoid systems). And have a look at Book Reviews...
      Thanks for your valuable input. It is greatly appreciated. :)

        In reading your responses to the posts, I'm not sure if you solved your problem.

        What you need to do is remove this line (line 2 or 3)
        print "Content-type: text/html\n\n";

        and put it after the last else, just before
        print "<HTML>\n";

Re: HTTP headers and redirection
by larryp (Deacon) on Nov 11, 2004 at 16:16 UTC

    One of your problems comes from the fact that you're printing the header at the top of your script, before your redirect logic.

    #!c:\phpdev\perl\bin\perl.exe print "Content-type: text/html\n\n"; # -----8<-----

    The print line in this block interferes with the redirect statements later in the code. Move your print line from this block to your HTML print block, like so:

    # -----8<----- else { print "Content-type: text/html\n\n"; # Line moved here. print "<HTML>\n"; print "<HEAD><TITLE>Patton Industries</TITLE><BASEFONT SIZE=5></HEAD>\ +n"; # -----8<-----

    In fact, you're printing these headers manually when you should be using CGI.pm. Doing so is simple enough, try this:

    my $cgi = new CGI(); # Declare this near the top of the script. print $cgi->header(); # In place of your "Print: content-type..." +statement.

    A similar convention exists for your redirect statements. Be sure to review the CGI.pm documentation. It will simplify things for you, even if it looks more complicated now.

    A few other suggestions/concerns:

    • What happens when $Salesperson eq "", $Sales == "", and $Rate == "" at the same time?
    • Look into HERE documents. They'll save you a lot of trouble retyping 'print' over and over at the end of your script. :)
    • Read up on CGI.pm. It will save you a lot of typing and tracking with respect to the HTML tags. To do so, open a DOS prompt and type "perldoc CGI.pm", without the quotes, on the command line.

    Hope this helps.

    /Larry

Re: HTTP headers and redirection
by nedals (Deacon) on Nov 12, 2004 at 02:10 UTC
    Follow up on 'Could you critique...'
    #!/usr/bin/perl use strict; # prevent Perl from creating undeclared variables AND con +trol variable scope use CGI qw(:standard -debug); use CGI::Carp(qw/fatalsToBrowser/); ## Fatal Errors to Browser for de +bugging my $q = new CGI; ## Declare a CGI object my %cgi_vars = $q->Vars; ## Read all your form variables into a hash +in one shot. # It's always a good idea to check any <form> data to ensure it is wha +t you expect. # ie: Assuming rate is supposed to be an integer for example # if ($cgi_vars{'Rate'} =~ /$\d+$/) { # all is well # } else { # That's not what's expected, so return an error message or som +ething # } ## calculate bonus rates using the $cgi_vars hash instead of declaring + lots of new variables my $bonus = $cgi_vars{'Rate'} * $cgi_vars{'Sales'}; if (!$cgi_vars{'Salesperson'} || !$cgi_vars{'Sales'} || !$cgi_vars{'Ra +te'}) { print "Location: http://carrotcake.nsm.tridenttech.edu/c12ex3b.htm +l\n\n"; ## The elsif's are not required. You do it all here } else { ## Try to keep your Perl and HTML seperated as much as practical $bonus = sprintf("%.2f", $bonus); my $sales = sprintf("%.2f", $cgi_vars{'Sales'}); my $rate = sprintf("%.1f", ($cgi_vars{'Rate'}*100)); print $q->header(); ## using the CGI module to ouput the required + HTTP header ## Using 'here-is' to ouput the HTML makes it easier to read print <<HTMLPAGE; <HTML> <HEAD><TITLE>Patton Industries</TITLE><BASEFONT SIZE=5></HEAD> <BODY> <H1>Bonus Calculation</H1> <!-- this was in the wrong place --> Salesperson: $cgi_vars{'Salesperson'}<BR> Your bonus is: $bonus<BR><BR> You entered a sales amount of $sales and a bonus rate of $rate </BODY> </HTML> HTMLPAGE }
    Just my thoughts :-)