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

Go to the SVN repository for this file.

1 /* $Id: ncbi_url.cpp 102636 2024-06-17 13:59:53Z satskyse $
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  * Authors: Alexey Grichenko, Vladimir Ivanov
27  *
28  * File Description: URL parsing classes
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbienv.hpp>
34 #include <corelib/ncbi_url.hpp>
35 #include <stdlib.h>
36 
37 
39 
40 NCBI_PARAM_DECL(bool, CUrl, enable_parsing_as_index);
41 NCBI_PARAM_DEF(bool, CUrl, enable_parsing_as_index, false);
42 typedef NCBI_PARAM_TYPE(CUrl, enable_parsing_as_index) TCUrlEnableParsingAsIndex;
43 
44 //////////////////////////////////////////////////////////////////////////////
45 //
46 // CUrlArgs_Parser
47 //
48 
51 {
52  CDefaultUrlEncoder encoder(encode);
53  SetQueryString(query, &encoder);
54 }
55 
56 
58  const IUrlEncoder& encoder)
59 {
60  SIZE_TYPE len = query.size();
61  _ASSERT(len);
62 
63  // No '=' and spaces must be present in the parsed string
64  _ASSERT(query.find_first_of("= \t\r\n") == NPOS);
65 
66  // Parse into indexes
67  unsigned int position = 1;
68  for (SIZE_TYPE beg = 0; beg < len; ) {
69  SIZE_TYPE end = query.find('+', beg);
70  // Skip leading '+' (empty value).
71  if (end == beg) {
72  beg++;
73  continue;
74  }
75  if (end == NPOS) {
76  end = len;
77  }
78 
79  AddArgument(position++,
80  encoder.DecodeArgName(query.substr(beg, end - beg)),
81  kEmptyStr,
82  eArg_Index);
83  beg = end + 1;
84  }
85 }
86 
87 
89  const IUrlEncoder* encoder)
90 {
91  if ( !encoder ) {
92  encoder = CUrl::GetDefaultEncoder();
93  }
94  // Parse and decode query string
95  SIZE_TYPE len = query.length();
96  if ( !len ) {
97  return;
98  }
99 
100  {{
101  // No spaces are allowed in the parsed string
102  SIZE_TYPE err_pos = query.find_first_of(" \t\r\n");
103  if (err_pos != NPOS) {
105  "Space character in URL arguments: \"" + query + "\"",
106  err_pos + 1);
107  }
108  }}
109 
110  // If no '=' present in the parsed string then try to parse it as ISINDEX
111  // RFC3875
112  if (((m_Flags & fEnableParsingAsIndex) || TCUrlEnableParsingAsIndex::GetDefault()) && (query.find("=") == NPOS)) {
113  x_SetIndexString(query, *encoder);
114  return;
115  }
116 
117  // Parse into entries
118  string mid_seps = "=&";
119  string end_seps = "&";
121  {
122  mid_seps += ';';
123  end_seps += ';';
124  }
125  unsigned int position = 1;
126  for (SIZE_TYPE beg = 0; beg < len; ) {
127  // ignore ampersand and "&amp;"
128  if (query[beg] == '&') {
129  ++beg;
130  if (beg < len && !NStr::CompareNocase(query, beg, 4, "amp;")) {
131  beg += 4;
132  }
133  continue;
134  }
135  // Alternative separator - ';'
136  else if ((m_Flags & fSemicolonIsArgDelimiter) && query[beg] == ';')
137  {
138  ++beg;
139  continue;
140  }
141 
142  // parse and URL-decode name
143  SIZE_TYPE mid = query.find_first_of(mid_seps, beg);
144  // '=' is the first char (empty name)? Skip to the next separator.
145  if (mid == beg) {
146  beg = query.find_first_of(end_seps, beg);
147  if (beg == NPOS) break;
148  continue;
149  }
150  if (mid == NPOS) {
151  mid = len;
152  }
153 
154  string name = encoder->DecodeArgName(query.substr(beg, mid - beg));
155 
156  // parse and URL-decode value(if any)
157  string value;
158  if (query[mid] == '=') { // has a value
159  mid++;
160  SIZE_TYPE end = query.find_first_of(end_seps, mid);
161  if (end == NPOS) {
162  end = len;
163  }
164 
165  value = encoder->DecodeArgValue(query.substr(mid, end - mid));
166 
167  beg = end;
168  } else { // has no value
169  beg = mid;
170  }
171 
172  // store the name-value pair
173  AddArgument(position++, name, value, eArg_Value);
174  }
175 }
176 
177 
178 //////////////////////////////////////////////////////////////////////////////
179 //
180 // CUrlArgs
181 //
182 
185  m_Case(NStr::eNocase),
186  m_IsIndex(false)
187 {
188  return;
189 }
190 
191 
194  m_Case(NStr::eNocase),
195  m_IsIndex(false)
196 {
198 }
199 
200 
201 CUrlArgs::CUrlArgs(const string& query, const IUrlEncoder* encoder, TFlags flags)
203  m_Case(NStr::eNocase),
204  m_IsIndex(false)
205 {
206  SetQueryString(query, encoder);
207 }
208 
209 
210 void CUrlArgs::AddArgument(unsigned int /* position */,
211  const string& name,
212  const string& value,
213  EArgType arg_type)
214 {
215  if (arg_type == eArg_Index) {
216  m_IsIndex = true;
217  }
218  else {
219  _ASSERT(!m_IsIndex);
220  }
221  m_Args.push_back(TArg(name, value));
222 }
223 
224 
226  NStr::EUrlEncode encode) const
227 {
228  CDefaultUrlEncoder encoder(encode);
229  return GetQueryString(amp_enc, &encoder);
230 }
231 
232 
234  const IUrlEncoder* encoder) const
235 {
236  if ( !encoder ) {
237  encoder = CUrl::GetDefaultEncoder();
238  }
239  // Encode and construct query string
240  string query;
241  string amp = (amp_enc == eAmp_Char) ? "&" : "&amp;";
242  ITERATE(TArgs, arg, m_Args) {
243  if ( !query.empty() ) {
244  query += m_IsIndex ? "+" : amp;
245  }
246  query += encoder->EncodeArgName(arg->name);
247  if ( !m_IsIndex ) {
248  query += "=";
249  query += encoder->EncodeArgValue(arg->value);
250  }
251  }
252  return query;
253 }
254 
255 
256 const string& CUrlArgs::GetValue(const string& name, bool* is_found) const
257 {
258  const_iterator iter = FindFirst(name);
259  if ( is_found ) {
260  *is_found = iter != m_Args.end();
261  return *is_found ? iter->value : kEmptyStr;
262  }
263  else if (iter != m_Args.end()) {
264  return iter->value;
265  }
266  NCBI_THROW(CUrlException, eName, "Argument not found: " + name);
267 }
268 
269 
270 void CUrlArgs::SetValue(const string& name, const string& value)
271 {
272  m_IsIndex = false;
273  iterator it = FindFirst(name);
274  if (it != m_Args.end()) {
275  it->value = value;
276  }
277  else {
278  m_Args.push_back(TArg(name, value));
279  }
280 }
281 
282 
283 void CUrlArgs::AddValue(const string& name, const string& value)
284 {
285  m_IsIndex = false;
286  m_Args.push_back(TArg(name, value));
287 }
288 
289 
290 void CUrlArgs::SetUniqueValue(const string& name, const string& value)
291 {
292  m_IsIndex = false;
293  iterator it = FindFirst(name);
294  while (it != m_Args.end()) {
295  iterator tmp = it;
296  it = FindNext(it);
297  m_Args.erase(tmp);
298  }
299  m_Args.push_back(TArg(name, value));
300 }
301 
302 
304  const iterator& start)
305 {
306  for(iterator it = start; it != m_Args.end(); ++it) {
307  if ( NStr::Equal(it->name, name, m_Case) ) {
308  return it;
309  }
310  }
311  return m_Args.end();
312 }
313 
314 
316  const const_iterator& start) const
317 {
318  for(const_iterator it = start; it != m_Args.end(); ++it) {
319  if ( NStr::Equal(it->name, name, m_Case) ) {
320  return it;
321  }
322  }
323  return m_Args.end();
324 }
325 
326 
327 //////////////////////////////////////////////////////////////////////////////
328 //
329 // CUrl
330 //
331 
332 CUrl::CUrl(void)
333  : m_IsGeneric(false)
334 {
335  return;
336 }
337 
338 
339 CUrl::CUrl(const string& url, const IUrlEncoder* encoder)
340  : m_IsGeneric(false)
341 {
342  SetUrl(url, encoder);
343 }
344 
345 
346 CUrl::CUrl(const CUrl& url)
347 {
348  *this = url;
349 }
350 
351 
353 {
354  if (this != &url) {
355  m_Scheme = url.m_Scheme;
356  m_IsGeneric = url.m_IsGeneric;
357  m_User = url.m_User;
358  m_Password = url.m_Password;
359  m_Host = url.m_Host;
360  m_Service = url.m_Service;
361  m_Port = url.m_Port;
362  m_Path = url.m_Path;
363  m_Fragment = url.m_Fragment;
364  m_OrigArgs = url.m_OrigArgs;
365  if ( url.m_ArgsList.get() ) {
366  m_ArgsList.reset(new CUrlArgs(*url.m_ArgsList));
367  } else {
368  m_ArgsList.reset();
369  }
370  }
371  return *this;
372 }
373 
374 
375 bool CUrl::x_IsHostPort(const string& scheme, string& unparsed, const IUrlEncoder& encoder)
376 {
377  static set<string> s_StdSchemes{
378  "http", "https", "file", "ftp"
379  };
380 
381  // Check for special case: host:port[/path[...]] (see CXX-11455)
382  if (scheme.empty()) return false;
383  string sch_lower = scheme;
384  NStr::ToLower(sch_lower);
385  if (s_StdSchemes.find(sch_lower) != s_StdSchemes.end()) return false;
386 
387  SIZE_TYPE port_end = unparsed.find_first_of("/?#");
388  string port = unparsed.substr(0, port_end);
389 
390  if (port.empty() ||
391  port[0] == '0' ||
392  port.size() > 5 ||
393  port.find_first_not_of("0123456789") != NPOS) return false;
394  int port_val = atoi(port.c_str());
395  if (port_val > 65535) return false;
396 
397  x_SetHost(scheme, encoder);
398  x_SetPort(port, encoder);
399  if (port_end != NPOS) {
400  unparsed = unparsed.substr(port_end);
401  }
402  else {
403  unparsed.clear();
404  }
405  return true;
406 }
407 
408 
409 void CUrl::SetUrl(const string& orig_url, const IUrlEncoder* encoder)
410 {
411  m_Scheme.clear();
412  m_IsGeneric = false;
413  m_User.clear();
414  m_Password.clear();
415  m_Host.clear();
416  m_Service.clear();
417  m_Port.clear();
418  m_Path.clear();
419  m_Fragment.clear();
420  m_OrigArgs.clear();
421  m_ArgsList.reset();
422 
423  string unparsed;
424 
425  if ( !encoder ) {
426  encoder = GetDefaultEncoder();
427  }
428 
429  // Special case - service name does not contain any URL reserved symbols
430  // (they must be URL-encoded).
431  if (orig_url.find_first_of(":/.?#") == NPOS) {
432  x_SetService(orig_url);
433  return;
434  }
435 
436  // Parse scheme and authority (user info, host, port).
437  SIZE_TYPE pos = orig_url.find("//");
438 
439  // The // can be in parameters part, so check that it is before the ?
440  bool slashes_are_in_args = false;
441  if (pos != NPOS) {
442  SIZE_TYPE question_mark_pos = orig_url.find("?");
443  if (question_mark_pos != NPOS) {
444  if (question_mark_pos < pos) {
445  slashes_are_in_args = true;
446  }
447  }
448  }
449 
450  SIZE_TYPE offset = 0;
451  string authority;
452  if (pos != NPOS && slashes_are_in_args == false) {
453  m_IsGeneric = true;
454  // Host is present, split into scheme/host/path.
455  if (pos > 0 && orig_url[pos - 1] == ':') {
456  // Scheme is present
457  x_SetScheme(orig_url.substr(0, pos - 1), *encoder);
458  }
459  pos += 2;
460  offset += pos;
461  unparsed = orig_url.substr(pos);
462  pos = unparsed.find_first_of("/?#");
463  authority = unparsed.substr(0, pos);
464  if (pos != NPOS) {
465  unparsed = unparsed.substr(pos);
466  }
467  else {
468  unparsed.clear();
469  }
470  string host;
471  pos = authority.find('@');
472  if (pos != NPOS) {
473  offset += pos;
474  string user_info = authority.substr(0, pos);
475  host = authority.substr(pos + 1);
476  pos = user_info.find(':');
477  if (pos != NPOS) {
478  x_SetUser(user_info.substr(0, pos), *encoder);
479  x_SetPassword(user_info.substr(pos + 1), *encoder);
480  }
481  else {
482  x_SetUser(user_info, *encoder);
483  }
484  }
485  else {
486  host = authority;
487  }
488  string port;
489  // Find port position, if any. Take IPv6 into account.
490  if (!host.empty() && host[0] == '[') {
491  // IPv6 address - skip to the closing ]
492  pos = host.find(']');
493  if (pos == NPOS) {
495  "Unmatched '[' in the URL: \"" + orig_url + "\"", pos + offset);
496  }
497  if (pos + 1 < host.size() && host[pos + 1] == ':') {
498  pos++;
499  }
500  else {
501  pos = NPOS;
502  }
503  }
504  else {
505  pos = host.find(':');
506  }
507  if (pos != NPOS) {
508  // Found port - make sure it's numeric.
509  try {
510  x_SetPort(host.substr(pos + 1), *encoder);
511  }
512  catch (const CStringException&) {
514  "Invalid port value: \"" + orig_url + "\"", pos + 1);
515  }
516  host.resize(pos);
517  }
518  size_t scheme_svc_pos = NStr::Find(m_Scheme,
519  string("+") + NCBI_SCHEME_SERVICE,
521  if (scheme_svc_pos != NPOS && scheme_svc_pos > 0) {
522  x_SetScheme(m_Scheme.substr(0, scheme_svc_pos), *encoder);
523  x_SetService(host);
524  }
526  m_Scheme.clear();
527  x_SetService(host);
528  }
529  else {
530  x_SetHost(host, *encoder);
531  }
532  }
533  else {
534  // No authority, check scheme.
535  SIZE_TYPE scheme_end = orig_url.find(':');
536  if (scheme_end != NPOS) {
537  string scheme = orig_url.substr(0, scheme_end);
538  unparsed = orig_url.substr(scheme_end + 1);
539 
540  if (!x_IsHostPort(scheme, unparsed, *encoder)) {
541  x_SetScheme(orig_url.substr(0, scheme_end), *encoder);
542  }
543  }
544  else {
545  unparsed = orig_url;
546  }
547  }
548 
549  if ( unparsed.empty() ) return;
550  if (unparsed[0] == '/') {
551  // Path present
552  pos = unparsed.find_first_of("?#");
553  x_SetPath(unparsed.substr(0, pos), *encoder);
554  // No args/fragment
555  if (pos == NPOS) return;
556  unparsed = unparsed.substr(pos);
557  }
558 
559  _ASSERT(!unparsed.empty());
560  if (unparsed[0] == '?') {
561  // Arguments
562  pos = unparsed.find('#');
563  x_SetArgs(unparsed.substr(1, pos - 1), *encoder);
564  if (pos == NPOS) return;
565  unparsed = unparsed.substr(pos);
566  }
567  // Fragment
568  _ASSERT(!unparsed.empty());
569  if (unparsed[0] == '#') {
570  x_SetFragment(unparsed.substr(1), *encoder);
571  }
572  else {
573  // Non-generic URL - path does not contain /, no args or fragment.
574  // E.g. scheme:foo:bar
575  x_SetPath(unparsed, *encoder);
576  }
577 }
578 
579 
581  const IUrlEncoder* encoder) const
582 {
583  if ( !encoder ) {
584  encoder = GetDefaultEncoder();
585  }
586  string url;
587 
588  // Service- or host- name only require some special processing.
589  bool host_only = (IsService() || !m_Host.empty())
590  && m_Scheme.empty()
591  && !m_IsGeneric
592  && m_User.empty()
593  && m_Password.empty()
594  && m_Port.empty()
595  && m_Path.empty()
596  && m_Fragment.empty()
597  && !HaveArgs();
598  if (host_only && IsService()) {
599  // Do not add ncbilb:// if only service name is set.
601  }
602 
603  if ( !m_Scheme.empty() ) {
604  url += m_Scheme;
605  }
606  if (IsService() && m_Scheme != NCBI_SCHEME_SERVICE) {
607  if ( !m_Scheme.empty() ) {
608  url += "+";
609  }
610  url += NCBI_SCHEME_SERVICE;
611  }
612  if (IsService() || !m_Scheme.empty()) {
613  url += ":";
614  }
615 
616  if (host_only || m_IsGeneric || IsService()) {
617  url += "//";
618  }
619  bool have_user_info = false;
620  if ( !m_User.empty() ) {
621  url += encoder->EncodeUser(m_User);
622  have_user_info = true;
623  }
624  if ( !m_Password.empty() ) {
625  url += ":" + encoder->EncodePassword(m_Password);
626  have_user_info = true;
627  }
628  if ( have_user_info ) {
629  url += "@";
630  }
631  if ( IsService() ) {
633  }
634  else if ( !m_Host.empty() ) {
635  url += m_Host;
636  }
637  if ( !m_Port.empty() ) {
638  url += ":" + m_Port;
639  }
640  url += encoder->EncodePath(m_Path);
641  if ( HaveArgs() ) {
642  url += "?" + m_ArgsList->GetQueryString(amp_enc, encoder);
643  }
644  if ( !m_Fragment.empty() ) {
645  url += "#" + encoder->EncodeFragment(m_Fragment);
646  }
647  return url;
648 }
649 
650 
651 void CUrl::SetScheme(const string& value)
652 {
653  size_t pos = value.find(NCBI_SCHEME_SERVICE);
654  if (pos != NPOS
655  && (pos == 0 || value[pos - 1] == '+')
656  && value.substr(pos) == NCBI_SCHEME_SERVICE) {
657  // Strip "ncbilb" scheme, switch to service.
658  if (!IsService()) {
660  }
661  if (pos == 0) {
662  m_Scheme.clear();
663  }
664  else {
665  m_Scheme = value.substr(0, pos - 1);
666  }
667  }
668  else {
669  m_Scheme = value;
670  }
671 }
672 
673 
674 const CUrlArgs& CUrl::GetArgs(void) const
675 {
676  if ( !m_ArgsList.get() ) {
677  NCBI_THROW(CUrlException, eNoArgs,
678  "The URL has no arguments");
679  }
680  return *m_ArgsList;
681 }
682 
683 
684 void CUrl::Adjust(const CUrl& other, TAdjustFlags flags)
685 {
686  static const int fUser_Mask = fUser_Replace | fUser_ReplaceIfEmpty;
687  static const int fPassword_Mask = fPassword_Replace | fPassword_ReplaceIfEmpty;
688  static const int fPath_Mask = fPath_Replace | fPath_Append;
689  static const int fFragment_Mask = fFragment_Replace | fFragment_ReplaceIfEmpty;
690  static const int fArgs_Mask = fArgs_Replace | fArgs_Append | fArgs_Merge;
691 
692  if ( !other.m_Scheme.empty() ) {
693  if (flags & fScheme_Replace) {
694  m_Scheme = other.m_Scheme;
695  }
696  }
697 
698  if ((flags & fUser_Mask) == fUser_Mask) {
699  NCBI_THROW(CUrlException, eFlags, "Multiple fUser_* flags are set.");
700  }
701  if ( !other.m_User.empty() ) {
702  if ((flags & fUser_ReplaceIfEmpty) && m_User.empty()) {
703  m_User = other.m_User;
704  }
705  else if (flags & fUser_Replace) {
706  m_User = other.m_User;
707  }
708  }
709 
710  if ((flags & fPassword_Mask) == fPassword_Mask) {
711  NCBI_THROW(CUrlException, eFlags, "Multiple fPassword_* flags are set.");
712  }
713  if ( !other.m_Password.empty() ) {
714  if ((flags & fPassword_ReplaceIfEmpty) && m_Password.empty()) {
715  m_Password = other.m_Password;
716  }
717  else if (flags & fPassword_Replace) {
718  m_Password = other.m_Password;
719  }
720  }
721 
722  if ((flags & fPath_Mask) == fPath_Mask) {
723  NCBI_THROW(CUrlException, eFlags, "Multiple fPath_* flags are set.");
724  }
725  if (flags & fPath_Replace) {
726  m_Path = other.m_Path;
727  }
728  else if ((flags & fPath_Append) && !other.m_Path.empty()) {
729  if ( m_Path.empty() ) {
730  m_Path = other.m_Path;
731  }
732  else {
733  size_t other_p = 0;
734  if (m_Path.back() == '/' && other.m_Path.front() == '/') {
735  other_p = 1;
736  }
737  else if (m_Path.back() != '/' && other.m_Path.front() != '/') {
738  m_Path.append(1, '/');
739  }
740  m_Path.append(other.m_Path.substr(other_p));
741  }
742  }
743 
744  if ((flags & fFragment_Mask) == fFragment_Mask) {
745  NCBI_THROW(CUrlException, eFlags, "Multiple fFragment_* flags are set.");
746  }
747  if ( !other.m_Fragment.empty() ) {
748  if ((flags & fFragment_ReplaceIfEmpty) && m_Fragment.empty()) {
749  m_Fragment = other.m_Fragment;
750  }
751  else if (flags & fFragment_Replace) {
752  m_Fragment = other.m_Fragment;
753  }
754  }
755 
756  switch (flags & fArgs_Mask) {
757  case 0:
758  break;
759  case fArgs_Replace:
760  m_OrigArgs = other.m_OrigArgs;
761  if ( other.m_ArgsList.get() ) {
762  m_ArgsList.reset(new CUrlArgs(*other.m_ArgsList));
763  } else {
764  m_ArgsList.reset();
765  }
766  break;
767  case fArgs_Append:
768  if ( other.m_ArgsList.get() ) {
769  if ( m_ArgsList.get() ) {
770  ITERATE(CUrlArgs::TArgs, it, other.m_ArgsList->GetArgs()) {
771  m_ArgsList->AddValue(it->name, it->value);
772  }
773  }
774  else {
775  m_ArgsList.reset(new CUrlArgs(*other.m_ArgsList));
776  }
777  }
778  break;
779  case fArgs_Merge:
780  {
781  unique_ptr<CUrlArgs> args(m_ArgsList.release());
782  m_ArgsList.reset(new CUrlArgs());
783  if ( args.get() ) {
784  // Copy existing arguments, if any, removing duplicate entries.
785  ITERATE(CUrlArgs::TArgs, it, args->GetArgs()) {
786  m_ArgsList->SetUniqueValue(it->name, it->value);
787  }
788  }
789  if ( other.m_ArgsList.get() ) {
790  ITERATE(CUrlArgs::TArgs, it, other.m_ArgsList->GetArgs()) {
791  m_ArgsList->SetUniqueValue(it->name, it->value);
792  }
793  }
794  break;
795  }
796  default:
797  // Several flags are set.
798  NCBI_THROW(CUrlException, eFlags, "Multiple fArgs_* flags are set.");
799  }
800 }
801 
802 
803 //////////////////////////////////////////////////////////////////////////////
804 //
805 // Url encode/decode
806 //
807 
809 {
810  static CSafeStatic<CDefaultUrlEncoder> s_DefaultEncoder;
811  return &s_DefaultEncoder.Get();
812 }
813 
814 
815 bool CUrl::IsEmpty(void) const
816 {
817  // At least one of host, service or path must be present.
818  return m_Host.empty() && !IsService() && m_Path.empty();
819 }
820 
821 
Default encoder, uses the selected encoding for argument names/values and eUrlEncode_Path for documen...
Definition: ncbi_url.hpp:124
CSafeStatic<>::
T & Get(void)
Create the variable if not created yet, return the reference.
CStringException –.
Definition: ncbistr.hpp:4500
CUrlArgs_Parser::
Definition: ncbi_url.hpp:170
CUrlArgs::
Definition: ncbi_url.hpp:240
CUrlException –.
Definition: ncbi_url.hpp:511
CUrlParserException –.
Definition: ncbi_url.hpp:539
CUrl –.
Definition: ncbi_url.hpp:353
IUrlEncoder::
Definition: ncbi_url.hpp:57
NStr –.
Definition: ncbistr.hpp:243
URL parsing classes.
static uch flags
#define false
Definition: bool.h:36
static char tmp[3200]
Definition: utf8.c:42
int offset
Definition: replacements.h:160
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
NCBI_DEPRECATED_CLASS NCBI_XCGI_EXPORT EUrlEncode decode
Definition: cgi_util.hpp:111
NCBI_DEPRECATED_CLASS NCBI_XCGI_EXPORT EUrlEncode encode
Definition: cgi_util.hpp:98
#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_THROW2(exception_class, err_code, message, extra)
Throw exception with extra parameter.
Definition: ncbiexpt.hpp:1754
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:132
#define kEmptyStr
Definition: ncbistr.hpp:123
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
Definition: ncbistr.cpp:219
EUrlEncode
URL-encode flags.
Definition: ncbistr.hpp:3143
#define NPOS
Definition: ncbistr.hpp:133
static SIZE_TYPE Find(const CTempString str, const CTempString pattern, ECase use_case=eCase, EDirection direction=eForwardSearch, SIZE_TYPE occurrence=0)
Find the pattern in the string.
Definition: ncbistr.cpp:2882
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
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 URLEncode(const CTempString str, EUrlEncode flag=eUrlEnc_SkipMarkChars)
URL-encode string.
Definition: ncbistr.cpp:6053
static string & ToLower(string &str)
Convert string to lower case – string& version.
Definition: ncbistr.cpp:405
@ eUrlEnc_ProcessMarkChars
Convert all non-alphanumeric chars, spaces are converted to '+'.
Definition: ncbistr.hpp:3145
@ eReverseSearch
Search in a backward direction.
Definition: ncbistr.hpp:1947
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
string GetQueryString(EAmpEncoding amp_enc, NStr::EUrlEncode encode) const
Construct and return complete query string.
Definition: ncbi_url.cpp:225
const string & GetHost(void) const
Definition: ncbi_url.hpp:411
const CUrlArgs & GetArgs(void) const
Get const list of arguments.
Definition: ncbi_url.cpp:674
string m_Port
Definition: ncbi_url.hpp:495
SUrlArg TArg
Definition: ncbi_url.hpp:275
string m_Host
Definition: ncbi_url.hpp:493
string m_User
Definition: ncbi_url.hpp:491
CUrl(void)
Default constructor.
Definition: Url.hpp:92
void Adjust(const CUrl &other, TAdjustFlags flags)
Adjust this URL using information from 'other' URL.
Definition: ncbi_url.cpp:684
void x_SetPort(const string &port, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:619
string m_Fragment
Definition: ncbi_url.hpp:497
EAmpEncoding
Ampersand encoding for composed URLs.
Definition: ncbi_url.hpp:253
virtual string EncodeFragment(const string &value) const =0
Encode fragment.
void x_SetPassword(const string &password, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:598
string m_Scheme
Definition: ncbi_url.hpp:489
string m_OrigArgs
Definition: ncbi_url.hpp:498
virtual string EncodeUser(const string &user) const =0
Encode user name.
void AddValue(const string &name, const string &value)
Add new value even if an argument with the same name already exists.
Definition: ncbi_url.cpp:283
int TAdjustFlags
Definition: ncbi_url.hpp:467
bool m_IsIndex
Definition: ncbi_url.hpp:338
void x_SetService(const string &service)
Definition: ncbi_url.hpp:613
TArgs::const_iterator const_iterator
Definition: ncbi_url.hpp:278
int TFlags
An inverted subset of CCgiRequest::TFlags.
Definition: ncbi_url.hpp:174
virtual void AddArgument(unsigned int position, const string &name, const string &value, EArgType arg_type)
Process next query argument.
Definition: ncbi_url.cpp:210
void x_SetUser(const string &user, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:591
CUrlArgs(TFlags flags=0)
Create an empty arguments set.
Definition: ncbi_url.cpp:183
void x_SetFragment(const string &fragment, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:634
#define NCBI_SCHEME_SERVICE
CUrl::
Definition: ncbi_url.hpp:350
bool HaveArgs(void) const
Check if the URL contains any arguments.
Definition: ncbi_url.hpp:431
virtual string DecodeArgName(const string &name) const =0
Decode URL argument name.
CUrl & operator=(const CUrl &url)
Definition: ncbi_url.cpp:352
void x_SetPath(const string &path, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:627
string m_Service
Definition: ncbi_url.hpp:494
iterator FindNext(const iterator &iter)
Take argument name from the iterator, find next argument with the same name, return GetArgs()....
Definition: ncbi_url.hpp:683
void SetQueryString(const string &query, NStr::EUrlEncode encode)
Parse query string, call AddArgument() to store each value.
Definition: ncbi_url.cpp:49
NStr::ECase m_Case
Definition: ncbi_url.hpp:337
string m_Password
Definition: ncbi_url.hpp:492
static IUrlEncoder * GetDefaultEncoder(void)
Return default URL encoder.
Definition: ncbi_url.cpp:808
void x_SetScheme(const string &scheme, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:584
const string & GetValue(const string &name, bool *is_found=0) const
Get value for the given name.
Definition: ncbi_url.cpp:256
bool m_IsGeneric
Definition: ncbi_url.hpp:490
string m_Path
Definition: ncbi_url.hpp:496
void x_SetHost(const string &host, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:605
void x_SetIndexString(const string &query, const IUrlEncoder &encoder)
Definition: ncbi_url.cpp:57
bool x_IsHostPort(const string &scheme, string &unparsed, const IUrlEncoder &encoder)
Definition: ncbi_url.cpp:375
virtual string EncodePath(const string &path) const =0
Encode path on server.
virtual string EncodePassword(const string &password) const =0
Encode password.
list< TArg > TArgs
Definition: ncbi_url.hpp:276
void x_SetArgs(const string &args, const IUrlEncoder &encoder)
Definition: ncbi_url.hpp:641
virtual string EncodeArgName(const string &name) const =0
Encode URL argument name.
TArgs m_Args
Definition: ncbi_url.hpp:339
bool IsEmpty(void) const
Definition: ncbi_url.cpp:815
TArgs::iterator iterator
Definition: ncbi_url.hpp:277
virtual string EncodeArgValue(const string &value) const =0
Encode URL argument value.
iterator x_Find(const string &name, const iterator &start)
Definition: ncbi_url.cpp:303
void SetValue(const string &name, const string &value)
Set new value for the first argument with the given name or add a new argument.
Definition: ncbi_url.cpp:270
void SetUniqueValue(const string &name, const string &value)
Set value, remove any other values for the name.
Definition: ncbi_url.cpp:290
iterator FindFirst(const string &name)
Find the first argument with the given name.
Definition: ncbi_url.hpp:667
void SetScheme(const string &value)
Definition: ncbi_url.cpp:651
virtual string DecodeArgValue(const string &value) const =0
Decode URL argument value.
virtual void AddArgument(unsigned int position, const string &name, const string &value, EArgType arg_type=eArg_Index)=0
Process next query argument.
bool IsService(void) const
Definition: ncbi_url.hpp:414
unique_ptr< CUrlArgs > m_ArgsList
Definition: ncbi_url.hpp:499
string ComposeUrl(CUrlArgs::EAmpEncoding amp_enc, const IUrlEncoder *encoder=0) const
Compose the URL.
Definition: ncbi_url.cpp:580
EArgType
Query type flag.
Definition: ncbi_url.hpp:203
@ eAmp_Char
Use & to separate arguments.
Definition: ncbi_url.hpp:254
@ fPassword_ReplaceIfEmpty
Replace password only if not yet set.
Definition: ncbi_url.hpp:456
@ fScheme_Replace
Replace scheme if set in 'other'.
Definition: ncbi_url.hpp:465
@ fFragment_Replace
Replace fragment if set in 'other'.
Definition: ncbi_url.hpp:459
@ fUser_Replace
Replace user if set in 'other'.
Definition: ncbi_url.hpp:453
@ fPath_Replace
Replace path.
Definition: ncbi_url.hpp:457
@ fFragment_ReplaceIfEmpty
Replace fragment only if not yet set.
Definition: ncbi_url.hpp:460
@ fPassword_Replace
Replace password if set in 'other'.
Definition: ncbi_url.hpp:455
@ fArgs_Append
Append args, allow duplicate names and values.
Definition: ncbi_url.hpp:462
@ fPath_Append
Append new path to the existing one.
Definition: ncbi_url.hpp:458
@ fUser_ReplaceIfEmpty
Replace user only if not yet set.
Definition: ncbi_url.hpp:454
@ fArgs_Merge
Append new args; replace values of existing args, do not allow to set multiple values with the same n...
Definition: ncbi_url.hpp:463
@ fArgs_Replace
Discard all args, replace with args from 'other'.
Definition: ncbi_url.hpp:461
@ fEnableParsingAsIndex
Enable parsing input as 'indexed' query (RFC3875) when no '=' is present.
Definition: ncbi_url.hpp:179
@ fSemicolonIsArgDelimiter
Treat semicolon as query string argument separator.
Definition: ncbi_url.hpp:177
@ eArg_Index
Query contains a list of names: name1+name2+name3.
Definition: ncbi_url.hpp:205
@ eArg_Value
Query contains name=value pairs.
Definition: ncbi_url.hpp:204
int len
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
NCBI_PARAM_DEF(bool, CUrl, enable_parsing_as_index, false)
typedef NCBI_PARAM_TYPE(CUrl, enable_parsing_as_index) TCUrlEnableParsingAsIndex
NCBI_PARAM_DECL(bool, CUrl, enable_parsing_as_index)
Defines unified interface to application:
static string query
#define _ASSERT
Modified on Fri Sep 20 14:57:01 2024 by modify_doxy.py rev. 669887