Download this (Unix text) file


#!/usr/bin/perl -w

# Send a postcard by adding to the postcards table in the hcc database
# and send the recipient an email message, using CGI, Perl, and DBI.
#
# (C)1999 by Wayne Pollock, Tampa Florida USA.  All Rights Reserved.
#
# Adapted by Wayne Pollock from an article in "Linux Journal", October 1997
# (Issue #42), pp. 106-111, "Integrating SQL with CGI, Part 1" by
# Reuven M. Lerner.  The Linux Journal is published by SSC, Inc., Seattle, WA.
# For reprint permissions contact linux@ssc.com.

# This is an example of a "combo-form"; with no data, this script
# displays the form.  But when the parameters are present, the data
# is processed.
#
# Correct use of this CGI script is to display an HTML form, with the
# action URL of this script.  The form should have six input fields:
# "sender_name", "sender_email", "recipient_name", "recipient_email",
# "graphic_id" (hidden), and "postcard_text".  The graphic is not
# typped in, but selected by clicking on a graphic.  This in turn sets
# the hidden field.  The graphics to use are fetched from the hcc
# database.

# Show which modules to use: (Perl has literally hundreds of modules!)
use strict;
use diagnostics;
use CGI;
use DBI;

# Define the database we want to talk to:
# (Syntax: DBI:<driver>:<database_name>:<host>:<port>
# where <driver> is 'mysql', <database_name> is 'hcc',
# and the <host> and <port> are optional (defaults to the
# standard port on 'localhost' if omitted).  Note that mySQL
# comes "out of the box" with a "test" database that has
# no security restrictions.  To use it, create a table 'postcards'
# and change "hcc" to "test".
my $db = 'DBI:mysql:hcc';

# Define the directory where the graphic files are
# (Relative to the DocumentRoot of the web server):
my $graphics_dir = "/graphics";

# Define the program to use to send email:
my $mailprog = '/usr/lib/sendmail';

# Create a CGI object:
my $cgi = new CGI;

# Connect to the database (via sockets):  (dbh: DataBase Handle)
# (The arguments to connect are database, username, password.
# The last two arguments are optional and default to 'undef'.)
my $dbh = DBI->connect( $db, 'wwwrun', '' )
   or die "Error on connect, DB=\"$db\": $DBI::errstr ($DBI::err)";

# Send the content type header for the reply:  (This is always the same
# whether we return the form, postcard sent message, or an error message.)
print $cgi->header( "text/html" );

# Get the recipient_email from the form data.  If missing
# $recipient_email will be set to undef; this means to display the form:
my $recipient_email = $cgi->param( "recipient_email" );

if ( (not defined $recipient_email) or ( length $recipient_email == 0 ) ) 
{
   &print_form;
   exit;
}

# Process the form data and add the card to the database:

# Fetch the remaining parameters from the form:
my $recipient_name = $cgi->param( "recipient_name" );
my $sender_name = $cgi->param( "sender_name" );
my $sender_email = $cgi->param( "sender_email" );
my $postcard_text = $cgi->param( "postcard_text" );
my $graphic_id = $cgi->param( "graphic_id" );

# Create the SQL Query (Note the zero means create id_number automatically):
my $sql = "insert into postcards ( ";
$sql .= "id_number, sender_name, sender_email, ";
$sql .= "recipient_name, recipient_email, ";
$sql .= "graphic_id, postcard_text, create_date) ";
$sql .= "values ( 0, \"$sender_name\", \"$sender_email\", ";
$sql .= "\"$recipient_name\", \"$recipient_email\", ";
$sql .= "\"$graphic_id\", \"$postcard_text\", curdate() )";

# Create the SQL Statement:  (sth: STatement Handle)
my $sth = $dbh->prepare( "$sql" )
   or die "Error on prepare, SQL=\"$sql\": $DBI::errstr ($DBI::err)";

# Execute the query, and make sure it worked:
$sth->execute
  or die "ERROR with SQL command \"$sql\" on \"$db\": $DBI::errstr ($DBI::err)";

# Send an email message to the recipient:
&send_email;

# Send the "all done" page back as HTML:
&print_done_page;

# Clean up the statement handle (release memory):
$sth->finish;

# Disconnect fron the database:
$dbh->disconnect;

# All done, time to exit Perl:
exit;

#---------------------------------------------------------------------

sub print_form
{
   # Create SQL query to fetch graphic file names and IDs:
   my $sql = "select id, graphic_file from graphics order by graphic_file";

   # Create the SQL Statement:  (sth: STatement Handle)
   my $sth = $dbh->prepare( "$sql" )
      or die "Error on prepare, SQL=\"$sql\": $DBI::errstr ($DBI::err)";

   # Execute the query, and make sure it worked:
   $sth->execute
     or die "ERROR with SQL command \"$sql\" on \"$db\": $DBI::errstr 
($DBI::err)";

   # Report an error if no rows of data are returned:
   if ( $sth->rows < 1 )
   {  print $cgi->start_html( -title => "Problem with Postcard Database" );
      print "<P> The lookup of the available graphic files failed.&nbsp; ";
      print "Please contact the webmaster of this web site to report the\n";
      print "problem!\n";
      print $cgi->end_html;
      exit;
   }

   # Print the first part of the form using a Here-is document:
   print $cgi->start_html( -title => "Send a Postcard from HCC.COM" );
   print <<"EOF";

<H1 align="CENTER"> Send a Postcard from HCC.COM </H1>
<P>
Just enter the requested information below, and a postcard
will be created and saved on our system for 90 days.&nbsp;
An email message will also be sent alerting the recipient
that a postcard is waiting for them!</P>
<P>
<FORM METHOD="POST" ACTION="/cgi-bin/send-postcard.pl">
<INPUT TYPE="HIDDEN" NAME="graphic_id">
<CENTER><TABLE BORDER="0">
<TR><TH ALIGN="LEFT"> Your name: </TH><TD> <INPUT TYPE="TEXT" 
NAME="sender_name"></TD></TR>
<TR><TH ALIGN="LEFT"> Your email address: </TH><TD> <INPUT TYPE="TEXT" 
NAME="sender_email"></TD></TR>
<TR><TH ALIGN="LEFT"> Recipient's name: </TH><TD> <INPUT TYPE="TEXT" 
NAME="recipient_name"></TD></TR>
<TR><TH ALIGN="LEFT"> Recipient's email address: </TH><TD> <INPUT TYPE="TEXT" 
NAME="recipient_email"></TD></TR>
<TR><TH ALIGN="LEFT"> Your message: </TH><TD> <TEXTAREA NAME="postcard_text" 
ROWS="8" COLS="40">
</TEXTAREA></TD></TR>
</TABLE></P>
<P>
Which of the following graphics would you like on your postcard?</P>

EOF

   # Print out the HTML code for each graphic file listed in the database:
   my ( $id, $file ) = ( "", "" );
   while ( ($id, $file) = $sth->fetchrow )
   {   print <<"EOF";

<A HREF="#" onClick='document.forms[0].graphic_id.value="$id"'; return false;">
<IMG SRC="$graphics_dir/$file" ALT="$file"></A>
EOF
   }

   # Output the rest of the form (using another Here-is document):
   print <<"EOF";

<P><TABLE BORDER="0"><TR><TD>
<INPUT TYPE="SUBMIT" VALUE="Send Postcard"> </TD><TD> &nbsp; </TD><TD>
<INPUT TYPE="RESET" VALUE="Clear Form"></TD></TR>
</TABLE><P>
</CENTER></FORM>
<P><BR><HR><P> The HCC.COM postcard system.
<BR>
&copy;1999 by HCC.COM.&nbsp; All Rights Reserved.
<BR>Contact:&nbsp;
<A HREF="mailto:webmaster\@hcc.com">webmaster\@hcc.com</A>
EOF
   print $cgi->end_html;
}

#---------------------------------------------------------------------

sub send_email
{
   # In order to send email, we need the (generated) id number for
   # the postcard just inserted.  This should be the maximum ID value:
   my $sql = "select MAX(id_number) from postcards";

   # Create the SQL Statement:  (sth: STatement Handle)
   my $sth = $dbh->prepare( "$sql" )
      or die "Error on prepare, SQL=\"$sql\": $DBI::errstr ($DBI::err)";

   # Execute the query, and make sure it worked:
   $sth->execute
     or die "ERROR with SQL command \"$sql\" on \"$db\": $DBI::errstr 
($DBI::err)";

   # Report an error if no rows (or more than one row) of data are returned:
   if ( $sth->rows != 1 )
   {  print $cgi->start_html( -title => "Problem with Postcard Database" );
      print "<P> The lookup of the postcard ID failed.&nbsp; ";
      print "Please contact the webmaster of this web site to report the\n";
      print "problem!\n";
      print $cgi->end_html;
      exit;
   }

   # Get the ID:
   my $id = $sth->fetchrow;

   # Clean up the statement handle (release memory):
   $sth->finish;

   open ( MAIL, "|$mailprog $recipient_email" )
      or die "Can't open \"$mailprog\"!\n";

   print MAIL "From: $sender_email\n";
   print MAIL "To: $recipient_email\n";
   print MAIL "Reply-to: $sender_email ($sender_name)\n";
   print MAIL "Content-type: text/html\n";
   print MAIL "Subject: A Postcard for you!\n\n";

   print MAIL "<HTML><HEAD><TITLE>A Postcard for You!</TITLE></HEAD>";
   print MAIL "<BODY><H1 ALIGN=\"CENTER\">A Postcard for You!</H1><P><PRE>";
   print MAIL "$sender_name has send you an electronic postcard ";
   print MAIL "using the HCC.COM postcard system.\n\n";
   print MAIL "You can retrieve your card for 90 days at the following 
URL:\n\n";
   print MAIL "\t<A HREF=\"http://wpollock.hcc.com/cgi-bin/show-postcard.pl?";
   print MAIL "$id\">http://wpollock.hcc.com/cgi-bin/show-postcard.pl?";
   print MAIL "$id</A>\n";
   print MAIL "</PRE></BODY></HTML>\n";

   close( MAIL );
}

#---------------------------------------------------------------------

sub print_done_page
{
   print $cgi->start_html( -title => "Postcard Sent to $recipient_name" );
   print "<H1 ALIGN=\"CENTER\">Your card has been sent!</H1>";
   print "<P> The card will be available for the next 90 days.";

   print "<P><HR><P> Sent through the HCC.COM postcard system.<BR>\n";
   print "&copy;1999 by HCC.COM.&nbsp; All Rights Reserved.\n";
   print "<BR>Contact: ";
   print ( '<A HREF="mailto:webmaster@hcc.com">webmaster@hcc.com</A>', "\n" );
   print $cgi->end_html;
}