Server-Side Files
In the preceding section, we demonstrated how to maintain state information about a user via cookies. The other mechanism by which to do so is to create server-side files (i.e., files that are located on the server or on the server's network). This is a slightly more secure method by which to maintain vital information. In this mechanism, only someone with access and permission to change files on the server can alter files. Figures 19.1819.19 ask users for contact information, then store it on the server. Figure 19.20 shows the file that is created by the script.
Figure 19.18. XHTML document to read user's contact information.
(This item is displayed on pages 949 - 950 in the print version)
"http://www.w3.org/1999/xhtml"> 9 10
1 6 7 8 |
Please enter your contact information 11 12 13 | 14
Please enter your information in the form below. 15Note: You must fill in all fields. 16 method = "post" action = "/cgi-bin/savefile.cgi"> 1718 First Name: 19 "text" name = "firstname" size = "10" /> 20 Last Name: 21 "text" name = "lastname" size = "15" /> 22 2324 Address: 25 "text" name = "address" size = "25" /> 26 Town: "text" name = "town" size = "10" /> 27 State: "text" name = "state" size = "2" /> 28 Zip Code: "text" name = "zipcode" size = "5" /> 29 Country: "text" name = "country" size = "10" /> 30 3132 E-mail Address: "text" name = "email" /> 33 34 "submit" value = "Enter" /> 35 "reset" value = "Clear" /> 36 37 38 |
Figure 19.19. Creating a server-side file to store user data.
(This item is displayed on pages 950 - 953 in the print version)
1 // Fig. 19.19: savefile.cpp 2 // Program to enter user's contact information into a 3 // server-side file. 4 #include 5 using std::cerr; 6 using std::cin; 7 using std::cout; 8 using std::ios; 9 10 #include 11 using std::ofstream; 12 13 #include 14 using std::string; 15 16 #include 17 using std::getenv; 18 using std::atoi; 19 using std::exit; 20 21 int main() 22 { 23 char postString[ 1024 ] = ""; 24 int contentLength = 0; 25 26 // variables to store user data 27 string dataString = ""; 28 string firstname = ""; 29 string lastname = ""; 30 string address = ""; 31 string town = ""; 32 string state = ""; 33 string zipcode = ""; 34 string country = ""; 35 string email = ""; 36 37 // data was posted 38 if ( getenv( "CONTENT_LENGTH" ) ) 39 contentLength = atoi( getenv( "CONTENT_LENGTH" ) ); 40 41 cin.read( postString, contentLength ); 42 dataString = postString; 43 44 // search for first '+' character 45 string::size_type charLocation = dataString.find( "+" ); 46 47 // search for next '+' character 48 while ( charLocation < string::npos ) ) 49 { 50 dataString.replace( charLocation, 1, " " ); 51 charLocation = dataString.find( "+", charLocation + 1 ); 52 } // end while 53 54 // find location of firstname 55 int firstStart = dataString.find( "firstname=" ) + 10; 56 int endFirst = dataString.find( "&lastname" ); 57 firstname = dataString.substr( firstStart, endFirst - firstStart ); 58 59 // find location of lastname 60 int lastStart = dataString.find( "lastname=" ) + 9; 61 int endLast = dataString.find( "&address" ); 62 lastname = dataString.substr( lastStart, endLast - lastStart ); 63 64 // find location of address 65 int addressStart = dataString.find( "address=" ) + 8; 66 int endAddress = dataString.find( "&town" ); 67 address = dataString.substr( addressStart, endAddress - addressStart ); 68 69 // find location of town 70 int townStart = dataString.find( "town=" ) + 5; 71 int endTown = dataString.find( "&state" ); 72 town = dataString.substr( townStart, endTown - townStart ); 73 74 // find location of state 75 int stateStart = dataString.find( "state=" ) + 6; 76 int endState = dataString.find( "&zipcode" ); 77 state = dataString.substr( stateStart, endState - stateStart ); 78 79 // find location of zip code 80 int zipStart = dataString.find( "zipcode=" ) + 8; 81 int endZip = dataString.find( "&country" ); 82 zipcode = dataString.substr( zipStart, endZip - zipStart ); 83 84 // find location of country 85 int countryStart = dataString.find( "country=" ) + 8; 86 int endCountry = dataString.find( "&email" ); 87 country = dataString.substr( countryStart, endCountry - countryStart ); 88 89 // find location of e-mail address 90 int emailStart = dataString.find( "email=" ) + 6; 91 int endEmail = dataString.find( "&submit" ); 92 email = dataString.substr( emailStart, endEmail - emailStart ); 93 94 cout << "Content-Type: text/html "; // output header 95 96 // output XML declaration and DOCTYPE 97 cout << "" 98 << " 99 << ""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">"; 100 101 // output html element and some of its contents 102 cout << "" 103 << "Contact Information entered"; 104 105 ofstream outFile( "clients.txt", ios::app ); // output to file 106 107 if ( !outFile ) // file was not opened properly 108 { 109 cerr << "Error: could not open contact file."; 110 exit( 1 ); 111 } // end if 112 113 // append data to clients.txt file 114 outFile << firstname << " " << lastname << " " << address << " " 115 << town << " " << state << " " << country << " " << zipcode 116 << " " << email << " "; 117 118 // output data to user 119 cout << "
|
Figure 19.20. Contents of clients.txt data file.
(This item is displayed on page 953 in the print version)
|
The XHTML document in Fig. 19.18 posts the form data to the CGI script in Fig. 19.19. In the CGI script, lines 4592 decode the parameters that were sent by the client. Line 105 creates an instance of the output file stream (outFile) that opens a file for appending. If the file clients.txt does not exist, it is created. Lines 114116 output the personal information to the file. (See Fig. 19.20 for the contents of the file.) The remainder of the program outputs an XHTML document that summarizes the user's information.
There are a few important points to make about this program. First, we do not perform any validation on the data before writing it to disk. Normally, the script would check for bad data, incomplete data, etc. Second, our file is located in the cgi-bin directory, which is publicly accessible. Someone who knew the filename would find it relatively easy to access someone else's contact information.
This script is not robust enough for deployment on the Internet, but it does provide an example of the use of server-side files to store information. Once the files are stored on the server, users cannot change them unless they are allowed to do so by the server administrator. Thus, storing these files on the server is safer than storing user data in cookies. [Note: Many systems store user information in password-protected databases for higher levels of security.]
Note that, in this example, we show how to write data to a server-side file. In the next section we show how to retrieve data from a server-side file, using the techniques used for reading from a file in Chapter 17, File Processing.