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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbicgir.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 18:39:22  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.21
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbicgir.cpp,v 1000.1 2004/06/01 18:39:22 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. * Authors:  Eugene Vasilchenko, Denis Vakatov
  35. *
  36. * File Description:
  37. *   CCgiResponse  -- CGI response generator class
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <cgi/ncbicgir.hpp>
  42. #include <cgi/cgi_exception.hpp>
  43. #include <time.h>
  44. // Mac OS has unistd.h, but STDOUT_FILENO is not defined
  45. #ifdef NCBI_OS_MAC 
  46. #  define STDOUT_FILENO 1
  47. #endif
  48. #ifdef HAVE_UNISTD_H
  49. #  include <unistd.h>
  50. #else
  51. #  define STDOUT_FILENO 1
  52. #endif
  53. BEGIN_NCBI_SCOPE
  54. const string CCgiResponse::sm_ContentTypeName    = "Content-Type";
  55. const string CCgiResponse::sm_ContentTypeDefault = "text/html";
  56. const string CCgiResponse::sm_HTTPStatusName     = "Status";
  57. const string CCgiResponse::sm_HTTPStatusDefault  = "200 OK";
  58. inline bool s_ZeroTime(const tm& date)
  59. {
  60.     static const tm kZeroTime = { 0 };
  61.     return ::memcmp(&date, &kZeroTime, sizeof(tm)) == 0;
  62. }
  63. CCgiResponse::CCgiResponse(CNcbiOstream* os, int ofd)
  64.     : m_IsRawCgi(false),
  65.       m_Output(os ? os : &NcbiCout),
  66.       m_OutputFD(os ? ofd : STDOUT_FILENO) // "os" is NOT a typo
  67. {
  68.     return;
  69. }
  70. CCgiResponse::~CCgiResponse(void)
  71. {
  72.     return;
  73. }
  74. bool CCgiResponse::HaveHeaderValue(const string& name) const
  75. {
  76.     return m_HeaderValues.find(name) != m_HeaderValues.end();
  77. }
  78. string CCgiResponse::GetHeaderValue(const string &name) const
  79. {
  80.     TMap::const_iterator ptr = m_HeaderValues.find(name);
  81.     return (ptr == m_HeaderValues.end()) ? kEmptyStr : ptr->second;
  82. }
  83. void CCgiResponse::RemoveHeaderValue(const string& name)
  84. {
  85.     m_HeaderValues.erase(name);
  86. }
  87. void CCgiResponse::SetHeaderValue(const string& name, const string& value)
  88. {
  89.     if ( value.empty() ) {
  90.         RemoveHeaderValue(name);
  91.     } else {
  92.         m_HeaderValues[name] = value;
  93.     }
  94. }
  95. void CCgiResponse::SetHeaderValue(const string& name, const tm& date)
  96. {
  97.     if ( s_ZeroTime(date) ) {
  98.         RemoveHeaderValue(name);
  99.         return;
  100.     }
  101.     char buff[30];
  102.     if ( !::strftime(buff, sizeof(buff),
  103.                      "%a, %d %b %Y %H:%M:%S GMT", &date) ) {
  104.         NCBI_THROW(CCgiErrnoException, eErrno,
  105.                    "CCgiResponse::SetHeaderValue() -- strftime() failed");
  106.     }
  107.     SetHeaderValue(name, buff);
  108. }
  109. void CCgiResponse::SetStatus(unsigned int code, const string& reason)
  110. {
  111.     if (code < 100) {
  112.         THROW1_TRACE(runtime_error,
  113.                      "CCgiResponse::SetStatus() -- code too small, below 100");
  114.     }
  115.     if (code > 999) {
  116.         THROW1_TRACE(runtime_error,
  117.                      "CCgiResponse::SetStatus() -- code too big, exceeds 999");
  118.     }
  119.     if (reason.find_first_of("rn") != string::npos) {
  120.         THROW1_TRACE(runtime_error,
  121.                      "CCgiResponse::SetStatus() -- text contains CR or LF");
  122.     }
  123.     SetHeaderValue(sm_HTTPStatusName, NStr::UIntToString(code) + ' ' + reason);
  124. }
  125. CNcbiOstream& CCgiResponse::out(void) const
  126. {
  127.     if ( !m_Output ) {
  128.         THROW1_TRACE(runtime_error, "CCgiResponse::out() on NULL out.stream");
  129.     }
  130.     return *m_Output;
  131. }
  132. CNcbiOstream& CCgiResponse::WriteHeader(CNcbiOstream& os) const
  133. {
  134.     // HTTP status line (if "raw CGI" response)
  135.     bool skip_status = false;
  136.     if ( IsRawCgi() ) {
  137.         string status = GetHeaderValue(sm_HTTPStatusName);
  138.         if ( status.empty() ) {
  139.             status = sm_HTTPStatusDefault;
  140.         } else {
  141.             skip_status = true;  // filter out the status from the HTTP header
  142.         }
  143.         os << "HTTP/1.1 " << status << HTTP_EOL;
  144.     }
  145.     // Default content type (if it's not specified by user already)
  146.     if ( !HaveHeaderValue(sm_ContentTypeName) ) {
  147.         os << sm_ContentTypeName << ": " << sm_ContentTypeDefault << HTTP_EOL;
  148.     }
  149.     // Cookies (if any)
  150.     if ( !Cookies().Empty() ) {
  151.         os << m_Cookies;
  152.     }
  153.     // All header lines (in alphabetical order)
  154.     ITERATE (TMap, i, m_HeaderValues) {
  155.         if (skip_status  &&
  156.             NStr::CompareNocase(i->first, sm_HTTPStatusName) == 0)
  157.             break;
  158.         os << i->first << ": " << i->second << HTTP_EOL;
  159.     }
  160.     // End of header (empty line)
  161.     return os << HTTP_EOL;
  162. }
  163. void CCgiResponse::Flush(void) const
  164. {
  165.     out() << NcbiFlush;
  166. }
  167. END_NCBI_SCOPE
  168. /*
  169. * ===========================================================================
  170. * $Log: ncbicgir.cpp,v $
  171. * Revision 1000.1  2004/06/01 18:39:22  gouriano
  172. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.21
  173. *
  174. * Revision 1.21  2004/05/17 20:56:50  gorelenk
  175. * Added include of PCH ncbi_pch.hpp
  176. *
  177. * Revision 1.20  2003/07/14 20:26:39  vakatov
  178. * CCgiResponse::SetHeaderValue() -- date format to conform with RFC1123
  179. *
  180. * Revision 1.19  2003/03/12 16:10:23  kuznets
  181. * iterate -> ITERATE
  182. *
  183. * Revision 1.18  2003/02/24 20:01:55  gouriano
  184. * use template-based exceptions instead of errno and parse exceptions
  185. *
  186. * Revision 1.17  2002/07/18 20:18:36  lebedev
  187. * NCBI_OS_MAC: STDOUT_FILENO define added
  188. *
  189. * Revision 1.16  2002/07/11 14:22:59  gouriano
  190. * exceptions replaced by CNcbiException-type ones
  191. *
  192. * Revision 1.15  2002/04/15 01:18:42  lavr
  193. * Check if status is less than 100
  194. *
  195. * Revision 1.14  2002/03/19 00:34:56  vakatov
  196. * Added convenience method CCgiResponse::SetStatus().
  197. * Treat the status right in WriteHeader() for both plain and "raw CGI" cases.
  198. * Made all header values to be case-insensitive.
  199. *
  200. * Revision 1.13  2001/10/04 18:17:53  ucko
  201. * Accept additional query parameters for more flexible diagnostics.
  202. * Support checking the readiness of CGI input and output streams.
  203. *
  204. * Revision 1.12  2001/07/17 22:39:54  vakatov
  205. * CCgiResponse:: Made GetOutput() fully consistent with out().
  206. * Prohibit copy constructor and assignment operator.
  207. * Retired "ncbicgir.inl", moved inline functions to the header itself, made
  208. * some non-inline. Improved comments, got rid of some unused STL headers.
  209. * Well-groomed the code.
  210. *
  211. * Revision 1.11  2000/11/01 20:36:31  vasilche
  212. * Added HTTP_EOL string macro.
  213. *
  214. * Revision 1.10  1999/11/02 20:35:43  vakatov
  215. * Redesigned of CCgiCookie and CCgiCookies to make them closer to the
  216. * cookie standard, smarter, and easier in use
  217. *
  218. * Revision 1.9  1999/05/11 03:11:52  vakatov
  219. * Moved the CGI API(along with the relevant tests) from "corelib/" to "cgi/"
  220. *
  221. * Revision 1.8  1999/04/28 16:54:43  vasilche
  222. * Implemented stream input processing for FastCGI applications.
  223. * Fixed POST request parsing
  224. *
  225. * Revision 1.7  1999/02/22 22:45:39  vasilche
  226. * Fixed map::insert(value_type) usage.
  227. *
  228. * Revision 1.6  1998/12/28 17:56:36  vakatov
  229. * New CVS and development tree structure for the NCBI C++ projects
  230. *
  231. * Revision 1.5  1998/12/23 13:57:55  vasilche
  232. * Default output stream will be NcbiCout.
  233. *
  234. * Revision 1.4  1998/12/11 22:00:34  vasilche
  235. * Added raw CGI response
  236. *
  237. * Revision 1.3  1998/12/11 18:00:54  vasilche
  238. * Added cookies and output stream
  239. *
  240. * Revision 1.2  1998/12/10 19:58:22  vasilche
  241. * Header option made more generic
  242. *
  243. * Revision 1.1  1998/12/09 20:18:18  vasilche
  244. * Initial implementation of CGI response generator
  245. *
  246. * ===========================================================================
  247. */