test.cpp
Go to the documentation of this file.
1 /* -*-mode:c++; c-file-style: "gnu";-*- */
2 /*
3  * $Id: test.cpp,v 1.27 2007/07/08 20:06:59 sebdiaz Exp $
4  *
5  * Copyright (C) 1996 - 2004 Stephen F. Booth <sbooth@gnu.org>
6  * 2007 Sebastien DIAZ <sebastien.diaz@gmail.com>
7  * Part of the GNU cgicc library, http://www.gnu.org/software/cgicc
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
22  */
23 
30 #include <new>
31 #include <string>
32 #include <vector>
33 #include <stdexcept>
34 #include <iostream>
35 #include <cstdlib>
36 
37 #include "cgicc/CgiDefs.h"
38 #include "cgicc/Cgicc.h"
39 #include "cgicc/HTTPHTMLHeader.h"
40 #include "cgicc/HTMLClasses.h"
41 
42 #if HAVE_SYS_UTSNAME_H
43 # include <sys/utsname.h>
44 #endif
45 
46 #if HAVE_SYS_TIME_H
47 # include <sys/time.h>
48 #endif
49 
50 #include "styles.h"
51 
52 using namespace std;
53 using namespace cgicc;
54 
55 // Function prototypes
56 void dumpEnvironment(const CgiEnvironment& env);
57 void dumpList(const Cgicc& formData);
58 void showForm(const Cgicc& formData);
59 
60 // Print the form for this CGI
61 void
62 printForm(const Cgicc& cgi)
63 {
64  cout << "<form method=\"post\" action=\""
65  << cgi.getEnvironment().getScriptName() << "\">" << endl;
66 
67  cout << "<table>" << endl;
68 
69  cout << "<tr><td class=\"title\">Your name</td>"
70  << "<td class=\"form\">"
71  << "<input type=\"text\" name=\"name\" value=\"Uncle Bob\" />"
72  << "</td></tr>" << endl;
73 
74  cout << "<tr><td class=\"title\">Your salary in millions<br />(80-120)</td>"
75  << "<td class=\"form\">"
76  << "<input type=\"text\" name=\"bucks\" value=\"93\" />"
77  << "</td></tr>" << endl;
78 
79  cout << "<tr><td class=\"title\">Hours you've wasted on the web</td>"
80  << "<td class=\"form\">"
81  << "<input type=\"text\" name=\"time\" value=\"100\" />"
82  << "</td></tr>" << endl;
83 
84  cout << "<tr><td class=\"title\">Your thoughts (on anything)</td>"
85  << "<td class=\"form\">"
86  << "<textarea name=\"thoughts\" rows=\"4\" cols=\"40\">"
87  << "I don't have any!</textarea>" << "</td></tr>" << endl;
88 
89  cout << "<tr><td class=\"title\">Are you hungry?</td>"
90  << "<td class=\"form\">"
91  << "<input type=\"checkbox\" name=\"hungry\" checked=\"checked\" />"
92  << "Yes</td></tr>" << endl;
93 
94  cout << "<tr><td class=\"title\">Your favorite flavors of ice cream</td>"
95  << "<td class=\"form\">"
96  << "<select name=\"flavors\" multiple=\"multiple\">"
97  << "<option value=\"cookie dough\">Cookie Dough</option>"
98  << "<option value=\"rocky road\">Rocky Road</option>"
99  << "<option value=\"chocolate\">Chocolate</option>"
100  << "<option value=\"strawberry\">Strawberry</option>"
101  << "<option value=\"vanilla\">Vanilla</option>"
102  << "</select>" << "</td></tr>" << endl;
103 
104  cout << "<tr><td class=\"title\">Your hair color</td>"
105  << "<td class=\"form\">"
106  << "<select name=\"hair\">"
107  << "<option value=\"blond\">Blond</option>"
108  << "<option value=\"brown\">Brown</option>"
109  << "<option value=\"red\">Red</option>"
110  << "<option value=\"black\">Black</option>"
111  << "<option value=\"white\">White</option>"
112  << "<option value=\"green\">Green</option>"
113  << "<option value=\"multicolored\">Multicolored</option>"
114  << "</select>" << "</td></tr>" << endl;
115 
116  cout << "<tr><td class=\"title\">Your web browser</td>"
117  << "<td class=\"form\">"
118  << "<input type=\"radio\" name=\"browser\" value=\"Konqueror\""
119  << " checked=\"checked\" />Konqeuror"
120  << "<input type=\"radio\" name=\"browser\" value=\"Lynx\" />Lynx"
121  << "<input type=\"radio\" name=\"browser\" value=\"Mozilla\" />Mozilla"
122  << "<input type=\"radio\" name=\"browser\" value=\"IE\" />IE"
123  << "<input type=\"radio\" name=\"browser\" value=\"Other\" />Other"
124  << "</td></tr>" << endl;
125 
126  cout << "<tr><td class=\"title\">Your favorite authors</td>"
127  << "<td class=\"form\">"
128  << "<input type=\"checkbox\" name=\"authors\" value=\"O'Brian\" />"
129  << "O'Brian"
130  << "<input type=\"checkbox\" name=\"authors\" value=\"Feynman\" />"
131  << "Feynman"
132  << "<input type=\"checkbox\" name=\"authors\" value=\"Camus\" />Camus"
133  << "<input type=\"checkbox\" name=\"authors\" value=\"Conrad\" />Conrad"
134  << "<input type=\"checkbox\" name=\"authors\" value=\"Vergil\" />Vergil"
135  << "<input type=\"checkbox\" name=\"authors\" value=\"Plato\" />Plato"
136  << "</td></tr>" << endl;
137 
138  cout << "<tr><td class=\"title\">In the output, show</td>"
139  << "<td class=\"form\">"
140  << "<input type=\"checkbox\" name=\"showEnv\" checked=\"checked\" />"
141  << "Data from CgiEnvironment<br />"
142  << "<input type=\"checkbox\" name=\"showFE\" checked=\"checked\" />"
143  << "All FormEntries<br />"
144  << "<input type=\"checkbox\" name=\"showForm\" checked=\"checked\" />"
145  << "Data from Cgicc"
146  << "</td></tr>" << endl;
147 
148  cout << "<tr><td class=\"title\">Exception Handling</td>"
149  << "<td class=\"form\">"
150  << "<input type=\"checkbox\" name=\"throw\" />"
151  << "Throw an exception to test error handling"
152  << "</td></tr>" << endl;
153 
154  cout << "<tr><td class=\"title\">Save and Restore</td>"
155  << "<td class=\"form\">"
156  << "<input type=\"checkbox\" name=\"save\" />"
157  <<" Save submission to a file<br />"
158  << "<input type=\"checkbox\" name=\"restore\" />"
159  << "Restore data from the last saved submission"
160  << "</td></tr>" << endl;
161 
162  cout << "</table>" << endl;
163 
164  cout << "<div class=\"center\"><p>"
165  << "<input type=\"submit\" name=\"submit\" value=\"Submit\" />"
166  << "<input type=\"reset\" value=\"Nevermind\" />"
167  << "</p></div></form>" << endl;
168 }
169 
170 // Main Street, USA
171 int
172 main(int /*argc*/,
173  char ** /*argv*/)
174 {
175  try {
176 #if HAVE_GETTIMEOFDAY
177  timeval start;
178  gettimeofday(&start, NULL);
179 #endif
180 
181  // Create a new Cgicc object containing all the CGI data
182  Cgicc cgi;
183 
184  // If the user wants to throw an exception, go ahead and do it
185  if(cgi.queryCheckbox("throw") && ! cgi.queryCheckbox("restore"))
186  throw std::runtime_error("User-requested Exception thrown in main()");
187 
188  // Output the HTTP headers for an HTML document, and the HTML 4.0 DTD info
189  cout << HTTPHTMLHeader() << HTMLDoctype(HTMLDoctype::eStrict) << endl;
190  cout << html().set("lang", "en").set("dir", "ltr") << endl;
191 
192  // Set up the page's header and title.
193  // I will put in lfs to ease reading of the produced HTML.
194  cout << head() << endl;
195 
196  // Output the style sheet portion of the header
197  cout << style() << comment() << endl;
198  cout << styles;
199  cout << comment() << style() << endl;
200 
201  cout << title() << "GNU cgicc v" << cgi.getVersion() << " Test"
202  << title() << endl;
203 
204  cout << head() << endl;
205 
206  // Start the HTML body
207  cout << body() << endl;
208 
209  cout << h1() << "GNU cgi" << span("cc").set("class","red")
210  << " v"<< cgi.getVersion() << " Test" << h1() << endl;
211 
212  // Get a pointer to the environment
213  const CgiEnvironment& env = cgi.getEnvironment();
214 
215  // Generic thank you message
216  cout << comment() << "This page generated by cgicc for "
217  << env.getRemoteHost() << comment() << endl;
218  cout << h4() << "Thanks for using cgi" << span("cc").set("class", "red")
219  << ", " << env.getRemoteHost()
220  << '(' << env.getRemoteAddr() << ")!" << h4() << endl;
221 
222  // If the user wants to save the submission, do it
223  if(cgi.queryCheckbox("save")) {
224  // Make sure the save file is readable and writable by the CGI process
225  cgi.save("save");
226  cout << p(h2("Data Saved")) << endl;
227 
228  cout << cgicc::div().set("class", "notice") << endl;
229  cout << "Your data has been saved, and may be restored (by anyone) "
230  << "via the same form." << endl << cgicc::div() << p() << endl;
231  }
232 
233  // If the user wants to restore from the last submission, do it
234  if(cgi.queryCheckbox("restore")) {
235  cgi.restore("save");
236  cout << p(h2("Data Restored")) << endl;
237 
238  cout << cgicc::div().set("class", "notice") << endl;
239  cout << "The data displayed has been restored from a file on disk."
240  << endl << cgicc::div() << p() << endl;
241  }
242 
243  // If the user requested a dump of the environment,
244  // create a simple table showing the values of the
245  // environment variables
246  if(cgi.queryCheckbox("showEnv"))
247  dumpEnvironment(env);
248 
249  // If the user requested, print out the raw form data from
250  // the vector of FormEntries. This will contain every
251  // element in the list.
252  // This is one of two ways to get at form data, the other
253  // being the use of Cgicc's getElement() methods.
254  if(cgi.queryCheckbox("showFE"))
255  dumpList(cgi);
256 
257  // If the user requested data via Cgicc's getElement() methods, do it.
258  // This is different than the use of the list of FormEntries
259  // because it requires prior knowledge of the name of form elements.
260  // Usually they will be known, but you never know.
261  if(cgi.queryCheckbox("showForm"))
262  showForm(cgi);
263 
264  // Print out the form to do it again
265  cout << br() << endl;
266  printForm(cgi);
267  cout << hr().set("class", "half") << endl;
268 
269  // Information on cgicc
270  cout << cgicc::div().set("align","center").set("class","smaller") << endl;
271  cout << "GNU cgi" << span("cc").set("class","red") << " v";
272  cout << cgi.getVersion() << br() << endl;
273  cout << "Compiled at " << cgi.getCompileTime();
274  cout << " on " << cgi.getCompileDate() << br() << endl;
275 
276  cout << "Configured for " << cgi.getHost();
277 #if HAVE_UNAME
278  struct utsname info;
279  if(uname(&info) != -1) {
280  cout << ". Running on " << info.sysname;
281  cout << ' ' << info.release << " (";
282  cout << info.nodename << ")." << endl;
283  }
284 #else
285  cout << "." << endl;
286 #endif
287 
288 #if HAVE_GETTIMEOFDAY
289  // Information on this query
290  timeval end;
291  gettimeofday(&end, NULL);
292  long us = ((end.tv_sec - start.tv_sec) * 1000000)
293  + (end.tv_usec - start.tv_usec);
294 
295  cout << br() << "Total time for request = " << us << " us";
296  cout << " (" << static_cast<double>(us/1000000.0) << " s)";
297 #endif
298 
299  // End of document
300  cout << cgicc::div() << endl;
301  cout << body() << html() << endl;
302 
303  // No chance for failure in this example
304  return EXIT_SUCCESS;
305  }
306 
307  // Did any errors occur?
308  catch(const std::exception& e) {
309 
310  // This is a dummy exception handler, as it doesn't really do
311  // anything except print out information.
312 
313  // Reset all the HTML elements that might have been used to
314  // their initial state so we get valid output
315  html::reset(); head::reset(); body::reset();
316  title::reset(); h1::reset(); h4::reset();
317  comment::reset(); td::reset(); tr::reset();
318  table::reset(); cgicc::div::reset(); p::reset();
319  a::reset(); h2::reset(); colgroup::reset();
320 
321  // Output the HTTP headers for an HTML document, and the HTML 4.0 DTD info
322  cout << HTTPHTMLHeader() << HTMLDoctype(HTMLDoctype::eStrict) << endl;
323  cout << html().set("lang","en").set("dir","ltr") << endl;
324 
325  // Set up the page's header and title.
326  // I will put in lfs to ease reading of the produced HTML.
327  cout << head() << endl;
328 
329  // Output the style sheet portion of the header
330  cout << style() << comment() << endl;
331  cout << "body { color: black; background-color: white; }" << endl;
332  cout << "hr.half { width: 60%; align: center; }" << endl;
333  cout << "span.red, STRONG.red { color: red; }" << endl;
334  cout << "div.notice { border: solid thin; padding: 1em; margin: 1em 0; "
335  << "background: #ddd; }" << endl;
336 
337  cout << comment() << style() << endl;
338 
339  cout << title("GNU cgicc exception") << endl;
340  cout << head() << endl;
341 
342  cout << body() << endl;
343 
344  cout << h1() << "GNU cgi" << span("cc", set("class","red"))
345  << " caught an exception" << h1() << endl;
346 
347  cout << cgicc::div().set("align","center").set("class","notice") << endl;
348 
349  cout << h2(e.what()) << endl;
350 
351  // End of document
352  cout << cgicc::div() << endl;
353  cout << hr().set("class","half") << endl;
354  cout << body() << html() << endl;
355 
356  return EXIT_SUCCESS;
357  }
358 }
359 
360 // Print out a table of the CgiEnvironment
361 void
362 dumpEnvironment(const CgiEnvironment& env)
363 {
364  // This is just a brain-dead dump of information.
365  // Almost all of this code is for HTML formatting
366  cout << h2("Environment information from CgiEnvironment") << endl;
367 
368  cout << cgicc::div().set("align","center") << endl;
369 
370  cout << table() << endl;
371 
372  cout << tr() << td("Request Method").set("class","title")
373  << td(env.getRequestMethod()).set("class","data") << tr() << endl;
374  cout << tr() << td("Path Info").set("class","title")
375  << td(env.getPathInfo()).set("class","data") << tr() << endl;
376  cout << tr() << td("Path Translated").set("class","title")
377  << td(env.getPathTranslated()).set("class","data") << tr() << endl;
378  cout << tr() << td("Script Name").set("class","title")
379  << td(env.getScriptName()).set("class","data") << tr() << endl;
380  cout << tr() << td("HTTP Referrer").set("class","title")
381  << td(env.getReferrer()).set("class","data") << tr() << endl;
382  cout << tr() << td("HTTP Cookie").set("class","title")
383  << td(env.getCookies()).set("class","data") << tr() << endl;
384  cout << tr() << td("Query String").set("class","title")
385  << td(env.getQueryString()).set("class","data") << tr() << endl;
386  cout << tr() << td("Content Length").set("class","title")
387  << td().set("class","data") << env.getContentLength()
388  << td() << tr() << endl;
389  cout << tr() << td("Post Data").set("class","title")
390  << td().set("class","data")
391  << pre(env.getPostData()).set("class","data") << td()
392  << tr() << endl;
393  cout << tr() << td("Remote Host").set("class","title")
394  << td(env.getRemoteHost()).set("class","data") << tr() << endl;
395  cout << tr() << td("Remote Address").set("class","title")
396  << td(env.getRemoteAddr()).set("class","data") << tr() << endl;
397  cout << tr() << td("Authorization Type").set("class","title")
398  << td(env.getAuthType()).set("class","data") << tr() << endl;
399  cout << tr() << td("Remote User").set("class","title")
400  << td(env.getRemoteUser()).set("class","data") << tr() << endl;
401  cout << tr() << td("Remote Identification").set("class","title")
402  << td(env.getRemoteIdent()).set("class","data") << tr() << endl;
403  cout << tr() << td("Content Type").set("class","title")
404  << td(env.getContentType()).set("class","data") << tr() << endl;
405  cout << tr() << td("HTTP Accept").set("class","title")
406  << td(env.getAccept()).set("class","data") << tr() << endl;
407  cout << tr() << td("User Agent").set("class","title")
408  << td(env.getUserAgent()).set("class","data") << tr() << endl;
409  cout << tr() << td("Server Software").set("class","title")
410  << td(env.getServerSoftware()).set("class","data") << tr() << endl;
411  cout << tr() << td("Server Name").set("class","title")
412  << td(env.getServerName()).set("class","data") << tr() << endl;
413  cout << tr() << td("Gateway Interface").set("class","title")
414  << td(env.getGatewayInterface()).set("class","data") << tr() << endl;
415  cout << tr() << td("Server Protocol").set("class","title")
416  << td(env.getServerProtocol()).set("class","data") << tr() << endl;
417  cout << tr() << td("Server Port").set("class","title")
418  << td().set("class","data") << env.getServerPort()
419  << td() << tr() << endl;
420  cout << tr() << td("HTTPS").set("class","title")
421  << td().set("class","data") << (env.usingHTTPS() ? "true" : "false")
422  << td() << tr() << endl;
423  cout << tr() << td("Redirect Request").set("class","title")
424  << td(env.getRedirectRequest()).set("class","data") << tr() << endl;
425  cout << tr() << td("Redirect URL").set("class","title")
426  << td(env.getRedirectURL()).set("class","data") << tr() << endl;
427  cout << tr() << td("Redirect Status").set("class","title")
428  << td(env.getRedirectStatus()).set("class","data") << tr() << endl;
429 
430  cout << table() << cgicc::div() << endl;
431 }
432 
433 // Print out the value of every form element
434 void
435 dumpList(const Cgicc& formData)
436 {
437  cout << h2("Form Data via vector") << endl;
438 
439  cout << cgicc::div().set("align","center") << endl;
440 
441  cout << table()<< endl;
442 
443  cout << tr().set("class","title") << td("Element Name")
444  << td("Element Value") << tr() << endl;
445 
446  // Iterate through the vector, and print out each value
447  const_form_iterator iter;
448  for(iter = formData.getElements().begin();
449  iter != formData.getElements().end();
450  ++iter) {
451  cout << tr().set("class","data") << td(iter->getName())
452  << td(iter->getValue()) << tr() << endl;
453  }
454  cout << table() << cgicc::div() << endl;
455 }
456 
457 // Print out information customized for each element
458 void
459 showForm(const Cgicc& formData)
460 {
461 
462  // I am using an if statement to check if each element is found
463  cout << h2("Form Data via Cgicc") << endl;
464 
465  cout << cgicc::div().set("class","notice") << endl;
466 
467  //getElement
468  const_form_iterator name = formData.getElement("name");
469  if(name != (*formData).end() && ! name->isEmpty())
470  cout << "Your name is " << **name << '.' << br() << endl;
471  else
472  cout << "You don't have a name." << br() << endl;
473 
474  // getElement and getDoubleValue
475  const_form_iterator salary = formData.getElement("bucks");
476  if(salary != (*formData).end() && ! salary->isEmpty())
477  cout << "You make " << (*salary).getDoubleValue(80, 120)
478  << " million dollars." << br() << endl;
479  else
480  cout << "You don't have a salary." << br() << endl;
481 
482  // getElement and getIntegerValue
483  const_form_iterator hours = formData.getElement("time");
484  if(hours != (*formData).end() && ! (*hours).isEmpty())
485  cout << "You've wasted " << (*hours).getIntegerValue()
486  << " hours on the web." << br() << endl;
487  else
488  cout << "You haven't wasted any time on the web." << br() << endl;
489 
490  // getElement and getStrippedValue
491  const_form_iterator thoughts = formData.getElement("thoughts");
492  if(thoughts != (*formData).end() && ! (*thoughts).isEmpty()) {
493  std::string temp = (*thoughts).getStrippedValue();
494  cout << "Your thoughts: " << temp << br() << endl;
495  }
496  else
497  cout << "You don't have any thoughts!?" << br() << endl;
498 
499  // queryCheckbox
500  if(formData.queryCheckbox("hungry"))
501  cout << "You are hungry." << br() << endl;
502  else
503  cout << "You are not hungry." << br() << endl;
504 
505  // getElement
506  std::vector<FormEntry> flavors;
507  formData.getElement("flavors", flavors);
508  if(! flavors.empty()) {
509  cout << "You like ";
510  for(std::string::size_type i = 0; i < flavors.size(); i++) {
511  cout << flavors[i].getValue();
512  if(i < flavors.size() - 2)
513  cout << ", ";
514  else if(i == flavors.size() - 2)
515  cout << " and ";
516  }
517  cout << " ice cream." << br() << endl;
518  }
519  else
520  cout << "You don't like ice cream!?" << br() << endl;
521 
522  // getElement
523  const_form_iterator hair = formData.getElement("hair");
524  if(hair != (*formData).end())
525  cout << "Your hair is " << **hair << '.' << br() << endl;
526  else
527  cout << "You don't have any hair." << br() << endl;
528 
529  cout << "You surf the web with " << formData("browser") << '.'
530  << br() << endl;
531 
532  // getElement
533  std::vector<FormEntry> authors;
534  formData.getElement("authors", authors);
535  if(! authors.empty()) {
536  cout << "You like to read books by ";
537  for(std::string::size_type i = 0; i < authors.size(); ++i) {
538  cout << authors[i].getValue();
539  if(i < authors.size() - 2)
540  cout << ", ";
541  else if(i == authors.size() - 2)
542  cout << " and ";
543  }
544  cout << "." << br() << endl;
545  }
546  else
547  cout << "You don't like to read!?" << br() << endl;
548 
549  cout << cgicc::div() << endl;
550 }

GNU cgicc - A C++ class library for writing CGI applications
Copyright © 1996 - 2004 Stephen F. Booth
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front Cover Texts, and with no Back-Cover Texts.
Documentation generated Wed Apr 10 2013 17:18:52 for cgicc by doxygen 1.8.2