cgicc: test.cpp Source File

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

# test.cpp

Go to the documentation of this file.

    00001 /* -*-mode:c++; c-file-style: "gnu";-*- */
    00002 /*
    00003  *  $Id: test.cpp,v 1.27 2007/07/08 20:06:59 sebdiaz Exp $
    00004  *
    00005  *  Copyright (C) 1996 - 2004 Stephen F. Booth <sbooth@gnu.org>
    00006  *                       2007 Sebastien DIAZ <sebastien.diaz@gmail.com>
    00007  *  Part of the GNU cgicc library, http://www.gnu.org/software/cgicc
    00008  *
    00009  *  This library is free software; you can redistribute it and/or
    00010  *  modify it under the terms of the GNU Lesser General Public
    00011  *  License as published by the Free Software Foundation; either
    00012  *  version 3 of the License, or (at your option) any later version.
    00013  *
    00014  *  This library is distributed in the hope that it will be useful,
    00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00017  *  Lesser General Public License for more details.
    00018  *
    00019  *  You should have received a copy of the GNU Lesser General Public
    00020  *  License along with this library; if not, write to the Free Software
    00021  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
    00022  */
    00023
    00030 #include <new>
    00031 #include <string>
    00032 #include <vector>
    00033 #include <stdexcept>
    00034 #include <iostream>
    00035 #include <cstdlib>
    00036
    00037 #include "cgicc/CgiDefs.h"
    00038 #include "cgicc/Cgicc.h"
    00039 #include "cgicc/HTTPHTMLHeader.h"
    00040 #include "cgicc/HTMLClasses.h"
    00041
    00042 #if HAVE_SYS_UTSNAME_H
    00043 #  include <sys/utsname.h>
    00044 #endif
    00045
    00046 #if HAVE_SYS_TIME_H
    00047 #  include <sys/time.h>
    00048 #endif
    00049
    00050 #include "styles.h"
    00051
    00052 using namespace std;
    00053 using namespace cgicc;
    00054
    00055 // Function prototypes
    00056 void dumpEnvironment(const CgiEnvironment& env);
    00057 void dumpList(const Cgicc& formData);
    00058 void showForm(const Cgicc& formData);
    00059
    00060 // Print the form for this CGI
    00061 void
    00062 printForm(const Cgicc& cgi)
    00063 {
    00064   cout << "<form method=\"post\" action=\""
    00065        << cgi.getEnvironment().getScriptName() << "\">" << endl;
    00066
    00067   cout << "<table>" << endl;
    00068
    00069   cout << "<tr><td class=\"title\">Your name</td>"
    00070        << "<td class=\"form\">"
    00071        << "<input type=\"text\" name=\"name\" value=\"Uncle Bob\" />"
    00072        << "</td></tr>" << endl;
    00073
    00074   cout << "<tr><td class=\"title\">Your salary in millions<br />(80-120)</td>"
    00075        << "<td class=\"form\">"
    00076        << "<input type=\"text\" name=\"bucks\" value=\"93\" />"
    00077        << "</td></tr>" << endl;
    00078
    00079   cout << "<tr><td class=\"title\">Hours you've wasted on the web</td>"
    00080        << "<td class=\"form\">"
    00081        << "<input type=\"text\" name=\"time\" value=\"100\" />"
    00082        << "</td></tr>" << endl;
    00083
    00084   cout << "<tr><td class=\"title\">Your thoughts (on anything)</td>"
    00085        << "<td class=\"form\">"
    00086        << "<textarea name=\"thoughts\" rows=\"4\" cols=\"40\">"
    00087        << "I don't have any!</textarea>" << "</td></tr>" << endl;
    00088
    00089   cout << "<tr><td class=\"title\">Are you hungry?</td>"
    00090        << "<td class=\"form\">"
    00091        << "<input type=\"checkbox\" name=\"hungry\" checked=\"checked\" />"
    00092        << "Yes</td></tr>" << endl;
    00093
    00094   cout << "<tr><td class=\"title\">Your favorite flavors of ice cream</td>"
    00095        << "<td class=\"form\">"
    00096        << "<select name=\"flavors\" multiple=\"multiple\">"
    00097        << "<option value=\"cookie dough\">Cookie Dough</option>"
    00098        << "<option value=\"rocky road\">Rocky Road</option>"
    00099        << "<option value=\"chocolate\">Chocolate</option>"
    00100        << "<option value=\"strawberry\">Strawberry</option>"
    00101        << "<option value=\"vanilla\">Vanilla</option>"
    00102        << "</select>" << "</td></tr>" << endl;
    00103
    00104   cout << "<tr><td class=\"title\">Your hair color</td>"
    00105        << "<td class=\"form\">"
    00106        << "<select name=\"hair\">"
    00107        << "<option value=\"blond\">Blond</option>"
    00108        << "<option value=\"brown\">Brown</option>"
    00109        << "<option value=\"red\">Red</option>"
    00110        << "<option value=\"black\">Black</option>"
    00111        << "<option value=\"white\">White</option>"
    00112        << "<option value=\"green\">Green</option>"
    00113        << "<option value=\"multicolored\">Multicolored</option>"
    00114        << "</select>" << "</td></tr>" << endl;
    00115
    00116   cout << "<tr><td class=\"title\">Your web browser</td>"
    00117        << "<td class=\"form\">"
    00118        << "<input type=\"radio\" name=\"browser\" value=\"Konqueror\""
    00119        << " checked=\"checked\" />Konqeuror"
    00120        << "<input type=\"radio\" name=\"browser\" value=\"Lynx\" />Lynx"
    00121        << "<input type=\"radio\" name=\"browser\" value=\"Mozilla\" />Mozilla"
    00122        << "<input type=\"radio\" name=\"browser\" value=\"IE\" />IE"
    00123        << "<input type=\"radio\" name=\"browser\" value=\"Other\" />Other"
    00124        << "</td></tr>" << endl;
    00125
    00126   cout << "<tr><td class=\"title\">Your favorite authors</td>"
    00127        << "<td class=\"form\">"
    00128        << "<input type=\"checkbox\" name=\"authors\" value=\"O'Brian\" />"
    00129        << "O'Brian"
    00130        << "<input type=\"checkbox\" name=\"authors\" value=\"Feynman\" />"
    00131        << "Feynman"
    00132        << "<input type=\"checkbox\" name=\"authors\" value=\"Camus\" />Camus"
    00133        << "<input type=\"checkbox\" name=\"authors\" value=\"Conrad\" />Conrad"
    00134        << "<input type=\"checkbox\" name=\"authors\" value=\"Vergil\" />Vergil"
    00135        << "<input type=\"checkbox\" name=\"authors\" value=\"Plato\" />Plato"
    00136        << "</td></tr>" << endl;
    00137
    00138   cout << "<tr><td class=\"title\">In the output, show</td>"
    00139        << "<td class=\"form\">"
    00140        << "<input type=\"checkbox\" name=\"showEnv\" checked=\"checked\" />"
    00141        << "Data from CgiEnvironment<br />"
    00142        << "<input type=\"checkbox\" name=\"showFE\" checked=\"checked\" />"
    00143        << "All FormEntries<br />"
    00144        << "<input type=\"checkbox\" name=\"showForm\" checked=\"checked\" />"
    00145        << "Data from Cgicc"
    00146        << "</td></tr>" << endl;
    00147
    00148   cout << "<tr><td class=\"title\">Exception Handling</td>"
    00149        << "<td class=\"form\">"
    00150        << "<input type=\"checkbox\" name=\"throw\" />"
    00151        << "Throw an exception to test error handling"
    00152        << "</td></tr>" << endl;
    00153
    00154   cout << "<tr><td class=\"title\">Save and Restore</td>"
    00155        << "<td class=\"form\">"
    00156        << "<input type=\"checkbox\" name=\"save\" />"
    00157        <<" Save submission to a file<br />"
    00158        << "<input type=\"checkbox\" name=\"restore\" />"
    00159        << "Restore data from the last saved submission"
    00160        << "</td></tr>" << endl;
    00161
    00162   cout << "</table>" << endl;
    00163
    00164   cout << "<div class=\"center\"><p>"
    00165        << "<input type=\"submit\" name=\"submit\"  value=\"Submit\" />"
    00166        << "<input type=\"reset\" value=\"Nevermind\" />"
    00167        << "</p></div></form>" << endl;
    00168 }
    00169
    00170 // Main Street, USA
    00171 int
    00172 main(int /*argc*/,
    00173      char ** /*argv*/)
    00174 {
    00175   try {
    00176 #if HAVE_GETTIMEOFDAY
    00177     timeval start;
    00178     gettimeofday(&start, NULL);
    00179 #endif
    00180
    00181     // Create a new Cgicc object containing all the CGI data
    00182     Cgicc cgi;
    00183
    00184     // If the user wants to throw an exception, go ahead and do it
    00185     if(cgi.queryCheckbox("throw") && ! cgi.queryCheckbox("restore"))
    00186       throw std::runtime_error("User-requested Exception thrown in main()");
    00187
    00188     // Output the HTTP headers for an HTML document, and the HTML 4.0 DTD info
    00189     cout << HTTPHTMLHeader() << HTMLDoctype(HTMLDoctype::eStrict) << endl;
    00190     cout << html().set("lang", "en").set("dir", "ltr") << endl;
    00191
    00192     // Set up the page's header and title.
    00193     // I will put in lfs to ease reading of the produced HTML.
    00194     cout << head() << endl;
    00195
    00196     // Output the style sheet portion of the header
    00197     cout << style() << comment() << endl;
    00198     cout << styles;
    00199     cout << comment() << style() << endl;
    00200
    00201     cout << title() << "GNU cgicc v" << cgi.getVersion() << " Test"
    00202          << title() << endl;
    00203
    00204     cout << head() << endl;
    00205
    00206     // Start the HTML body
    00207     cout << body() << endl;
    00208
    00209     cout << h1() << "GNU cgi" << span("cc").set("class","red")
    00210          << " v"<< cgi.getVersion() << " Test" << h1() << endl;
    00211
    00212     // Get a pointer to the environment
    00213     const CgiEnvironment& env = cgi.getEnvironment();
    00214
    00215     // Generic thank you message
    00216     cout << comment() << "This page generated by cgicc for "
    00217          << env.getRemoteHost() << comment() << endl;
    00218     cout << h4() << "Thanks for using cgi" << span("cc").set("class", "red")
    00219          << ", " << env.getRemoteHost()
    00220          << '(' << env.getRemoteAddr() << ")!" << h4() << endl;
    00221
    00222     // If the user wants to save the submission, do it
    00223     if(cgi.queryCheckbox("save")) {
    00224       // Make sure the save file is readable and writable by the CGI process
    00225       cgi.save("save");
    00226       cout << p(h2("Data Saved")) << endl;
    00227
    00228       cout << cgicc::div().set("class", "notice") << endl;
    00229       cout << "Your data has been saved, and may be restored (by anyone) "
    00230            << "via the same form." << endl << cgicc::div() << p() << endl;
    00231     }
    00232
    00233     // If the user wants to restore from the last submission, do it
    00234     if(cgi.queryCheckbox("restore")) {
    00235       cgi.restore("save");
    00236       cout << p(h2("Data Restored")) << endl;
    00237
    00238       cout << cgicc::div().set("class", "notice") << endl;
    00239       cout << "The data displayed has been restored from a file on disk."
    00240            << endl << cgicc::div() << p() << endl;
    00241     }
    00242
    00243     // If the user requested a dump of the environment,
    00244     // create a simple table showing the values of the
    00245     // environment variables
    00246     if(cgi.queryCheckbox("showEnv"))
    00247       dumpEnvironment(env);
    00248
    00249     // If the user requested, print out the raw form data from
    00250     // the vector of FormEntries.  This will contain every
    00251     // element in the list.
    00252     // This is one of two ways to get at form data, the other
    00253     // being the use of Cgicc's getElement() methods.
    00254     if(cgi.queryCheckbox("showFE"))
    00255       dumpList(cgi);
    00256
    00257     // If the user requested data via Cgicc's getElement() methods, do it.
    00258     // This is different than the use of the list of FormEntries
    00259     // because it requires prior knowledge of the name of form elements.
    00260     // Usually they will be known, but you never know.
    00261     if(cgi.queryCheckbox("showForm"))
    00262       showForm(cgi);
    00263
    00264     // Print out the form to do it again
    00265     cout << br() << endl;
    00266     printForm(cgi);
    00267     cout << hr().set("class", "half") << endl;
    00268
    00269     // Information on cgicc
    00270     cout << cgicc::div().set("align","center").set("class","smaller") << endl;
    00271     cout << "GNU cgi" << span("cc").set("class","red") << " v";
    00272     cout << cgi.getVersion() << br() << endl;
    00273     cout << "Compiled at " << cgi.getCompileTime();
    00274     cout << " on " << cgi.getCompileDate() << br() << endl;
    00275
    00276     cout << "Configured for " << cgi.getHost();
    00277 #if HAVE_UNAME
    00278     struct utsname info;
    00279     if(uname(&info) != -1) {
    00280       cout << ". Running on " << info.sysname;
    00281       cout << ' ' << info.release << " (";
    00282       cout << info.nodename << ")." << endl;
    00283     }
    00284 #else
    00285     cout << "." << endl;
    00286 #endif
    00287
    00288 #if HAVE_GETTIMEOFDAY
    00289     // Information on this query
    00290     timeval end;
    00291     gettimeofday(&end, NULL);
    00292     long us = ((end.tv_sec - start.tv_sec) * 1000000)
    00293       + (end.tv_usec - start.tv_usec);
    00294
    00295     cout << br() << "Total time for request = " << us << " us";
    00296     cout << " (" << static_cast<double>(us/1000000.0) << " s)";
    00297 #endif
    00298
    00299     // End of document
    00300     cout << cgicc::div() << endl;
    00301     cout << body() << html() << endl;
    00302
    00303     // No chance for failure in this example
    00304     return EXIT_SUCCESS;
    00305   }
    00306
    00307   // Did any errors occur?
    00308   catch(const std::exception& e) {
    00309
    00310     // This is a dummy exception handler, as it doesn't really do
    00311     // anything except print out information.
    00312
    00313     // Reset all the HTML elements that might have been used to
    00314     // their initial state so we get valid output
    00315     html::reset();      head::reset();          body::reset();
    00316     title::reset();     h1::reset();            h4::reset();
    00317     comment::reset();   td::reset();            tr::reset();
    00318     table::reset();     cgicc::div::reset();    p::reset();
    00319     a::reset();         h2::reset();            colgroup::reset();
    00320
    00321     // Output the HTTP headers for an HTML document, and the HTML 4.0 DTD info
    00322     cout << HTTPHTMLHeader() << HTMLDoctype(HTMLDoctype::eStrict) << endl;
    00323     cout << html().set("lang","en").set("dir","ltr") << endl;
    00324
    00325     // Set up the page's header and title.
    00326     // I will put in lfs to ease reading of the produced HTML.
    00327     cout << head() << endl;
    00328
    00329     // Output the style sheet portion of the header
    00330     cout << style() << comment() << endl;
    00331     cout << "body { color: black; background-color: white; }" << endl;
    00332     cout << "hr.half { width: 60%; align: center; }" << endl;
    00333     cout << "span.red, STRONG.red { color: red; }" << endl;
    00334     cout << "div.notice { border: solid thin; padding: 1em; margin: 1em 0; "
    00335          << "background: #ddd; }" << endl;
    00336
    00337     cout << comment() << style() << endl;
    00338
    00339     cout << title("GNU cgicc exception") << endl;
    00340     cout << head() << endl;
    00341
    00342     cout << body() << endl;
    00343
    00344     cout << h1() << "GNU cgi" << span("cc", set("class","red"))
    00345          << " caught an exception" << h1() << endl;
    00346
    00347     cout << cgicc::div().set("align","center").set("class","notice") << endl;
    00348
    00349     cout << h2(e.what()) << endl;
    00350
    00351     // End of document
    00352     cout << cgicc::div() << endl;
    00353     cout << hr().set("class","half") << endl;
    00354     cout << body() << html() << endl;
    00355
    00356     return EXIT_SUCCESS;
    00357   }
    00358 }
    00359
    00360 // Print out a table of the CgiEnvironment
    00361 void
    00362 dumpEnvironment(const CgiEnvironment& env)
    00363 {
    00364   // This is just a brain-dead dump of information.
    00365   // Almost all of this code is for HTML formatting
    00366   cout << h2("Environment information from CgiEnvironment") << endl;
    00367
    00368   cout << cgicc::div().set("align","center") << endl;
    00369
    00370   cout << table() << endl;
    00371
    00372   cout << tr() << td("Request Method").set("class","title")
    00373        << td(env.getRequestMethod()).set("class","data") << tr() << endl;
    00374   cout << tr() << td("Path Info").set("class","title")
    00375        << td(env.getPathInfo()).set("class","data") << tr() << endl;
    00376   cout << tr() << td("Path Translated").set("class","title")
    00377        << td(env.getPathTranslated()).set("class","data") << tr() << endl;
    00378   cout << tr() << td("Script Name").set("class","title")
    00379        << td(env.getScriptName()).set("class","data") << tr() << endl;
    00380   cout << tr() << td("HTTP Referrer").set("class","title")
    00381        << td(env.getReferrer()).set("class","data") << tr() << endl;
    00382   cout << tr() << td("HTTP Cookie").set("class","title")
    00383        << td(env.getCookies()).set("class","data") << tr() << endl;
    00384   cout << tr() << td("Query String").set("class","title")
    00385        << td(env.getQueryString()).set("class","data") << tr() << endl;
    00386   cout << tr() << td("Content Length").set("class","title")
    00387        << td().set("class","data") << env.getContentLength()
    00388        << td() << tr() << endl;
    00389   cout << tr() << td("Post Data").set("class","title")
    00390        << td().set("class","data")
    00391        << pre(env.getPostData()).set("class","data") << td()
    00392        << tr() << endl;
    00393   cout << tr() << td("Remote Host").set("class","title")
    00394        << td(env.getRemoteHost()).set("class","data") << tr() << endl;
    00395   cout << tr() << td("Remote Address").set("class","title")
    00396        << td(env.getRemoteAddr()).set("class","data") << tr() << endl;
    00397   cout << tr() << td("Authorization Type").set("class","title")
    00398        << td(env.getAuthType()).set("class","data") << tr() << endl;
    00399   cout << tr() << td("Remote User").set("class","title")
    00400        << td(env.getRemoteUser()).set("class","data") << tr() << endl;
    00401   cout << tr() << td("Remote Identification").set("class","title")
    00402        << td(env.getRemoteIdent()).set("class","data") << tr() << endl;
    00403   cout << tr() << td("Content Type").set("class","title")
    00404        << td(env.getContentType()).set("class","data") << tr() << endl;
    00405   cout << tr() << td("HTTP Accept").set("class","title")
    00406        << td(env.getAccept()).set("class","data") << tr() << endl;
    00407   cout << tr() << td("User Agent").set("class","title")
    00408        << td(env.getUserAgent()).set("class","data") << tr() << endl;
    00409   cout << tr() << td("Server Software").set("class","title")
    00410        << td(env.getServerSoftware()).set("class","data") << tr() << endl;
    00411   cout << tr() << td("Server Name").set("class","title")
    00412        << td(env.getServerName()).set("class","data") << tr() << endl;
    00413   cout << tr() << td("Gateway Interface").set("class","title")
    00414        << td(env.getGatewayInterface()).set("class","data") << tr() << endl;
    00415   cout << tr() << td("Server Protocol").set("class","title")
    00416        << td(env.getServerProtocol()).set("class","data") << tr() << endl;
    00417   cout << tr() << td("Server Port").set("class","title")
    00418        << td().set("class","data") << env.getServerPort()
    00419        << td() << tr() << endl;
    00420   cout << tr() << td("HTTPS").set("class","title")
    00421        << td().set("class","data") << (env.usingHTTPS() ? "true" : "false")
    00422        << td() << tr() << endl;
    00423   cout << tr() << td("Redirect Request").set("class","title")
    00424        << td(env.getRedirectRequest()).set("class","data") << tr() << endl;
    00425   cout << tr() << td("Redirect URL").set("class","title")
    00426        << td(env.getRedirectURL()).set("class","data") << tr() << endl;
    00427   cout << tr() << td("Redirect Status").set("class","title")
    00428        << td(env.getRedirectStatus()).set("class","data") << tr() << endl;
    00429
    00430   cout << table() << cgicc::div() << endl;
    00431 }
    00432
    00433 // Print out the value of every form element
    00434 void
    00435 dumpList(const Cgicc& formData)
    00436 {
    00437   cout << h2("Form Data via vector") << endl;
    00438
    00439   cout << cgicc::div().set("align","center") << endl;
    00440
    00441   cout << table()<< endl;
    00442
    00443   cout << tr().set("class","title") << td("Element Name")
    00444        << td("Element Value") << tr() << endl;
    00445
    00446   // Iterate through the vector, and print out each value
    00447   const_form_iterator iter;
    00448   for(iter = formData.getElements().begin();
    00449       iter != formData.getElements().end();
    00450       ++iter) {
    00451     cout << tr().set("class","data") << td(iter->getName())
    00452          << td(iter->getValue()) << tr() << endl;
    00453   }
    00454   cout << table() << cgicc::div() << endl;
    00455 }
    00456
    00457 // Print out information customized for each element
    00458 void
    00459 showForm(const Cgicc& formData)
    00460 {
    00461
    00462   // I am using an if statement to check if each element is found
    00463   cout << h2("Form Data via Cgicc") << endl;
    00464
    00465   cout << cgicc::div().set("class","notice") << endl;
    00466
    00467   //getElement
    00468   const_form_iterator name = formData.getElement("name");
    00469   if(name != (*formData).end() && ! name->isEmpty())
    00470     cout << "Your name is " << **name << '.' << br() << endl;
    00471   else
    00472     cout << "You don't have a name." << br() << endl;
    00473
    00474   // getElement and getDoubleValue
    00475   const_form_iterator salary = formData.getElement("bucks");
    00476   if(salary != (*formData).end() && ! salary->isEmpty())
    00477     cout << "You make " << (*salary).getDoubleValue(80, 120)
    00478          << " million dollars." << br() << endl;
    00479   else
    00480     cout << "You don't have a salary." << br() << endl;
    00481
    00482   // getElement and getIntegerValue
    00483   const_form_iterator hours = formData.getElement("time");
    00484   if(hours != (*formData).end() && ! (*hours).isEmpty())
    00485     cout << "You've wasted " << (*hours).getIntegerValue()
    00486          << " hours on the web." << br() << endl;
    00487   else
    00488     cout << "You haven't wasted any time on the web." << br() << endl;
    00489
    00490   // getElement and getStrippedValue
    00491   const_form_iterator thoughts = formData.getElement("thoughts");
    00492   if(thoughts != (*formData).end() && ! (*thoughts).isEmpty()) {
    00493     std::string temp = (*thoughts).getStrippedValue();
    00494     cout << "Your thoughts: " << temp << br() << endl;
    00495   }
    00496   else
    00497     cout << "You don't have any thoughts!?" << br() << endl;
    00498
    00499   // queryCheckbox
    00500   if(formData.queryCheckbox("hungry"))
    00501     cout << "You are hungry." << br() << endl;
    00502   else
    00503     cout << "You are not hungry." << br() << endl;
    00504
    00505   // getElement
    00506   std::vector<FormEntry> flavors;
    00507   formData.getElement("flavors", flavors);
    00508   if(! flavors.empty()) {
    00509     cout << "You like ";
    00510     for(std::string::size_type i = 0; i < flavors.size(); i++) {
    00511       cout << flavors[i].getValue();
    00512       if(i < flavors.size() - 2)
    00513         cout << ", ";
    00514       else if(i == flavors.size() - 2)
    00515         cout << " and ";
    00516     }
    00517     cout << " ice cream." << br() << endl;
    00518   }
    00519   else
    00520     cout << "You don't like ice cream!?" << br() << endl;
    00521
    00522   // getElement
    00523   const_form_iterator hair = formData.getElement("hair");
    00524   if(hair != (*formData).end())
    00525     cout << "Your hair is " << **hair << '.' << br() << endl;
    00526   else
    00527     cout << "You don't have any hair." << br() << endl;
    00528
    00529   cout << "You surf the web with " << formData("browser") << '.'
    00530        << br() << endl;
    00531
    00532   // getElement
    00533   std::vector<FormEntry> authors;
    00534   formData.getElement("authors", authors);
    00535   if(! authors.empty()) {
    00536     cout << "You like to read books by ";
    00537     for(std::string::size_type i = 0; i < authors.size(); ++i) {
    00538       cout << authors[i].getValue();
    00539       if(i < authors.size() - 2)
    00540         cout << ", ";
    00541       else if(i == authors.size() - 2)
    00542         cout << " and ";
    00543     }
    00544     cout << "." << br() << endl;
    00545   }
    00546   else
    00547     cout << "You don't like to read!?" << br() << endl;
    00548
    00549   cout << cgicc::div() << endl;
    00550 }