Recipe 19.12 Saving a Form to a File or Mail Pipe
19.12.1 Problem
Your CGI script needs to save or mail
the entire form contents to a file.
19.12.2 Solution
To store a form, use the CGI module's
save_parameters function or
save method, which take a filehandle argument. You
can save to a file:
# first open and exclusively lock the file
open(FH, ">>/tmp/formlog") or die "can't append to formlog: $!";
flock(FH, 2) or die "can't flock formlog: $!";
# either using the procedural interface
use CGI qw(:standard);
save_parameters(*FH); # with CGI::save
# or using the object interface
use CGI;
$query = CGI->new( );
$query->save(*FH);
close(FH) or die "can't close formlog: $!";
or save to a pipe, such as one connected to a mailer process:
use CGI qw(:standard);
open(MAIL, "|/usr/lib/sendmail -oi -t") or die "can't fork sendmail: $!";
print MAIL <<EOF;
From: $0 (your cgi script)
To: hisname\@hishost.com
Subject: mailed form submission
EOF
save_parameters(*MAIL);
close(MAIL) or die "can't close sendmail: $!";
19.12.3 Discussion
Sometimes all you want to do with
form data is to save it for later use. The
save_parameters function and
save method in CGI.pm write form parameters to an
open filehandle. That filehandle can be attached to an open file
(preferably one opened in append mode and locked, as in the
Solution), or to a pipe whose other end is a mail program.
File entries are stored one per line as
variable=value pairs, with any funny characters
URL-escaped. Each record is separated by a line with a single equals
sign. These are typically read back by invoking the
CGI->new method with a filehandle argument that
manages all of the unescaping automatically, as described later.
If you want to add extra information to your query before you save
it, the param function (or method, if you're using
the object-oriented interface) can take more than one argument,
setting the value(s) of a form parameter. For example, here's how to
save a time stamp and the entire environment:
param("_timestamp", scalar localtime);
param("_environs", %ENV);
Once you have the forms in a file, process them by using the object
interface.
To load a query object from a filehandle, call the
new method with a filehandle argument. Each time
you do this, it returns a complete form. When end of file is hit, the
returned form has no parameters. The following code demonstrates this
approach. It keeps a running total of all "items
request" parameters, but only if the form was not
submitted from a perl.com site. Remember, we
added the _environs and
_timestamp parameters when we wrote the file.
use CGI;
open(FORMS, "< /tmp/formlog") or die "can't read formlog: $!";
flock(FORMS, 1) or die "can't lock formlog: $!";
while ($query = CGI->new(*FORMS)) {
last unless $query->param( ); # means end of file
%his_env = $query->param('_environs');
$count += $query->param('items requested')
unless $his_env{REMOTE_HOST} =~ /(^|\.)perl\.com$/
}
print "Total orders: $count\n";
File ownership and access permissions are an issue here, as for any
files created by CGI scripts.
19.12.4 See Also
Recipe 18.3; Recipe 19.3
|