cgitest.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:23k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: cgitest.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:39:31  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: cgitest.cpp,v 1000.2 2004/06/01 18:39:31 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Denis Vakatov, Eugene Vasilchenko, Vsevolod Sandomirsky
  35.  *
  36.  * File Description:
  37.  *   TEST for:  NCBI C++ core CGI API
  38.  *   Note:  this is a CGI part of former "coretest.cpp" test
  39.  *
  40.  */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbiapp.hpp>
  43. #include <corelib/ncbienv.hpp>
  44. #include <corelib/ncbireg.hpp>
  45. #include <cgi/ncbires.hpp>
  46. #include <cgi/ncbicgir.hpp>
  47. #include <algorithm>
  48. #include <time.h>
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <test/test_assert.h>  /* This header must go last */
  52. // This is to use the ANSI C++ standard templates without the "std::" prefix
  53. // and to use NCBI C++ entities without the "ncbi::" prefix
  54. USING_NCBI_SCOPE;
  55. /////////////////////////////////
  56. // CGI
  57. //
  58. static void TestCgi_Cookies(void)
  59. {
  60.     CCgiCookies cookies("coo1=kie1BAD1;coo2=kie2_ValidPath; ");
  61.     cookies.Add("  coo1=kie1BAD2;CooT=KieT_ExpTime  ");
  62.     string str = "eee;  Coo11=Kie11_OK; Coo2=Kie2BAD;  uuu; coo1=Kie1_OK; Coo6=kie6; iii";
  63.     cookies.Add(str);
  64.     cookies.Add("RemoveThisCookie", "BAD");
  65.     cookies.Add(str);
  66.     assert( !cookies.Find("Coo2", "qq.rr.oo", NcbiEmptyString) );
  67.     assert(cookies.Find("Coo2") == cookies.Find("Coo2", "", ""));
  68.     cookies.Find("Coo2")->SetValue("Kie2_OK");
  69.     CCgiCookie c0("Coo5", "Kie5BAD");
  70.     CCgiCookie c1("Coo5", "Kie", "aaa.bbb.ccc", "/");
  71.     CCgiCookie c2(c1);
  72.     c2.SetValue("Kie5_Dom_Sec");
  73.     c2.SetPath("");
  74.     c2.SetSecure(true);
  75.     cookies.Add(c1);
  76.     cookies.Add(c2);
  77.     CCgiCookie* c3 = cookies.Find("coo2", NcbiEmptyString, "");
  78.     c3->SetPath("coo2_ValidPath");
  79.     assert( !cookies.Remove(cookies.Find("NoSuchCookie")) );
  80.     assert( cookies.Remove(cookies.Find("RemoveThisCookie")) );
  81.     assert( !cookies.Remove(cookies.Find("RemoveThisCookie")) );
  82.     assert( !cookies.Find("RemoveThisCookie") );
  83.     assert( cookies.Find("CoO5") );
  84.     assert( cookies.Find("cOo5") == cookies.Find("Coo5", "aaa.bBb.ccC", "") );
  85.     assert( cookies.Find("Coo5")->GetDomain() == "aaa.bbb.ccc" );
  86.     assert( cookies.Find("coo2")->GetDomain().empty() );
  87.     assert( cookies.Find("cOO5")->GetSecure() );
  88.     assert( !cookies.Find("cOo2")->GetSecure() );
  89.     time_t timer = time(0);
  90.     tm *date = gmtime(&timer);
  91.     CCgiCookie *ct = cookies.Find("CooT");
  92.     ct->SetExpDate(*date);
  93.     cookies.Add("AAA", "11", "qq.yy.dd");
  94.     cookies.Add("AAA", "12", "QQ.yy.Dd");
  95.     assert( cookies.Find("AAA", "qq.yy.dd", NcbiEmptyString)->GetValue()
  96.             == "12" );
  97.     cookies.Add("aaa", "1", "QQ.yy.Dd");
  98.     assert( cookies.Find("AAA", "qq.yy.dd", NcbiEmptyString)->GetValue()
  99.             == "1" );
  100.     cookies.Add("aaa", "19");
  101.     cookies.Add("aaa", "21", "QQ.yy.Dd", "path");
  102.     assert( cookies.Find("AAA", "qq.yy.dd", "path")->GetValue() == "21");
  103.     cookies.Add("aaa", "22", "QQ.yy.Dd", "Path");
  104.     assert( cookies.Find("AAA", "qq.yy.dd", "path")->GetValue() == "21" );
  105.     assert( cookies.Find("AAA")->GetValue() == "19" );
  106.     cookies.Add("AAA", "2", "QQ.yy.Dd", "path");
  107.     assert( cookies.Find("AAA", "qq.yy.dd", "path")->GetValue() == "2" );
  108.     cookies.Add("AAA", "3");
  109.     cookies.Add("BBA", "BBA1");
  110.     cookies.Add("BBA", "BBA2", "", "path");
  111.     cookies.Add("BBB", "B1", "oo.pp.yy");
  112.     cookies.Add("BBB", "B2");
  113.     cookies.Add("BBB", "B3", "bb.pp.yy", "path3");
  114.     cookies.Add("BBB", "B3", "cc.pp.yy", "path3");
  115.     CCgiCookies::TRange range;
  116.     assert( cookies.Find("BBA", &range)->GetValue() == "BBA1" );
  117.     assert( cookies.Remove(range) );
  118.     cookies.Add("BBB", "B3", "dd.pp.yy", "path3");
  119.     cookies.Add("BBB", "B3", "aa.pp.yy", "path3");
  120.     cookies.Add("BBB", "B3", "",         "path3");
  121.     cookies.Add("BBC", "BBC1", "", "path");
  122.     cookies.Add("BBC", "BBC2", "44.88.99", "path");
  123.     cookies.Add("BBD", "BBD1",  "", "path");
  124.     cookies.Add("BBD", "BBD20", "44.88.99", "path");
  125.     cookies.Add("BBD", "BBD2",  "44.88.99", "path");
  126.     cookies.Add("BBD", "BBD3",  "77.99.00", "path");
  127.     assert( cookies.Remove( cookies.Find("BBB", "dd.pp.yy", "path3") ) );
  128.     cookies.Add("DDD", "DDD1", "aa.bb.cc", "p1/p2");
  129.     cookies.Add("DDD", "DDD2", "aa.bb.cc");
  130.     cookies.Add("DDD", "DDD3", "aa.bb.cc", "p3/p4");
  131.     cookies.Add("DDD", "DDD4", "aa.bb.cc", "p1");
  132.     cookies.Add("DDD", "DDD5", "aa.bb.cc", "p1/p2/p3");
  133.     cookies.Add("DDD", "DDD6", "aa.bb.cc", "p1/p4");
  134.     assert( cookies.Find("DDD", &range)->GetValue() == "DDD2" );
  135.     assert( cookies.Find("BBD", "44.88.99", "path")->GetValue() == "BBD2" );
  136.     assert( cookies.Remove(cookies.Find("BBD", "77.99.00", "path")) );
  137.     assert( cookies.Remove("BBD") == 2 ); 
  138.     NcbiCerr << "nnCookies:nn" << cookies << NcbiEndl;
  139. }
  140. static void PrintEntries(TCgiEntries& entries)
  141. {
  142.     for (TCgiEntries::iterator iter = entries.begin();
  143.          iter != entries.end();  ++iter) {
  144.         assert( !NStr::StartsWith(iter->first, "amp;", NStr::eNocase) );
  145.         NcbiCout << "  ("" << iter->first << "", ""
  146.                  << iter->second << "")" << NcbiEndl;
  147.     }
  148. }
  149. static bool TestEntries(TCgiEntries& entries, const string& str)
  150. {
  151.     NcbiCout << "n Entries: `" << str << "'n";
  152.     SIZE_TYPE err_pos = CCgiRequest::ParseEntries(str, entries);
  153.     PrintEntries(entries);
  154.     if ( err_pos ) {
  155.         NcbiCout << "-- Error at position #" << err_pos << NcbiEndl;
  156.         return false;
  157.     }
  158.     return true;
  159. }
  160. static void PrintIndexes(TCgiIndexes& indexes)
  161. {
  162.     for (TCgiIndexes::iterator iter = indexes.begin();
  163.          iter != indexes.end();  ++iter) {
  164.         NcbiCout << "  "" << *iter << ""    ";
  165.     }
  166.     NcbiCout << NcbiEndl;
  167. }
  168. static bool TestIndexes(TCgiIndexes& indexes, const string& str)
  169. {
  170.     NcbiCout << "n Indexes: `" << str << "'n";
  171.     SIZE_TYPE err_pos = CCgiRequest::ParseIndexes(str, indexes);
  172.     PrintIndexes(indexes);
  173.     if ( err_pos ) {
  174.         NcbiCout << "-- Error at position #" << err_pos << NcbiEndl;
  175.         return false;
  176.     }
  177.     return true;
  178. }
  179. static void TestCgi_Request_Static(void)
  180. {
  181.     // Test CCgiRequest::ParseEntries()
  182.     TCgiEntries entries;
  183.     assert(  TestEntries(entries, "aa=bb&cc=dd") );
  184.     assert(  TestEntries(entries, "e%20e=f%26f&g%2Ag=h+h%2e") );
  185.     entries.clear();
  186.     assert( !TestEntries(entries, " xx=yy") );
  187.     assert(  TestEntries(entries, "xx=&yy=zz") );
  188.     assert(  TestEntries(entries, "rr=") );
  189.     assert( !TestEntries(entries, "xx&") );
  190.     entries.clear();
  191.     // Give a temporary slack to some buggy clients -- allow leading ampersand
  192.     // assert( !TestEntries(entries, "&zz=qq") );
  193.     assert( TestEntries(entries, "&zz=qq") );
  194.     // assert( !TestEntries(entries, "tt=qq=pp") );
  195.     assert( !TestEntries(entries, "=ggg&ppp=PPP") );
  196.     assert(  TestEntries(entries, "a=d&eee") );
  197.     assert(  TestEntries(entries, "xxx&eee") );
  198.     assert(  TestEntries(entries, "xxx+eee") );
  199.     assert(  TestEntries(entries, "UUU") );
  200.     assert( !TestEntries(entries, "a=d&&eee") );
  201.     assert(  TestEntries(entries, "a%21%2f%25aa=%2Fd%2c&eee=%3f") );
  202.     // some older browsers fail to parse &amp; in HREFs; ensure that
  203.     // we handle it properly.
  204.     assert(  TestEntries(entries, "a=b&amp;c=d&amp;e=f") );
  205.     // Test CCgiRequest::ParseIndexes()
  206.     TCgiIndexes indexes;
  207.     assert(  TestIndexes(indexes, "a+bb+ccc+d") );
  208.     assert(  TestIndexes(indexes, "e%20e+f%26f+g%2Ag+hh%2e") );
  209.     indexes.clear();
  210.     assert( !TestIndexes(indexes, " jhg") );
  211.     assert( !TestIndexes(indexes, "e%h%2e+3") );
  212.     assert(  TestIndexes(indexes, "aa+%20+bb") );
  213.     assert( !TestIndexes(indexes, "aa++bb") );
  214.     indexes.clear();
  215.     assert( !TestIndexes(indexes, "+1") );
  216.     assert( !TestIndexes(indexes, "aa+") );
  217.     assert( !TestIndexes(indexes, "aa+bb  ") );
  218.     assert( !TestIndexes(indexes, "c++b") );
  219.     assert( !TestIndexes(indexes, "ff++ ") );
  220.     assert( !TestIndexes(indexes, "++") );
  221. }
  222. static void TestCgi_Request_Full(CNcbiIstream*         istr,
  223.                                  const CNcbiArguments* args = 0,
  224.                                  CCgiRequest::TFlags   flags = 0)
  225. {
  226.     CCgiRequest CCR(args, 0, istr, flags);
  227.     NcbiCout << "nnCCgiRequest::n";
  228.     try {
  229.         NcbiCout << "GetContentLength(): "
  230.                  << CCR.GetContentLength() << NcbiEndl;
  231.     }
  232.     STD_CATCH ("TestCgi_Request_Full");
  233.     NcbiCout << "GetRandomProperty("USER_AGENT"): "
  234.              << CCR.GetRandomProperty("USER_AGENT") << NcbiEndl;
  235.     NcbiCout << "GetRandomProperty("MY_RANDOM_PROP"): "
  236.              << CCR.GetRandomProperty("MY_RANDOM_PROP") << NcbiEndl;
  237.     NcbiCout << "GetRandomProperty("HTTP_MY_RANDOM_PROP"): "
  238.              << CCR.GetRandomProperty("HTTP_MY_RANDOM_PROP")
  239.              << NcbiEndl;
  240.     NcbiCout << "GetRandomProperty("HTTP_MY_RANDOM_PROP", false): "
  241.              << CCR.GetRandomProperty("HTTP_MY_RANDOM_PROP", false)
  242.              << NcbiEndl;
  243.     NcbiCout << "nCCgiRequest::  All properties:n";
  244.     for (size_t prop = 0;  prop < (size_t)eCgi_NProperties;  prop++) {
  245.         NcbiCout << NcbiSetw(24)
  246.                  << CCgiRequest::GetPropertyName((ECgiProp)prop) << " = ""
  247.                  << CCR.GetProperty((ECgiProp)prop) << ""n";
  248.     }
  249.     CCgiCookies cookies;
  250.     {{  // Just an example of copying the cookies from a request data
  251.         // Of course, we could use the original request's cookie set
  252.         // ("x_cookies") if we performed only "const" operations on it
  253.         const CCgiCookies& x_cookies = CCR.GetCookies();
  254.         cookies.Add(x_cookies);
  255.     }}
  256.     NcbiCout << "nCCgiRequest::  All cookies:n";
  257.     if ( cookies.Empty() )
  258.         NcbiCout << "No cookies specified" << NcbiEndl;
  259.     else
  260.         NcbiCout << cookies << NcbiEndl;
  261.     TCgiEntries entries = CCR.GetEntries();
  262.     NcbiCout << "nCCgiRequest::  All entries:n";
  263.     if ( entries.empty() ) {
  264.         NcbiCout << "No entries specified" << NcbiEndl;
  265.     } else {
  266.         PrintEntries(entries);
  267.         if ( !CCR.GetEntry("get_query1").empty() ) {
  268.             NcbiCout << "GetEntry() check." << NcbiEndl;
  269.             assert(CCR.GetEntry("get_query1") == "gq1");
  270.             bool is_found = false;
  271.             assert(CCR.GetEntry("get_query1", &is_found) == "gq1");
  272.             assert(is_found);
  273.             assert(CCR.GetEntry("get_query2", 0).empty());
  274.             is_found = false;
  275.             assert(CCR.GetEntry("get_query2", &is_found).empty());
  276.             assert(is_found);
  277.             assert(CCR.GetEntry("qwe1rtyuioop", &is_found).empty());
  278.             assert(!is_found);
  279.         }
  280.     }
  281.     TCgiIndexes indexes = CCR.GetIndexes();
  282.     NcbiCout << "nCCgiRequest::  ISINDEX values:n";
  283.     if ( indexes.empty() ) {
  284.         NcbiCout << "No ISINDEX values specified" << NcbiEndl;
  285.     } else {
  286.         PrintIndexes(indexes);
  287.     }
  288.     CNcbiIstream* is = CCR.GetInputStream();
  289.     if ( is ) {
  290.         NcbiCout << "nUn-parsed content body:n";
  291.         NcbiCout << is->rdbuf() << NcbiEndl << NcbiEndl;
  292.     }
  293. }
  294. static void TestCgiMisc(void)
  295. {
  296.     const string str("_ _%_;_n_:_'_*_\_"_");
  297.     {{
  298.         string url = "qwerty";
  299.         url = URL_EncodeString(str);
  300.         NcbiCout << str << NcbiEndl << url << NcbiEndl;
  301.         assert( url.compare("_+_%25_%3B_%0A_%3A_'_*_%5C_%22_") == 0 );
  302.         string str1 = URL_DecodeString(url);
  303.         assert( str1 == str );
  304.         string url1 = URL_EncodeString(str1);
  305.         assert( url1 == url );
  306.     }}
  307.     {{
  308.         string url = "qwerty";
  309.         url = URL_EncodeString(str, eUrlEncode_ProcessMarkChars);
  310.         NcbiCout << str << NcbiEndl << url << NcbiEndl;
  311.         assert( url.compare("%5F+%5F%25%5F%3B%5F%0A%5F%3A%5F%27%5F%2A%5F%5C%5F%22%5F") == 0 );
  312.         string str1 = URL_DecodeString(url);
  313.         assert( str1 == str );
  314.         string url1 = URL_EncodeString(str1, eUrlEncode_ProcessMarkChars);
  315.         assert( url1 == url );
  316.     }}
  317.     const string bad_url("%ax");
  318.     try {
  319.         URL_DecodeString(bad_url);
  320.     } STD_CATCH("%ax");
  321. }
  322. static void TestCgi(const CNcbiArguments& args)
  323. {
  324.     // this is to get rid of warnings on some strict compilers (like SUN Forte)
  325. #define X_PUTENV(s)  ::putenv((char*) s)
  326.     TestCgi_Cookies();
  327.     TestCgi_Request_Static();
  328.     assert( !X_PUTENV("CONTENT_TYPE=application/x-www-form-urlencoded") );
  329.     try { // POST only
  330.         char inp_str[] = "post11=val11&post12void=&post13=val13";
  331.         CNcbiIstrstream istr(inp_str);
  332.         char len[32];
  333.         assert(::sprintf(len, "CONTENT_LENGTH=%ld", (long) ::strlen(inp_str)));
  334.         assert( !::putenv(len) );
  335.         assert( !X_PUTENV("SERVER_PORT=") );
  336.         assert( !X_PUTENV("REMOTE_ADDRESS=") );
  337.         assert( !X_PUTENV("REQUEST_METHOD=POST") );
  338.         assert( !X_PUTENV("QUERY_STRING=") );
  339.         assert( !X_PUTENV("HTTP_COOKIE=") );
  340.         TestCgi_Request_Full(&istr);
  341.     } STD_CATCH("TestCgi(POST only)");
  342.     try { // POST, fDoNotParseContent
  343.         char inp_str[] = "post11=val11&post12void=&post13=val13";
  344.         CNcbiIstrstream istr(inp_str);
  345.         char len[32];
  346.         assert(::sprintf(len, "CONTENT_LENGTH=%ld", (long) ::strlen(inp_str)));
  347.         assert( !::putenv(len) );
  348.         assert( !X_PUTENV("SERVER_PORT=") );
  349.         assert( !X_PUTENV("REMOTE_ADDRESS=") );
  350.         assert( !X_PUTENV("REQUEST_METHOD=POST") );
  351.         assert( !X_PUTENV("QUERY_STRING=") );
  352.         assert( !X_PUTENV("HTTP_COOKIE=") );
  353.         TestCgi_Request_Full(&istr, 0, CCgiRequest::fDoNotParseContent);
  354.     } STD_CATCH("TestCgi(POST only)");
  355.     try { // POST + aux. functions
  356.         char inp_str[] = "post22void=&post23void=";
  357.         CNcbiIstrstream istr(inp_str);
  358.         char len[32];
  359.         assert(::sprintf(len, "CONTENT_LENGTH=%ld", (long) ::strlen(inp_str)));
  360.         assert( !::putenv(len) );
  361.         assert( !X_PUTENV("SERVER_PORT=9999") );
  362.         assert( !X_PUTENV("HTTP_USER_AGENT=MyUserAgent") );
  363.         assert( !X_PUTENV("HTTP_MY_RANDOM_PROP=MyRandomPropValue") );
  364.         assert( !X_PUTENV("REMOTE_ADDRESS=130.14.25.129") );
  365.         TestCgi_Request_Full(&istr);
  366.     } STD_CATCH("TestCgi(POST + aux. functions)");
  367.     // this is for all following tests...
  368.     char inp_str[] = "postXXX=valXXX";
  369.     char len[32];
  370.     assert( ::sprintf(len, "CONTENT_LENGTH=%ld", (long) ::strlen(inp_str)) );
  371.     assert( !::putenv(len) );
  372.     try { // POST + ISINDEX(action)
  373.         CNcbiIstrstream istr(inp_str);
  374.         assert( !X_PUTENV("QUERY_STRING=isidx1+isidx2+isidx3") );
  375.         TestCgi_Request_Full(&istr);
  376.     } STD_CATCH("TestCgi(POST + ISINDEX(action))");
  377.     try { // POST + QUERY(action)
  378.         CNcbiIstrstream istr(inp_str);
  379.         assert( !X_PUTENV("QUERY_STRING=query1=vv1&query2=") );
  380.         TestCgi_Request_Full(&istr);
  381.     } STD_CATCH("TestCgi(POST + QUERY(action))");
  382.     try { // GET ISINDEX + COOKIES
  383.         CNcbiIstrstream istr(inp_str);
  384.         assert( !X_PUTENV("QUERY_STRING=get_isidx1+get_isidx2+get_isidx3") );
  385.         assert( !X_PUTENV("HTTP_COOKIE=cook1=val1; cook2=val2;") );
  386.         TestCgi_Request_Full(&istr, 0, CCgiRequest::fIndexesNotEntries);
  387.     } STD_CATCH("TestCgi(GET ISINDEX + COOKIES)");
  388.     try { // GET REGULAR, NO '='
  389.         CNcbiIstrstream istr(inp_str);
  390.         assert( !X_PUTENV("QUERY_STRING=get_query1_empty&get_query2_empty") );
  391.         TestCgi_Request_Full(&istr);
  392.     } STD_CATCH("TestCgi(GET REGULAR, NO '=' )");
  393.     try { // GET REGULAR + COOKIES
  394.         CNcbiIstrstream istr(inp_str);
  395.         assert( !X_PUTENV("QUERY_STRING=get_query1=gq1&get_query2=") );
  396.         assert( !X_PUTENV("HTTP_COOKIE=_cook1=_val1;_cook2=_val2") );
  397.         TestCgi_Request_Full(&istr);
  398.     } STD_CATCH("TestCgi(GET REGULAR + COOKIES)");
  399.     try { // ERRONEOUS STDIN
  400.         CNcbiIstrstream istr("123");
  401.         assert( !X_PUTENV("QUERY_STRING=get_query1=gq1&get_query2=") );
  402.         assert( !X_PUTENV("HTTP_COOKIE=_cook1=_val1;_cook2=_val2") );
  403.         TestCgi_Request_Full(&istr);
  404.     } STD_CATCH("TestCgi(ERRONEOUS STDIN)");
  405.     try { // USER INPUT(real STDIN)
  406.         assert( !X_PUTENV("QUERY_STRING=u_query1=uq1") );
  407.         assert( !X_PUTENV("HTTP_COOKIE=u_cook1=u_val1; u_cook2=u_val2") );
  408.         assert( !X_PUTENV("REQUEST_METHOD=POST") );
  409.         NcbiCout << "Enter the length of CGI posted data now: " << NcbiFlush;
  410.         long l = 0;
  411.         if (!(NcbiCin >> l)  ||  len < 0) {
  412.             NcbiCin.clear();
  413.             runtime_error("Invalid length of CGI posted data");
  414.         }
  415.         char cs[32];
  416.         assert( ::sprintf(cs, "CONTENT_LENGTH=%ld", (long) l) );
  417.         assert( !X_PUTENV(cs) );
  418.         NcbiCout << "Enter the CGI posted data now(no spaces): " << NcbiFlush;
  419.         NcbiCin >> NcbiWs;
  420.         TestCgi_Request_Full(0);
  421.         NcbiCin.clear();
  422.     } STD_CATCH("TestCgi(USER STDIN)");
  423.     try { // CMD.-LINE ARGS
  424.         assert( !X_PUTENV("REQUEST_METHOD=") );
  425.         assert( !X_PUTENV("QUERY_STRING=MUST NOT BE USED HERE!!!") );
  426.         TestCgi_Request_Full(&NcbiCin/* dummy */, &args);
  427.     } STD_CATCH("TestCgi(CMD.-LINE ARGS)");
  428.     TestCgiMisc();
  429. #undef X_PUTENV
  430. }
  431. static void TestCgiResponse(const CNcbiArguments& args)
  432. {
  433.     NcbiCout << "Starting CCgiResponse test" << NcbiEndl;
  434.     CCgiResponse response;
  435.     
  436.     response.SetOutput(&NcbiCout);
  437.     if (args.Size() > 2) {
  438.         CCgiCookies cookies(args[2]);
  439.         response.Cookies().Add(cookies);
  440.     }
  441.     response.Cookies().Remove(response.Cookies().Find("to-Remove"));
  442.     NcbiCout << "Cookies: " << response.Cookies() << NcbiEndl;
  443.     NcbiCout << "Generated simple HTTP response:" << NcbiEndl;
  444.     response.WriteHeader() << "Data1" << NcbiEndl << NcbiFlush;
  445.     response.out() << "Data2" << NcbiEndl << NcbiFlush;
  446.     NcbiCout << "End of simple HTTP response" << NcbiEndl << NcbiEndl;
  447.     response.SetHeaderValue("Some-Header-Name", "Some Header Value");
  448.     response.SetHeaderValue("status", "399 Something is BAAAAD!!!!!");
  449.     response.SetStatus(301, "Moved");
  450.     NcbiCout << "Generated HTTP response:" << NcbiEndl;
  451.     response.WriteHeader() << "Data1" << NcbiEndl << NcbiFlush;
  452.     response.out() << "Data2" << NcbiEndl << NcbiFlush;
  453.     NcbiCout << "End of HTTP response" << NcbiEndl << NcbiEndl;
  454.     response.SetRawCgi(true);
  455.     NcbiCout << "Generated HTTP "raw CGI" response:" << NcbiEndl;
  456.     response.WriteHeader() << "Data1" << NcbiEndl << NcbiFlush;
  457.     response.out() << "Data2" << NcbiEndl << NcbiFlush;
  458.     NcbiCout << "End of HTTP "raw CGI" response" << NcbiEndl << NcbiEndl;
  459. }
  460. /////////////////////////////////
  461. // Test CGI application
  462. //
  463. class CTestApplication : public CNcbiApplication
  464. {
  465. public:
  466.     virtual ~CTestApplication(void);
  467.     virtual int Run(void);
  468. };
  469. int CTestApplication::Run(void)
  470. {
  471.     TestCgi( GetArguments() );
  472.     TestCgiResponse( GetArguments() );
  473.     return 0;
  474. }
  475. CTestApplication::~CTestApplication()
  476. {
  477.     SetDiagStream(0);
  478. }
  479. /////////////////////////////////
  480. // APPLICATION OBJECT
  481. //   and
  482. // MAIN
  483. //
  484. // Note that if the application's object ("theTestApplication") was defined
  485. // inside the scope of function "main()", then its destructor could be
  486. // called *before* destructors of other statically allocated objects
  487. // defined in other modules.
  488. // It would cause a premature closure of diag. stream, and disallow the
  489. // destructors of other projects to refer to this application object:
  490. //  - the singleton method CNcbiApplication::Instance() would return NULL, and
  491. //  - if there is a "raw"(direct) pointer to "theTestApplication" then it
  492. //    might cause a real trouble.
  493. static CTestApplication theTestApplication;
  494. int main(int argc, const char* argv[])
  495. {
  496.     // Execute main application function
  497.     return theTestApplication.AppMain(argc, argv);
  498. }
  499. /*
  500.  * ==========================================================================
  501.  * $Log: cgitest.cpp,v $
  502.  * Revision 1000.2  2004/06/01 18:39:31  gouriano
  503.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  504.  *
  505.  * Revision 1.20  2004/05/17 20:57:14  gorelenk
  506.  * Added include of PCH ncbi_pch.hpp
  507.  *
  508.  * Revision 1.19  2004/04/26 16:39:34  ucko
  509.  * Don't try to pass temporary CCgiCookies objects, even by const
  510.  * reference, as CCgiCookies has no public copy constructor.
  511.  *
  512.  * Revision 1.18  2003/11/24 18:15:21  ucko
  513.  * Verify &amp; -> & conversion.
  514.  *
  515.  * Revision 1.17  2003/08/20 22:48:38  ucko
  516.  * Allow equal signs in values.
  517.  *
  518.  * Revision 1.16  2003/07/08 19:07:28  ivanov
  519.  * Added into TestCgi() test for URL_Encode() mark characters encoding
  520.  *
  521.  * Revision 1.15  2002/12/30 21:13:29  vakatov
  522.  * Cosmetics and compiler warning elimination
  523.  *
  524.  * Revision 1.14  2002/07/10 18:41:53  ucko
  525.  * Drop unnecessary uses of c_str().
  526.  * Adapt slightly for CCgiEntry.
  527.  *
  528.  * Revision 1.13  2002/04/16 18:47:10  ivanov
  529.  * Centralize threatment of assert() in tests.
  530.  * Added #include <test/test_assert.h>. CVS log moved to end of file.
  531.  *
  532.  * Revision 1.12  2002/03 /19 00:36:20  vakatov
  533.  * TestCgiResponse() -- three tests (and more extended ones) in the place
  534.  * of one
  535.  *
  536.  * Revision 1.11  2001/12/06 00:31:51  vakatov
  537.  * CCgiRequest::ParseEntries() -- allow leading '&' in the query string (temp.)
  538.  *
  539.  * Revision 1.10  2001/06/19 20:08:31  vakatov
  540.  * CCgiRequest::{Set,Get}InputStream()  -- to provide safe access to the
  541.  * requests' content body
  542.  *
  543.  * Revision 1.9  2001/01/30 23:17:33  vakatov
  544.  * + CCgiRequest::GetEntry()
  545.  *
  546.  * Revision 1.8  2000/06/26 16:35:25  vakatov
  547.  * Test for CCgiCookies::Add(const string&), which is now maimed to
  548.  * workaround MS IE bug
  549.  * (it sent empty cookies w/o "=" in versions prior to 5.5)
  550.  *
  551.  * Revision 1.7  2000/02/01 22:19:58  vakatov
  552.  * CCgiRequest::GetRandomProperty() -- allow to retrieve value of
  553.  * properties whose names are not prefixed by "HTTP_" (optional).
  554.  * Get rid of the aux.methods GetServerPort() and GetRemoteAddr() which
  555.  * are obviously not widely used (but add to the volume of API).
  556.  *
  557.  * Revision 1.6  2000/01/20 17:55:46  vakatov
  558.  * Fixes to follow the "CNcbiApplication" change.
  559.  *
  560.  * Revision 1.5  1999/12/30 22:06:14  vakatov
  561.  * TestCgi() -- use $CONTENT_TYPE
  562.  *
  563.  * Revision 1.4  1999/11/22 19:57:09  vakatov
  564.  * TestCgiResponse() -- made "static"
  565.  *
  566.  * Revision 1.3  1999/11/12 17:50:05  vakatov
  567.  * To be more careful with _DEBUG to suit some ugly MSVC++ features
  568.  *
  569.  * Revision 1.2  1999/11/02 20:35:44  vakatov
  570.  * Redesigned of CCgiCookie and CCgiCookies to make them closer to the
  571.  * cookie standard, smarter, and easier in use
  572.  *
  573.  * Revision 1.1  1999/05/11 03:11:57  vakatov
  574.  * Moved the CGI API(along with the relevant tests) from "corelib/" to "cgi/"
  575.  *
  576.  * ==========================================================================
  577.  */