Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
B.Eckel - Thinking in C++, Vol.2, 2nd edition.pdf
Скачиваний:
50
Добавлен:
08.05.2013
Размер:
2.09 Mб
Скачать

The first command-line argument is the list of email addresses, one per line. The names are read one at a time into the string called name using getline( ). Then a temporary file called m.txt is created to build the customized message for that individual; the customization is the note about how to remove themselves, along with the URL. Then the message body, which is in the file specified by the second command-line argument, is appended to m.txt. Finally, the command is built inside a string: the “-F” argument to fastmail is who it’s from, the “-r” argument is who to reply to. The “-s” is the subject line, the next argument is the file containing the mail and the last argument is the email address to send it to.

You can start this program in the background and tell Unix not to stop the program when you sign off of the server. However, it takes a while to run for a long list (this isn’t because of the program itself, but the mailing process). I like to keep track of the progress of the program by sending a status message to another email account, which is accomplished in the last few lines of the program.

A general information-extraction CGI program

One of the problems with CGI is that you must write and compile a new program every time you want to add a new facility to your Web site. However, much of the time all that your CGI program does is capture information from the user and store it on the server. If you could use hidden fields to specify what to do with the information, then it would be possible to write a single CGI program that would extract the information from any CGI request. This information could be stored in a uniform format, in a subdirectory specified by a hidden field in the HTML form, and in a file that included the user’s email address – of course, in the general case the email address doesn’t guarantee uniqueness (the user may post more than one submission) so the date and time of the submission can be mangled in with the file name to make it unique. If you can do this, then you can create a new data-collection page just by defining the HTML and creating a new subdirectory on your server. For example, every time I come up with a new class or workshop, all I have to do is create the HTML form for signups – no CGI programming is required.

The following HTML page shows the format for this scheme. Since a CGI POST is more general and doesn’t have any limit on the amount of information it can send, it will always be used instead of a GET for the ExtractInfo.cpp program that will implement this system. Although this form is simple, yours can be as complicated as you need it.

//:! C10:INFOtest.html <html><head><title>

Extracting information from an HTML POST</title> </head>

<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080"> <hr>

<p>Extracting information from an HTML POST</p>

Appendix B: Programming Guidelines

560

<form action="/cgi-bin/ExtractInfo.exe" method="POST">

<input type="hidden" name="subject-field" value="test-extract-info">

<input type="hidden" name="reminder" value="Remember your lunch!">

<input type="hidden" name="test-field" value="on">

<input type="hidden" name="mail-copy" value="Bruce@EckelObjects.com;eckel@aol.com"> <input type="hidden" name="confirmation" value="confirmation1">

<p>Email address (Required): <input type="text" size="45" name="email-address" > </p>Comment:<br>

<textarea name="Comment" rows="6" cols="55"> </textarea>

<p><input type="submit" name="submit"> <input type="reset" name="reset"</p> </form><hr></body></html>

///:~

Right after the form’s action statement, you see

<input type="hidden"

This means that particular field will not appear on the form that the user sees, but the information will still be submitted as part of the data for the CGI program.

The value of this field named “subject-field” is used by ExtractInfo.cpp to determine the subdirectory in which to place the resulting file (in this case, the subdirectory will be “test- extract-info”). Because of this technique and the generality of the program, the only thing you’ll usually need to do to start a new database of data is to create the subdirectory on the server and then create an HTML page like the one above. The ExtractInfo.cpp program will do the rest for you by creating a unique file for each submission. Of course, you can always change the program if you want it to do something more unusual, but the system as shown will work most of the time.

The contents of the “reminder” field will be displayed on the form that is sent back to the user when their data is accepted. The “test-field” indicates whether to dump test information to the resulting Web page. If “mail-copy” exists and contains anything other than “no” the value string will be parsed for mailing addresses separated by ‘;’ and each of these addresses will get a mail message with the data in it. The “email-address” field is required in each case and the email address will be checked to ensure that it conforms to some basic standards.

The “confirmation” field causes a second program to be executed when the form is posted. This program parses the information that was stored from the form into a file, turns it into

Appendix B: Programming Guidelines

561

human-readable form and sends an email message back to the client to confirm that their information was received (this is useful because the user may not have entered their email address correctly; if they don’t get a confirmation message they’ll know something is wrong). The design of the “confirmation” field allows the person creating the HTML page to select more than one type of confirmation. Your first solution to this may be to simply call the program directly rather than indirectly as was done here, but you don’t want to allow someone else to choose – by modifying the web page that’s downloaded to them – what programs they can run on your machine.

Here is the program that will extract the information from the CGI request:

//: C10:ExtractInfo.cpp

//Extracts all the information from a CGI POST

//submission, generates a file and stores the

//information on the server. By generating a

//unique file name, there are no clashes like

//you get when storing to a single file. #include "CGImap.h"

#include <iostream> #include <fstream> #include <cstdio> #include <ctime> using namespace std;

const string contact("Bruce@EckelObjects.com");

//Paths in this program are for Linux/Unix. You

//must use backslashes (two for each single

//slash) on Win32 servers:

const string rootpath("/home/eckel/");

void show(CGImap& m, ostream& o);

//The definition for the following is the only

//thing you must change to customize the program void

store(CGImap& m, ostream& o, string nl = "\n");

int main() {

cout << "Content-type:

text/html\n"<< endl;

Post p; // Collect the

POST data

CGImap query(p);

 

// "test-field" set to

"on" will dump contents

if(query["test-field"]

== "on") {

cout << "map size: "

<< query.size() << "<br>";

query.dump(cout);

 

Appendix B: Programming Guidelines

562

}

if(query["subject-field"].size() == 0) { cout << "<h2>Incorrect form. Contact " << contact << endl;

return 0;

}

string email = query["email-address"]; if(email.size() == 0) {

cout << "<h2>Please enter your email address" << endl;

return 0;

}

if(email.find_first_of(" \t") != string::npos){ cout << "<h2>You cannot include white space "

"in your email address" << endl; return 0;

}

if(email.find('@') == string::npos) {

cout << "<h2>You must include a proper email" " address including an '@' sign" << endl;

return 0;

}

if(email.find('.') == string::npos) {

cout << "<h2>You must include a proper email" " address including a '.'" << endl;

return 0;

}

//Create a unique file name with the user's

//email address and the current time in hex const int bsz = 1024;

char fname[bsz]; time_t now;

time(&now); // Encoded date & time sprintf(fname, "%s%X.txt", email.c_str(), now); string path(rootpath + query["subject-field"] +

"/" + fname);

ofstream out(path.c_str()); if(!out) {

cout << "cannot open " << path << "; Contact"

<<contact << endl;

return 0;

}

// Store the file and path information:

Appendix B: Programming Guidelines

563

out << "///{" << path << endl; // Display optional reminder:

if(query["reminder"].size() != 0)

cout <<"<H1>" << query["reminder"] <<"</H1>"; show(query, cout); // For results page store(query, out); // Stash data in file

cout << "<br><H2>Your submission has been " "posted as<br>" << fname << endl

<< "<br>Thank you</H2>" << endl; out.close();

//Optionally send generated file as email

//to recipients specified in the field: if(query["mail-copy"].length() != 0 &&

query["mail-copy"] != "no") { string to = query["mail-copy"];

//Parse out the recipient names, separated

//by ';', into a vector.

vector<string> recipients; int ii = to.find(';'); while(ii != string::npos) {

recipients.push_back(to.substr(0, ii)); to = to.substr(ii + 1);

ii = to.find(';');

}

recipients.push_back(to); // Last one

// "fastmail" only available on Linux/Unix: for(int i = 0; i < recipients.size(); i++) {

string cmd("fastmail -s"" \"" + query["subject-field"] + "\" " + path + " " + recipients[i]);

system(cmd.c_str());

}

}

//Execute a confirmation program on the file.

//Typically, this is so you can email a

//processed data file to the client along with

//a confirmation message: if(query["confirmation"].length() != 0) {

string conftype = query["confirmation"]; if(conftype == "confirmation1") {

string command("./ProcessApplication.exe "+ path + " &");

//The data file is the argument, and the

Appendix B: Programming Guidelines

564

// ampersand runs it as a separate process: system(command.c_str());

string logfile("Extract.log"); ofstream log(logfile.c_str());

}

}

}

//For displaying the information on the html

//results page:

void show(CGImap& m, ostream& o) { string nl("<br>");

o << "<h2>The data you entered was:"

<<"</h2><br>"

<<"From[" << m["email-address"] << ']' <<nl; for(CGImap::iterator it = m.begin();

it != m.end(); it++) { string name = (*it).first,

value = (*it).second; if(name != "email-address" &&

name != "confirmation" && name != "submit" &&

name != "mail-copy" && name != "test-field" && name != "reminder")

o << "<h3>" << name << ": </h3>"

<<"<pre>" << value << "</pre>";

}

}

// Change this to customize the program:

void store(CGImap& m, ostream& o, string nl) {

o << "From[" << m["email-address"] << ']' <<nl; for(CGImap::iterator it = m.begin();

it != m.end(); it++) { string name = (*it).first,

value = (*it).second; if(name != "email-address" &&

name != "confirmation" && name != "submit" &&

name != "mail-copy" && name != "test-field" && name != "reminder")

Appendix B: Programming Guidelines

565

Соседние файлы в предмете Численные методы
  • #
    08.05.20133.99 Mб22A.Menezes, P.van Oorschot,S.Vanstone - HANDBOOK OF APPLIED CRYPTOGRAPHY.djvu
  • #
  • #
    08.05.20135.91 Mб24B.Eckel - Thinking in Java, 3rd edition (beta).pdf
  • #
  • #
    08.05.20136.09 Mб17D.MacKay - Information Theory, Inference, and Learning Algorithms.djvu
  • #
    08.05.20133.85 Mб15DIGITAL Visual Fortran ver.5.0 - Programmers Guide to Fortran.djvu
  • #
    08.05.20131.84 Mб12E.A.Lee, P.Varaiya - Structure and Interpretation of Signals and Systems.djvu