Saving a Form to a File or Mail Pipe (Perl Cookbook, 2nd Edition)

## 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

Copyright © 2003 O'Reilly & Associates. All rights reserved.