The class CGI offers an interface to data submitted by web-forms. The data is sent to a script handling the data using a <form action="/path/to/form/script"> stanza. Very often this is indeed a script, like a Perl script, but there is no need to use a scripting language. The class CGI allows C++ programmers to process the form by an executable usually resulting in faster processing and in construction time benefits from the type safety offered by C++. The class CGI handles data submitted using the GET method as well as data submitted using the POST method automatically.
By default the class's constructor writes the customary Content-type header lines to the standard output stream. Additional (html) output of a reply page must be provided by other code. Therefore, a program processing an uploaded form will have an organization comparable to the following basic setup:
// assume includes and namespace std/FBB were defined int main() { CGI cgi; cout << "<html><body>\n"; if (parametersOK(cgi)) { process(cgi); generateReplyPage(); } else generateErrorPage(); cout << "</body></html>\n; }
When errors in the received form-data are detected an error message is written to the standard output stream and an FBB::Errno exception is thrown.
The CGI::Create enumeration is used to request or suppress creation of the directory to contain any file uploaded by a form:
Note: the following three insertion operators defining sets of characters that should be escaped can only be used until the first time one of the param(), begin() or end() members is called. Once one of these latter three members has been called the set of characters to be escaped is fixed and attempts to modify them will fail silently.
The insertion operator can be used to fine-tune the set of characters that will be shown escaped in strings returned by param() (see below). Depending on the value of the constructor's defaultEscape parameter characters inserted into the CGI object will or will not be escaped by a backslash. If the constructor's defaultEscape parameter was specified as true then the insertion operator will define a set of characters that will not be escaped. If defaultEscape was specified as false then the insertion operator will define a set of characters that will be escaped. Once an insertion operator has been used the backlash itself will always be escaped and a request to use it unescaped is silently ignored. The accept string can be specified as a regular expression character set without specifying the surrounding square brackets. E.g., an insertion like cgi << "-a-z0-9" will accept the dash, lower case letters and the digits. Individual characters, character ranges using the dash and all standard character classes ([:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:], and [:xdigit:]) can be used to specify a set of characters. In addition to these standard character classes the class [:cgi:] is available representing the set " ' ` ; and \. Note that standard character classes do require you to specify square brackets. When a series of insertions are performed then the union of the sets defined by these insertions are used. Note: using unescaped single quotes, the double quotes, backtick characters and semicolons in CGI-programs might be risky and is not advised.
This insertion operator is used to change the default escape handling of a single character c. The int parameter is cast internally to a char.
This insertion operator can be used to change the default escape handling of a range of characters. The pair's second character must be equal to or exceed the position of the pair's first character in the ASCII collating sequence or the member will have no effect.
The copy and move assignment operators are available.
The following status report messages are presently defined:
#include "main.ih" void outstr(string const &str) { cout << CGI::dos2unix(str) << "\n" " "; } void showParam(CGI::MapStringVector::value_type const &mapValue) { cout << "Param: " << mapValue.first << "\n" " "; FBB::for_each(mapValue.second.begin(), mapValue.second.end(), outstr); cout << endl; } int main(int argc, char **argv) try { Arg &arg = Arg::initialize("evhm:", argc, argv); arg.versionHelp(usage, version, 2); ifstream in(arg[0]); string line; while (getline(in, line)) { size_t pos = line.find('='); if (pos == string::npos) continue; if (setenv(line.substr(0, pos).c_str(), line.substr(pos + 1).c_str(), true) == 0) { if (arg.option('e')) cout << line.substr(0, pos).c_str() << '=' << line.substr(pos + 1).c_str() << endl; } else cout << "FAILED: setenv " << line << endl; } CGI cgi(false); // by default no escapes cgi << arg[1]; if (arg.option(&line, 'm')) cgi.setMaxUploadSize(A2x(line), *line.rbegin()); cout << "Max upload size (b): " << cgi.maxUploadSize() << endl; CGI::Method method = cgi.method(); cout << "To escape:\n" << cgi << "\n" "Method: " << (method == CGI::GET ? "GET" : "POST") << endl; cout << "Query string: " << cgi.query() << endl; cgi.param("submit"); FBB::for_each(cgi.begin(), cgi.end(), &showParam); cout << "END OF PROGRAM\n"; } catch (Errno const &err) { cout << err.why() << endl; return 1; } catch (...) { return 1; }
To test the program provide it, e.g., with the following file at its standard input:
INFO=This is an abbreviated set of environment variables SERVER_ADMIN=f.b.brokken@rug.nl GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_METHOD=GET QUERY_STRING=hidden=hidval&submit=Submit+%20Query