JMAD2016
JMAD2016

Reputation: 121

Perl: CGI redirect from multiple submit buttons

I have a small CGI Script with 2 submit buttons. I want that the current Script redirects the User to another script, depending on which submit button is pressed.

The CGi-Script:

#!/usr/bin/perl -w

# Modules
use strict;
use warnings;
use CGI;

my $q                           = CGI->new();
print $q->header();
print $q->submit(-name=>'button',-value => 'disable');
print $q->submit(-name=>'button',-value => 'enable');

if ($q->param('button') eq "disable"){
         print $q->redirect(-uri=>"http://1.1.1.1./cgi-bin/services/switch_XXX.cgi?disable");
} elsf ($q->param('button') eq "enable"){
        print $q->redirect(-uri=>"http://1.1.1.1./cgi-bin/services/switch_XXX.cgi?enable");
} else {
}

But none of the actions is actually performed. The Error-Log shows the following:

[Tue Mar 06 11:48:44 2018] [error] [client XXXX] Use of uninitialized value in string eq at /var/www/cgi-bin/test.cgi line 23.
[Tue Mar 06 11:48:44 2018] [error] [client XXXX] Use of uninitialized value in string eq at /var/www/cgi-bin/test.cgi line 26.

Could someone of you tell me what causes the error and why the redirect is not working?

Many thanks in advance!

Upvotes: 1

Views: 828

Answers (2)

Dave Cross
Dave Cross

Reputation: 69274

If you are just starting to write web applications in Perl, I would urge you to read CGI::Alternatives and decide whether you really want to use such old technology when newer and better (and still Perl-based) alternatives are available.

However, if you decide to stick with CGI (and CGI.pm) then there are a couple of things that can make your life easier.

It's a rare CGI program that needs two CGI objects

For most CGI programs, using an object-oriented approach is overkill. You rarely need objects. CGI.pm has a, simpler, function-based approach that you can use instead. Simply, import the functions that you want to use as you load the module:

use CGI qw[param header redirect];

Then use them without creating an object first:

if (param) {
  print redirect(...);
} else {
  print header(...);
}

The CGI-Generation functions are a terrible idea

It's even in the documentation.

HTML Generation functions should no longer be used

All HTML generation functions within CGI.pm are no longer being maintained. Any issues, bugs, or patches will be rejected unless they relate to fundamentally broken page rendering.

The rationale for this is that the HTML generation functions of CGI.pm are an obfuscation at best and a maintenance nightmare at worst. You should be using a template engine for better separation of concerns. See CGI::Alternatives for an example of using CGI.pm with the Template::Toolkit module.

These functions, and perldoc for them, are considered deprecated, they are no longer being maintained and no fixes or features for them will be accepted. They will, however, continue to exist in CGI.pm without any deprecation warnings ("soft" deprecation) so you can continue to use them if you really want to. All documentation for these functions has been moved to CGI::HTML::Functions.

Putting your HTML into an external template is a much better idea. And it will be easier for your front-end developer to edit. Yes, I realise you probably don't have a front-end developer on your project right now - but don't you want to plan ahead?

Having said that, your program becomes something like this:

#!/usr/bin/perl

use strict;
use warnings;
use CGI qw[param header redirect];

my $disable_url = '...';
my $enable_url  = '...';

if (param('button') {
  if (param('button') eq 'disable') {
    print redirect($disable_url);
  } elsif (param('button') eq 'enable') {
    print redirect($enable_url);
  }
  exit;
} 

print header;
print $some_output_that_is_generated_from_a_template.

Upvotes: 2

haukex
haukex

Reputation: 3013

See "Generating a redirection header" in the CGI docs: "If you use redirection like this, you should not print out a header as well."

The messages you're seeing in the log are referring to the $q->param('button') eq "disable" checks: $q->param('button') is returning undef because the field has not been submitted yet, so you're comparing "disable" to the undefined value. These are warning messages only, that you can avoid by first checking if $q->param('button') has a true value before doing the eq comparison. (Note: In other cases, one might want to use defined to check for undef, because there are some values in Perl that are defined but still false, see Truth and Falsehood - but in this case, both "disable" and "enable" are true values.)

Also, your submit buttons need to be in a <form>. And note you've got a typo with elsf. This works for me:

#!/usr/bin/env perl
use strict;
use warnings;
use CGI;

my $q = CGI->new();
if ( $q->param('button') && $q->param('button') eq "disable" ) {
    print $q->redirect(-uri=>"...");
} elsif ( $q->param('button') && $q->param('button') eq "enable" ) {
    print $q->redirect(-uri=>"...");
} else {
    print $q->header();
    print $q->start_html;
    print $q->start_form;
    print $q->submit(-name=>'button', -value=>'disable');
    print $q->submit(-name=>'button', -value=>'enable');
    print $q->end_form;
    print $q->end_html;
}

Upvotes: 3

Related Questions