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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: redirect.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:15:48  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.6
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: redirect.cpp,v 1000.1 2004/06/01 19:15:48 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: Vladimir Ivanov
  35.  *
  36.  * File Description:
  37.  *    Class CCgiRedirectApplication - framework to redirec CGI requests.
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <misc/cgi_redirect/redirect.hpp>
  41. #include <cgi/cgictx.hpp>
  42. BEGIN_NCBI_SCOPE
  43. //////////////////////////////////////////////////////////////////////////////
  44. //
  45. // CCgiRedirectApplication
  46. //
  47. // Default page template
  48. const char* const kDefaultRedirectTemplate = "
  49. <html><head><title><@_TITLE_@></title></head>n 
  50. <body>n 
  51.     <center>n 
  52.     <h1><@_HEADER_@></h1>n 
  53.     <h3><@_MESSAGE_@></h3>n 
  54.     <p>This web page has moved. Please, update your bookmarks and links.</p>n 
  55.     <p><a href="<@_URL_@>">Go to the new page</a></p>.n 
  56.     </center> 
  57. </body> 
  58. </html>";
  59. void CCgiRedirectApplication::Init(void)
  60. {
  61.     CParent::Init();
  62.     const CNcbiRegistry& reg = GetConfig();
  63.     // Set page title and messages
  64.     m_Page.AddTagMap("_TITLE_",  new CHTMLText(reg.Get("Main","PageTitle")));
  65.     m_Page.AddTagMap("_HEADER_", new CHTMLText(reg.Get("Main","Header")));
  66.     m_Page.AddTagMap("_MESSAGE_",new CHTMLText(reg.Get("Main","Message")));
  67.     
  68.     // Wait time before redirect (if used by template)
  69.     m_Page.AddTagMap("_TIMER_",  new CHTMLText(reg.Get("Main", "Timer")));
  70.     // Set page template.
  71.     string template_name = reg.Get("Main", "Template");
  72.     if ( !template_name.empty() ) {
  73.         m_Page.SetTemplateFile(template_name);
  74.     } else {
  75.         m_Page.SetTemplateBuffer(kDefaultRedirectTemplate,
  76.                                  strlen(kDefaultRedirectTemplate));
  77.     }
  78. }
  79. bool s_FindEntryName(const string& name, list<string>& lst)
  80. {
  81.     ITERATE(list<string>, i, lst) {
  82.         if (*i == name)
  83.             return true;
  84.     }
  85.     return false;
  86. }
  87. void s_AssignEntryValue(const string& name,
  88.                         const string& value,
  89.                         TCgiEntries&  old_entries,
  90.                         TCgiEntries&  new_entries)
  91. {
  92.     SIZE_TYPE pos = 0;
  93.     string s(value);
  94.     while ( (pos = s.find("&{", pos)) != NPOS ) {
  95.         SIZE_TYPE pos_end = s.find("}", pos + 2);
  96.         if ( pos_end == NPOS ) {
  97.             break;
  98.         }
  99.         string name = value.substr(pos + 2, pos_end - pos - 2);
  100.         TCgiEntriesCI ci = old_entries.find(name);
  101.         if (ci != old_entries.end()) {
  102.             s.replace(pos, pos_end - pos + 1, URL_EncodeString((ci->second).GetValue()));
  103.         } else {
  104.             s.erase(pos, pos_end - pos + 1);
  105.         }
  106.         pos++;
  107.     }
  108.     s = URL_DecodeString(s);
  109.     CCgiEntry entry(s);
  110.     new_entries.insert(TCgiEntries::value_type(name, entry));
  111. }
  112. int CCgiRedirectApplication::ProcessRequest(CCgiContext& ctx)
  113. {
  114.     const CNcbiRegistry& reg = ctx.GetConfig();
  115.     TCgiEntries new_entries;
  116.     // Remap CGI entries.
  117.     try {
  118.         RemapEntries(ctx, new_entries);
  119.     } catch (exception& e) {
  120.         ERR_POST("Failed to remap CGI entries: " << e.what());
  121.         return 1;
  122.     }
  123.     // Gnerate URLs
  124.     string base_url = reg.Get("Main", "BaseUrl");
  125.     m_Page.AddTagMap("_BASEURL_", new CHTMLText(base_url));
  126.     string url;
  127.     ITERATE(TCgiEntries, i, new_entries) {
  128.         if ( (i->first).empty() ) {
  129.             continue;
  130.          }
  131.         if ( !url.empty() ) {
  132.             url += '&';
  133.         }
  134.         url += i->first;
  135.         if ( !(i->second).empty() ) {
  136.             url += '=';
  137.             url += URL_EncodeString(i->second);
  138.         }
  139.         // Map each entry.
  140.         m_Page.AddTagMap(i->first, new CHTMLText(i->second));
  141.     }
  142.     m_Page.AddTagMap("_URL_", new CHTMLText(base_url + "?" + url));
  143.     // Compose and flush the resultant HTML page
  144.     try {
  145.         CCgiResponse& response = ctx.GetResponse();
  146.         response.WriteHeader();
  147.         m_Page.Print(response.out(), CNCBINode::eHTML);
  148.     } catch (exception& e) {
  149.         ERR_POST("Failed to compose/send HTML page: " << e.what());
  150.         return 1;
  151.     }
  152.     return 0;
  153. }
  154. TCgiEntries& CCgiRedirectApplication::RemapEntries(CCgiContext& ctx,
  155.                                                    TCgiEntries& new_entries)
  156. {
  157.     const CCgiRequest& request = ctx.GetRequest();
  158.     TCgiEntries& entries = const_cast<TCgiEntries&>(request.GetEntries());
  159.     const CNcbiRegistry& reg = ctx.GetConfig();
  160.     // Substitute entries
  161.     // Get list of entries to remove
  162.     list<string> remove_entries;
  163.     string str = reg.Get("Entries", "Remove");
  164.     NStr::Split(str, " ", remove_entries);
  165.     // Get list of entries to clear
  166.     list<string> clear_entries;
  167.     str = reg.Get("Entries", "Clear");
  168.     NStr::Split(str, " ", clear_entries);
  169.     // Get list of entries to add as empty
  170.     list<string> add_empty_entries;
  171.     str = reg.Get("Entries", "Add");
  172.     NStr::Split(str, " ", add_empty_entries);
  173.     // Get substitutions for present entries
  174.     list<string> change_entries;
  175.     reg.EnumerateEntries("Change", &change_entries);
  176.     // Get list of new entries to add
  177.     list<string> add_value_entries;
  178.     reg.EnumerateEntries("Add", &add_value_entries);
  179.     // Create empty entry
  180.     CCgiEntry empty_entry(kEmptyStr);
  181.     ITERATE(TCgiEntries, i, entries) {
  182.         // Check entries marked to remove.
  183.         bool is_removed = false;
  184.         if ( s_FindEntryName(i->first, remove_entries)) {
  185.             is_removed = true;
  186.         }
  187.         // Replace entries marked to clear.
  188.         if ( s_FindEntryName(i->first, clear_entries) ) {
  189.             _TRACE("Add empty: " << i->first);
  190.             new_entries.insert(TCgiEntries::value_type(i->first, empty_entry));
  191.             continue;
  192.         }
  193.         // Change entry as specified in the [Change] section.
  194.         if ( s_FindEntryName(i->first, change_entries) ) {
  195.             _TRACE("Change: " << i->first);
  196.             str = reg.Get("Change", i->first);
  197.             s_AssignEntryValue(i->first, str, entries, new_entries);
  198.             continue;
  199.         }
  200.         // The entry was marked for deletion, do not add it.
  201.         if ( is_removed ) {
  202.             continue;
  203.         }
  204.         // Here we have entry, for which rules is not defined,
  205.         /// so just copy it as is.
  206.         new_entries.insert(*i);
  207.     }
  208.     // Add new empty entries.
  209.     ITERATE(list<string>, i, add_empty_entries) {
  210.         TCgiEntriesCI ci = entries.find(*i);
  211.         if (ci == entries.end()) {
  212.             new_entries.insert(TCgiEntries::value_type(*i, empty_entry));
  213.         }
  214.     }
  215.     // Add new values entries.
  216.     ITERATE(list<string>, i, add_value_entries) {
  217.         TCgiEntriesCI ci = entries.find(*i);
  218.         if (ci == entries.end()) {
  219.             str = reg.Get("Add", *i);
  220.             s_AssignEntryValue(*i, str, entries, new_entries);
  221.         }
  222.     }
  223.     return new_entries;
  224. }
  225. END_NCBI_SCOPE
  226. /*
  227.  * ===========================================================================
  228.  * $Log: redirect.cpp,v $
  229.  * Revision 1000.1  2004/06/01 19:15:48  gouriano
  230.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.6
  231.  *
  232.  * Revision 1.6  2004/05/17 21:01:48  gorelenk
  233.  * Added include of PCH ncbi_pch.hpp
  234.  *
  235.  * Revision 1.5  2004/03/19 16:10:42  ivanov
  236.  * ProcessRequest(): use ctx.GetConfig()
  237.  *
  238.  * Revision 1.4  2004/02/17 16:21:38  ivanov
  239.  * Changed method of using another variables from "&var" to "&{var}".
  240.  * Also, all new string values in the registry file must be specified
  241.  * in the URL-encoded format.
  242.  *
  243.  * Revision 1.3  2004/02/10 15:25:37  ivanov
  244.  * Enclosed mapped tag names with undescores to avoid conflicts default tags
  245.  * with names of automaticaly mapped entries.
  246.  *
  247.  * Revision 1.2  2004/02/10 13:31:44  ivanov
  248.  * Added missed n in the default template
  249.  *
  250.  * Revision 1.1  2004/02/09 19:32:34  ivanov
  251.  * Initial revision
  252.  *
  253.  * ===========================================================================
  254.  */