1.
Form handling 2.
References
by Jürgen Hermann
last updated 2000/01/31
(version 1.1)
also available as XML
This is the second installment of CGI Bits & Pieces, which shows you how to parse
data submitted from a HTML form and send it as a mail to a predefined email account.
If you are a CGI novice,
see the references at the end of this article. Having read
Brent's article is the bare minimum to understand anything that follows.
All examples are implemented in C++ and usually compiled and tested on both
Windows NT4 using Visual C++ 5.0 and FreeBSD/linux using egcs.
| |
The data a user inputs into the fields of a form is sent to the URL that
is contained in the ACTION property of the FORM tag. But you do not get the data
as it is entered, but in a coded form that allows you to dissect control information from
user data. The control information is the name of the form fields, so you are able to
associate the data with the field it was entered into.
The fields are sent as a string of name=value pairs, and if there are several
fields, those pairs are separated by an ampersand "& ". Certain chars in the name and value part
are www-url-encoded, which means spaces are sent as a "+ " character, and all other special
characters are sent as a per-cent sign "%" followed by the code of the character as two hex-digits.
Obviously, the characters "%&+= " have to be encoded in that form; which characters are encoded exactly
is the decision of the browser.
The following code echos this encoded form information,
in clear text form, into a mail. Additionally, relevant information from the cgi-bin environment
is also included in the mail. To prevent people from sending to any email address
(i.e. using our server to spam), we have a config file that defines valid destination addresses; this also allows
us to define a follow-up URL that is showed to the user after he clicked on the submit button.
Both these configuration values are accessed by an alias name that is appended to the URL in the form tag and thus
can be found in the QUERY_STRING variable.
Below, you find the HTML code of a sample form, the C++ source code and a sample configuration file.
Finally, you can see a mail generated by the program compiled for RedHat Linux 2.0.36 using
egcs-2.91.60 .
A sample FORM
| | | |
<form method=post action="/cgi-bin/wwwmail?jh">
<input type=text name=topic><br>
<textarea name=memo cols=60 rows=3></textarea><br>
<input type=submit name=button value=" Send it! ">
</form>
| | | | |
wwwmail.cpp
| | | |
// Send form data to an email account
//
// Copyright (c) 1999 by Jürgen Hermann, All Rights Reserved.
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>
#include <sstream>
// this is the return address put into the mail (should be in the config file)
const char* POSTMASTER = "David Stiles <pingme@home.com>";
// get delimited substring from "str" and remove it from "str"
std::string strParse(std::string& str, const char* delim)
{
std::string result;
std::string::size_type pos = str.find_first_of(delim);
if (pos == std::string::npos) {
result = str;
str = "";
} else {
result = str.substr(0, pos);
str.erase(0, pos+1);
}
return result;
}
// send an environment value to a stream, if it actually exists
void echoEnv(ostream& out, const char* envvar)
{
char* val = getenv(envvar);
if (val) out << envvar << '=' << val << '\n';
}
// the main program
int main()
{
// init
mode_t oldmask = umask(0);
umask(oldmask & ~mode_t(0770));
// scan the .cfg file and check for allowed destinations
char* query = getenv("QUERY_STRING");
string mailto;
string jumpto;
if (query) {
ifstream in("wwwmail.cfg");
string line;
while (!in.eof()) {
getline(in, line);
if (!in.good() || in.eof()) break;
string alias = strParse(line, ";");
if (alias == query) {
mailto = strParse(line, ";");
jumpto = strParse(line, ";");
break;
}
}
}
if (!query || mailto.empty() || jumpto.empty()) {
cout << "Content-Type: text/plain\n"
<< "\n"
<< "Internal error!\n";
exit(666);
}
// build the mail header
char* formpage = getenv("HTTP_REFERER");
ostringstream mail;
mail << "To: " << mailto << '\n'
<< "From: " << POSTMASTER << '\n'
<< "Subject: Form submit from '"
<< (formpage ? formpage : "Unknown URL") << "'\n"
<< "\n";
// send identification of the remote user
echoEnv(mail, "HTTP_USER_AGENT");
echoEnv(mail, "REMOTE_ADDR");
echoEnv(mail, "REMOTE_IDENT");
echoEnv(mail, "REMOTE_HOST");
echoEnv(mail, "REMOTE_USER");
// send form data
int ch;
while ((ch = cin.get(), !cin.eof())) {
switch (ch) {
default: mail << char(ch); break;
case '+': mail << ' '; break;
case '&': mail << '\n'; break;
case '%': {
char buf[3];
buf[0] = cin.get();
buf[1] = cin.get();
buf[2] = '\0';
mail << char(strtol(buf, 0, 16));
break;
} // case
} // switch
} // while
mail << '\n';
// send the mail
FILE* sendmail = popen("/usr/lib/sendmail -i -t", "w");
if (sendmail) {
fputs(mail.str().c_str(), sendmail);
pclose(sendmail);
}
// redir to follow-up page
cout << "Location: " << jumpto << "\n\n";
return 0;
}
| | | | |
wwwmail.cfg
| | | |
jh;Juergen Hermann <jh@schiele-ct.de>;http://megaton.cscene.org/~snibril/
xgc;Jon Armstrong <armstron@eznet.net>;http://megaton.cscene.org/c/thankyou.html
| | | | |
A sample mail
| | | |
Date: Thu, 25 Mar 1999 18:31:08 -0800
Message-Id: <199903260231.SAA19302@cx505299-a.fed1.sdca.home.com>
To: Juergen Hermann <jh@schiele-ct.de>
From: David Stiles <pingme@home.com>
Subject: Form submit from 'http://megaton.cscene.org/~snibril/'
X-UIDL: e7cc1b08bd03fcdfc5273bf7d79d9b44
HTTP_USER_AGENT=Mozilla/4.03 [en] (WinNT; I ;Nav)
REMOTE_ADDR=193.141.27.190
REMOTE_HOST=193.141.27.190
topic=test
memo=abc
def
button= Send it!
| | | | |
|
| |
Gundavaram, Shishir, CGI Programming on the World Wide Web.
O'Reilly, 1996, 433 p., covers CGI basics as well as hot topics like data base interfacing, details of the HTTP protocol and their use, forms, server side includes, hyper-media, client-pull and server-push (examples in Perl), ISBN 1-56592-168-2.
Hermann, Jürgen, Sending image files via CGI.
C-Scene, 1998.
York, Brent, CGI in C - A starter's tutorial.
C-Scene, 1997.
|
This article is Copyright © 1999 by Jürgen Hermann
and Copyright © 1999 by C-Scene. All Rights Reserved.
|