FBB::CGI(3bobcat)
FBB::CGI(3bobcat) β CGI interface π
Okay so bestie, let me tell you about FBB::CGI β she's the moment. π
NAME πΈ
FBB::CGI β handles GET and POST submitted form data, periodt. π
SYNOPSIS β¨
#include <bobcat/cgi>
Linking option: -lbobcat
DESCRIPTION π¦
Okay so real talk. The class CGI offers an interface to data submitted by web-forms. That data is sent to a script handling the data using a <form action="/path/to/form/script"> stanza. Very often it's indeed a script, like a Perl script, but bestie there is no need to use a scripting language. The class CGI lets C++ programmers process the form by an executable, which usually results in faster processing and in construction time benefits from the type safety C++ offers. And the class CGI automatically handles data submitted using the GET method as well as data submitted using the POST method. So no cap, she handles both. π
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::Exception exception is thrown. So like, if something's off, she's gonna yell about it. π
NAMESPACE π
FBB
All constructors, members, operators and manipulators mentioned in this man-page are defined in the namespace FBB. So that's the vibe. β¨
INHERITS FROM π
-
She doesn't inherit from anything, bestie. It's giving self-made, independent, main character energy. π
TYPEDEF π§
CGI::MapStringVectorβ A shorthand forstd::unordered_map<std::string, std::vector<std::string> >, which is the data type in which form-variables are stored. So like, that's where all your form data lives. π
ENUMERATIONS π
The CGI::Method enumeration specifies values indicating the way the form's data were submitted:
CGI::UNDETERMINEDβ Used internally indicating that the form's method was neitherGETnorPOST. She's like "idk what this is" πCGI::GETβ Indicates that theGETmethod was used when submitting the form's data.CGI::POSTβ Indicates that thePOSTmethod was used when submitting the form's data.
The CGI::Create enumeration is used to request or suppress creation of the directory to contain any file uploaded by a form:
CGI::DONT_CREATE_PATHβ When uploading files, the destination directory must exist.CGI::CREATE_PATHβ When uploading files, the destination directory will be created.
CONSTRUCTORS π
CGI(bool defaultEscape = true, char const *header = "Content-type: text/html", std::ostream &out = std::cout)β The default constructor writes the standard content type header to the standard output stream and will usestd::coutfor output. Specifying0asheadersuppresses outputting theContent-typeline. Otherwise the content type line is also followed by two\r\ncharacter combinations. By default all characters in retrieved form-variables are escaped. The overloaded insertion operators (see below) can be used to modify the default set of characters to escape. The backslash is used as the escape character. The escape-prefix is not used if thedefaultEscapevalue is specified asfalseand if no insertions into theCGIobject were performed.
Copy and move constructors (and assignment operators) are available. So you can copy her, move her, assign her β she's flexible like that. π«Ά
β¨ OERLOADED OPERATORS β¨
Note: the following three insertion operators, defining sets of characters that should be escaped, can only be used before calling any of theparam,beginorendmembers. As soon as one of these latter three members has been called the set of characters to be escaped is fixed and attempts to modify that set is silently ignored. So like, once you call one of those, the door is closed, bestie. πͺπ
char const *operator[](std::string const &key) constβ The index operator returns the value of the environment variable specified as the index.0is returned if the variable specified atkeyis not defined. So if it's not there, you get a null pointer, not a crash. πCGI &operator<<(std::string const &accept)β This member's actions are suppressed onceparam,beginorend(see below) has been called.
The insertion operator can be used to fine-tune the set of characters that are 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 can be used to define a set of characters that are not escaped.
If defaultEscape was specified as false then the insertion operator will define a set of characters that will be escaped.
The backslash itself is always escaped and a request to use it unescaped is silently ignored.
The accept string can be specified as a regular expression character set, without the usual surrounding square brackets. E.g., an insertion like cgi << "-a-z0-9" defines the set consisting of the dash, the lower case letters and the digits.
Individual characters, character ranges (using the dash to specify a range) 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:] can be used to define the set consisting of the characters ", β, `, ;, and \.
Note that standard and [:cgi:] character classes do require 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. So like, don't do it unless you wanna catch a vibe check from the security gods. π
CGI &operator<<(int c)β This member's actions are suppressed onceparam,beginorend(see below) has been called.
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.
CGI &operator<<(std::pair<char, char> range)β This member's actions are suppressed onceparam,beginorend(see below) has been called.
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. So like, if you try to go backwards, she's just gonna ignore you. π
std::ostream &std::operator<<(std::ostream &out, CGI const &cgi)βCGIobjects can be inserted into ostreams to display the characters that will appear escaped in strings returned by theparam()member function. Each character for whichisprint()returnstruewill be displayed as character, surrounded by single quotes. For all other characters their ASCII values are displayed. Each character is displayed on a line by itself. So it's like a little escape character showcase, bestie. β¨
β¨ MEMBER FUNCTIONS β¨
CGI::MapStringVector::const_iterator begin()β hands you the begin iterator of the form's parameter map π«. Any iterator value that isn't equal toend(peep below) points at a pair of values: the first one is the name of a field the form defined, and the second one is a vector of strings holding that field's value(s). Also go look at the description of theparammember just below, it's related, iykyk.CGI::MapStringVector::const_iterator end()β returns the end iterator of the form's parameter map. That's it, that's the whole vibe, she's the boundary π.unsigned long long maxUploadSize() constβ tells you the current maximum file upload size, measured in bytes. Slay π .CGI::Method method() constβ returns the method that was used when the form got submitted. It's eitherCGI::GETorCGI::POST, no third option, she's loyal π¦.std::vector<std::string> const ¶m(std::string const &variable)β gives you the value of the form-variable named by the argument. If the form's data never provided that variable, you get back an empty vector (bestie said no π).
If the same variable showed up multiple times, or if its value stretches across multiple lines (this one's only with multipart/form-data), then the vector is holding multiple strings.
With GET and POST methods that are not using multipart/form-data, input fields that stretch over multiple lines get stored in one string, using \r\n combinations in between those lines.
Now listen, when files get uploaded, the vectors contain sets of four strings π:
- The first string gives the path name of the uploaded file;
- the second string gives the file name specified in the form itself (so, the name of the file at the remote location);
- the third string shows the content type the remote browser specified (like, e.g.,
application/octet-stream); - the fourth string contains
OKif the file was successfully uploaded, andtruncatedif the file was truncated.
Existing files will not be overwritten. Periodt. And when uploading a file, a usable filename must be found within 100 trials β no infinite searching, she has limits.
std::string param1(std::string const &variable)β returns the first element of thevector<string>thatparamwould hand you, or an empty string ifvariablewasn't defined by the received form. One-string shortcut, iconic π.std::string const &query() constβ returns the query-string that got submitted withCGI::GETorCGI::POSTforms. Quick heads up though: if the POSTed form specifiedENCTYPE="multipart/form-data", the query string is empty. That's just how it is π.report()β silently returns if no errors were encountered while processing form-data (silence is golden, no notes β¨). But if something did go wrong, the html file generated by the CGI program shows a line starting withFBB::CGI, followed by the status report.
These are the status report messages that are presently defined:
Content-Disposition not recognized in:β followed by the line where theContent-Dispositionwas expected. This may happen when processingmultipart/formdata.Invalid multipart/form-data.β this message can be generated while reading lines duringmultipart/formdata processing.GET/POST REQUEST_METHOD not found.β shown if the program couldn't find the form'sREQUEST_METHODtype (so,GETorPOST).Invalid CONTENT_LENGHT in POSTed form.β shown if the content-length header has an incorrect value.Content-Type not found for file-field, followed by the file's field name. Shown if noContent-Typespecification was found in an uploaded form.Can't open a file to write an uploaded file.β this one means the CGI program was unable to open a file to write an uploaded file to. Could be an overfull disk or partition, or incorrect write-permissions, so go check π.multipart/form-data: no end-boundary found.β shown if the end-boundary was missing in amultipart/form-dataform.
void setFileDestination(std::string const &path, std::string const &prefix = "", Create create = CREATE_PATH)β this member is how you specify the path and prefix of uploaded files. Uploaded files get stored atpath/prefixNr, whereNris an internally used number that starts at one π’. WhenCREATE_PATHis specified,pathmust be available, or the CGI object must be able to create the path. IfDONT_CREATE_PATHis specified, the specified path must be available β and if it's not, anFBB::Exceptionexception gets thrown. No chill, no grace.void setMaxUploadSize(size_t maxSize, int unit = 'M')β use this to change the maximum size of uploaded files. Its default value is 100Mb. Theunitcan be one ofb(bytes, the default),K(Kbytes),M(Mbytes) orG(Gbytes). Unit-specifiers are interpreted case insensitively, she doesn't care about your capitalisation π . File uploads keep going until the maximum upload size is exceeded, and after that any remainder gets discarded ποΈ.void swap(CGI &other)β the current object andotherget swapped. Heads up though: the first time one of theparam(),begin()orend()members is called, these members may detect errors in the received form data. If that happens, an error message is written to the standard output stream and anFBB::Exceptionexception will be thrown π₯.
π STATIC MEMBERS π
std::string dos2unix(std::string const &text)β converts all\r\ncharacter combinations intextinto plain\ncharacters, and returns the converted text. Glow-up for your line endings β¨.std::string unPercent(std::string const &text)β converts all%xxencoded characters into their corresponding ASCII values. Also,+characters get converted into single blank spaces. You get the converted string back π.
π EXAMPLE π
#include "main.ih"
void showParam(CGI::MapStringVector::value_type const &mapValue)
{
cout << "Param: " << mapValue.first << '\n';
for (auto &str: mapValue.second)
cout << " " << CGI::dos2unix(str) << "\n"
" ";
cout << '\n';
}
int main(int argc, char **argv)
try
{
Arg &arg = Arg::initialize("evhm:", argc, argv);
// usage and version are in the source archive in .../cgi/driver
// 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;
// set environment vars simulating
// a GET form
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() << '\n';
}
else
cout << "FAILED: setenv " << line << '\n';
}
CGI cgi(false); // chars are not escaped
cgi << arg[1];
if (arg.option(&line, 'm'))
cgi.setMaxUploadSize(stoul(line), *line.rbegin());
cout << "Max upload size (b): " << cgi.maxUploadSize() << '\n';
CGI::Method method = cgi.method();
cout << "To escape:\n" <<
cgi << "\n"
"Method: " << (method == CGI::GET ? "GET" : "POST") <<
'\n';
cout << "Query string: " << cgi.query() << '\n';
cout << "Submit string: `" << cgi.param1("submit") << "'\n";
for (auto &mapElement: cgi)
showParam(mapElement);
cout << "END OF PROGRAM\n";
}
catch (exception const &err)
{
cout << err.what() << '\n';
return 1;
}
catch (...)
{
return 1;
}
To test the program's get form processing, call it as driver get '[:cgi:]', with the file get containing:
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
To test the program's post form processing, call it as driver post1 '[:cgi:]', using post1 and post1.cin found in Bobcat's source archive under ../cgi/driver π¦.
π FILES π
bobcat/cgiβ defines the class interface
π SEE ALSO π
π BUGS π
None Reported. (Not a single one, we stay winning π)
π«Ά BOBCAT PROJECT FILES π«Ά
- https://fbb-git.gitlab.io/bobcat/ β gitlab project page;
Debian Bobcat project files:
libbobcat6β debian package containing the shared library, changelog and copyright note;libbobcat-devβ debian package containing the static library, headers, manual pages, and developer info;
π§ BOBCAT π§
Bobcat is an acronym of `Brokken's Own Base Classes And Templates'.
β COPYRIGHT β
This is free software, distributed under the terms of the GNU General Public License (GPL).
πΈ AUTHOR πΈ
Frank B. Brokken (f.b.brokken@rug.nl).
Ok bestie, that's the whole page, we made it π. This one ships as libbobcat-dev_6.15.01, dated 2005-2026, and it lives at FBB::CGI(3bobcat). Go upload something responsibly, mwah πβ¨
π¦ where this page comes from
- ubuntu stonking: libbobcat-dev 6.15.01-1 Β· GPL-3.0-or-later WITH OpenSSL exception
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms