perlnewbie-newbie has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm the latest newbie to Perl, and I've only started doing it a few weeks ago. I've searched around a little bit here and found that using cgi.pm is the way to go when it comes to generating a web form and processing it. However, my codes don't use cgi.pm, and I'm wondering whether I'm doing things the way I'm supposed to...

Here's a rundown of my code:

#!/usr/bin/perl use CGI::Carp "fatalsToBrowser"; use DBI; ### Subroutine that parses the form. sub parse_form { # Get the input. read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); # Splits the name-value pairs @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $FORM{$name} = $value; } ### Subroutine that catches form variables sub get_variables { $name = $FORM{'name'}; $username = $FORM{'username'}; $email = $FORM{'email'}; #other variables follow . . . } ### Subroutine that validates form submission sub validate_form { #validation routines, eg: if ($name eq "") { $error = '1'; $errname = '1'; $error1 = "<a href=\"javascript:alert('Please enter a name.')\ +"><img src=\"/pics/generic/error.gif\" border=\"0\"></a>"; } . . . } ### Subroutine that generates the page with error indications sub printHTML { print "Content-Type: text/html\n\n"; $filename = "signup.htm"; open (INFILE,$filename); while (<INFILE>) { #alot of substitutions here...eg: if ($errname='1') { s/<input type="hidden" name="hiddenField" value= +"~error1~">/$error1/g; } . . . print $_; } close(INFILE); } ########### Main body #form submitted with arguments, so process it if ($ENV{'CONTENT_LENGTH'}) { &parse_form; &get_variables; &validate_form; #if no error, insert into db if ($error eq '0') { #insert form data into db } #if errors, substitute hidden fields with arrows indicating error l +ocations & messages else { &printHTML; } } #first time in: no arguments in form, so present empty form else { print "Content-Type: text/html\n\n"; $filename = "signup.htm"; open (INFILE,$filename); while (<INFILE>) { print $_; } close (INFILE); }
What I'm getting now is that the form doesnt remember the user's input data into all the form fields. The error arrows and messages show up correctly, just that each time I submit the form with errors, the input data will be erased which is surely unuser-friendly. I guess the general idea of doing it is: retrieve all the input data variables (ie $name, $username etc) and put them back into the form fields, all these in &printHTML subroutine.

But the exact way of doing that I'm not sure. I'd greatly appreciate any help here. Thanx in advance!

Edit by tye to add <p>,<readmore>.

Replies are listed 'Best First'.
Re: Remembering form data without cgi.pm
by Juerd (Abbot) on Apr 11, 2002 at 07:44 UTC

    Warning: I'm not going to answer the question itself, as usage of CGI.pm will fix that almost automagically.

    • You use only global variables. For example, the @pairs you use in your parsing routine, is visibile everywhere. This might not be a problem in small scripts, but when you code larger programs, it will definitely bite you. Try using strict and declaring variables with my. When you do so, variables will cease to exist when the surrounding scope (block) ends.
    • Your parsing routine can't handle multiple values. This may not be a problem now, but will be when you use multiple form elements that have the same name. With a query string of foo=bar&foo=xyzzy, the bar value is lost, and overwritten by the xyzzy one. You might think it's not likely to have multiple form elements with the same name, but think about <select multiple> for example, or a greater number of form fields, which can be handy if you use JavaScript to generate more elements if required.
    • A value containing multiple = characters will not be parsed right: foo=bar=baz will not set $FORM{foo} to bar=baz but to bar.
    • Your indenting in the last else block is terrible. You seem to understand why indenting is important and how it works, but you don't pay attention to it over where, leaving a whitespace mess.
    • CONTENT_LENGTH is not what you want to check for POST requests, as POST requests can be empty - try using REQUEST_METHOD.
    • Have you been reading a Perl 4 book? The & character when without parens and used to call a sub distributes the current @_, which isn't useful in this case, and will bite you in more complex code if you continue to use it when you don't need @_ to be passed around.

    Yes, I reinvent wheels.
    

Re: Remembering form data without cgi.pm
by George_Sherston (Vicar) on Apr 11, 2002 at 09:11 UTC
    However, my codes don't use cgi.pm, and I'm wondering whether I'm doing things the way I'm supposed to...

    Wonder no more! You *aren't* doing things the way you're supposed to! Well, of course the glory of Perl is there *is* no way you're supposed to do things; but there are some ways which are so well tried (and the alternatives so provenly poor) that it makes no sense to do anything else. CGI.pm is one of them. I know. I went on for six months rolling my own and getting more and more tangled in coils of unaccountable legacy code and taking hours to script stuff that should have taken minutes. Then I made the very limited effort to read the CGI docs. And... well, let's just say I wish I'd done it earlier.

    This is why you'll find few monks will answer your question directly. Most people here are so convinced, for good reasons, about CGI.pm that they feel, rightly, that it's a waste of everyone's time to help someone figure out how to do without it. (NB don't take it personally if somebody shoots down the question - it's just that it's been asked quite a few times before!)

    § George Sherston
Re: Remembering form data without cgi.pm
by derby (Abbot) on Apr 11, 2002 at 11:56 UTC
    And just to add to the discussion, look at (and bookmark) Ovid's home page (especially the 'Use CGI or die" node). The take a look at CGI and while your at it, send some money Lincoln's way.

    -derby

Re: Remembering form data without cgi.pm
by perlnewbie-newbie (Initiate) on Apr 11, 2002 at 16:40 UTC
    Thanks Juerd, George and Derby for your input! Well I guess it's everyone's guess that I'm practically a newbie not only in Perl but also in programming in general. Really appreciate you guys' feedback and will bear in mind what you have said here. This is really a treasure trove of resources here, it's hard to believe sucha site exists. Keep up the good work! And oh, just a last note to say that I've got my little program up there running as I want it - I guess it's one long and arduous way around the problem but I'm running short on time and just hoping that my solution oughta do the job (though I'm sure it doesnt epitomise good programming and efficiency ;) Thanks once again!
    A reply falls below the community's threshold of quality. You may see it by logging in.