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

I'm attempting to write a form that redirects users to certain pages based on their domain name. They must choose webmail or email administration, and then type their domain. When they submit, the script will redirect them to the proper page based on their input. Here's the code:

# takes input from a form and redirects # users to proper web page use CGI qw(:standard); my $domain = param("domain"); my $type = param("type"); if ($type eq 'webmail' && $domain ne ''){ print "Content-type: text/html\n\n"; print "<html><head><META http-equiv=\"refresh\" content=\"0; url=h +ttp://mail.$domain/cgi-bin/sqwebmail\">\n"; print "</head></html>\n"; } elsif ($type eq 'admin' && $domain ne ''){ print "Content-type: text/html\n\n"; print "<html>\n"; print "<head>\n"; print "<META http-equiv=\"refresh\" content=\"0; url=http://mail.$ +domain/cgi-bin/qmailadmin\">\n"; print "</head>\n"; print "</html>\n"; } else { print header(), start_html("Mail Login"); print "<form action=\"/cgi-bin/maillogin.pl\" method=\"POST\">\n"; print "<p><input type=\"radio\" name=\"type\" value=\"webmail\">\n +"; print "Webmail Login</p>\n"; print "<p><input type=\"radio\" name=\"type\" value=\"admin\">\n"; print "E-mail Administration</p>\n"; print "<p>Domain name (without \"www\"): <input name=\"domain\"></ +p>\n"; print "<p><input type=\"submit\" value=\"Go to login\"></p>\n"; print "</form>\n"; }

I wrote this quickly to get started. It works just fine, with an exception: If the domain is mistyped, I will be redirected to a nonexistent page and I get the DNS error in the browser. I can deal with that; it's not my problem if people can't spell their domain names. The real problem is if the "back" button is pressed in the browser. The variables still have the incorrect values and I'm stuck in a loop.

Maintaining a list of domain names for validation would be difficult at this point for a few reasons. Is there some way I can rewrite the script to avoid the above behavior?

Thanks in advance for any help. Oh, and by the way, the lack of a shebang line is due to the fact that this is running on a Win server with IIS.

Replies are listed 'Best First'.
Re: Problem with form submission and redirect
by Aristotle (Chancellor) on Aug 26, 2002 at 16:47 UTC

    Since you've already been given the solution, I want to put in a few words on style.

    First of all, you can avoid backslashitis by using the quotelike operators that let you use any character as quote terminator:

    print qq!<p><input type="radio" name="type" value="admin">\n!; Better yet, if you use an opening curly, bracket, paren or such, the terminator will be a closing one: print qq{<p><input type="radio" name="type" value="admin">\n}; However, please, please avoid rows of print statements. Use here documents instead.
    print <<"EOT"; Content-type: text/html <html> <head> <meta http-equiv="refresh"content="0;url=http://mail.$domain/cgi-bin/s +qwebmail"> </head> </html> EOT

    Makeshifts last the longest.

      Thanks for the tips. I was going to use a here document, but I couldn't get it working initially. I didn't realize I needed to wrap it in quotes until I looked at an old script I wrote that made use of a here document.

      Having never had any sort of instruction in Perl, I'm not sure of the reason why rows of print statements are to be avoided. Is it simply for readability, or is there a functional advantage?

        Well, compare
        print "Content-type: text/html\n\n"; print "<html>\n"; print "<head>\n"; print "<META http-equiv=\"refresh\" content=\"0; url=http://mail.$ +domain/cgi-bin/qmailadmin\">\n"; print "</head>\n"; print "</html>\n";
        with
        print <<REDIRECT; Content-type: text/html <html> <head> <META http-equiv="refresh" content="0; url=http://mail.$domain/cgi-bin +/qmailadmin> </head> </html> REDIRECT

        I would say that the second one is more readable and more maintainable. And be sure to read merlyn's strong suggestion to use CGI.pm for this particular application, instead of the code above.

        --t. alex
        but my friends call me T.

Re: Problem with form submission and redirect
by fglock (Vicar) on Aug 26, 2002 at 16:25 UTC

    Using "Refresh" with time=0 is a problem in most browsers.

    You'd better use a bigger time (5 seconds is ok) and put a small message in the page ("You are being redirected to ... " with a link). This will allow the user to press "back" to go back to your form, or press the link to go fast forward. If it doesn't connect to the redirected page, the user can press "back" 2 times to get to the form.

      Hmm, I've never had a problem with a zero second refresh time. I've tested it with IE 5.0 and 5.5; Mozilla 1.0 and 1.1b; and Opera 6.0x.

      Hitting the back button twice will solve the problem, but that relies on the end user having the wherewithal to realize they need to do that. I do see how a five second delay with a link should give them an opportunity to hit "back" twice, but I'm not sure I want to rely on anyone's ability to figure that out. Unfortunately.

        Please do not use the HTML hack for redirect if you're generating the entire response anyway. The HTML hack is merely for those (hopefully rare) situations where only the content of a page is accessible to the content provider. In a CGI situation, this is clearly not the case.

        I'd suggest studying the redirect method of the CGI module.

        And yes, I'd fail your code in a code review because of that. Red flagged, not permitted to be deployed.

        -- Randal L. Schwartz, Perl hacker

Re: Problem with form submission and redirect
by zentara (Cardinal) on Aug 28, 2002 at 00:24 UTC
    Just for fun I read Merlyn's warning, and decided to test some of this code with the Mozilla browser and Apache. Wow!!!!!!!! The following code acts as a "BrowserBomb", my little Mozilla icon in the upper right corner starts flashing, the STOP button dosn't work, and I need to kill the browser to stop it. Red Flag is right
    #!/usr/bin/perl print <<REDIRECT; Content-type: text/html <html> <head> <META http-equiv="refresh" content="0; url=http://192.168.0.1> </head> </html> REDIRECT