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

Back when I started Perl/CGI ages ago I always had trouble with HTML forms transfering data to my CGI script. I decided against that since the beginning and have always designed forms completely in CGI so there was no worry about how to collect the data otherwise.

But now I've come to a script that is an HTML form for a login system. I have never really done HTML>CGI before, it's always been CGI>CGI forms.

Any tips on how to go about this quick and easy? There are just two textfields (user and password).



"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Replies are listed 'Best First'.
Re: CGI forms (basic)
by bmann (Priest) on Oct 13, 2004 at 18:35 UTC
    You'd handle the parameters the same way you would if the cgi script generated the html, using CGI's param method. There is a whole lot more to consider here, especially security - password will be passed in plain text. You may want to look at Ovid's cgi course before you get started.

    That said, assume the form is defined like so:

    <form action="cgi-bin/testcgi.cgi" method="post"> <input type="text" name="user"> <input type="password" name="password"> <input type="submit"> </form>
    Look at this cgi script:
    #!/usr/bin/perl -T use warnings; use strict; use CGI; my $q = CGI->new(); print $q->header, $q->start_html; # find and display all parameters print "$_: " . $q->param($_) . "<br>" for $q->param; print $q->end_html;
    $q->param in list context returns a list of each parameter, and $q->param('some_param') returns the value.

Re: CGI forms (basic)
by Yendor (Pilgrim) on Oct 13, 2004 at 17:49 UTC
    login.html:
    <html> <head> <title>Login Page</title> </head> <body> <h1>Login Page</h1> <form name="LoginForm" action="/cgi-bin/login.pl" method="post"> <table align="center"> <tr> <td>Username:</td> <td><input type="text" name="Username" /></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="Password" /></td> </tr> <tr> <td colspan="2" align="right"> <input type="reset" value="Clear" /> <input type="submit" value="Login" /> </td> </tr> </table> </form> </body> </html>
    login.pl:
    #!/usr/bin/perl -wT ######################################### ### Name : login.pl ### Date : December 2002 ### Purpose : To provide a script that will take the input ### : of an HTML input form with Username and ### : Password fields and validate the input ### : against information stored in a Postgres ### : database on localhost. ######################################### #BEGIN { # print "Content-type: text/plain\n\n"; #} use strict; use lib qw ( . ); use CGI::Pretty; use CGI::Session qw/-ip-match/; use DBI; use Constants; $|++; $CGI::Pretty::INDENT = " "; require "./include/db.pl"; require "./include/validate.pl"; require "./include/hope_generics.pl"; main(); ####################################################### ### Username and password match. Successful login. ####################################################### sub print_content { my %login = @_; print "<div class=\"Content\">\n\n"; print "<h1>You've logged in!</h1>\n\n"; print "<p>Welcome, $login{USERNAME}</p>\n\n"; print "</div>\n\n"; $sql->finish(); db_disconnect($dbh); } sub debug_inputs { my $cgi = shift;; my %login = @_; print $cgi->div({-class=>'Content'}, $cgi->p('Username = ' . $login{USERNAME}), $cgi->p('Password = ' . $login{PASSWORD}), $cgi->p('Match = ' . $login{MATCH}), ); } sub validate_inputs { my $cgi = shift; my $debug = 0; my %login = ( USERNAME => validate_char($cgi->param('Username'), 20), PASSWORD => validate_alphanumeric($cgi->param('Password'), 20), VALID => 0 ); if ($login{USERNAME} ne "" && $login{PASSWORD} ne "") { $login{VALID} = 1; } else { $login{VALID} = 0; } if ($debug != 0) { debug_inputs($cgi, %login); } return %login; } sub check_password { my %login = @_; my $dbh = db_connect(); ####################################################### ### Grab the password stored in the database for the ### username entered. ### There's a possibility that the username doesn't ### exist. This should be handled gracefully. ####################################################### my $sql = $dbh->prepare_cached(' SELECT L_ID, L_Password FROM Login WHERE L_Username = ?;'); $sql->execute($login{USERNAME}); my ($db_id, $db_password) = $sql->fetchrow_array(); if ($db_password eq $login{PASSWORD}) { $login{MATCH} = 1; $login{USERID} = $db_id; $sql = $dbh->prepare_cached(' INSERT INTO LoginHistory (LH_L_ID, LH_CreatedDate) VALUES (?, CURRENT_TIMESTAMP);'); $sql->execute($db_id); } else { $login{MATCH} = 0; } $sql->finish(); db_disconnect($dbh); return %login; } sub print_bad_password { my $cgi = shift; print $cgi->div({-class => 'Content'}, $cgi->h1("The username you entered does not exist, or the password does not match.") ); } sub main { my $cgi = create_cgi(); my $session = new CGI::Session("driver:File", $cgi, { Directory => $Constants::DIRECTORY }); $session->expire('+15m'); my $cookie = $cgi->cookie(CGISESSID => $session->id); my %login = validate_inputs($cgi); if ($login{VALID} == 1) { %login = check_password(%login); if ($login{MATCH} == 1) { $session->param("USERNAME", $login{USERNAME}); $session->param("USERID", $login{USERID}); print $cgi->header( -cookie => $cookie ); print_head(); print_content(%login); } else { print $cgi->header(); print_head(); print_bad_password($cgi); } } else { print $cgi->header(); print_head(); print_not_logged_in(); } print_footer(); exit(0); }

    NOTE: This code is ugly, sloppy, and bad form. But it works (at least, it does on my machine where I have all the required files. print_head() basically prints from <html> up to <body>. print_footer() prints their closing tags. The validate methods basically untaint the user input from the form's textfields. db_connect() sets up all the required fields for logging into my database (Postgres, as mentioned), and does a return DBI->connect(...);. db_disconnect() simply does a $dbh->disconnect();

    This could be implemented MUCH better, and more cleanly. I will be the first to admit that I have not yet worked with any of the (supposedly) great HTML templating languages provided by CPAN. That's the next step I plan to take with the application from which I've pulled this code. But, as they say..."In my spare time..."

Re: CGI forms (basic)
by csuhockey3 (Curate) on Oct 13, 2004 at 17:24 UTC
A reply falls below the community's threshold of quality. You may see it by logging in.