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

I have an HTML form which contains two fields, one is called "name" and the other is called "email". (Bonus points if you can guess what they contain!)

What I'd like to do is take these fields and append them to a file. I'm sure that it must be a 2 line program to do this. I've searched through the archives, and apparently CGI.pm is the way to go- unfortunately, I'm new to Perl and not certain about how to utilize it. The examples I tried did not seem to work. Help?

Replies are listed 'Best First'.
(Ovid) Re: CGI Form processing
by Ovid (Cardinal) on Jun 29, 2001 at 00:41 UTC

    The basic steps are as follows:

    • Read form data
    • Untaint this data (see perlsec)
    • open and then flock a lockfile.
    • open the log file and write the data to it.

    The reason for the lockfile is simple: you can't flock a file until it's opened, but by then something else might already have opened that file and done something to it. Two programs trying to access your log at the same time (say, one for reading and one for writing) could cause data corruption or a race condition. By using a lock file, you have a file that can safely be opened and flocked without worrying about whether or not it's going to get corrupted.

    #!/usr/bin/perl -wT use strict; use Fcntl qw/:flock/; use CGI qw/:standard/; my $log = 'somelog.log'; my $lockfile = "$log.lock"; # grab form data my $_name = param( 'name' ); my $_email = param( 'email' ); # untaint form data my ( $name ) = ( $_name =~ /^([\w.',]{1,30})$/ ) or some_error_routine( $_name ); # I *hate* dot-star untainting, but virtually any character # is valid in an email address. my ( $email ) = ( $_email =~ /^(.{1,500})$/ ) or some_error_routine( $_name ); # We're getting rid of ASCII zero as this is the delimiter # in the file we're writing to. $email =~ s/\0//g; open LOCK, "> $lockfile" or die "Cannot open $lockfile: $!"; flock LOCK, LOCK_EX or die "Cannot flock $lockfile: $!"; open LOG, ">> $log" or die "Can't open $log for appending: $!"; print LOG "$name\0$email\n"; close LOG; close LOCK; # output some response here

    Note that the above code is incomplete and untested. Further, I have limited the length of the $name and $email variables. This is done to ensure that someone doesn't try to enter unreasonably large values for this data.

    Cheers,
    Ovid

    Vote for paco!

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      If all programs are going to read or write the log, then there is no need for the lockfile. Everything can flock the log directly.

      There are two good reasons to use a lockfile. The first is that you may have operations involving multiple data sources and you want to maintain sync. The second is that you are both reading and writing to the same file and you want to avoid race conditions due to dropping the lock. But if everything is either just reading or just writing, then there is no race to worry about.

      Also one warning on lockfiles. If you want to get atomic behaviour (if you don't know what that is then let your eyes glaze over and say "Yes") then you do not want to delete the lockfile. Else 2 processes can go to create it at once, one creates, the other overwrites with its new, both have filehandles to different files. (One is temporary.) The flocks both are captured at once, both think they have the lock. The timing has to be reasonably precise to do this, but it is worth knowing about.

      If you're sure that the data you're appending is under BUFSIZ chars (like 8192 on most modern Unix systems), you can use syswrite and avoid the flock, because append-writes are atomic. Saves a few steps, anyway.

      -- Randal L. Schwartz, Perl hacker

        As I recall, if you use syswrite, then the value of BUFSIZ doesn't matter. BUFSIZ matters if you allow buffering or if you are using pipes.

                - tye (but my friends call me "Tye")
      Thank you very much!
Re: CGI Form processing
by mexnix (Pilgrim) on Jun 29, 2001 at 00:10 UTC
Re: CGI Form processing
by cLive ;-) (Prior) on Jun 29, 2001 at 00:01 UTC
    Read this and come back if you're still stuck with a code example showing where you got to.

    cLive ;-)

      cLive, I cannot thank you enough.
      I have been struggling with some hand coded CGI for a week and this looks like exactly what the doctor ordered.

      DanH