A Complex Cookie Example With Multipage Forms
#!/usr/bin/perl -w

#  The final step towards completion: making sure the data entered by the user 
#  is not nonsense!!  Formatting data into final form!!
#  An additional step -- recovering on formatting errors!

use DBI;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser); # Makes die work acceptably! Very important!!
use CGI::Cookie;

%param = cookie("data");
foreach (qw(Name SSN Color Number))
{
    $param{$_} = param($_) || $param{$_};
}

$go = param("go");
$page = param("page");

($go eq "Submit Information") ? ($exp = "-1d") : ($exp = "+30d");
$cookie = cookie(-name => "data", -value => \%param, -expires => "$exp");

print header(-cookie => $cookie);
print start_html;



if ($go eq "Save Session")
{
     $param{'Name'}   = param('Name');
     $param{'Color'}  = param('Color');
     $param{'SSN'}    = param('SSN');
     $param{'Number'} = param('Number');
     print p(strong("Thanks for visiting our site!\n"));
     print end_html;
     exit;
}


print_page1(\%param) if $go eq "Return to Form" || $page eq "" || 
                       ($go eq "Previous Page"  && $page == 2);
print_page2(\%param) if $go eq "Next Page" && $page == 1;
print_page2(\%param) if $go eq "Previous Page" && $page == 3;
print_page3(\%param) if $go eq "Next Page" && $page == 2;

if ($go eq "Submit Information")
{
     $db = DBI->connect("DBI:CSV:f_dir=.") || 
            die "Cannot connect:  $DBI::errstr\n";

#  Better to create the table definition in the database itself
#  rather than a script.  But here's what it looks like!

   if (!-e "people")
   {
       $cmd = $db->prepare("CREATE TABLE people(
       name varchar(32) not null,
       SSN varchar(32) not null,
       Color varchar(32),
       number integer )");
       $cmd->execute() || die "Cannot create table!\n";
    }

    $name   = param("Name");
    $SSN    = param("SSN");
    $Color  = param("Color");
    $number = param("Number");
    verify($name, $SSN, $number);

    $row = $db->prepare(
                    "INSERT INTO people (name, SSN, Color, number)
                     VALUES            ('$name', '$SSN', '$Color', '$number')");

#  Run the prepared insert statement.
   $row->execute();
   $statement = "SELECT * from people";
      $doit = $db->prepare($statement);
      $doit->execute();
      while (($name, $SSN, $Color, $number) = $doit->fetchrow_array)
             {print p("data: $name, $SSN, $Color, $number\n\n")}
      $db->disconnect() || die "Cannot disconnect\n";
      print end_html;
}


sub print_page1
{
    my ($param) = shift;
 
    print start_form,
          p("Name: "),
          textfield(-name => "Name", -size => 50, -value => $param->{'Name'}),
          p("Social Security Number: "),
          textfield(-name => "SSN", -size => 9, -value => $param->{'SSN'}),
          reset(-name => "Reset"),
          submit(-name => "go", -value => "Next Page"),
          hidden(-name => "page", -value => "1", -override => 1),
 #  Parameter values for Color and Number saved if they exist!!
          hidden(-name => "Color",-value => $param->{'Color'},-override => 1),
          hidden(-name => "Number", -value => $param->{'Number'},
                 -override => 1),
          end_form,
          end_html;
} 


sub print_page2
{
    my ($param) = shift;

    print start_form,
          p("Favorite Color"),
          radio_group(-name => 'Color',
                      -value => ['blue', 'red', 'green', 'yellow', 'purple',
                                 'orange', 'white', 'black', 'brown'],
                      -default => $param->{"Color"}) ,
          p("Favorite Number"),
          textfield(-name => "Number", -size => 3,
                    -default => $param->{"Number"}),
          reset(-name => 'Reset'), 
          submit(-name => "go", -value => 'Previous Page'),
          submit(-name => "go", -value => "Next Page"),
          hidden(-name => "page", -value => "2", -override => 1),
          hidden(-name => "SSN"), hidden(-name => "Name"),
          end_form,
          end_html;
}



sub print_page3
{
    my ($param) = shift;
    my (@rows, $field);

    print start_form;
    foreach $field (qw(Name SSN Color Number))
    {
        push(@rows, Tr(th({-align => LEFT}, $field), td($param->{$field})));
        print hidden(-name => $field);
    }

    print table(@rows), 
          hidden(-name => "page", -value => 3, -override => 1),
          submit(-name => "go", -value => "Previous Page"),
          submit(-name => "go", -value => "Submit Information"),
          submit(-name => "go", -value => "Save Session");

    print end_form, end_html;
}


sub create_hidden
{
     foreach ('Name', 'SSN', 'Color', 'Number')
     {
         print hidden(-name => $_);
     }
} 



sub verify
{
     my ($name, $SSN, $number) = @_;
     my ($err) = 0;

     print (p("Illegal Name!")), $err = 1
            if $name   !~ /^\s*[a-z]+\s+[a-z]+\s*$/i;
     print (p("Illegal Social Security Number!!\n")), $err = 1 
            if $SSN    !~ /^\d{9}$/;
     print (p("Illegal Favorite Number!!\n")), $err = 1
            if $number !~ /^\s*\d{1,3}\s*$/;
     if ($err)
     {
         print start_form;
         create_hidden;
         print submit(-name => "go",  -value => "Return to Form");
         print end_form; 
         print end_html;
         exit;
     }
}