NCBI C++ ToolKit
cgictx.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: cgictx.cpp 100890 2023-09-25 14:21:32Z lavr $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Eugene Vasilchenko
27 *
28 * File Description:
29 * Definition CGI application class and its context class.
30 *
31 */
32 
33 #include <ncbi_pch.hpp>
34 #include <corelib/ncbistd.hpp>
35 #include <corelib/ncbireg.hpp>
36 #include <corelib/ncbidiag.hpp>
37 #include <corelib/request_ctx.hpp>
39 #include <corelib/ncbi_url.hpp>
40 #include <cgi/ncbires.hpp>
41 #include <cgi/cgictx.hpp>
42 #include <cgi/cgi_util.hpp>
43 #include <cgi/cgi_session.hpp>
44 #include <cgi/cgiapp.hpp>
45 #include <cgi/error_codes.hpp>
46 
47 
48 #ifdef NCBI_OS_UNIX
49 # ifdef HAVE_POLL_H
50 # include <poll.h>
51 # endif
52 # ifdef _AIX32 // version 3.2 *or higher*
53 # include <strings.h> // needed for bzero()
54 # endif
55 # include <sys/time.h>
56 # include <unistd.h> // needed for select() on some platforms
57 #endif
58 
59 
60 #define NCBI_USE_ERRCODE_X Cgi_Application
61 
62 
64 
65 
66 /////////////////////////////////////////////////////////////////////////////
67 // CCgiServerContext::
68 //
69 
71 {
72  return;
73 }
74 
75 
76 
77 /////////////////////////////////////////////////////////////////////////////
78 // CCtxMsg::
79 //
80 
82 {
83  return;
84 }
85 
86 
87 
88 /////////////////////////////////////////////////////////////////////////////
89 // CCtxMsgString::
90 //
91 
92 const char* CCtxMsgString::sm_nl = "\n";
93 
94 
96 {
97  return;
98 }
99 
100 
102 {
103  return os << m_Message << sm_nl;
104 }
105 
106 
107 /////////////////////////////////////////////////////////////////////////////
108 // CCgiContext::
109 //
110 
112  const CNcbiArguments* args,
113  const CNcbiEnvironment* env,
114  CNcbiIstream* inp,
115  CNcbiOstream* out,
116  int ifd,
117  int ofd,
118  size_t errbuf_size,
120  : m_App(&app),
121  m_Request(new CCgiRequest(args ? args : &app.GetArguments(),
122  env ? env : &app.GetEnvironment(),
123  inp, flags, ifd, errbuf_size)),
124  m_Response(out, ofd),
125  m_IsSecure(false),
126  m_StatusCode(CCgiException::eStatusNotSet)
127 {
128  m_Response.SetRequestMethod(m_Request->GetRequestMethod());
130 
133  }
135  return;
136 }
137 
138 
140  CNcbiIstream* is,
141  CNcbiOstream* os,
143  : m_App(&app),
144  m_Request(new CCgiRequest()),
145  m_Response(os, -1),
146  m_IsSecure(false),
147  m_StatusCode(CCgiException::eStatusNotSet)
148 {
149  m_Request->Deserialize(*is,flags);
151  return;
152 }
153 
154 
156  const CNcbiArguments* args,
157  const CNcbiEnvironment* env,
158  CNcbiIstream* inp,
159  CNcbiOstream* out,
160  int ifd,
161  int ofd,
162  size_t errbuf_size,
164  : m_App(nullptr),
165  m_Request(new CCgiRequest(args, env, inp, flags, ifd, errbuf_size)),
166  m_Response(out, ofd),
167  m_IsSecure(false),
168  m_StatusCode(CCgiException::eStatusNotSet)
169 {
170  m_Response.SetRequestMethod(m_Request->GetRequestMethod());
172 
175  }
176  x_InitSession(flags, session_storage);
177  return;
178 }
179 
180 
182 {
183  if ( !m_App ) {
184  NCBI_THROW(CCgiAppException, eApp, "NULL CCgiApplication in CCgiContext");
185  }
186  return *m_App;
187 }
188 
189 
191  ICgiSessionStorage* session_storage)
192 {
193  CCgiSessionParameters params;
194  ICgiSessionStorage* impl = session_storage;
195  if (!session_storage && m_App) {
196  impl = m_App->GetSessionStorage(params);
197  }
198  m_Session.reset(new CCgiSession(*m_Request,
199  impl,
200  params.m_ImplOwner,
201  params.m_CookieEnabled ?
204  );
205  m_Session->SetSessionIdName(params.m_SessionIdName);
206  m_Session->SetSessionCookieDomain(params.m_SessionCookieDomain);
207  m_Session->SetSessionCookiePath(params.m_SessionCookiePath);
208  m_Session->SetSessionCookieExpTime(params.m_SessionCookieExpTime);
209 
210  m_Request->x_SetSession(*m_Session);
212  string track_cookie_value = RetrieveTrackingId();
213  m_Request->SetTrackingCookie(track_cookie_value);
214  bool bad_tracking_cookie = false;
216  try {
218  ctx.SetSessionID(track_cookie_value);
219  if (ctx.GetSessionID() != track_cookie_value) {
220  // Bad session-id was ignored
221  track_cookie_value = ctx.SetSessionID();
222  m_Request->SetTrackingCookie(kEmptyStr);
223  }
224  }
225  catch (CRequestContextException& e) {
226  m_Request->SetTrackingCookie(kEmptyStr);
228  bad_tracking_cookie = true;
229  }
230  }
231  if( !bad_tracking_cookie && !TCGI_DisableTrackingCookie::GetDefault() ) {
232  m_Response.SetTrackingCookie(TCGI_TrackingCookieName::GetDefault(),
233  track_cookie_value,
234  TCGI_TrackingCookieDomain::GetDefault(),
235  TCGI_TrackingCookiePath::GetDefault());
236  }
237 
238  GetSelfURL();
240 }
241 
242 
244 {
245  return;
246 }
247 
248 
250 {
251  return x_GetApp().GetConfig();
252 }
253 
254 
256 {
257  return x_GetApp().GetConfig();
258 }
259 
260 
262 {
263  return x_GetApp().GetResource();
264 }
265 
266 
268 {
269  return x_GetApp().GetResource();
270 }
271 
272 
274 {
276  if ( !context ) {
277  context = x_GetApp().LoadServerContext(const_cast<CCgiContext&>(*this));
278  if ( !context ) {
279  ERR_POST_X(12, "CCgiContext::GetServerContext: no server context set");
280  throw runtime_error("no server context set");
281  }
282  const_cast<CCgiContext&>(*this).m_ServerContext.reset(context);
283  }
284  return *context;
285 }
286 
287 
288 const CCgiEntry& CCgiContext::GetRequestValue(const string& name,
289  bool* is_found)
290  const
291 {
292  pair<TCgiEntriesCI, TCgiEntriesCI> range =
294 
295  if (range.second == range.first) {
296  if ( is_found ) {
297  *is_found = false;
298  }
299  static CSafeStatic<CCgiEntry> s_EmptyCgiEntry;
300  return s_EmptyCgiEntry.Get();
301  }
302  if ( is_found ) {
303  *is_found = true;
304  }
305 
306  const CCgiEntry& value = range.first->second;
307  while (++range.first != range.second) {
308  if (range.first->second != value) {
309  THROW1_TRACE(runtime_error,
310  "duplicate entries in request with name: " +
311  name + ": " + value.GetValue() + "!=" +
312  range.first->second.GetValue());
313  }
314  }
315  return value;
316 }
317 
318 
319 void CCgiContext::RemoveRequestValues(const string& name)
320 {
321  GetRequest().GetEntries().erase(name);
322 }
323 
324 
325 void CCgiContext::AddRequestValue(const string& name, const CCgiEntry& value)
326 {
328 }
329 
330 
331 void CCgiContext::ReplaceRequestValue(const string& name,
332  const CCgiEntry& value)
333 {
334  RemoveRequestValues(name);
335  AddRequestValue(name, value);
336 }
337 
338 
339 const string& CCgiContext::GetSelfURL(void) const
340 {
341  if ( !m_SelfURL.empty() )
342  return m_SelfURL;
343 
344  ESecureMode secure = x_IsSecure();
345 
346  // Compose self URL
347  CUrl url;
348 
349  // Forwarded URL
350  const string& caf_url = GetRequest().GetRandomProperty("CAF_URL");
351  if ( !caf_url.empty() ) {
352  url.SetUrl(caf_url);
353  url.GetArgs().clear();
354  url.SetFragment(kEmptyStr);
355  if (secure != eSecure_On) {
356  secure = NStr::EqualNocase(caf_url, 0, 8, "https://")
358  }
359  }
360  m_IsSecure = secure == eSecure_On;
361 
362  // Check HTTP_X_FORWARDED_HOST for host:port
363  const string& x_fwd_host =
364  GetRequest().GetRandomProperty("X_FORWARDED_HOST");
365  // Fallback to HTTP_HOST if no HTTP_X_FORWARDED_HOST
366  const string& host_port = !x_fwd_host.empty() ? x_fwd_host
367  : caf_url.empty() ? GetRequest().GetRandomProperty("HOST") : kEmptyStr;
368 
369  CTempString host, port;
370  bool no_host = false, no_port = false;
371  if ( !host_port.empty() ) {
372  size_t pos = host_port.find(':');
373  host = CTempString(host_port, 0, pos != NPOS ? pos : host_port.size());
374  port = CTempString(host_port, pos != NPOS? pos + 1 : host_port.size(),
375  host_port.size());
376  } else if ( !caf_url.empty() ) {
377  no_host = no_port = true;
378  port = url.GetPort();
379  } else {
382  }
383  // Skip port if it's default for the selected scheme
384  if ((secure == eSecure_Off && port == "80") ||
385  (secure == eSecure_On && port == "443")) {
386  no_port = false;
387  port.clear();
388  }
389  if ( !no_host ) {
390  url.SetHost(host);
391  }
392  if ( !no_port ) {
393  url.SetPort(port);
394  }
395 
396  string path;
397  if ( !caf_url.empty() ) {
398  path = url.GetPath();
399  } else {
400  path = GetRequest().GetRandomProperty("SCRIPT_URL", false);
401  if ( path.empty() ) {
403  }
404  // Remove args if any
405  size_t pos = path.find_first_of("?#");
406  if (pos != NPOS) {
407  path.resize(pos);
408  }
409  }
410  // (replace adjacent '//' to work around a bug in the "www.ncbi" proxy;
411  // it should not hurt, and may help with similar proxies outside NCBI)
412  url.SetPath(NStr::ReplaceInPlace(path, "//", "/"));
413 
414  if (!url.IsEmpty()) {
415  url.SetIsGeneric(true);
416  if (secure != eSecure_NotSet) {
417  url.SetScheme(m_IsSecure ? "https" : "http");
418  } else {
419  _ASSERT(url.GetScheme().empty());
420  }
421  url.ComposeUrl(CUrlArgs::eAmp_Char/*no args anyways*/).swap(m_SelfURL);
422  }
423  return m_SelfURL;
424 }
425 
426 
428 {
429  ESecureMode secure;
430  const string& x_fwd_proto
431  = GetRequest().GetRandomProperty("X_FORWARDED_PROTO");
432  if ( !x_fwd_proto.empty() ) {
433  if ( NStr::EqualNocase(x_fwd_proto, "https") )
434  return eSecure_On;
435  if ( NStr::EqualNocase(x_fwd_proto, "http") )
436  return eSecure_Off;
437  secure = eSecure_Off;
438  } else {
439  secure = eSecure_NotSet;
440  }
441  return NStr::EqualNocase
442  (GetRequest().GetRandomProperty("HTTPS", false), "on")
443  ? eSecure_On : secure;
444 }
445 
446 
449 {
450  TStreamStatus result = 0;
451 
452 #if defined(NCBI_OS_UNIX)
453  int ifd = m_Request->GetInputFD();
454  int ofd = m_Response.GetOutputFD();
455 
456 # if defined(HAVE_POLL_H) && \
457  !defined(NCBI_OS_DARWIN) && !defined(NCBI_OS_CYGWIN)
458  if (max(ifd, ofd) >= 0) {
459  struct pollfd pfd[2] = { {ifd, POLLIN, 0},
460  {ofd, POLLOUT, 0} };
461  int tmo = timeout.IsInfinite() ? -1
462  : timeout.IsZero() || timeout.IsDefault() ? 0
463  : (int) timeout.GetAsMilliSeconds();
464  if (::poll(pfd, 2, tmo) > 0) {
465  if (pfd[0].revents)
466  result |= fInputReady;
467  if (pfd[1].revents)
468  result |= fOutputReady;
469  }
470  }
471 # else
472  fd_set readfds, *rfds = 0, writefds, *wfds = 0;
473  int nfds = -1;
474 
475  if (ifd >= 0 && ifd < FD_SETSIZE) {
476  rfds = &readfds;
477  FD_ZERO(rfds);
478  FD_SET(ifd, rfds);
479  nfds = ifd;
480  }
481  if (ofd >= 0 && ofd < FD_SETSIZE) {
482  wfds = &writefds;
483  FD_ZERO(wfds);
484  FD_SET(ofd, wfds);
485  if (nfds < ofd)
486  nfds = ofd;
487  }
488  if (++nfds) {
489  struct timeval tv, *tvp = 0;
490  if (timeout.IsFinite()) {
491  tvp = &tv;
492  ::memset(tvp, 0, sizeof(*tvp));
493  if (!timeout.IsZero() && !timeout.IsDefault()) {
494  unsigned int sec, usec;
495  timeout.Get(&sec, &usec);
496  tv.tv_sec = sec;
497  tv.tv_usec = usec;
498  }
499  }
500  if (::select(nfds, rfds, wfds, NULL, tvp) > 0) {
501  if (rfds && FD_ISSET(ifd, rfds))
502  result |= fInputReady;
503  if (wfds && FD_ISSET(ofd, wfds))
504  result |= fOutputReady;
505  }
506  }
507 # endif /*HAVE_POLL_H && !NCBI_OS_DARWIN && !NCBI_OS_CYGWIN*/
508 
509 #else
510  (void) timeout;
511 #endif
512 
513  return result;
514 }
515 
516 
517 static inline bool s_CheckValueForTID(const string& value, string& tid)
518 {
519  string part1, part2;
520  NStr::SplitInTwo(value, "@", part1, part2);
521  if (NStr::EndsWith(part2, "SID")) {
522  tid = part2;
523  return true;
524  }
525  return false;
526 }
527 
528 
529 static inline bool s_CheckCookieForTID(const CCgiCookies& cookies,
530  const string& cookie_name, string& tid)
531 {
532  const CCgiCookie* cookie = cookies.Find(cookie_name);
533 
534  return cookie != NULL && s_CheckValueForTID(cookie->GetValue(), tid);
535 }
536 
537 
538 static inline bool s_CheckRequestEntryForTID(const CCgiRequest* request,
539  const string& entry_name, string& tid)
540 {
541  bool is_found = false;
542  const CCgiEntry* entry = &request->GetEntry(entry_name, &is_found);
543 
544  return is_found && s_CheckValueForTID(entry->GetValue(), tid);
545 }
546 
547 
548 // Check if TID is non-empty and (if Discard_UNK_SESSION is set) not UNK_SESSION.
549 NCBI_PARAM_DECL(bool, CGI, Discard_UNK_SESSION);
550 NCBI_PARAM_DEF_EX(bool, CGI, Discard_UNK_SESSION, false, eParam_NoThread,
551  NCBI_CGI_DISCARD_UNK_SESSION);
552 typedef NCBI_PARAM_TYPE(CGI, Discard_UNK_SESSION) TParamDiscardUnkSession;
553 
554 static inline bool s_IsTID(const string& tid)
555 {
556  if (tid.empty()) return false;
557  if (TParamDiscardUnkSession::GetDefault())
558  return tid != "UNK_SESSION";
559  return true;
560 }
561 
562 
564 {
565  static const char* cookie_or_entry_name_1 = "WebCubbyUser";
566  static const char* cookie_or_entry_name_2 = "WebEnv";
567 
568  // The order of checking SID is:
569  // - Check entries (GET and POST) for ncbi_sid.
570  // - Check cookies for WebCubbyUser, ncbi_sid and WebEnv.
571  // - Check entries for WebCubbyUser and WebEnv.
572  // - Generate a new SID.
573 
574  bool is_found = false;
575  const CCgiEntry* entry =
576  &m_Request->GetEntry(TCGI_TrackingCookieName::GetDefault(), &is_found);
577  if (is_found && s_IsTID(entry->GetValue())) {
578  return entry->GetValue();
579  }
580 
581  const CCgiCookies& cookies = m_Request->GetCookies();
582  string tid;
583 
584  if (s_CheckCookieForTID(cookies, cookie_or_entry_name_1, tid))
585  return tid;
586  const CCgiCookie* cookie = cookies.Find(
587  TCGI_TrackingCookieName::GetDefault(), kEmptyStr, kEmptyStr);
588  if (cookie && s_IsTID(cookie->GetValue())) {
589  return cookie->GetValue();
590  }
591  if (s_CheckCookieForTID(cookies, cookie_or_entry_name_2, tid))
592  return tid;
593  if (s_CheckRequestEntryForTID(m_Request.get(), cookie_or_entry_name_1, tid))
594  return tid;
595  if (s_CheckRequestEntryForTID(m_Request.get(), cookie_or_entry_name_2, tid))
596  return tid;
597 
598  string tag_name = TCGI_TrackingTagName::GetDefault();
599  NStr::ReplaceInPlace(tag_name, "-", "_");
601  m_Request->GetRandomProperty(tag_name, true));
602  if (s_IsTID(tid)) {
603  return tid;
604  }
605 
607  // If UNK_SESSION is set through HTTP_NCBI_SID, replace it with a valid SID
608  s_IsTID(CDiagContext::GetRequestContext().GetSessionID()) ?
611 }
612 
613 
615 {
616  m_StatusCode = code;
618 }
619 
620 
621 void CCgiContext::CheckStatus(void) const
622 {
624 
627  ex.SetStatus(m_StatusCode);
629 }
630 
631 
632 // Param controlling cross-origin resource sharing headers. If set to true,
633 // non-empty parameters for individual headers are used as values for the
634 // headers.
635 NCBI_PARAM_DECL(bool, CGI, CORS_Enable);
636 NCBI_PARAM_DEF_EX(bool, CGI, CORS_Enable, false,
637  eParam_NoThread, CGI_CORS_ENABLE);
638 typedef NCBI_PARAM_TYPE(CGI, CORS_Enable) TCORS_Enable;
639 
640 // Access-Control-Allow-Headers
641 NCBI_PARAM_DECL(string, CGI, CORS_Allow_Headers);
642 NCBI_PARAM_DEF_EX(string, CGI, CORS_Allow_Headers, "",
643  eParam_NoThread, CGI_CORS_ALLOW_HEADERS);
644 typedef NCBI_PARAM_TYPE(CGI, CORS_Allow_Headers) TCORS_AllowHeaders;
645 
646 // Access-Control-Allow-Methods
647 NCBI_PARAM_DECL(string, CGI, CORS_Allow_Methods);
648 NCBI_PARAM_DEF_EX(string, CGI, CORS_Allow_Methods, "GET, POST, OPTIONS",
649  eParam_NoThread, CGI_CORS_ALLOW_METHODS);
650 typedef NCBI_PARAM_TYPE(CGI, CORS_Allow_Methods) TCORS_AllowMethods;
651 
652 // Access-Control-Allow-Origin. Should be a list of domain suffixes
653 // separated by space (e.g. 'foo.com bar.org'). The Origin header
654 // sent by the client is matched against the list. If there's no match,
655 // CORS is not enabled. If matched, the client provided Origin is copied
656 // to the outgoing Access-Control-Allow-Origin. To allow any origin
657 // set the value to '*' (this should be a single char, not part of the list).
658 NCBI_PARAM_DECL(string, CGI, CORS_Allow_Origin);
659 NCBI_PARAM_DEF_EX(string, CGI, CORS_Allow_Origin, "ncbi.nlm.nih.gov",
660  eParam_NoThread, CGI_CORS_ALLOW_ORIGIN);
661 typedef NCBI_PARAM_TYPE(CGI, CORS_Allow_Origin) TCORS_AllowOrigin;
662 
663 // Access-Control-Allow-Credentials
664 NCBI_PARAM_DECL(bool, CGI, CORS_Allow_Credentials);
665 NCBI_PARAM_DEF_EX(bool, CGI, CORS_Allow_Credentials, false,
666  eParam_NoThread, CGI_CORS_ALLOW_CREDENTIALS);
667 typedef NCBI_PARAM_TYPE(CGI, CORS_Allow_Credentials) TCORS_AllowCredentials;
668 
669 // Access-Control-Expose-Headers
670 NCBI_PARAM_DECL(string, CGI, CORS_Expose_Headers);
671 NCBI_PARAM_DEF_EX(string, CGI, CORS_Expose_Headers, "",
672  eParam_NoThread, CGI_CORS_EXPOSE_HEADERS);
673 typedef NCBI_PARAM_TYPE(CGI, CORS_Expose_Headers) TCORS_ExposeHeaders;
674 
675 // Access-Control-Max-Age
676 NCBI_PARAM_DECL(string, CGI, CORS_Max_Age);
677 NCBI_PARAM_DEF_EX(string, CGI, CORS_Max_Age, "",
678  eParam_NoThread, CGI_CORS_MAX_AGE);
679 typedef NCBI_PARAM_TYPE(CGI, CORS_Max_Age) TCORS_MaxAge;
680 
681 
682 // Param to enable JQuery JSONP hack to allow cross-origin resource sharing
683 // for browsers that don't support CORS (e.g. IE versions earlier than 11).
684 // If it is set to true and the HTTP request contains entry "callback" whose
685 // value starts with "JQuery_" (case-insensitive, configurable), then:
686 // - Set the response Content-Type to "text/javascript"
687 // - Wrap the response content into: "JQuery_foobar(original_content)"
688 NCBI_PARAM_DECL(bool, CGI, CORS_JQuery_Callback_Enable);
689 NCBI_PARAM_DEF_EX(bool, CGI, CORS_JQuery_Callback_Enable, false,
690  eParam_NoThread, CGI_CORS_JQUERY_CALLBACK_ENABLE);
691 typedef NCBI_PARAM_TYPE(CGI, CORS_JQuery_Callback_Enable)
692  TCORS_JQuery_Callback_Enable;
693 
694 // If ever need to use a prefix other than "JQuery_" for the JQuery JSONP hack
695 // callback name (above). Use symbol '*' if any name is good.
696 NCBI_PARAM_DECL(string, CGI, CORS_JQuery_Callback_Prefix);
697 NCBI_PARAM_DEF_EX(string, CGI, CORS_JQuery_Callback_Prefix, "*",
698  eParam_NoThread, CGI_CORS_JQUERY_CALLBACK_PREFIX);
699 typedef NCBI_PARAM_TYPE(CGI, CORS_JQuery_Callback_Prefix)
700  TCORS_JQuery_Callback_Prefix;
701 
702 
703 static const char* kAC_Origin = "Origin";
704 static const char* kAC_RequestMethod = "Access-Control-Request-Method";
705 static const char* kAC_RequestHeaders = "Access-Control-Request-Headers";
706 static const char* kAC_AllowHeaders = "Access-Control-Allow-Headers";
707 static const char* kAC_AllowMethods = "Access-Control-Allow-Methods";
708 static const char* kAC_AllowOrigin = "Access-Control-Allow-Origin";
709 static const char* kAC_AllowCredentials = "Access-Control-Allow-Credentials";
710 static const char* kAC_ExposeHeaders = "Access-Control-Expose-Headers";
711 static const char* kAC_MaxAge = "Access-Control-Max-Age";
712 static const char* kSimpleHeaders =
713  " Accept Accept-Language Content-Language Content-Type";
714 static const char* kDefaultHeaders =
715  " Origin Cache-Control Expires Last-Modified Pragma X-Accept-Charset X-Accept"
716  " X-Requested-With NCBI-SID NCBI-PHID";
717 
718 
719 typedef list<string> TStringList;
720 
721 
722 // Check if the origin matches Allow-Origin parameter. Matching rules are:
723 // - If Allow-Origin is empty, return false.
724 // - If Allow-Origin contains an explicit list of origins, check if the
725 // input matches (case-sensitive) any of them, put this single value
726 // into the 'origin' argument and return true; return false otherwise.
727 // - If Allow-Origin is '*' (any), and the input origin is not empty,
728 // return true.
729 // - If Allow-Origin is '*' and the input origin is empty, check
730 // Allow-Credentials flag. Return false if it's enabled. Otherwise
731 // set 'origin' argument to '*' and return true.
732 static bool s_IsAllowedOrigin(const string& origin)
733 {
734  if ( origin.empty() ) {
735  // Origin header is not set - this is not a CORS request.
736  return false;
737  }
738  const string& allowed = TCORS_AllowOrigin::GetDefault();
739  if ( allowed.empty() ) {
740  return false;
741  }
742  if (NStr::Equal(allowed, "*")) {
743  // Accept any origin, it must be non-empty by now.
744  return true;
745  }
746 
747  TStringList origins;
748  NStr::Split(allowed, ", ", origins,
750  ITERATE(TStringList, it, origins) {
751  if (NStr::EndsWith(origin, *it, NStr::eCase)) {
752  return true;
753  }
754  }
755  return false;
756 }
757 
758 
759 // Check if the method is in the list of allowed methods. Empty
760 // method is a no-match. Comparison is case-sensitive.
761 static bool s_IsAllowedMethod(const string& method)
762 {
763  if ( method.empty() ) {
764  return false;
765  }
766  TStringList methods;
767  NStr::Split(TCORS_AllowMethods::GetDefault(), ", ", methods,
769  ITERATE(TStringList, it, methods) {
770  // Methods are case-sensitive.
771  if (*it == method) return true;
772  }
773  return false;
774 }
775 
776 
777 // Declaration only; definition is in cgiapp.cpp.
778 NCBI_PARAM_DECL(bool, CGI, ValidateCSRFToken);
779 typedef NCBI_PARAM_TYPE(CGI, ValidateCSRFToken) TParamValidateCSRFToken;
780 static const char* kCSRFTokenHeader = " NCBI-CSRF-Token";
781 
782 
783 // Check if the (space separated) list of headers is a subset of the
784 // list of allowed headers. Empty list of headers is a match.
785 // Comparison is case-insensitive.
786 // NOTE: The following simple headers are matched automatically:
787 // Cache-Control
788 // Content-Language
789 // Expires
790 // Last-Modified
791 // Pragma
792 static bool s_IsAllowedHeaderList(const string& headers)
793 {
794  if ( headers.empty() ) {
795  // Empty header list is a subset of allowed headers.
796  return true;
797  }
798  TStringList allowed, requested;
799 
800  string ah = TCORS_AllowHeaders::GetDefault();
801  // Always allow simple headers.
802  ah += kSimpleHeaders;
803  ah += kDefaultHeaders;
804  if (TParamValidateCSRFToken::GetDefault()) {
805  ah += kCSRFTokenHeader;
806  }
807 
808  NStr::ToUpper(ah);
809  NStr::Split(ah, ", ", allowed,
811  allowed.sort();
812 
813  string rh = headers;
814  NStr::ToUpper(rh);
815  NStr::Split(rh, ", ", requested,
817  requested.sort();
818 
819  TStringList::const_iterator ait = allowed.begin();
820  TStringList::const_iterator rit = requested.begin();
821  while (ait != allowed.end() && rit != requested.end()) {
822  if (*ait == *rit) {
823  ++rit; // found match
824  }
825  ++ait; // check next allowed
826  }
827  // Found match for each requested header?
828  return rit == requested.end();
829 }
830 
831 
832 inline string s_HeaderToHttp(const char* name)
833 {
834  string http_name(name);
835  return NStr::ToUpper(NStr::ReplaceInPlace(http_name, "-", "_"));
836 }
837 
838 
840  CCgiResponse& response)
841 {
842  // CORS requests handling, see http://www.w3.org/TR/cors/
843 
844  // Is CORS processing enabled?
845  if ( !TCORS_Enable::GetDefault() ) {
846  return false; // CORS disabled, so -- do regular request processing
847  }
848 
849  const CCgiRequest::ERequestMethod method = request.GetRequestMethod();
850 
851  // Is this a standard CORS request?
852  const string& origin = request.GetRandomProperty(s_HeaderToHttp(kAC_Origin));
853  if ( origin.empty() ) {
854  // Is this a JQuery based hack for browsers that don't yet support CORS?
855  string jquery_callback = request.GetEntry("callback");
856  if (TCORS_JQuery_Callback_Enable::GetDefault()
857  && (method == CCgiRequest::eMethod_GET ||
858  method == CCgiRequest::eMethod_POST ||
859  method == CCgiRequest::eMethod_Other)
860  && !jquery_callback.empty()) {
861  string prefix = TCORS_JQuery_Callback_Prefix::GetDefault();
862  if (prefix == "*" ||
863  NStr::StartsWith(jquery_callback, prefix, NStr::eNocase)) {
864  // Activate JQuery hack;
865  // skip standard CORS processing; do regular request processing
866  response.m_JQuery_Callback = jquery_callback;
867  }
868  }
869  return false;
870  }
871 
872  if ( !s_IsAllowedOrigin(origin) ) {
873  // CORS with invalid origin -- terminate request.
874  response.DisableTrackingCookie();
876  response.WriteHeader();
877  return true;
878  }
879 
880  _ASSERT(!origin.empty());
881 
882  // Is this a preflight CORS request?
883  if (method == CCgiRequest::eMethod_OPTIONS) {
884  const string& method_str = request.GetRandomProperty
886  const string& headers = request.GetRandomProperty
888  if (!s_IsAllowedMethod(method_str) || !s_IsAllowedHeaderList(headers)) {
889  // This is CORS request, but the method or headers are not allowed.
890  response.DisableTrackingCookie();
892  response.WriteHeader();
893  return true;
894  }
895  // Yes, it's a preflight CORS request, so -- set and send back
896  // the required headers, and don't do regular (non-CORS) request
897  // processing
899  if ( TCORS_AllowCredentials::GetDefault() ) {
900  response.SetHeaderValue(kAC_AllowCredentials, "true");
901  }
902  const string& allow_methods = TCORS_AllowMethods::GetDefault();
903  if ( !allow_methods.empty() ) {
904  response.SetHeaderValue(kAC_AllowMethods, allow_methods);
905  }
906  string allow_headers = TCORS_AllowHeaders::GetDefault();
907  allow_headers += kDefaultHeaders;
908  if ( !allow_headers.empty() ) {
909  // Make comma-separated list.
910  TStringList allowed_list;
911  NStr::Split(allow_headers, ", ", allowed_list,
913  allow_headers = NStr::Join(allowed_list, ", ");
914  response.SetHeaderValue(kAC_AllowHeaders, allow_headers);
915  }
916  const string& max_age = TCORS_MaxAge::GetDefault();
917  if ( !max_age.empty() ) {
918  response.SetHeaderValue(kAC_MaxAge, max_age);
919  }
920  response.DisableTrackingCookie();
921  response.RemoveHeaderValue("NCBI-PHID");
922  response.WriteHeader();
923  // This was CORS preflight request (valid or not) - skip normap processing.
924  return true;
925  }
926 
927  // This is a normal CORS request (not a preflight), so -- set the required
928  // CORS headers, and then do regular (non-CORS) request processing
930  if ( TCORS_AllowCredentials::GetDefault() ) {
931  response.SetHeaderValue(kAC_AllowCredentials, "true");
932  }
933  string exp_headers = TCORS_ExposeHeaders::GetDefault();
934  if ( !exp_headers.empty() ) {
935  response.SetHeaderValue(kAC_ExposeHeaders, exp_headers);
936  }
937 
938  // Proceed to ProcessRequest()
939  return false;
940 }
941 
942 
API to store CGI session data between Web requests.
static const char * kCSRFTokenHeader
Definition: cgictx.cpp:780
static const char * kAC_RequestMethod
Definition: cgictx.cpp:704
string s_HeaderToHttp(const char *name)
Definition: cgictx.cpp:832
static const char * kAC_Origin
Definition: cgictx.cpp:703
static const char * kAC_AllowOrigin
Definition: cgictx.cpp:708
static bool s_IsTID(const string &tid)
Definition: cgictx.cpp:554
static bool s_IsAllowedOrigin(const string &origin)
Definition: cgictx.cpp:732
list< string > TStringList
Definition: cgictx.cpp:719
NCBI_PARAM_DECL(bool, CGI, Discard_UNK_SESSION)
static const char * kAC_ExposeHeaders
Definition: cgictx.cpp:710
NCBI_PARAM_DEF_EX(bool, CGI, Discard_UNK_SESSION, false, eParam_NoThread, NCBI_CGI_DISCARD_UNK_SESSION)
static const char * kAC_MaxAge
Definition: cgictx.cpp:711
static const char * kAC_AllowHeaders
Definition: cgictx.cpp:706
static bool s_CheckCookieForTID(const CCgiCookies &cookies, const string &cookie_name, string &tid)
Definition: cgictx.cpp:529
static const char * kAC_AllowCredentials
Definition: cgictx.cpp:709
static const char * kAC_RequestHeaders
Definition: cgictx.cpp:705
static const char * kAC_AllowMethods
Definition: cgictx.cpp:707
static bool s_CheckValueForTID(const string &value, string &tid)
Definition: cgictx.cpp:517
static const char * kDefaultHeaders
Definition: cgictx.cpp:714
static bool s_IsAllowedMethod(const string &method)
Definition: cgictx.cpp:761
typedef NCBI_PARAM_TYPE(CGI, Discard_UNK_SESSION) TParamDiscardUnkSession
static const char * kSimpleHeaders
Definition: cgictx.cpp:712
static bool s_CheckRequestEntryForTID(const CCgiRequest *request, const string &entry_name, string &tid)
Definition: cgictx.cpp:538
static bool s_IsAllowedHeaderList(const string &headers)
Definition: cgictx.cpp:792
CCgiAppException –.
CCgiCookie::
Definition: ncbicgi.hpp:67
CCgiCookies::
Definition: ncbicgi.hpp:219
CCgiRequest::
Definition: ncbicgi.hpp:685
CCgiSession –.
Definition: cgi_session.hpp:62
CNcbiArguments –.
Definition: ncbienv.hpp:236
CNcbiEnvironment –.
Definition: ncbienv.hpp:110
CNcbiRegistry –.
Definition: ncbireg.hpp:913
CSafeStatic<>::
T & Get(void)
Create the variable if not created yet, return the reference.
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
CTimeout – Timeout interval.
Definition: ncbitime.hpp:1693
CUrl –.
Definition: ncbi_url.hpp:353
ICgiSessionStorage –.
const_iterator_pair equal_range(const key_type &key) const
Definition: map.hpp:296
void erase(iterator pos)
Definition: map.hpp:307
iterator insert(const value_type &val)
Definition: map.hpp:305
URL parsing classes.
Include a standard set of the NCBI C++ Toolkit most basic headers.
static uch flags
std::ofstream out("events_result.xml")
main entry point for tests
CS_CONTEXT * ctx
Definition: t0006.c:12
#define false
Definition: bool.h:36
static HENV env
Definition: transaction2.c:38
#define POLLIN
Definition: poll.h:37
#define poll(fds, nfds, timeout)
Definition: poll.h:81
#define FD_SETSIZE
Definition: poll.h:30
#define POLLOUT
Definition: poll.h:38
const CNcbiRegistry & GetConfig(void) const
Get the application's cached configuration parameters (read-only).
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
CCgiContext(CCgiApplication &app, const CNcbiArguments *args=0, const CNcbiEnvironment *env=0, CNcbiIstream *inp=0, CNcbiOstream *out=0, int ifd=-1, int ofd=-1, size_t errbuf_size=256, CCgiRequest::TFlags flags=0)
Definition: cgictx.cpp:111
int TStreamStatus
Definition: cgictx.hpp:234
virtual ~CCtxMsg(void)
Definition: cgictx.cpp:81
TStreamStatus GetStreamStatus(void) const
Definition: cgictx.hpp:454
virtual ~CCgiContext(void)
Definition: cgictx.cpp:243
ESecureMode x_IsSecure(void) const
Definition: cgictx.cpp:427
CCgiApplication & x_GetApp(void) const
Definition: cgictx.cpp:181
const CCgiRequest & GetRequest(void) const
Definition: cgictx.hpp:374
static const char * sm_nl
Definition: cgictx.hpp:106
void RemoveRequestValues(const string &name)
Definition: cgictx.cpp:319
const CCgiEntry & GetRequestValue(const string &name, bool *is_found=0) const
Definition: cgictx.cpp:288
string RetrieveTrackingId() const
Definition: cgictx.cpp:563
CCgiException::EStatusCode m_StatusCode
Definition: cgictx.hpp:285
unique_ptr< CCgiServerContext > m_ServerContext
Definition: cgictx.hpp:278
virtual ~CCgiServerContext(void)
Definition: cgictx.cpp:70
CTime m_SessionCookieExpTime
Definition: cgictx.hpp:348
EOwnership m_ImplOwner
Definition: cgictx.hpp:343
string m_SessionCookieDomain
Definition: cgictx.hpp:346
virtual ICgiSessionStorage * GetSessionStorage(CCgiSessionParameters &params) const
Get instance of CGI session storage interface.
Definition: cgiapp.cpp:1419
CCgiServerContext & x_GetServerContext(void) const
Definition: cgictx.cpp:273
bool m_IsSecure
Definition: cgictx.hpp:281
virtual ~CCtxMsgString(void)
Definition: cgictx.cpp:95
string m_SelfURL
Definition: cgictx.hpp:280
void ReplaceRequestValue(const string &name, const CCgiEntry &value)
Definition: cgictx.cpp:331
static bool ProcessCORSRequest(const CCgiRequest &request, CCgiResponse &response)
Process cross-origin resource sharing (CORS) request.
Definition: cgictx.cpp:839
void x_SetStatus(CCgiException::EStatusCode code, const string &msg) const
Definition: cgictx.cpp:614
const CNcbiRegistry & GetConfig(void) const
Definition: cgictx.cpp:249
string m_StatusMessage
Definition: cgictx.hpp:286
string m_Message
Definition: cgictx.hpp:109
unique_ptr< CCgiRequest > m_Request
Definition: cgictx.hpp:269
const string & GetSelfURL(void) const
Using HTTP environment variables, compose the CGI's own URL as: SCHEME://SERVER_NAME[:SERVER_PORT]/SC...
Definition: cgictx.cpp:339
bool IsSecure(void) const
Check if the current scheme is secure (https) or not (http).
Definition: cgictx.hpp:227
CCgiApplication * m_App
Definition: cgictx.hpp:268
unique_ptr< CCgiSession > m_Session
Definition: cgictx.hpp:271
void AddRequestValue(const string &name, const CCgiEntry &value)
Definition: cgictx.cpp:325
virtual CNcbiOstream & Write(CNcbiOstream &os) const
Definition: cgictx.cpp:101
string m_SessionCookiePath
Definition: cgictx.hpp:347
const CNcbiResource & GetResource(void) const
Get server 'resource'. Throw exception if the resource is not set.
Definition: cgiapp.hpp:83
CCgiResponse m_Response
Definition: cgictx.hpp:270
virtual CCgiServerContext * LoadServerContext(CCgiContext &context)
Definition: cgiapp.cpp:893
void CheckStatus(void) const
Check if the context has any pending errors, perform any required actions (e.g.
Definition: cgictx.cpp:621
const CNcbiResource & GetResource(void) const
Definition: cgictx.cpp:261
void x_InitSession(CCgiRequest::TFlags flags, ICgiSessionStorage *session_storage=nullptr)
Definition: cgictx.cpp:190
CGI
Definition: cgiapp.hpp:688
@ eSecure_NotSet
Definition: cgictx.hpp:262
@ fOutputReady
Definition: cgictx.hpp:232
EStatusCode
HTTP status codes.
@ eStatusNotSet
Internal value - code not set.
void SetRequestMethod(CCgiRequest::ERequestMethod method)
Set HTTP request method.
Definition: ncbicgir.hpp:422
const TCgiEntries & GetEntries(void) const
Get a set of entries(decoded) received from the client.
Definition: ncbicgi.hpp:1181
CCgiCookie * Find(const string &name, const string &domain, const string &path)
Return NULL if cannot find this exact cookie.
Definition: ncbicgi.cpp:690
const string & GetValue(void) const
All "const string& GetXXX(...)" methods beneath return reference to "NcbiEmptyString" if the requeste...
Definition: ncbicgi.hpp:1034
void SetHeaderValue(const string &name, const string &value)
Definition: ncbicgir.cpp:151
void x_SetSession(const CCgiSession &session)
Definition: ncbicgir.hpp:416
string m_JQuery_Callback
Definition: ncbicgir.hpp:312
const string & GetValue() const
Get the value as a string, (necessarily) prefetching it all if applicable; the result remains availab...
Definition: ncbicgi.hpp:470
void SetStatus(unsigned int code, const string &reason=kEmptyStr)
Definition: ncbicgir.cpp:197
void SetTrackingCookie(const string &name, const string &value, const string &domain, const string &path, const CTime &exp_time=CTime())
Definition: ncbicgir.cpp:539
void SetCgiRequest(const CCgiRequest &request)
Definition: ncbicgir.hpp:411
const string & GetProperty(ECgiProp prop) const
Get value of a "standard" property (return empty string if not defined)
Definition: ncbicgi.cpp:1432
const CCgiCookies & Cookies(void) const
Definition: ncbicgir.hpp:381
const string & GetRandomProperty(const string &key, bool http=true) const
Get value of a random client property; if "http" is TRUE then add prefix "HTTP_" to the property name...
Definition: ncbicgi.cpp:1438
CNcbiOstream & WriteHeader(void) const
Write HTTP response header to the output stream.
Definition: ncbicgir.hpp:396
void RemoveHeaderValue(const string &name)
Definition: ncbicgir.cpp:125
const CCgiEntry & GetEntry(const string &name, bool *is_found=0) const
Get entry value by name.
Definition: ncbicgi.cpp:1449
ERequestMethod
Standard request methods.
Definition: ncbicgi.hpp:905
int TFlags
Startup initialization.
Definition: ncbicgi.hpp:703
void SetSecure(bool secure)
Set secure connection flag.
Definition: ncbicgi.hpp:320
int GetOutputFD(void) const
Get file descriptor of the output stream (-1 if not applicable)
Definition: ncbicgir.hpp:391
ERequestMethod GetRequestMethod(void) const
Get request method.
Definition: ncbicgi.cpp:1810
void DisableTrackingCookie(void)
Definition: ncbicgir.cpp:557
@ eCgi_ServerName
Definition: ncbicgi.hpp:381
@ eCgi_ServerPort
Definition: ncbicgi.hpp:384
@ eCgi_ScriptName
Definition: ncbicgi.hpp:398
@ fDisableTrackingCookie
Do not set outgoing tracking cookie.
Definition: ncbicgi.hpp:734
@ fSkipDiagProperties
Set client-ip and session-id properties for logging.
Definition: ncbicgi.hpp:725
@ eMethod_OPTIONS
Definition: ncbicgi.hpp:911
@ eMethod_Other
Unknown method, use GetRequestMethodName to read.
Definition: ncbicgi.hpp:914
@ eUseCookie
A session cookie will be added to the response.
Definition: cgi_session.hpp:83
@ eNoCookie
A session cookie will not be added to the response.
Definition: cgi_session.hpp:84
#define NULL
Definition: ncbistd.hpp:225
CDiagContext & GetDiagContext(void)
Get diag context instance.
Definition: logging.cpp:818
string GetSessionID(void) const
Session ID.
void SetSessionID(const string &session)
static string SelectLastSessionID(const string &session_ids)
Select the last session id from the list of ids separated with commas and optional spaces,...
bool IsSetSessionID(void) const
static CRequestContext & GetRequestContext(void)
Shortcut to CDiagContextThreadData::GetThreadData().GetRequestContext()
Definition: ncbidiag.cpp:1901
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
#define NCBI_EXCEPTION_VAR(name, exception_class, err_code, message)
Create an instance of the exception to be thrown later.
Definition: ncbiexpt.hpp:684
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define NCBI_EXCEPTION_THROW(exception_var)
Throw an existing exception object.
Definition: ncbiexpt.hpp:688
#define THROW1_TRACE(exception_class, exception_arg)
Throw trace.
Definition: ncbiexpt.hpp:417
@ eParam_NoThread
Do not use per-thread values.
Definition: ncbi_param.hpp:418
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
Definition: ncbistre.hpp:146
#define kEmptyStr
Definition: ncbistr.hpp:123
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3452
static bool EndsWith(const CTempString str, const CTempString end, ECase use_case=eCase)
Check if a string ends with a specified suffix value.
Definition: ncbistr.hpp:5424
#define NPOS
Definition: ncbistr.hpp:133
static string Join(const TContainer &arr, const CTempString &delim)
Join strings using the specified delimiter.
Definition: ncbistr.hpp:2699
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5406
void clear(void)
Clears the string.
Definition: tempstr.hpp:351
static bool SplitInTwo(const CTempString str, const CTempString delim, string &str1, string &str2, TSplitFlags flags=0)
Split a string into two pieces using the specified delimiters.
Definition: ncbistr.cpp:3545
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5347
size_type find(const CTempString match, size_type pos=0) const
Find the first instance of the entire matching string within the current string, beginning at an opti...
Definition: tempstr.hpp:655
static bool Equal(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2, ECase use_case=eCase)
Test for equality of a substring with another string.
Definition: ncbistr.hpp:5378
static string & ReplaceInPlace(string &src, const string &search, const string &replace, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3396
static string & ToUpper(string &str)
Convert string to upper case – string& version.
Definition: ncbistr.cpp:424
@ fSplit_Truncate
Definition: ncbistr.hpp:2503
@ fSplit_MergeDelimiters
Merge adjacent delimiters.
Definition: ncbistr.hpp:2500
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
@ eCase
Case sensitive compare.
Definition: ncbistr.hpp:1205
bool IsInfinite() const
Definition: ncbitime.hpp:2729
bool IsZero() const
Definition: ncbitime.cpp:3476
unsigned long GetAsMilliSeconds(void) const
Get as number of milliseconds.
Definition: ncbitime.cpp:3490
bool IsDefault() const
Definition: ncbitime.hpp:2723
void Get(unsigned int *sec, unsigned int *microsec) const
Get timeout in seconds and microseconds.
Definition: ncbitime.cpp:3545
bool IsFinite() const
Check if timeout holds a numeric value.
Definition: ncbitime.hpp:2735
const CUrlArgs & GetArgs(void) const
Get const list of arguments.
Definition: ncbi_url.cpp:674
void SetPath(const string &value)
Definition: ncbi_url.hpp:422
void SetFragment(const string &value)
Definition: ncbi_url.hpp:425
void clear(void)
Clear the list.
Definition: ncbi_url.hpp:250
const string & GetPath(void) const
Definition: ncbi_url.hpp:421
const string & GetPort(void) const
Definition: ncbi_url.hpp:418
const string & GetScheme(void) const
Definition: ncbi_url.hpp:398
void SetPort(const string &value)
Definition: ncbi_url.hpp:419
void SetUrl(const string &url, const IUrlEncoder *encoder=0)
Parse the URL.
Definition: ncbi_url.cpp:409
bool IsEmpty(void) const
Definition: ncbi_url.cpp:815
void SetHost(const string &value)
Definition: ncbi_url.hpp:569
void SetIsGeneric(bool value)
Definition: ncbi_url.hpp:403
void SetScheme(const string &value)
Definition: ncbi_url.cpp:651
string ComposeUrl(CUrlArgs::EAmpEncoding amp_enc, const IUrlEncoder *encoder=0) const
Compose the URL.
Definition: ncbi_url.cpp:580
@ eAmp_Char
Use & to separate arguments.
Definition: ncbi_url.hpp:254
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
Definition of all error codes used in cgi (xcgi.lib).
range(_Ty, _Ty) -> range< _Ty >
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
Static variables safety - create on demand, destroy on application termination.
Defines NCBI C++ diagnostic APIs, classes, and macros.
#define nullptr
Definition: ncbimisc.hpp:45
Process information in the NCBI Registry, including working with configuration files.
T max(T x_, T y_)
static const GLdouble origin[]
Defines CRequestContext class for NCBI C++ diagnostic API.
static SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
Definition: inftrees.h:24
Definition: poll.h:52
short revents
Definition: poll.h:55
#define _ASSERT
else result
Definition: token2.c:20
static CS_CONTEXT * context
Definition: will_convert.c:21
Modified on Fri Sep 20 14:58:06 2024 by modify_doxy.py rev. 669887