Introduction to C++ CGI – Processing Forms

In this post I will show you how to process HTML forms easily using CGIs in C++. I assume you have already basic knowledge of writing CGIs in C++, if you don’t go a head and read Introduction to C++ CGI.

Processing forms is the basic function of any CGI script and the main purpose of CGIs. As you probably know there are two common ways to send form data back to the web server: “post” and “get”. When form data is sent with the “get” method it is appended to the URL string of the form submission URL. The “post” method is much like the “get” except the data is transmitted via http headers and not via the URL itself. When a form uses “get” it allows the user to easily bookmark the query created by the form as the data is transmitted in URL itself, on the other hand the “post” method allows to send much more data and spares to user from seeing the data in the URL.

Getting the “post” and “get” data is relatively easy. To get the data sent by “get” you can just call getenv("QUERY_STRING") and you will receive a pointer to null-terminated string containing the “get” data. Reading the “post” data is a bit more complicated. The data needs to be read from the standard input, but the program won’t receive an EOF when it reaches the end of the data but instead it should stop reading after reading a specified amount of bytes, which is defined in the environment variable “CONTENT_LENGTH“. So you should read getenv("CONTENT_LENGTH") bytes from the standard input to receive the “post” data.

But here it’s get tricky. The data is received in an encoded way. The data for both “post” and “get” is a string in the form of “var1=value1&var2=value2&var3=value3” and so on, where the “var*” is the names of the submitted form elements and “value*” is their values respectively. And now it gets a bit more tricky, both the elements’ names and values are url-encoded. That means that almost every non alphanumeric character will be encoded as %XX, where XX represents its ASCII value (see the linked Wikipedia article for more information and extra reading). So to sum up the process of processing forms in CGI you should do the following:

  1. Get the data (either by “post” or “get”).
  2. Parse the data to get key-value pairs.
  3. Decode the url-encoded key-value pairs.
  4. Process the data.

Getting the first and last step done is easy. The second and third step require some work, but fortunately when done properly they should only have to be done once, as you will create functions/classes to handle those, so it is really only a one time job. That leaves you only to do yourself the first and last steps.

As I said the second and third steps are troublesome only when not done before. Here is an implementation for those steps that I’ve written as a part of (yet unreleased) CGI library for C++. It implements functions that take the care of the first three steps and return to the user an STL map containing the form elements’ names in the key and their value in the map pair’s value. This functions allows to process forms in a similar way to processing forms in PHP using $_GET and $_POST.

Here is a simple example of processing a “get” form using the above getpost.h header file.

#include <iostream>
#include <string>
#include <map>
#include "getpost.h"

using namespace std;

int main()
{
	map<string,string> Get;
	initializeGet(Get); //notice that the variable is passed by reference!
	cout<<"Content-type: text/html"<<endl<<endl;
	cout<<"<html><body>"<<endl;
	cout<<"<h1>Processing forms</h1>"<<endl;
	cout<<"<form method=\"get\">"<<endl;
	cout<<" <label for=\"fname\">First name: </label>"<<endl;
	cout<<" <input type=\"text\" name=\"fname\" id=\"fname\"><br>"<<endl;
	cout<<" <label for=\"lname\">Last name: </label>"<<endl;
	cout<<" <input type=\"text\" name=\"lname\" id=\"lname\"><br>"<<endl;
	cout<<" <input type=\"submit\" />"<<endl;
	cout<<"</form><br /><br />"<<endl;

	if (Get.find("fname")!=Get.end() && Get.find("lname")!=Get.end()) {
		cout<<"Hello "<<Get["fname"]<<" "<<Get["lname"]<<", isn\'t "
			"processing CGI forms with C++ quite easy?"<<endl;
	} else {
		cout<<"Fill up the above from and press submit"<<endl;
	}
	cout<<"</body></html>"<<endl;

	return 0;
}

While this is a simple example, it’s enough to demonstarte how stuff is done. The same way you can process the “post” variables. Feel free to take a look at the getpost.h source-code to see how the URL decoding and the other implementation aspects were done.

Update 2009-09-18: There was a bug in getpost.h, see my comment bellow.

6 thoughts on “Introduction to C++ CGI – Processing Forms”

  1. Hi,

    Thank you for nice tutorial. I like using C/C++ for CGI programming for their simplicity & lightweight execution. Wondering how to process multiple file upload with multiple input at the same time via their names and with upload progress. If you have any idea, please enlighten me. Thank you.

  2. Thomas Gauss contacted me (thanks!) and pointed a bug in getpost.h. The bug causes an access to a unallocated memory. The patch bellow fixes it (it basically changes line 113).

    Looking back at the code, I want to point two things:
    1. It doesn’t handle nulls well (if the post data wasn’t encoded correctly it may chop data off)
    2. This isn’t production ready code, it is meant to demonstrate the processing process.

    --- getpost.h   2009-09-18 14:31:35.000000000 +0300
    +++ getpost-new.h       2009-09-18 14:38:19.000000000 +0300
    @@ -110,7 +110,7 @@
            }
    
            try {
    -               buffer = new char[content_length*sizeof(char)];
    +               buffer = new char[content_length+1];
            } catch (std::bad_alloc xa) {
                    Post.clear();
                    return;
    
  3. Good afternoon,

    When I compile a cpp compiler using getpost.h cpp55, an error occurs.
    Should not I use the same for the post.
    You know how to help me

    att,
    Luiz Carlos

    User Brasilian


  4. Hello,

    The initializePost function may have a memory leak. The HEAP memory allocated to local variable char* buffer is not released before the buffer gets out of the scope. I would add
    delete [ ] buffer;
    at the last line of initializePost(map &Post)

    All the Best,

    Richard Owczarzy

  5. Sir
    Recently, found your example. After so much years, so many developments, still It is relevant – a hidden treasure. I know a bit about tomcat-java-jsp architecture and a little bit c, cpp but never thought web with cpp. Thank you for that shock.
    After that I google little bit to know more. Interestingly I found every example with only one page and putting all their code in main(). I can’t understand how to write multi-page, does every page need to be compiled separately, or put them in root directory as cpp file.
    If you provide me an example like above said, or provide me few links it will be great help to me.
    Thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *