You are on page 1of 16

19

Web
Programming
This is the common air that
bathes the globe.
Walt Whitman

The longest part of the


journey is said to be the
passing of the gate.
Marcus Terentius Varro

Railway termini ... are our


gates to the glorious and
unknown. Through them we
pass out into adventure and
sunshine, to them, alas! we
return.
E. M. Forster

There comes a time in a


mans life when to get where
he has to goif there are no
doors or windowshe walks
through a wall.

OBJECTIVES
In this chapter you will learn:

The Common Gateway Interface (CGI) protocol.


The Hypertext Transfer Protocol (HTTP) and HTTP
headers.

Web servers functionality.

The Apache HTTP Server.

To request documents from a Web server.

To implement CGI scripts.

To send input to CGI scripts using XHTML forms.

Bernard Malamud

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Chapter 19 Web Programming

Self-Review Exercises
19.1

Fill in the blanks in each of the following statements:


a) The two most common HTTP request types are
and
.
ANS: get and post.
b) Browsers often
Web pages for quick reloading.
ANS: cache.
c) In a three-tier application, a Web server is typically part of the
tier.
ANS: middle.
d) In the URL http://www.deitel.com/books/downloads.html, www.deitel.com is the
of the server, where a client can find the desired resource.
ANS: machine name.
e) A(n)
document is a text file containing markings that describe to a Web
browser how to display and format the information in the document.
ANS: XHTML.
f) The environment variable
provides a mechanism for supplying data to
CGI scripts.
ANS: QUERY_STRING.
g) A common way of reading input from the user is to implement the XHTML
element.
ANS: form.

19.2

State whether each of the following is true or false. If false, explain why.
a) Web servers and clients communicate with each other through the platform-independent HTTP.
ANS: True.
b) Web servers often cache Web pages for reloading.
ANS: True.
c) The information tier implements business logic to control the type of information that
is presented to a particular client.
ANS: False. The middle tier implements business logic to control interactions between application clients and application data.
d) A dynamic Web page is a Web page that is not created programmatically.
ANS: False. A dynamic Web page is a Web page that is created programmatically.
e) We put data into a query string using a format that consists of a series of name-value
pairs joined with exclamation points (!).
ANS: False. The pairs are joined with an ampersand (&).
f) Using a CGI script is more efficient than using an XHTML document.
ANS: False. XHTML documents are more efficient than CGI scripts, because they do not
need to be executed on the server side before they are output to the client.
g) The post method of submitting form data is preferable to get when sending personal
information to the Web server.
ANS: True.

Exercises
19.3

Define the following terms:


a) HTTP.
ANS: A platform-independent protocol for transferring requests and files over the Internet
(i.e., between Web servers and Web browsers).

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Exercises

b) Multitier application.
ANS: Multitier applications divide functionality into separate tiers (i.e., logical groupings
of functionality). Tiers can be located on the same computer or on separate computers.
c) Request method.
ANS: A request method specifies how a client makes requests from a server. The two most
common request methods are get and post.
19.4 Explain the difference between the get request type and the post request type. When is it
ideal to use the post request type?
ANS: A get request gets (or retrieves) information from a server. Such requests often retrieve an HTML document or an image. A post request posts (or sends) data to a
server, such as authentication information or data from a form that gathers user input. Usually, post requests are used to post a message to a news group or a discussion
forum, pass user input to a data-handling process and store or update the data on a
server. A get request sends form data as part of the URL. A get request limits the
query string to a predefined number of characters that varies from server to server. If
the query string exceeds this limit, a post request must be used. The data sent in a
post request is not part of the URL and cannot be seen by users. Sensitive form fields,
such as passwords, should be sent using post requests.
19.5

Write a CGI script that prints the squares of the integers from 1 to 10 on separate lines.
ANS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

// Exercise 19.5 Solution: ex19_05.cpp


// Numbers 1 through 10 and their squares
#include <iostream>
using std::cout;
int main()
{
cout << "Content-type: text/html\n\n"; // output HTTP header
// output XML declaration and DOCTYPE
cout << "<?xml version = \"1.0\"?>"
<< "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
<< "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">";
// output html element and its contents
cout << "<html xmlns = \"http://www.w3.org/1999/xhtml\">"
<< "<head><title>Numbers 1 through 10 Squared</title>"
<< "</head><body>Numbers 1 through 10 Squared<br /><br />";
// display squares from 1 to 10
for ( int i = 1; i <= 10; i++ )
cout << "The square of " << i << " is " << i * i << "<br />";
cout << "</body></html>";
return 0;
} // end main

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Chapter 19 Web Programming

19.6 Write a CGI script that receives as input three numbers from the client and displays a statement indicating whether the three numbers could represent an equilateral triangle (all three sides
are the same length), an isosceles triangle (two sides are the same length) or a right triangle (the
square of one side is equal to the sum of the squares of the other two sides).
ANS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

// Exercise 19.6 Solution: ex19_06.cpp


// Evaluate 3 sides of a triangle.
#include <iostream>
using std::cin;
using std::cout;
#include <string>
using std::string;
#include <cstdlib>
using std::getenv;
using std::atoi;
int main()
{
char postString[ 1024 ] = ""; // variable to hold query string
string dataString = "";
string oneString = "";
string twoString = "";
string threeString = "";
int contentLength = 0;
// content was submitted

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Exercises
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

if ( getenv( "CONTENT_LENGTH" ) )
{
contentLength = atoi( getenv( "CONTENT_LENGTH" ) );
cin.read( postString, contentLength );
dataString = postString;
} // end if
cout << "Content-type: text/html\n\n"; // output HTTP header
// output XML declaration and DOCTYPE
cout << "<?xml version = \"1.0\"?>"
<< "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
<< "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">";
// output html element and some of its contents
cout << "<html xmlns = \"http://www.w3.org/1999/xhtml\">"
<< "<head><title>Using POST with Forms</title></head><body>";
// output xhtml form
cout << "<p>Enter three integers:</p>"
<< "<form method = \"post\" action = \"ex19_06.cgi\">"
<< "One<br /><input type = \"text\" name = \"one\" /><br />"
<< "Two<br /><input type = \"text\" name = \"two\" /><br />"
<< "Three<br /><input type = \"text\" name = \"three\" /><br />"
<< "<br /><input type = \"submit\" value = \"Submit Numbers\" />"
<< "</form>";
// data was sent using POST
if ( contentLength > 0 )
{
// retrieve first value
int oneLocation = dataString.find( "one=" ) + 4;
int endOne = dataString.find( "&two" ) ;
oneString = dataString.substr( oneLocation, endOne - oneLocation );
// retrieve second value
int twoLocation = dataString.find( "two=" ) + 4;
int endTwo = dataString.find( "&three" ) ;
twoString = dataString.substr( twoLocation, endTwo - twoLocation );
// retrieve third value
int threeLocation = dataString.find( "three=" ) + 6;
threeString = dataString.substr( threeLocation );
// convert values to int
int one = atoi( oneString.c_str() );
int two = atoi( twoString.c_str() );
int three = atoi( threeString.c_str() );
// equilateral triangle
if( one == two && two == three )
cout << "This is an equilateral triangle";
// isosceles triangle

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

6
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

Chapter 19 Web Programming

if( ( one == two && one != three ) || ( two == three && two != one )
|| ( one == three && one != two ) )
cout << "This is an isosceles triangle";
// square sides of triangle
int onesquared = one * one;
int twosquared = two * two;
int threesquared = three * three;
// right triangle
if ( ( onesquared == ( twosquared + threesquared ) ) ||
( twosquared == ( onesquared + threesquared ) ) ||
( threesquared == ( onesquared + twosquared ) ) )
cout << "This is a right triangle.";
} // end if
else // no data was sent
cout << "<p>Please enter data in the form.</p>";
cout << "</body></html>";
return 0;
} // end main

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Exercises

19.7 Write a soothsayer script that allows the user to submit a question. When the question is
submitted, the script should choose a random response from a list of answers (such as "It could
be", "Probably not", "Definitely", "Not looking too good" and "Yes") and display the answer
to the client.
ANS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

// Exercise 19.7 Solution: ex19_07.cpp


// Soothsayer Exercise
#include <iostream>
using std::cin;
using std::cout;
#include <string>
using std::string;
#include <cstdlib>
using std::getenv;
using std::atoi;
using std::rand;
using std::srand;
#include <ctime>
using std::time;
int main()
{
char postString[ 1024 ] = ""; // variable to hold posted string
string dataString = "";
string questionString = "";
int contentLength = 0;
// content was submitted
if ( getenv( "CONTENT_LENGTH" ) )
{
contentLength = atoi( getenv( "CONTENT_LENGTH" ) );
// get user entered question
cin.read( postString, contentLength );
dataString = postString;
} // end if
cout << "Content-type: text/html\n\n"; // output HTTP header
// output XML declaration and DOCTYPE
cout << "<?xml version = \"1.0\"?>"
<< "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
<< "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">";
// output html element and some of its contents
cout << "<html xmlns = \"http://www.w3.org/1999/xhtml\">"
<< "<head><title>Using POST with Forms</title></head><body>";
// output xhtml form
cout << "<p>Please enter a question:</p>"

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

8
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

Chapter 19 Web Programming

<<
<<
<<
<<

"<form method = \"post\" action = \"ex19_07.cgi\">"


"<input type = \"text\" name = \"question\" size=50 /><br />"
"<br /><input type = \"submit\" value = \"Ask Question\" />"
"</form>";

// data was sent using POST


if ( contentLength > 0 )
{
// retrieve first value
int questionLocation = dataString.find( "question=" ) + 9;
questionString = dataString.substr( questionLocation );
srand( time ( 0 ) );
int randomNumber = 1 + rand() % 5;
// choose which vague answer to display
switch ( randomNumber )
{
case 1:
cout << "It could be.";
break;
case 2:
cout << "Probably not.";
break;
case 3:
cout << "Definitely.";
break;
case 4:
cout << "Not looking too good.";
break;
case 5:
cout << "Yes.";
break;
default:
cout << "Your question was too vague.";
break;
} // end switch
// ask user for another question
cout << "<br/><br/>Please ask another question.";
} // end if
else // no data was sent
cout << "<p>Please enter data in the form.</p>";
cout << "</body></html>"; // close html page
return 0;
} // end main

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Exercises

19.8 Modify the program of Figs. 19.1319.14 to incorporate the opening XHTML form and
the processing of the data into a single CGI script (i.e., combine the XHTML of Fig. 19.13 into the
CGI script of Fig. 19.14). When the CGI script is requested initially, the form should be displayed.
When the form is submitted, the CGI script should display the result.
ANS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

// Exercise 19.8 Solution: ex19_08.cpp


// Modified Bug2Bug Travel portal.
#include <iostream>
using std::cin;
using std::cout;
#include <string>
using std::string;
#include <cstdlib>
using std::getenv;
using std::atoi;
int main()
{
char postString[ 1024 ] = "";
string dataString = "";
string nameString = "";

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

10
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

Chapter 19 Web Programming

string passwordString = "";


int contentLength = 0;
// data was posted
if ( getenv( "CONTENT_LENGTH" ) )
{
contentLength = atoi( getenv( "CONTENT_LENGTH" ) );
// get entered data
cin.read( postString, contentLength );
dataString = postString;
// search string for input data
int namelocation = dataString.find( "namebox=" ) + 8;
int endNamelocation = dataString.find( "&" );
int password = dataString.find( "passwordbox=" ) + 12;
int endPassword = dataString.find( "&button" );
// get values for name and password
nameString = dataString.substr(
namelocation, endNamelocation - namelocation );
passwordString = dataString.substr(
password, endPassword - password );
} // end if
cout << "Content-type: text/html\n\n"; // output HTTP header
// output XML declaration and DOCTYPE
cout << "<?xml version = \"1.0\"?>"
<< "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
<< "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">";
// output html element and some of its contents
cout << "<html xmlns = \"http://www.w3.org/1999/xhtml\">"
<< "<head><title>Bug2Bug Travel</title></head><body>";
// output response
if ( getenv( "CONTENT_LENGTH" ) )
{
// output specials
cout << "<h1>Welcome " << nameString << "!</h1>"
<< "<p>Here are our weekly specials:</p>"
<< "<ul><li>Boston to Taiwan ($875)</li>"
<< "<li>San Diego to Hong Kong ($750)</li>"
<< "<li>Chicago to Mexico City ($568)</li></ul>";
// password is correct
if ( passwordString == "coast2coast" )
cout << "<hr /><p>Current member special: "
<< "Seattle to Tokyo ($400)</p>";
else // password was incorrect
cout << "<p>Sorry. You have entered an incorrect password</p>";
} // end if
else // output a form

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Exercises
73
74
75
76
77
78
79
80
81
82
83
84

11

cout << "<form method = \"post\" action = \"/cgi-bin/ex19_08.cgi\">"


<< "<p>Please enter your name and password:</p>"
<< "<input type = \"text\" name = \"namebox\" />"
<< "<input type = \"password\" name = \"passwordbox\" />"
<< "<p>password is not encrypted</p>"
<< "<input type = \"submit\" name = \"button\" /></form>";
} // end else
cout << "</body></html>"; // end html page
return 0;
} // end main

19.9 Modify the viewcart.cgi script (Fig. 19.23) to enable users to remove some items from the
shopping cart.
ANS:

1
2
3

// Exercise 19.9 Solution: viewcart.cpp


// Program to view books in the shopping cart.
#include <iostream>

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

12
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

Chapter 19 Web Programming

using
using
using
using

std::cerr;
std::cin;
std::cout;
std::ios;

#include <fstream>
using std::ifstream;
#include <string>
using std::string;
#include <cstdlib>
using std::getenv;
using std::atoi;
using std::exit;
void displayShoppingCart( const string & );
int main()
{
char query[ 1024 ] = ""; // variable to store query string
string cartData; // variable to hold contents of cart
string dataString = "";
string cookieString = "";
string isbnEntered = "";
string addString = "";
int contentLength = 0;
// retrieve cookie data
if ( getenv( "HTTP_COOKIE" ) )
{
cartData = getenv( "HTTP_COOKIE" );
cookieString = cartData;
} // end if
// data was entered
if ( getenv( "CONTENT_LENGTH" ) )
{
contentLength = atoi( getenv( "CONTENT_LENGTH" ) );
cin.read( query, contentLength );
dataString = query;
// find location of isbn value
int addLocation = dataString.find( "add=" ) + 4;
int endAdd = dataString.find( "&isbn" );
int isbnLocation = dataString.find( "isbn=" ) + 5;
// retrieve isbn number to add to cart
addString = dataString.substr( addLocation, endAdd - addLocation );
// retrieve isbn number to add to cart
isbnEntered = dataString.substr( isbnLocation );

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Exercises
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

// write cookie
string expires = "Friday, 14-MAY-10 16:00:00 GMT";
int cartLocation = cookieString.find( "CART=" ) + 5;
if ( cartLocation > 4 ) // cookie exists
cookieString = cookieString.substr( cartLocation );
if( addString == "true" ) // add book to shopping cart
{
if ( cookieString == "" ) // no cookie data exists
cookieString = isbnEntered;
else // cookie data exists
cookieString = cookieString + "," + isbnEntered;
// set cookie
cout << "set-cookie: CART=" << cookieString << "; expires="
<< expires << "; path=\n";
} // end if
if ( addString == "false" ) // remove book from shopping cart
{
string::size_type x = cookieString.find( isbnEntered );
// remove all instances of ISBN
while ( x < string::npos )
{
cookieString.replace( x, 13, "" );
x = cookieString.find( isbnEntered );
} // end while
// set cookie
cout << "set-cookie: CART=" << cookieString << "; expires="
<< expires << "; path=\n";
} // end if
} // end if
cout << "Content-Type: text/html\n\n"; // output HTTP header
// output XML declaration and DOCTYPE
cout << "<?xml version = \"1.0\"?>"
<< "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
<< "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">";
// output html element and some of its contents
cout << "<html xmlns = \"http://www.w3.org/1999/xhtml\">"
<< "<head><title>Shopping Cart</title></head><body><center>";
if ( cookieString != "" ) // cookie data exists
{
cout << "<p>Here is your current order:</p>";
displayShoppingCart( cookieString );
} // end if
else
cout << "<p>The shopping cart is empty.</p>";

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

13

14
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

Chapter 19 Web Programming

// output links back to book list and to check out


cout << "</center><br/>";
cout << "<a href=\"/cgi-bin/shop.cgi\">Back to book list</a><br/>";
cout << "<a href=\"/cgi-bin/checkout.cgi\">Check Out</a>";
cout << "</body></html>\n";
return 0;
} // end main
// function to display items in shopping cart
void displayShoppingCart( const string &cookieRef )
{
char book[ 50 ] = "";
char year[ 50 ] = "";
char isbn[ 50 ] = "";
char price[ 50 ] = "";
string
string
string
string

bookString = "";
yearString = "";
isbnString = "";
priceString = "";

ifstream userData( "catalog.txt", ios::in ); // open file for input


if ( !userData ) // file could not be opened
{
cerr << "Could not open database.";
exit( 1 );
} // end if
cout << "<table border = 1 cellpadding = 7 >";
cout << "<tr><td>Title</td><td>Copyright</td><td>ISBN</td>"
<< "<td>Price</td><td>Count</td><td> </td></tr>";
// file is open
while ( !userData.eof() )
{
// retrieve book information
userData.getline( book, 50 );
bookString = book;
// retrieve year information
userData.getline( year, 50 );
yearString = year;
// retrieve isbn number
userData.getline( isbn, 50 );
isbnString = isbn;
// retrieve price
userData.getline( price, 50 );
priceString = price;
int match = cookieRef.find( isbnString, 0 );

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Exercises

15

166
int count = 0;
167
168
// match has been made
169
while ( match >= 0 && isbnString != "" )
170
{
171
count++;
172
match = cookieRef.find( isbnString, match + 13 );
173
} // end while
174
175
// output table row with book information
176
if ( count != 0 )
177
cout << "<tr>"
178
<< "<form method=\"post\" action=\"/cgi-bin/viewcart.cgi\">"
179
<< "<input type=\"hidden\" name=\"add\" value=\"false\"/>"
180
<< "<input type=\"hidden\" name=\"isbn\" value=\""
181
<< isbnString << "\"/><td>" << bookString << "</td><td>"
182
<< yearString << "</td><td>" << isbnString << "</td><td>"
183
<< priceString << "</td><td>" << count << "</td>"
184
<< "<td><input type=\"submit\" value=\"Remove\"/>\n</td>"
185
<< "</form></tr>";
186
} // end while
187
188
cout << "</table>"; // end table
189 } // end function displayShoppingCart

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

16

Chapter 19 Web Programming

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

You might also like