libzypp  11.13.5
Url.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include "zypp/Url.h"
14 #include "zypp/Pathname.h"
15 #include "zypp/base/Gettext.h"
16 #include "zypp/base/String.h"
17 #include "zypp/base/Regex.h"
18 #include <stdexcept>
19 #include <iostream>
20 
21 
23 namespace zypp
24 {
25 
26 
27  using namespace zypp::url;
28 
29 
30  // -----------------------------------------------------------------
31  /*
32  * url = [scheme:] [//authority] /path [?query] [#fragment]
33  */
34  #define RX_SPLIT_URL "^([^:/?#]+:|)" \
35  "(//[^/?#]*|)" \
36  "([^?#]*)" \
37  "([?][^#]*|)" \
38  "(#.*|)"
39 
40 
42  namespace
43  {
44 
45 
46  // ---------------------------------------------------------------
47  class LDAPUrl: public UrlBase
48  {
49  public:
50  LDAPUrl(): UrlBase()
51  {
52  configure();
53  }
54 
55  LDAPUrl(const LDAPUrl &url): UrlBase(url)
56  {}
57 
58  virtual UrlBase *
59  clone() const
60  {
61  return new LDAPUrl(*this);
62  }
63 
64  virtual UrlSchemes
65  getKnownSchemes() const
66  {
67  UrlSchemes schemes(2);
68  schemes[0] = "ldap";
69  schemes[1] = "ldaps";
70  return schemes;
71  }
72 
73  virtual void
74  configure()
75  {
76  config("sep_pathparams", "");
77 
78  config("psep_querystr", "?");
79  config("vsep_querystr", "");
80 
81  // host is required (isValid=>false)
82  // but not mandatory (see RFC 2255),
83  // that is, accept empty host.
84  config("require_host", "y");
85 
86  // not allowed here
87  config("rx_username", "");
88  config("rx_password", "");
89  config("rx_fragment", "");
90  config("rx_pathparams", "");
91  }
92 
93  virtual zypp::url::ParamMap
94  getQueryStringMap(zypp::url::EEncoding eflag) const
95  {
96  static const char * const keys[] = {
97  "attrs", "scope", "filter", "exts", NULL
98  };
100  zypp::url::ParamVec pvec( getQueryStringVec());
101  if( pvec.size() <= 4)
102  {
103  for(size_t i=0; i<pvec.size(); i++)
104  {
105  if(eflag == zypp::url::E_ENCODED)
106  pmap[keys[i]] = pvec[i];
107  else
108  pmap[keys[i]] = zypp::url::decode( pvec[i]);
109  }
110  }
111  else
112  {
113  ZYPP_THROW(url::UrlNotSupportedException(
114  _("Invalid LDAP URL query string")
115  ));
116  }
117  return pmap;
118  }
119 
120  virtual void
121  setQueryStringMap(const zypp::url::ParamMap &pmap)
122  {
123  static const char * const keys[] = {
124  "attrs", "scope", "filter", "exts", NULL
125  };
126 
127  // remove psep ("?") from safe chars
128  std::string join_safe;
129  std::string safe(config("safe_querystr"));
130  std::string psep(config("psep_querystr"));
131  for(std::string::size_type i=0; i<safe.size(); i++)
132  {
133  if( psep.find(safe[i]) == std::string::npos)
134  join_safe.append(1, safe[i]);
135  }
136 
137  zypp::url::ParamVec pvec(4);
138  zypp::url::ParamMap::const_iterator p;
139  for(p=pmap.begin(); p!=pmap.end(); ++p)
140  {
141  bool found=false;
142  for(size_t i=0; i<4; i++)
143  {
144  if(p->first == keys[i])
145  {
146  found=true;
147  pvec[i] = zypp::url::encode(p->second, join_safe);
148  }
149  }
150  if( !found)
151  {
152  ZYPP_THROW(url::UrlNotSupportedException(
153  str::form(_("Invalid LDAP URL query parameter '%s'"),
154  p->first.c_str())
155  ));
156  }
157  }
158  setQueryStringVec(pvec);
159  }
160  };
161 
162 
163  // ---------------------------------------------------------------
164  // FIXME: hmm..
165  class UrlByScheme
166  {
167  private:
168  typedef std::map<std::string,UrlRef> UrlBySchemeMap;
169  UrlBySchemeMap urlByScheme;
170 
171  public:
172  UrlByScheme()
173  {
174  UrlRef ref;
175 
176  // =====================================
177  ref.reset( new LDAPUrl());
178  addUrlByScheme("ldap", ref);
179  addUrlByScheme("ldaps", ref);
180 
181 
182  // =====================================
183  ref.reset( new UrlBase());
184  ref->config("with_authority", "n"); // disallow host,...
185  ref->config("require_pathname", "m"); // path is mandatory
186  addUrlByScheme("hd", ref);
187  addUrlByScheme("cd", ref);
188  addUrlByScheme("dvd", ref);
189  addUrlByScheme("dir", ref);
190  addUrlByScheme("iso", ref);
191 
192  // don't show empty authority
195  addUrlByScheme("mailto", ref);
196  addUrlByScheme("urn", ref);
197  addUrlByScheme("plugin", ref); // zypp plugable media handler:
198 
199  // RFC1738, 3.10: may contain a host
200  ref->config("with_authority", "y"); // allow host,
201  ref->config("with_port", "n"); // but no port,
202  ref->config("rx_username", ""); // username or
203  ref->config("rx_password", ""); // password ...
204  addUrlByScheme("file", ref);
205 
206  // =====================================
207  ref.reset( new UrlBase());
208  ref->config("require_host", "m"); // host is mandatory
209  addUrlByScheme("nfs", ref);
210  addUrlByScheme("nfs4", ref);
211  addUrlByScheme("smb", ref);
212  addUrlByScheme("cifs", ref);
213  addUrlByScheme("http", ref);
214  addUrlByScheme("https", ref);
215  ref->config("path_encode_slash2", "y"); // always encode 2. slash
216  addUrlByScheme("ftp", ref);
217  addUrlByScheme("sftp", ref);
218  addUrlByScheme("tftp", ref);
219  }
220 
221  bool
222  addUrlByScheme(const std::string &scheme,
223  UrlRef urlImpl)
224  {
225  if( urlImpl && urlImpl->isValidScheme(scheme))
226  {
227  UrlRef ref(urlImpl);
228  ref->clear();
229  urlByScheme[str::toLower(scheme)] = ref;
230  return true;
231  }
232  return false;
233  }
234 
235  UrlRef
236  getUrlByScheme(const std::string &scheme) const
237  {
238  UrlBySchemeMap::const_iterator i(urlByScheme.find(str::toLower(scheme)));
239  if( i != urlByScheme.end())
240  {
241  return i->second;
242  }
243  return UrlRef();
244  }
245 
246  bool
247  isRegisteredScheme(const std::string &scheme) const
248  {
249  return urlByScheme.find(str::toLower(scheme)) != urlByScheme.end();
250  }
251 
252  UrlSchemes
253  getRegisteredSchemes() const
254  {
255  UrlBySchemeMap::const_iterator i(urlByScheme.begin());
256  UrlSchemes schemes;
257 
258  schemes.reserve(urlByScheme.size());
259  for( ; i != urlByScheme.end(); ++i)
260  {
261  schemes.push_back(i->first);
262  }
263  return schemes;
264  }
265  };
266 
267 
268  // ---------------------------------------------------------------
269  UrlByScheme & g_urlSchemeRepository()
270  {
271  static UrlByScheme _v;
272  return _v;
273  }
274 
276  } // anonymous namespace
278 
279 
280  // -----------------------------------------------------------------
282  {
283  }
284 
285 
286  // -----------------------------------------------------------------
288  : m_impl( new UrlBase())
289  {
290  }
291 
292 
293  // -----------------------------------------------------------------
294  Url::Url(const Url &url)
295  : m_impl( url.m_impl)
296  {
297  if( !m_impl)
298  {
300  _("Unable to clone Url object")
301  ));
302  }
303  }
304 
305 
306  // -----------------------------------------------------------------
308  : m_impl( url)
309  {
310  if( !m_impl)
311  {
313  _("Invalid empty Url object reference")
314  ));
315  }
316  }
317 
318 
319  // -----------------------------------------------------------------
320  Url::Url(const std::string &encodedUrl)
321  : m_impl( parseUrl(encodedUrl))
322  {
323  if( !m_impl)
324  {
326  _("Unable to parse Url components")
327  ));
328  }
329  }
330 
331 
332  // -----------------------------------------------------------------
333  Url&
334  Url::operator = (const std::string &encodedUrl)
335  {
336  UrlRef url( parseUrl(encodedUrl));
337  if( !url)
338  {
340  _("Unable to parse Url components")
341  ));
342  }
343  m_impl = url;
344  return *this;
345  }
346 
347 
348  // -----------------------------------------------------------------
349  Url&
351  {
352  m_impl = url.m_impl;
353  return *this;
354  }
355 
356 
357  // -----------------------------------------------------------------
358  // static
359  bool
360  Url::registerScheme(const std::string &scheme,
361  UrlRef urlImpl)
362  {
363  return g_urlSchemeRepository().addUrlByScheme(scheme, urlImpl);
364  }
365 
366 
367  // -----------------------------------------------------------------
368  // static
369  UrlRef
370  Url::parseUrl(const std::string &encodedUrl)
371  {
372  UrlRef url;
373  str::smatch out;
374  bool ret = false;
375 
376  try
377  {
379  ret = str::regex_match(encodedUrl, out, rex);
380  }
381  catch( ... )
382  {}
383 
384  if(ret && out.size() == 6)
385  {
386  std::string scheme = out[1];
387  if (scheme.size() > 1)
388  scheme = scheme.substr(0, scheme.size()-1);
389  std::string authority = out[2];
390  if (authority.size() >= 2)
391  authority = authority.substr(2);
392  std::string query = out[4];
393  if (query.size() > 1)
394  query = query.substr(1);
395  std::string fragment = out[5];
396  if (fragment.size() > 1)
397  fragment = fragment.substr(1);
398 
399  url = g_urlSchemeRepository().getUrlByScheme(scheme);
400  if( !url)
401  {
402  url.reset( new UrlBase());
403  }
404  url->init(scheme, authority, out[3],
405  query, fragment);
406  }
407  return url;
408  }
409 
410 
411  // -----------------------------------------------------------------
412  // static
415  {
416  return g_urlSchemeRepository().getRegisteredSchemes();
417  }
418 
419 
420  // -----------------------------------------------------------------
421  // static
422  bool
423  Url::isRegisteredScheme(const std::string &scheme)
424  {
425  return g_urlSchemeRepository().isRegisteredScheme(scheme);
426  }
427 
428 
429  // -----------------------------------------------------------------
432  {
433  return m_impl->getKnownSchemes();
434  }
435 
436 
437  // -----------------------------------------------------------------
438  bool
439  Url::isValidScheme(const std::string &scheme) const
440  {
441  return m_impl->isValidScheme(scheme);
442  }
443 
444 
446  namespace
447  {
448  inline bool isInList( const char ** begin_r, const char ** end_r, const std::string & scheme_r )
449  {
450  for ( ; begin_r != end_r; ++begin_r )
451  if ( scheme_r == *begin_r )
452  return true;
453  return false;
454  }
455  }
456  bool Url::schemeIsLocal( const std::string & scheme_r )
457  {
458  static const char * val[] = { "cd", "dvd", "dir", "hd", "iso", "file" };
459  return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
460  }
461 
462  bool Url::schemeIsRemote( const std::string & scheme_r )
463  {
464  static const char * val[] = { "http", "https", "nfs", "nfs4", "smb", "cifs", "ftp", "sftp", "tftp" };
465  return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
466  }
467 
468  bool Url::schemeIsVolatile( const std::string & scheme_r )
469  {
470  static const char * val[] = { "cd", "dvd" };
471  return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
472  }
473 
474  bool Url::schemeIsDownloading( const std::string & scheme_r )
475  {
476  static const char * val[] = { "http", "https", "ftp", "sftp", "tftp" };
477  return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
478  }
480 
481  // -----------------------------------------------------------------
482  bool
483  Url::isValid() const
484  {
485  return m_impl->isValid();
486  }
487 
488 
489  // -----------------------------------------------------------------
490  std::string
492  {
493  return m_impl->asString();
494  }
495 
496 
497  // -----------------------------------------------------------------
498  std::string
500  {
501  // make sure, all url components are included;
502  // regardless of the current configuration...
503  ViewOptions opts(getViewOptions() +
513  return m_impl->asString(opts);
514  }
515 
516 
517  // -----------------------------------------------------------------
518  std::string
519  Url::asString(const ViewOptions &opts) const
520  {
521  return m_impl->asString(opts);
522  }
523 
524 
525  // -----------------------------------------------------------------
526  std::string
528  {
529  return m_impl->getScheme();
530  }
531 
532 
533  // -----------------------------------------------------------------
534  std::string
536  {
537  return m_impl->getAuthority();
538  }
539 
540  // -----------------------------------------------------------------
541  std::string
543  {
544  return m_impl->getPathData();
545  }
546 
547 
548  // -----------------------------------------------------------------
549  std::string
551  {
552  return m_impl->getQueryString();
553  }
554 
555 
556  // -----------------------------------------------------------------
557  std::string
559  {
560  return m_impl->getFragment(eflag);
561  }
562 
563 
564  // -----------------------------------------------------------------
565  std::string
567  {
568  return m_impl->getUsername(eflag);
569  }
570 
571 
572  // -----------------------------------------------------------------
573  std::string
575  {
576  return m_impl->getPassword(eflag);
577  }
578 
579 
580  // -----------------------------------------------------------------
581  std::string
582  Url::getHost(EEncoding eflag) const
583  {
584  return m_impl->getHost(eflag);
585  }
586 
587 
588  // -----------------------------------------------------------------
589  std::string
590  Url::getPort() const
591  {
592  return m_impl->getPort();
593  }
594 
595 
596  // -----------------------------------------------------------------
597  std::string
599  {
600  return m_impl->getPathName(eflag);
601  }
602 
603 
604  // -----------------------------------------------------------------
605  std::string
607  {
608  return m_impl->getPathParams();
609  }
610 
611 
612  // -----------------------------------------------------------------
615  {
616  return m_impl->getPathParamsVec();
617  }
618 
619 
620  // -----------------------------------------------------------------
623  {
624  return m_impl->getPathParamsMap(eflag);
625  }
626 
627 
628  // -----------------------------------------------------------------
629  std::string
630  Url::getPathParam(const std::string &param, EEncoding eflag) const
631  {
632  return m_impl->getPathParam(param, eflag);
633  }
634 
635 
636  // -----------------------------------------------------------------
639  {
640  return m_impl->getQueryStringVec();
641  }
642 
643 
644  // -----------------------------------------------------------------
647  {
648  return m_impl->getQueryStringMap(eflag);
649  }
650 
651 
652  // -----------------------------------------------------------------
653  std::string
654  Url::getQueryParam(const std::string &param, EEncoding eflag) const
655  {
656  return m_impl->getQueryParam(param, eflag);
657  }
658 
659 
660  // -----------------------------------------------------------------
661  void
662  Url::setScheme(const std::string &scheme)
663  {
664  if(scheme == m_impl->getScheme())
665  {
666  return;
667  }
668  if( m_impl->isKnownScheme(scheme))
669  {
670  m_impl->setScheme(scheme);
671  return;
672  }
673 
674  UrlRef url = g_urlSchemeRepository().getUrlByScheme(scheme);
675  if( !url)
676  {
677  url.reset( new UrlBase());
678  }
679  url->init(
680  scheme,
681  m_impl->getAuthority(),
682  m_impl->getPathData(),
685  );
686  m_impl = url;
687  }
688 
689 
690  // -----------------------------------------------------------------
691  void
692  Url::setAuthority(const std::string &authority)
693  {
694  m_impl->setAuthority(authority);
695  }
696 
697 
698  // -----------------------------------------------------------------
699  void
700  Url::setPathData(const std::string &pathdata)
701  {
702  m_impl->setPathData(pathdata);
703  }
704 
705 
706  // -----------------------------------------------------------------
707  void
708  Url::setQueryString(const std::string &querystr)
709  {
710  m_impl->setQueryString(querystr);
711  }
712 
713 
714  // -----------------------------------------------------------------
715  void
716  Url::setFragment(const std::string &fragment, EEncoding eflag)
717  {
718  m_impl->setFragment(fragment, eflag);
719  }
720 
721 
722  // -----------------------------------------------------------------
723  void
724  Url::setUsername(const std::string &user,
725  EEncoding eflag)
726  {
727  m_impl->setUsername(user, eflag);
728  }
729 
730 
731  // -----------------------------------------------------------------
732  void
733  Url::setPassword(const std::string &pass,
734  EEncoding eflag)
735  {
736  m_impl->setPassword(pass, eflag);
737  }
738 
739 
740  // -----------------------------------------------------------------
741  void
742  Url::setHost(const std::string &host)
743  {
744  m_impl->setHost(host);
745  }
746 
747 
748  // -----------------------------------------------------------------
749  void
750  Url::setPort(const std::string &port)
751  {
752  m_impl->setPort(port);
753  }
754 
755 
756  // -----------------------------------------------------------------
757  void
758  Url::setPathName(const std::string &path,
759  EEncoding eflag)
760  {
761  m_impl->setPathName(path, eflag);
762  }
763 
764  void
765  Url::setPathName(const Pathname &path,
766  EEncoding eflag)
767  {
768  m_impl->setPathName(path.asString(), eflag);
769  }
770 
771  void
772  Url::setPathName(const char *path,
773  EEncoding eflag)
774  {
775  m_impl->setPathName(path, eflag);
776  }
777 
778  // -----------------------------------------------------------------
779  void
780  Url::setPathParams(const std::string &params)
781  {
782  m_impl->setPathParams(params);
783  }
784 
785 
786  // -----------------------------------------------------------------
787  void
789  {
790  m_impl->setPathParamsVec(pvec);
791  }
792 
793 
794  // -----------------------------------------------------------------
795  void
797  {
798  m_impl->setPathParamsMap(pmap);
799  }
800 
801 
802  // -----------------------------------------------------------------
803  void
804  Url::setPathParam(const std::string &param, const std::string &value)
805  {
806  m_impl->setPathParam(param, value);
807  }
808 
809 
810  // -----------------------------------------------------------------
811  void
813  {
814  m_impl->setQueryStringVec(pvec);
815  }
816 
817 
818  // -----------------------------------------------------------------
819  void
821  {
822  m_impl->setQueryStringMap(pmap);
823  }
824 
825  // -----------------------------------------------------------------
826  void
827  Url::setQueryParam(const std::string &param, const std::string &value)
828  {
829  m_impl->setQueryParam(param, value);
830  }
831 
832  // -----------------------------------------------------------------
833  void
834  Url::delQueryParam(const std::string &param)
835  {
836  m_impl->delQueryParam(param);
837  }
838 
839  // -----------------------------------------------------------------
842  {
843  return m_impl->getViewOptions();
844  }
845 
846  // -----------------------------------------------------------------
847  void
849  {
850  m_impl->setViewOptions(vopts);
851  }
852 
853  // -----------------------------------------------------------------
854  std::ostream & operator<<( std::ostream & str, const Url & url )
855  {
856  return str << url.asString();
857  }
858 
859  bool operator<( const Url &lhs, const Url &rhs )
860  {
861  return (lhs.asCompleteString() < rhs.asCompleteString());
862  }
863 
864  bool operator==( const Url &lhs, const Url &rhs )
865  {
866  return (lhs.asCompleteString() == rhs.asCompleteString());
867  }
868 
869  bool operator!=( const Url &lhs, const Url &rhs )
870  {
871  return (lhs.asCompleteString() != rhs.asCompleteString());
872  }
873 
875 } // namespace zypp
877 /*
878 ** vim: set ts=2 sts=2 sw=2 ai et:
879 */