#include <stdexcept>
#include "cgi_post.h"

using namespace std;

namespace {

  string make_presentable(const string& str);
  string encode_all(const string& s);

  struct cgi_variables {
    string name;
    string sex;
    string humor;
    string fish;
    string glycol;
    string svga;
    string angst;
    string catcon;
    string vitamin;

    cgi_variables(cgi_post& cgi) {
      name    = encode_all(cgi["name"]);
      sex     = encode_all(cgi["sex"]);
      humor   = cgi["humor"];
      fish    = cgi["fish"];
      glycol  = cgi["glycol"];
      svga    = cgi["svga"];
      angst   = cgi["angst"];
      catcon  = cgi["catcon"];
      vitamin = cgi["vitamin"];
    }

    bool contains_things() {
      if( humor.length() > 0 || fish.length() > 0 || glycol.length() > 0
          || svga.length() > 0 || angst.length() > 0 || catcon.length() > 0
          || vitamin.length() > 0 )
        {
          return true;
        }
      return false;
    }
  };

  string make_presentable(const string& s)
  {
    //
    // For the ISO-8859-1 character set, these are the known
    // metacharacters for basic presentation.  There are other
    // contexts where there are different metacharacters.  See the
    // following URL:
    //
    //     http://www.cert.org/tech_tips/malicious_code_mitigation.html
    //
    string rv;
    string::size_type len = s.length();
    for( unsigned i = 0 ; i < len ; ++i ) {
      switch( s[i] ) {
      case '<':
        rv += "&lt;";
        break;
      case '>':
        rv += "&gt;";
        break;
      case '&':
        rv += "&amp;";
        break;
      default:
        rv += s[i];
        break;
      }
    }
    return rv;
  }

  string encode_all(const string& s)
  {
    //
    // Sometimes the easiest thing to do is to just encoded everything
    // in the untrusted string.
    //
    static char* encode_all_map[] = {
       "&#00;",    "&#01;",    "&#02;",    "&#03;",    "&#04;", 
       "&#05;",    "&#06;",    "&#07;",    "&#08;",    "&#09;", 
       "&#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;",    "&#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;",   "&#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;",   "&#166;",   "&#167;",   "&#168;",   "&#169;", 
      "&#170;",   "&#171;",   "&#172;",   "&#173;",   "&#174;", 
      "&#175;",   "&#176;",   "&#177;",   "&#178;",   "&#179;", 
      "&#180;",   "&#181;",   "&#182;",   "&#183;",   "&#184;", 
      "&#185;",   "&#186;",   "&#187;",   "&#188;",   "&#189;", 
      "&#190;",   "&#191;",   "&#192;",   "&#193;",   "&#194;", 
      "&#195;",   "&#196;",   "&#197;",   "&#198;",   "&#199;", 
      "&#200;",   "&#201;",   "&#202;",   "&#203;",   "&#204;", 
      "&#205;",   "&#206;",   "&#207;",   "&#208;",   "&#209;", 
      "&#210;",   "&#211;",   "&#212;",   "&#213;",   "&#214;", 
      "&#215;",   "&#216;",   "&#217;",   "&#218;",   "&#219;", 
      "&#220;",   "&#221;",   "&#222;",   "&#223;",   "&#224;", 
      "&#225;",   "&#226;",   "&#227;",   "&#228;",   "&#229;", 
      "&#230;",   "&#231;",   "&#232;",   "&#233;",   "&#234;", 
      "&#235;",   "&#236;",   "&#237;",   "&#238;",   "&#239;", 
      "&#240;",   "&#241;",   "&#242;",   "&#243;",   "&#244;", 
      "&#245;",   "&#246;",   "&#247;",   "&#248;",   "&#249;", 
      "&#250;",   "&#251;",   "&#252;",   "&#253;",   "&#254;", 
      "&#255;"
    };
    string rv;
    string::size_type len = s.length();
    for( unsigned i = 0 ; i < len ; ++i ) {
      unsigned s_value = s[i];
      if( s_value < 256 ) {
        rv += encode_all_map[s_value];
      }
    }
    return rv;
  }

}

int main(int argc, char* argv[])
{
  try {
    cgi_post cgi;
    cgi_variables vars(cgi);
    
    // This is where you put your HTML headers.  Notice that a double
    // space separates the headers from the HTML you see.  They've
    // added a meta tag for Content-Type, but it seems you still need
    // this header.
    cout << "Content-Type: text/html" << "\n";
    cout << "\n";

    cout << "<html>" << "\n";
    cout << "  <head>" << "\n";
    cout << "    <meta http-equiv=\"Content-Type\" "
                         "content=\"text/html; charset=ISO-8859-1\">" << "\n";
    cout << "    <title>The Surrealist's Survey:  Thank You</title>" << "\n";
    cout << "  </head>" << "\n";

    cout << "  <body>" << "\n";
    cout << "    <p><h1>Thank You for Participating</h1></p>" << "\n";
    cout << "    <hr>" << "\n";
    cout << "    <p>Your responses were:</p>" << "\n";

    cout << "    <ul>" << "\n";
    if( vars.name.length() == 0 ) {
      cout << "    <li>You don't have a name.</li>" << "\n";
    } else {
      cout << "    <li>Your name is " << vars.name << "</li>" << "\n";
    }

    if( vars.sex.length() == 0 ) {
      cout << "    <li>You don't have a sex.</li>" << "\n";
    } else {
      cout << "    <li>Your sex is " << vars.sex << "</li>" << "\n";
    }

    if( vars.contains_things() ) {
      cout << "    <li>You contain:</li>" << "\n";
      cout << "      <ul>" << "\n";
      if( vars.humor.length() > 0 )
        cout << "      <li>Vitreous Humor</li>" << "\n";
      if( vars.fish.length() > 0 )
        cout << "      <li>Fish</li>" << "\n";
      if( vars.glycol.length() > 0 )
        cout << "      <li>Propylene Glycol</li>" << "\n";
      if( vars.svga.length() > 0 )
        cout << "      <li>SVGA Support</li>" << "\n";
      if( vars.angst.length() > 0 )
        cout << "      <li>Angst</li>" << "\n";
      if( vars.catcon.length() > 0 )
        cout << "      <li>Catalytic Converter</li>" << "\n";
      if( vars.vitamin.length() > 0 )
        cout << "      <li>Ten Essential Vitamins and Minerals</li>" << "\n";
      cout << "      </ul>" << "\n";
    }

    cout << "    </ul>" << "\n";
    cout << "    <hr>" << "\n";

    cout << "    <center>" << "\n";

    // For serice.net:
    cout << "    <img src=\"/apache_pb.gif\">" << "\n";

    // For local:
    //cout << "    <img src=\"/~ugs/apache_pb.gif\">" << "\n";

    cout << "    </center>" << "\n";

    cout << "  </body>" << "\n";
    cout << "</html>" << "\n";

  } catch( exception& e) {
    cerr << e.what() << "\n";
    return 1;
  }
  return 0;
}

