CGImap parses and holds all the name-value pairs submitted from the form as part of a CGI request. You might think that anything that has the word “map” in it’s name should be
inherited from the STL map, but map has it’s own way of ordering the elements it stores whereas here it’s useful to keep the elements in the order that they appear on the Web page.
So CGImap is inherited from vector<CGIpair> , and operator[ ] is overloaded so you get the associative-array lookup of a map.
You can also see that CGImap has a copy-constructor and an operator=, but they’re both declared as private. This is to prevent the compiler from synthesizing the two functions (which it will do if you don’t declare them yourself), but it also prevents the client
programmer from passing a CGImap by value or from using assignment.
CGImap’s job is to take the input data and parse it into name-value pairs, which it will do with the aid of CGIpair (effectively, CGIpair is only a helper class, but it also seems to make it easier to understand the code). After copying the query string (you’ll see where the
query string comes from later) into a local string object gq, the nextPair( ) member function is used to parse the string into raw name-value pairs, delimited by ‘=‘ and ‘& ’ signs. Each resulting CGIpair object is added to the vector using the standard vector::push_back( ).
When nextPair( ) runs out of input from the query string, it returns zero.
The CGImap::operator[ ] takes the brute-force approach of a linear search through the
elements. Since the CGImap is intentionally not sorted and they tend to be small, this is not too terrible. The dump( ) function is used for testing, typically by sending information to the resulting Web page, as you might guess from the default value of nl, which is an HTML
“break line” token.
Using GET can be fine for many applications. However, GET passes its data to the CGI
program through an environment variable (called QUERY_STRING), and operating systems
typically run out of environment space with long GET strings (you should start worrying at
about 200 characters). CGI provides a solution for this: POST. With POST, the data is
encoded and concatenated the same way as with GET, but POST uses standard input to pass
the encoded query string to the CGI program and has no length limitation on the input. All
you have to do in your CGI program is determine the length of the query string. This length is stored in the environment variable CONTENT_LENGTH. Once you know the length, you
can allocate storage and read the precise number of bytes from standard input. Because POST
is the less-fragile solution, you should probably prefer it over GET, unless you know for sure that your input will be short. In fact, one might surmise that the only reason for GET is that it is slightly easier to code a CGI program in C using GET. However, the last class in
CGImap.h is a tool that makes handling a POST just as easy as handling a GET, which
means you can always use POST.
The class Post inherits from a string and only has a constructor. The job of the constructor is to get the query data from the POST into itself (a string). It does this by reading the CONTENT_LENGTH environment variable using the Standard C library function getenv( ).
This comes back as a pointer to a C character string. If this pointer is zero, the
Appendix A: Et cetera
1016
CONTENT_LENGTH environment variable has not been set, so something is wrong.
Otherwise, the character string must be converted to an integer using the Standard C library
function atoi( ). The resulting length is used with new to allocate enough storage to hold the query string (plus its null terminator), and then read( ) is called for cin. The read( ) function takes a pointer to the destination buffer and the number of bytes to read. The resulting buffer is inserted into the current string using string::append( ). At this point, the POST data is just a string object and can be easily used without further concern about where it came from.
Testing the CGI parser