Gateways and CGI Programming

What we have so far

  1. The non-empty cgi-bin directories.

  2. CGI programs and the forms that launch them:
    1. BMI with a name.
      1. bmi.html: click on this file.
      2. bmi.C
    2. Pizza per square inch.
      1. pizza.html: click on this file.
      2. pizza.C

Launch a C++ program from the web

  1. In theTime.C, we saw a C++ program that gets the current date and time.
    Here is a program that gets the current date, and that can be launched from the web.
    1. date.C (Click here to run it.)
    A program launched from the web must be in the cgi-bin directory of your public_html directory.
    Create this directory cgi-bin if you have not already done so.
    Note that public_html has an underscore, and cgi-bin has a dash.
    cd
    cd public_html
    pwd
    /home/students/jsmith/public_html
    
    mkdir cgi-bin                   (Make a new directory.)
    ls -ld cgi-bin
    drwxr-xr-x 2 jsmith students 7 Apr  9 21:18 cgi-bin
    
    cd cgi-bin
    pwd
    /home/students/jsmith/public_html/cgi-bin
    
    wget https://markmeretzky.com/fordham/2000/src/gateway/date.C
    ls -l date.C                    (Should have a new file named date.C)
    
    c++ -o date.cgi date.C          (Create an ouput file named date.cgi)
    ls -l date.cgi                  (Should have a new file named date.cgi)
    
    ./date.cgi                      (Dot means your current directory.)
    Today is Thursday, April 9, 2026.
    
    To run the C++ program from any web browser, anywhere in the world (even on your phone), point the browser at
    https://storm.cis.fordham.edu/~jsmith/cgi-bin/date.cgi
    where jsmith is your Fordham ID.
    Or put this link into a web page:
    Click
    <A HREF = "https://storm.cis.fordham.edu/~jsmith/cgi-bin/date.cgi">here</A>
    to see the current date.
    
    where jsmith is your Fordham ID.
    Click here to see the current date.

    To sum up, here are the three things you must do differently to launch your C++ program from any web browser:

    1. The first line output by your C++ program must be
      Content-type: text/plain
      
      followed by two newlines (\n\n). text/plain is the simplest example of a MIME type.
    2. The executable file you create with the c++ comand must have a name that ends with .cgi
    3. The executable file must be placed in the cgi-bin subdirectory of your public_html directory.

  2. Exercise.
    Run the above program from the web.
    Then make it also output the current hour, minute, and second.
    (We saw how to get these values in theTime.C.)
    To output an int with two digits, even if it is a single-digit number,
    #include <iomanip>   //for the i/o manipulators setw and setfill
    
    	cout << setw(2) << setfill('0') << hour;
    
    Click here to see the current date and time.
    Why not output today’s astrological sign, too? Use the tm_yday field (0 to 365 inclusive) of the tm structure.
    For example, if you were born today you’d be an Aries.

    Let’s see who has created an executable date.cgi:

    fdb4
    jc208
    mrd22
    did4
    eh141
    mjj1
    kklassen2
    ljl8
    jmm56
    an151
    aco8
    tdp2
    fs89
    jt88
    ju13
    lov
    kwesner1
    rz54
    

Output HTML instead of plain text.

  1. To output HTML instead of plain text, change the MIME-type header from text/plain to text/html.
    1. datehtml.C
    Click here to see the current date and time in HTML.

Hidden machinery

  1. string.C, string.txt
    Class string in contemporary C++, vs. a pointer to a char in old fashioned C style code.

  2. environment.C, environment.txt
    Read the environment variables.
    The LS_COLORS are used by the ls command.
    env
    env | more
    

Class map

  1. Class pair.
    A pair object holds two data members, named first and second.
    You get to decide what data type they are.
    It doesn’t do anything else.
    See here for another pair example.
    1. pair.C, pair.txt

  2. map.C, map.txt
    Create and search a map, a.k.a. an “associative array”.
    Report “could not find” if not found.
    A map contains two columns because it is made of a series of pairs.

    Note that the for loop output the pairs in alphabetical order.
    Searching an array of n items might require n itertions of a for loop.
    But searching a map of n items would require at most log2 n iterations of the loop inside the find member function of the map.
    log2 n is much smaller than n. For example, if n = 64, then log2 n = 6.
    That’s because 64 = 2 × 2 × 2 × 2 × 2 × 2.


  3. Exercise.
    map2.C, map2.txt.
    Remove the two vectors and the for loop that searched the first one. Replace them with a map<string, int>.
    Answer: map2b.C

  4. Another exercise.
    In the manual::decide member function in manual.h, remove the array of structures and the for loop that searched it.
    Replace them with a map<char, pair<int, int> >.
    Each value in the first column of the map will be a char.
    Each value in the second column of the map will be a pair<int, int>, which is an object that holds two ints named first and second.
    Remember to #include <map> for class map, and to #include <utility> for class pair.
    The map will look like this:
    		static const map<char, pair<int, int> > m {
    			{'h', {-1,  0}},  //left
    			{'j', { 0,  1}},  //down
    			//etc.
    		};
    
    		if (const char k {key()}) {        //If a key was pressed,
    			const auto it {m.find(k)}; //try to find it in the map.
    			if (it == end(m)) {        //If the key wasn't in the map,
    				punish();          //the key was invalid.
    			} else {
    				//it->second is a pair<int, int>.
    				*dx = it->second.first
    				*dy = it->second.second;
    			}
    		}
    

Get input from a form containing widgets.

  1. Click here to run this program.
    Fill in the three numbers and press the Submit button.
    1. bmi.html. Put this file in your public_html directory and make sure the name of the file ends with .html.
      This file is a web page that contains a form that launches the following C++ program.
      When you view this page in a Chrome browser on a Mac, you can select View → Developer → View Source.
      The form contains widgets, which are INPUT elements.
      Each widget of type NUMBER in this form has a NAME attribute.
      The names are feet, inches, pounds.
    2. cgi.h is the header file for class cgi.
    3. cgi.C is the implementation file for class cgi.
    4. bmi.C contains the main function that receives data from the form.
      For simplicity, it doesn’t bother to check for errors from the functions stoi and stod, since that would have required “catching exceptions”.
    Compute your BMI (Body Mass Index) by pointing your browser here.
    To download and run your own copy of this form and this program,
    cd
    cd public_html
    pwd
    /home/students/jsmith/public_html
    
    wget https://markmeretzky.com/fordham/2000/src/gateway/bmi.html
    ls -l bmi.html
    
    mkdir cgi-bin      (if you have not already made this directory)
    ls -ld cgi-bin
    
    cd cgi-bin
    pwd
    /home/students/jsmith/public_html/cgi-bin
    
    wget https://markmeretzky.com/fordham/2000/src/gateway/cgi.h
    wget https://markmeretzky.com/fordham/2000/src/gateway/cgi.C
    wget https://markmeretzky.com/fordham/2000/src/gateway/bmi.C
    ls -l cgi.h cgi.C bmi.C
    
    c++ -o bmi.cgi cgi.C bmi.C
    ls -l bmi.cgi
    -rwxr-xr-x 1 jsmith students 74128 Apr  6 21:27 bmi.cgi
    

    Then edit the bmi.html you just downloaded into your public_html directory, and in the ACTION attribute of the FORM tag, change my Fordham name mmeretzky to your Fordham name (e.g., jsmith).
    Then point your browser at
    https://storm.cis.fordham.edu/~jsmith/bmi.html
    where jsmith is your Fordham name.


  2. Exercise.
    In the above program, output the error messages in red. For example, change
    		cout << "<BR/>Your weight must be positive.\n";
    
    to
    		cout << "<BR/><SPAN STYLE = \"color: red\">Your weight must be positive.</SPAN>\n";
    

Other types of widgets

  1. Click here to run this program.
    1. form.html is a web page containing a form containing many other types of widgets.
    2. cgi.h
    3. cgi.C
    4. display.C contains the main function that receives data from the form.
    cd                   (Go to your home directory on storm.cis.fordham.edu.)
    cd public_html       (public_html has an underscore, not a dash.)
    pwd
    /home/students/jsmith/public_html
    
    wget https://markmeretzky.com/fordham/2000/src/gateway/form.html
    ls -l form.html
    
    cd cgi-bin     (assuming you have already created this directory)
    pwd
    /home/students/jsmith/public_html/cgi-bin
    
    wget https://markmeretzky.com/fordham/2000/src/gateway/display.C
    ls -l display.C
    
    c++ -o display.cgi cgi.C display.C      (assuming you have already downloaded cgi.h and cgi.C)
    ls -l display.cgi
    

    Then edit the form.html you just downloaded to your public_html directory, and in the ACTION attribute of the FORM tag, change my Fordham name mmeretzky to your Fordham name (e.g., jsmith).
    Then point your browser at
    https://storm.cis.fordham.edu/~jsmith/form.html
    where jsmith is your Fordham name.


  2. A form with pop-up menus.
    1. sign.html: click here.
      Instead of the two menus, we could have used one INPUT widget of type DATE.
    2. sign.C
    c++ -o sign.cgi cgi.C sign.C
    

  3. The most recently modified .html files.
    Two-dimensional array: language1.C
    	const map<string, map<string, string>> m {
    		{"summer",	{
    					{"blue",   "Greece"},
    					{"yellow", "Spain"},
    					{"",       "Italy"}
    				}},
    
    		{"winter",	{
    					{"red",    "Switzerland"},
    					{"blue",   "Iceland"},
    					{"",       "Montenegro"}
    				}},
    
    		{"spring",	{
    					{"pink",   "Japan"},
    					{"",       "Netherlands"}
    				}},
    
    		{"fall",	{
    					{"green",  "USA (New England)"},
    					{"",       "Germany"}
    				}}
    	};
    
    	const string season {get value from widget};
    
    	const auto it {m.find(season)};
    	if (it == end(m)) {
    		//Season not found.
    		cout << "a surprise destination somewhere beautiful";
        	} else {
    		const string color {get value from widget};
         		const map<string, string>& colormap {it->second};
    		auto it2 {colormap.find(color);
    		if (it2 == end(colormap)) {
    			//Color not found.  Find the default destination for this season.
    			it2 = colormap.find("");
    			cout << it2->second;
    		} else {
    			cout << it2->second;  //the destination for this season and color.
    		}
    	}