00001
00002
00003
00004
00005
00006
00007
00008
00013 #include <zypp/Url.h>
00014 #include <zypp/base/Gettext.h>
00015 #include <zypp/base/String.h>
00016 #include <zypp/base/Regex.h>
00017 #include <stdexcept>
00018 #include <iostream>
00019
00020
00022 namespace zypp
00023 {
00024
00025
00026 using namespace zypp::url;
00027
00028
00029
00030
00031
00032
00033 #define RX_SPLIT_URL "^([^:/?#]+:|)" \
00034 "(//[^/?#]*|)" \
00035 "([^?#]*)" \
00036 "([?][^#]*|)" \
00037 "(#.*|)"
00038
00039
00041 namespace
00042 {
00043
00044
00045
00046 class LDAPUrl: public UrlBase
00047 {
00048 public:
00049 LDAPUrl(): UrlBase()
00050 {
00051 configure();
00052 }
00053
00054 LDAPUrl(const LDAPUrl &url): UrlBase(url)
00055 {}
00056
00057 virtual UrlBase *
00058 clone() const
00059 {
00060 return new LDAPUrl(*this);
00061 }
00062
00063 virtual UrlSchemes
00064 getKnownSchemes() const
00065 {
00066 UrlSchemes schemes(2);
00067 schemes[0] = "ldap";
00068 schemes[1] = "ldaps";
00069 return schemes;
00070 }
00071
00072 virtual void
00073 configure()
00074 {
00075 config("sep_pathparams", "");
00076
00077 config("psep_querystr", "?");
00078 config("vsep_querystr", "");
00079
00080
00081
00082
00083 config("require_host", "y");
00084
00085
00086 config("rx_username", "");
00087 config("rx_password", "");
00088 config("rx_fragment", "");
00089 config("rx_pathparams", "");
00090 }
00091
00092 virtual zypp::url::ParamMap
00093 getQueryStringMap(zypp::url::EEncoding eflag) const
00094 {
00095 static const char * const keys[] = {
00096 "attrs", "scope", "filter", "exts", NULL
00097 };
00098 zypp::url::ParamMap pmap;
00099 zypp::url::ParamVec pvec( getQueryStringVec());
00100 if( pvec.size() <= 4)
00101 {
00102 for(size_t i=0; i<pvec.size(); i++)
00103 {
00104 if(eflag == zypp::url::E_ENCODED)
00105 pmap[keys[i]] = pvec[i];
00106 else
00107 pmap[keys[i]] = zypp::url::decode( pvec[i]);
00108 }
00109 }
00110 else
00111 {
00112 ZYPP_THROW(url::UrlNotSupportedException(
00113 _("Invalid LDAP URL query string")
00114 ));
00115 }
00116 return pmap;
00117 }
00118
00119 virtual void
00120 setQueryStringMap(const zypp::url::ParamMap &pmap)
00121 {
00122 static const char * const keys[] = {
00123 "attrs", "scope", "filter", "exts", NULL
00124 };
00125
00126
00127 std::string join_safe;
00128 std::string safe(config("safe_querystr"));
00129 std::string psep(config("psep_querystr"));
00130 for(std::string::size_type i=0; i<safe.size(); i++)
00131 {
00132 if( psep.find(safe[i]) == std::string::npos)
00133 join_safe.append(1, safe[i]);
00134 }
00135
00136 zypp::url::ParamVec pvec(4);
00137 zypp::url::ParamMap::const_iterator p;
00138 for(p=pmap.begin(); p!=pmap.end(); ++p)
00139 {
00140 bool found=false;
00141 for(size_t i=0; i<4; i++)
00142 {
00143 if(p->first == keys[i])
00144 {
00145 found=true;
00146 pvec[i] = zypp::url::encode(p->second, join_safe);
00147 }
00148 }
00149 if( !found)
00150 {
00151 ZYPP_THROW(url::UrlNotSupportedException(
00152 str::form(_("Invalid LDAP URL query parameter '%s'"),
00153 p->first.c_str())
00154 ));
00155 }
00156 }
00157 setQueryStringVec(pvec);
00158 }
00159 };
00160
00161
00162
00163
00164 class UrlByScheme
00165 {
00166 private:
00167 typedef std::map<std::string,UrlRef> UrlBySchemeMap;
00168 UrlBySchemeMap urlByScheme;
00169
00170 public:
00171 UrlByScheme()
00172 {
00173 UrlRef ref;
00174
00175
00176 ref.reset( new LDAPUrl());
00177 addUrlByScheme("ldap", ref);
00178 addUrlByScheme("ldaps", ref);
00179
00180
00181
00182 ref.reset( new UrlBase());
00183 ref->config("with_authority", "n");
00184 ref->config("require_pathname", "m");
00185 addUrlByScheme("hd", ref);
00186 addUrlByScheme("cd", ref);
00187 addUrlByScheme("dvd", ref);
00188 addUrlByScheme("dir", ref);
00189 addUrlByScheme("iso", ref);
00190
00191
00192 ref->setViewOptions( zypp::url::ViewOption::DEFAULTS -
00193 zypp::url::ViewOption::EMPTY_AUTHORITY);
00194 addUrlByScheme("mailto", ref);
00195 addUrlByScheme("urn", ref);
00196 addUrlByScheme("plugin", ref);
00197
00198
00199 ref->config("with_authority", "y");
00200 ref->config("with_port", "n");
00201 ref->config("rx_username", "");
00202 ref->config("rx_password", "");
00203 addUrlByScheme("file", ref);
00204
00205
00206 ref.reset( new UrlBase());
00207 ref->config("require_host", "m");
00208 addUrlByScheme("nfs", ref);
00209 addUrlByScheme("nfs4", ref);
00210 addUrlByScheme("smb", ref);
00211 addUrlByScheme("cifs", ref);
00212 addUrlByScheme("http", ref);
00213 addUrlByScheme("https", ref);
00214 ref->config("path_encode_slash2", "y");
00215 addUrlByScheme("ftp", ref);
00216 addUrlByScheme("sftp", ref);
00217 addUrlByScheme("tftp", ref);
00218 }
00219
00220 bool
00221 addUrlByScheme(const std::string &scheme,
00222 UrlRef urlImpl)
00223 {
00224 if( urlImpl && urlImpl->isValidScheme(scheme))
00225 {
00226 UrlRef ref(urlImpl);
00227 ref->clear();
00228 urlByScheme[str::toLower(scheme)] = ref;
00229 return true;
00230 }
00231 return false;
00232 }
00233
00234 UrlRef
00235 getUrlByScheme(const std::string &scheme) const
00236 {
00237 UrlBySchemeMap::const_iterator i(urlByScheme.find(str::toLower(scheme)));
00238 if( i != urlByScheme.end())
00239 {
00240 return i->second;
00241 }
00242 return UrlRef();
00243 }
00244
00245 bool
00246 isRegisteredScheme(const std::string &scheme) const
00247 {
00248 return urlByScheme.find(str::toLower(scheme)) != urlByScheme.end();
00249 }
00250
00251 UrlSchemes
00252 getRegisteredSchemes() const
00253 {
00254 UrlBySchemeMap::const_iterator i(urlByScheme.begin());
00255 UrlSchemes schemes;
00256
00257 schemes.reserve(urlByScheme.size());
00258 for( ; i != urlByScheme.end(); ++i)
00259 {
00260 schemes.push_back(i->first);
00261 }
00262 return schemes;
00263 }
00264 };
00265
00266
00267
00268 UrlByScheme & g_urlSchemeRepository()
00269 {
00270 static UrlByScheme _v;
00271 return _v;
00272 }
00273
00275 }
00277
00278
00279
00280 Url::~Url()
00281 {
00282 }
00283
00284
00285
00286 Url::Url()
00287 : m_impl( new UrlBase())
00288 {
00289 }
00290
00291
00292
00293 Url::Url(const Url &url)
00294 : m_impl( url.m_impl)
00295 {
00296 if( !m_impl)
00297 {
00298 ZYPP_THROW(url::UrlException(
00299 _("Unable to clone Url object")
00300 ));
00301 }
00302 }
00303
00304
00305
00306 Url::Url(const zypp::url::UrlRef &url)
00307 : m_impl( url)
00308 {
00309 if( !m_impl)
00310 {
00311 ZYPP_THROW(url::UrlException(
00312 _("Invalid empty Url object reference")
00313 ));
00314 }
00315 }
00316
00317
00318
00319 Url::Url(const std::string &encodedUrl)
00320 : m_impl( parseUrl(encodedUrl))
00321 {
00322 if( !m_impl)
00323 {
00324 ZYPP_THROW(url::UrlParsingException(
00325 _("Unable to parse Url components")
00326 ));
00327 }
00328 }
00329
00330
00331
00332 Url&
00333 Url::operator = (const std::string &encodedUrl)
00334 {
00335 UrlRef url( parseUrl(encodedUrl));
00336 if( !url)
00337 {
00338 ZYPP_THROW(url::UrlParsingException(
00339 _("Unable to parse Url components")
00340 ));
00341 }
00342 m_impl = url;
00343 return *this;
00344 }
00345
00346
00347
00348 Url&
00349 Url::operator = (const Url &url)
00350 {
00351 m_impl = url.m_impl;
00352 return *this;
00353 }
00354
00355
00356
00357
00358 bool
00359 Url::registerScheme(const std::string &scheme,
00360 UrlRef urlImpl)
00361 {
00362 return g_urlSchemeRepository().addUrlByScheme(scheme, urlImpl);
00363 }
00364
00365
00366
00367
00368 UrlRef
00369 Url::parseUrl(const std::string &encodedUrl)
00370 {
00371 UrlRef url;
00372 str::smatch out;
00373 bool ret = false;
00374
00375 try
00376 {
00377 str::regex rex(RX_SPLIT_URL);
00378 ret = str::regex_match(encodedUrl, out, rex);
00379 }
00380 catch( ... )
00381 {}
00382
00383 if(ret && out.size() == 5)
00384 {
00385 std::string scheme = out[1];
00386 if (scheme.size() > 1)
00387 scheme = scheme.substr(0, scheme.size()-1);
00388 std::string authority = out[2];
00389 if (authority.size() >= 2)
00390 authority = authority.substr(2);
00391 std::string query = out[4];
00392 if (query.size() > 1)
00393 query = query.substr(1);
00394 std::string fragment = out[5];
00395 if (fragment.size() > 1)
00396 fragment = fragment.substr(1);
00397
00398 url = g_urlSchemeRepository().getUrlByScheme(scheme);
00399 if( !url)
00400 {
00401 url.reset( new UrlBase());
00402 }
00403 url->init(scheme, authority, out[3],
00404 query, fragment);
00405 }
00406 return url;
00407 }
00408
00409
00410
00411
00412 zypp::url::UrlSchemes
00413 Url::getRegisteredSchemes()
00414 {
00415 return g_urlSchemeRepository().getRegisteredSchemes();
00416 }
00417
00418
00419
00420
00421 bool
00422 Url::isRegisteredScheme(const std::string &scheme)
00423 {
00424 return g_urlSchemeRepository().isRegisteredScheme(scheme);
00425 }
00426
00427
00428
00429 zypp::url::UrlSchemes
00430 Url::getKnownSchemes() const
00431 {
00432 return m_impl->getKnownSchemes();
00433 }
00434
00435
00436
00437 bool
00438 Url::isValidScheme(const std::string &scheme) const
00439 {
00440 return m_impl->isValidScheme(scheme);
00441 }
00442
00443
00445 namespace
00446 {
00447 inline bool isInList( const char ** begin_r, const char ** end_r, const std::string & scheme_r )
00448 {
00449 for ( ; begin_r != end_r; ++begin_r )
00450 if ( scheme_r == *begin_r )
00451 return true;
00452 return false;
00453 }
00454 }
00455 bool Url::schemeIsLocal( const std::string & scheme_r )
00456 {
00457 static const char * val[] = { "cd", "dvd", "dir", "hd", "iso", "file" };
00458 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00459 }
00460
00461 bool Url::schemeIsRemote( const std::string & scheme_r )
00462 {
00463 static const char * val[] = { "http", "https", "nfs", "nfs4", "smb", "cifs", "ftp", "sftp", "tftp" };
00464 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00465 }
00466
00467 bool Url::schemeIsVolatile( const std::string & scheme_r )
00468 {
00469 static const char * val[] = { "cd", "dvd" };
00470 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00471 }
00472
00473 bool Url::schemeIsDownloading( const std::string & scheme_r )
00474 {
00475 static const char * val[] = { "http", "https", "ftp", "sftp", "tftp" };
00476 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00477 }
00479
00480
00481 bool
00482 Url::isValid() const
00483 {
00484 return m_impl->isValid();
00485 }
00486
00487
00488
00489 std::string
00490 Url::asString() const
00491 {
00492 return m_impl->asString();
00493 }
00494
00495
00496
00497 std::string
00498 Url::asCompleteString() const
00499 {
00500
00501
00502 ViewOptions opts(getViewOptions() +
00503 ViewOption::WITH_SCHEME +
00504 ViewOption::WITH_USERNAME +
00505 ViewOption::WITH_PASSWORD +
00506 ViewOption::WITH_HOST +
00507 ViewOption::WITH_PORT +
00508 ViewOption::WITH_PATH_NAME +
00509 ViewOption::WITH_PATH_PARAMS +
00510 ViewOption::WITH_QUERY_STR +
00511 ViewOption::WITH_FRAGMENT);
00512 return m_impl->asString(opts);
00513 }
00514
00515
00516
00517 std::string
00518 Url::asString(const ViewOptions &opts) const
00519 {
00520 return m_impl->asString(opts);
00521 }
00522
00523
00524
00525 std::string
00526 Url::getScheme() const
00527 {
00528 return m_impl->getScheme();
00529 }
00530
00531
00532
00533 std::string
00534 Url::getAuthority() const
00535 {
00536 return m_impl->getAuthority();
00537 }
00538
00539
00540 std::string
00541 Url::getPathData() const
00542 {
00543 return m_impl->getPathData();
00544 }
00545
00546
00547
00548 std::string
00549 Url::getQueryString() const
00550 {
00551 return m_impl->getQueryString();
00552 }
00553
00554
00555
00556 std::string
00557 Url::getFragment(zypp::url::EEncoding eflag) const
00558 {
00559 return m_impl->getFragment(eflag);
00560 }
00561
00562
00563
00564 std::string
00565 Url::getUsername(EEncoding eflag) const
00566 {
00567 return m_impl->getUsername(eflag);
00568 }
00569
00570
00571
00572 std::string
00573 Url::getPassword(EEncoding eflag) const
00574 {
00575 return m_impl->getPassword(eflag);
00576 }
00577
00578
00579
00580 std::string
00581 Url::getHost(EEncoding eflag) const
00582 {
00583 return m_impl->getHost(eflag);
00584 }
00585
00586
00587
00588 std::string
00589 Url::getPort() const
00590 {
00591 return m_impl->getPort();
00592 }
00593
00594
00595
00596 std::string
00597 Url::getPathName(EEncoding eflag) const
00598 {
00599 return m_impl->getPathName(eflag);
00600 }
00601
00602
00603
00604 std::string
00605 Url::getPathParams() const
00606 {
00607 return m_impl->getPathParams();
00608 }
00609
00610
00611
00612 zypp::url::ParamVec
00613 Url::getPathParamsVec() const
00614 {
00615 return m_impl->getPathParamsVec();
00616 }
00617
00618
00619
00620 zypp::url::ParamMap
00621 Url::getPathParamsMap(EEncoding eflag) const
00622 {
00623 return m_impl->getPathParamsMap(eflag);
00624 }
00625
00626
00627
00628 std::string
00629 Url::getPathParam(const std::string ¶m, EEncoding eflag) const
00630 {
00631 return m_impl->getPathParam(param, eflag);
00632 }
00633
00634
00635
00636 zypp::url::ParamVec
00637 Url::getQueryStringVec() const
00638 {
00639 return m_impl->getQueryStringVec();
00640 }
00641
00642
00643
00644 zypp::url::ParamMap
00645 Url::getQueryStringMap(EEncoding eflag) const
00646 {
00647 return m_impl->getQueryStringMap(eflag);
00648 }
00649
00650
00651
00652 std::string
00653 Url::getQueryParam(const std::string ¶m, EEncoding eflag) const
00654 {
00655 return m_impl->getQueryParam(param, eflag);
00656 }
00657
00658
00659
00660 void
00661 Url::setScheme(const std::string &scheme)
00662 {
00663 if(scheme == m_impl->getScheme())
00664 {
00665 return;
00666 }
00667 if( m_impl->isKnownScheme(scheme))
00668 {
00669 m_impl->setScheme(scheme);
00670 return;
00671 }
00672
00673 UrlRef url = g_urlSchemeRepository().getUrlByScheme(scheme);
00674 if( !url)
00675 {
00676 url.reset( new UrlBase());
00677 }
00678 url->init(
00679 scheme,
00680 m_impl->getAuthority(),
00681 m_impl->getPathData(),
00682 m_impl->getQueryString(),
00683 m_impl->getFragment(zypp::url::E_ENCODED)
00684 );
00685 m_impl = url;
00686 }
00687
00688
00689
00690 void
00691 Url::setAuthority(const std::string &authority)
00692 {
00693 m_impl->setAuthority(authority);
00694 }
00695
00696
00697
00698 void
00699 Url::setPathData(const std::string &pathdata)
00700 {
00701 m_impl->setPathData(pathdata);
00702 }
00703
00704
00705
00706 void
00707 Url::setQueryString(const std::string &querystr)
00708 {
00709 m_impl->setQueryString(querystr);
00710 }
00711
00712
00713
00714 void
00715 Url::setFragment(const std::string &fragment, EEncoding eflag)
00716 {
00717 m_impl->setFragment(fragment, eflag);
00718 }
00719
00720
00721
00722 void
00723 Url::setUsername(const std::string &user,
00724 EEncoding eflag)
00725 {
00726 m_impl->setUsername(user, eflag);
00727 }
00728
00729
00730
00731 void
00732 Url::setPassword(const std::string &pass,
00733 EEncoding eflag)
00734 {
00735 m_impl->setPassword(pass, eflag);
00736 }
00737
00738
00739
00740 void
00741 Url::setHost(const std::string &host)
00742 {
00743 m_impl->setHost(host);
00744 }
00745
00746
00747
00748 void
00749 Url::setPort(const std::string &port)
00750 {
00751 m_impl->setPort(port);
00752 }
00753
00754
00755
00756 void
00757 Url::setPathName(const std::string &path,
00758 EEncoding eflag)
00759 {
00760 m_impl->setPathName(path, eflag);
00761 }
00762
00763
00764
00765 void
00766 Url::setPathParams(const std::string ¶ms)
00767 {
00768 m_impl->setPathParams(params);
00769 }
00770
00771
00772
00773 void
00774 Url::setPathParamsVec(const zypp::url::ParamVec &pvec)
00775 {
00776 m_impl->setPathParamsVec(pvec);
00777 }
00778
00779
00780
00781 void
00782 Url::setPathParamsMap(const zypp::url::ParamMap &pmap)
00783 {
00784 m_impl->setPathParamsMap(pmap);
00785 }
00786
00787
00788
00789 void
00790 Url::setPathParam(const std::string ¶m, const std::string &value)
00791 {
00792 m_impl->setPathParam(param, value);
00793 }
00794
00795
00796
00797 void
00798 Url::setQueryStringVec(const zypp::url::ParamVec &pvec)
00799 {
00800 m_impl->setQueryStringVec(pvec);
00801 }
00802
00803
00804
00805 void
00806 Url::setQueryStringMap(const zypp::url::ParamMap &pmap)
00807 {
00808 m_impl->setQueryStringMap(pmap);
00809 }
00810
00811
00812 void
00813 Url::setQueryParam(const std::string ¶m, const std::string &value)
00814 {
00815 m_impl->setQueryParam(param, value);
00816 }
00817
00818
00819 void
00820 Url::delQueryParam(const std::string ¶m)
00821 {
00822 m_impl->delQueryParam(param);
00823 }
00824
00825
00826 ViewOptions
00827 Url::getViewOptions() const
00828 {
00829 return m_impl->getViewOptions();
00830 }
00831
00832
00833 void
00834 Url::setViewOptions(const ViewOptions &vopts)
00835 {
00836 m_impl->setViewOptions(vopts);
00837 }
00838
00839
00840 std::ostream & operator<<( std::ostream & str, const Url & url )
00841 {
00842 return str << url.asString();
00843 }
00844
00845 bool operator<( const Url &lhs, const Url &rhs )
00846 {
00847 return (lhs.asCompleteString() < rhs.asCompleteString());
00848 }
00849
00850 bool operator==( const Url &lhs, const Url &rhs )
00851 {
00852 return (lhs.asCompleteString() == rhs.asCompleteString());
00853 }
00854
00855 bool operator!=( const Url &lhs, const Url &rhs )
00856 {
00857 return (lhs.asCompleteString() != rhs.asCompleteString());
00858 }
00859
00861 }
00863
00864
00865