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
00197
00198 ref->config("with_authority", "y");
00199 ref->config("with_port", "n");
00200 ref->config("rx_username", "");
00201 ref->config("rx_password", "");
00202 addUrlByScheme("file", ref);
00203
00204
00205 ref.reset( new UrlBase());
00206 ref->config("require_host", "m");
00207 addUrlByScheme("nfs", ref);
00208 addUrlByScheme("nfs4", ref);
00209 addUrlByScheme("smb", ref);
00210 addUrlByScheme("cifs", ref);
00211 addUrlByScheme("http", ref);
00212 addUrlByScheme("https", ref);
00213 ref->config("path_encode_slash2", "y");
00214 addUrlByScheme("ftp", ref);
00215 addUrlByScheme("sftp", ref);
00216 }
00217
00218 bool
00219 addUrlByScheme(const std::string &scheme,
00220 UrlRef urlImpl)
00221 {
00222 if( urlImpl && urlImpl->isValidScheme(scheme))
00223 {
00224 UrlRef ref(urlImpl);
00225 ref->clear();
00226 urlByScheme[str::toLower(scheme)] = ref;
00227 return true;
00228 }
00229 return false;
00230 }
00231
00232 UrlRef
00233 getUrlByScheme(const std::string &scheme) const
00234 {
00235 UrlBySchemeMap::const_iterator i(urlByScheme.find(str::toLower(scheme)));
00236 if( i != urlByScheme.end())
00237 {
00238 return i->second;
00239 }
00240 return UrlRef();
00241 }
00242
00243 bool
00244 isRegisteredScheme(const std::string &scheme) const
00245 {
00246 return urlByScheme.find(str::toLower(scheme)) != urlByScheme.end();
00247 }
00248
00249 UrlSchemes
00250 getRegisteredSchemes() const
00251 {
00252 UrlBySchemeMap::const_iterator i(urlByScheme.begin());
00253 UrlSchemes schemes;
00254
00255 schemes.reserve(urlByScheme.size());
00256 for( ; i != urlByScheme.end(); ++i)
00257 {
00258 schemes.push_back(i->first);
00259 }
00260 return schemes;
00261 }
00262 };
00263
00264
00265
00266 UrlByScheme & g_urlSchemeRepository()
00267 {
00268 static UrlByScheme _v;
00269 return _v;
00270 }
00271
00273 }
00275
00276
00277
00278 Url::~Url()
00279 {
00280 }
00281
00282
00283
00284 Url::Url()
00285 : m_impl( new UrlBase())
00286 {
00287 }
00288
00289
00290
00291 Url::Url(const Url &url)
00292 : m_impl( url.m_impl)
00293 {
00294 if( !m_impl)
00295 {
00296 ZYPP_THROW(url::UrlException(
00297 _("Unable to clone Url object")
00298 ));
00299 }
00300 }
00301
00302
00303
00304 Url::Url(const zypp::url::UrlRef &url)
00305 : m_impl( url)
00306 {
00307 if( !m_impl)
00308 {
00309 ZYPP_THROW(url::UrlException(
00310 _("Invalid empty Url object reference")
00311 ));
00312 }
00313 }
00314
00315
00316
00317 Url::Url(const std::string &encodedUrl)
00318 : m_impl( parseUrl(encodedUrl))
00319 {
00320 if( !m_impl)
00321 {
00322 ZYPP_THROW(url::UrlParsingException(
00323 _("Unable to parse Url components")
00324 ));
00325 }
00326 }
00327
00328
00329
00330 Url&
00331 Url::operator = (const std::string &encodedUrl)
00332 {
00333 UrlRef url( parseUrl(encodedUrl));
00334 if( !url)
00335 {
00336 ZYPP_THROW(url::UrlParsingException(
00337 _("Unable to parse Url components")
00338 ));
00339 }
00340 m_impl = url;
00341 return *this;
00342 }
00343
00344
00345
00346 Url&
00347 Url::operator = (const Url &url)
00348 {
00349 m_impl = url.m_impl;
00350 return *this;
00351 }
00352
00353
00354
00355
00356 bool
00357 Url::registerScheme(const std::string &scheme,
00358 UrlRef urlImpl)
00359 {
00360 return g_urlSchemeRepository().addUrlByScheme(scheme, urlImpl);
00361 }
00362
00363
00364
00365
00366 UrlRef
00367 Url::parseUrl(const std::string &encodedUrl)
00368 {
00369 UrlRef url;
00370 str::smatch out;
00371 bool ret = false;
00372
00373 try
00374 {
00375 str::regex rex(RX_SPLIT_URL);
00376 ret = str::regex_match(encodedUrl, out, rex);
00377 }
00378 catch( ... )
00379 {}
00380
00381 if(ret && out.size() == 5)
00382 {
00383 std::string scheme = out[1];
00384 if (scheme.size() > 1)
00385 scheme = scheme.substr(0, scheme.size()-1);
00386 std::string authority = out[2];
00387 if (authority.size() >= 2)
00388 authority = authority.substr(2);
00389 std::string query = out[4];
00390 if (query.size() > 1)
00391 query = query.substr(1);
00392 std::string fragment = out[5];
00393 if (fragment.size() > 1)
00394 fragment = fragment.substr(1);
00395
00396 url = g_urlSchemeRepository().getUrlByScheme(scheme);
00397 if( !url)
00398 {
00399 url.reset( new UrlBase());
00400 }
00401 url->init(scheme, authority, out[3],
00402 query, fragment);
00403 }
00404 return url;
00405 }
00406
00407
00408
00409
00410 zypp::url::UrlSchemes
00411 Url::getRegisteredSchemes()
00412 {
00413 return g_urlSchemeRepository().getRegisteredSchemes();
00414 }
00415
00416
00417
00418
00419 bool
00420 Url::isRegisteredScheme(const std::string &scheme)
00421 {
00422 return g_urlSchemeRepository().isRegisteredScheme(scheme);
00423 }
00424
00425
00426
00427 zypp::url::UrlSchemes
00428 Url::getKnownSchemes() const
00429 {
00430 return m_impl->getKnownSchemes();
00431 }
00432
00433
00434
00435 bool
00436 Url::isValidScheme(const std::string &scheme) const
00437 {
00438 return m_impl->isValidScheme(scheme);
00439 }
00440
00441
00443 namespace
00444 {
00445 inline bool isInList( const char ** begin_r, const char ** end_r, const std::string & scheme_r )
00446 {
00447 for ( ; begin_r != end_r; ++begin_r )
00448 if ( scheme_r == *begin_r )
00449 return true;
00450 return false;
00451 }
00452 }
00453 bool Url::schemeIsLocal( const std::string & scheme_r )
00454 {
00455 static const char * val[] = { "cd", "dvd", "dir", "hd", "iso", "file" };
00456 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00457 }
00458
00459 bool Url::schemeIsRemote( const std::string & scheme_r )
00460 {
00461 static const char * val[] = { "http", "https", "nfs", "nfs4", "smb", "cifs", "ftp", "sftp" };
00462 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00463 }
00464
00465 bool Url::schemeIsVolatile( const std::string & scheme_r )
00466 {
00467 static const char * val[] = { "cd", "dvd" };
00468 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00469 }
00470
00471 bool Url::schemeIsDownloading( const std::string & scheme_r )
00472 {
00473 static const char * val[] = { "http", "https", "ftp", "sftp" };
00474 return isInList( arrayBegin(val), arrayEnd(val), scheme_r );
00475 }
00477
00478
00479 bool
00480 Url::isValid() const
00481 {
00482 return m_impl->isValid();
00483 }
00484
00485
00486
00487 std::string
00488 Url::asString() const
00489 {
00490 return m_impl->asString();
00491 }
00492
00493
00494
00495 std::string
00496 Url::asCompleteString() const
00497 {
00498
00499
00500 ViewOptions opts(getViewOptions() +
00501 ViewOption::WITH_SCHEME +
00502 ViewOption::WITH_USERNAME +
00503 ViewOption::WITH_PASSWORD +
00504 ViewOption::WITH_HOST +
00505 ViewOption::WITH_PORT +
00506 ViewOption::WITH_PATH_NAME +
00507 ViewOption::WITH_PATH_PARAMS +
00508 ViewOption::WITH_QUERY_STR +
00509 ViewOption::WITH_FRAGMENT);
00510 return m_impl->asString(opts);
00511 }
00512
00513
00514
00515 std::string
00516 Url::asString(const ViewOptions &opts) const
00517 {
00518 return m_impl->asString(opts);
00519 }
00520
00521
00522
00523 std::string
00524 Url::getScheme() const
00525 {
00526 return m_impl->getScheme();
00527 }
00528
00529
00530
00531 std::string
00532 Url::getAuthority() const
00533 {
00534 return m_impl->getAuthority();
00535 }
00536
00537
00538 std::string
00539 Url::getPathData() const
00540 {
00541 return m_impl->getPathData();
00542 }
00543
00544
00545
00546 std::string
00547 Url::getQueryString() const
00548 {
00549 return m_impl->getQueryString();
00550 }
00551
00552
00553
00554 std::string
00555 Url::getFragment(zypp::url::EEncoding eflag) const
00556 {
00557 return m_impl->getFragment(eflag);
00558 }
00559
00560
00561
00562 std::string
00563 Url::getUsername(EEncoding eflag) const
00564 {
00565 return m_impl->getUsername(eflag);
00566 }
00567
00568
00569
00570 std::string
00571 Url::getPassword(EEncoding eflag) const
00572 {
00573 return m_impl->getPassword(eflag);
00574 }
00575
00576
00577
00578 std::string
00579 Url::getHost(EEncoding eflag) const
00580 {
00581 return m_impl->getHost(eflag);
00582 }
00583
00584
00585
00586 std::string
00587 Url::getPort() const
00588 {
00589 return m_impl->getPort();
00590 }
00591
00592
00593
00594 std::string
00595 Url::getPathName(EEncoding eflag) const
00596 {
00597 return m_impl->getPathName(eflag);
00598 }
00599
00600
00601
00602 std::string
00603 Url::getPathParams() const
00604 {
00605 return m_impl->getPathParams();
00606 }
00607
00608
00609
00610 zypp::url::ParamVec
00611 Url::getPathParamsVec() const
00612 {
00613 return m_impl->getPathParamsVec();
00614 }
00615
00616
00617
00618 zypp::url::ParamMap
00619 Url::getPathParamsMap(EEncoding eflag) const
00620 {
00621 return m_impl->getPathParamsMap(eflag);
00622 }
00623
00624
00625
00626 std::string
00627 Url::getPathParam(const std::string ¶m, EEncoding eflag) const
00628 {
00629 return m_impl->getPathParam(param, eflag);
00630 }
00631
00632
00633
00634 zypp::url::ParamVec
00635 Url::getQueryStringVec() const
00636 {
00637 return m_impl->getQueryStringVec();
00638 }
00639
00640
00641
00642 zypp::url::ParamMap
00643 Url::getQueryStringMap(EEncoding eflag) const
00644 {
00645 return m_impl->getQueryStringMap(eflag);
00646 }
00647
00648
00649
00650 std::string
00651 Url::getQueryParam(const std::string ¶m, EEncoding eflag) const
00652 {
00653 return m_impl->getQueryParam(param, eflag);
00654 }
00655
00656
00657
00658 void
00659 Url::setScheme(const std::string &scheme)
00660 {
00661 if(scheme == m_impl->getScheme())
00662 {
00663 return;
00664 }
00665 if( m_impl->isKnownScheme(scheme))
00666 {
00667 m_impl->setScheme(scheme);
00668 return;
00669 }
00670
00671 UrlRef url = g_urlSchemeRepository().getUrlByScheme(scheme);
00672 if( !url)
00673 {
00674 url.reset( new UrlBase());
00675 }
00676 url->init(
00677 scheme,
00678 m_impl->getAuthority(),
00679 m_impl->getPathData(),
00680 m_impl->getQueryString(),
00681 m_impl->getFragment(zypp::url::E_ENCODED)
00682 );
00683 m_impl = url;
00684 }
00685
00686
00687
00688 void
00689 Url::setAuthority(const std::string &authority)
00690 {
00691 m_impl->setAuthority(authority);
00692 }
00693
00694
00695
00696 void
00697 Url::setPathData(const std::string &pathdata)
00698 {
00699 m_impl->setPathData(pathdata);
00700 }
00701
00702
00703
00704 void
00705 Url::setQueryString(const std::string &querystr)
00706 {
00707 m_impl->setQueryString(querystr);
00708 }
00709
00710
00711
00712 void
00713 Url::setFragment(const std::string &fragment, EEncoding eflag)
00714 {
00715 m_impl->setFragment(fragment, eflag);
00716 }
00717
00718
00719
00720 void
00721 Url::setUsername(const std::string &user,
00722 EEncoding eflag)
00723 {
00724 m_impl->setUsername(user, eflag);
00725 }
00726
00727
00728
00729 void
00730 Url::setPassword(const std::string &pass,
00731 EEncoding eflag)
00732 {
00733 m_impl->setPassword(pass, eflag);
00734 }
00735
00736
00737
00738 void
00739 Url::setHost(const std::string &host)
00740 {
00741 m_impl->setHost(host);
00742 }
00743
00744
00745
00746 void
00747 Url::setPort(const std::string &port)
00748 {
00749 m_impl->setPort(port);
00750 }
00751
00752
00753
00754 void
00755 Url::setPathName(const std::string &path,
00756 EEncoding eflag)
00757 {
00758 m_impl->setPathName(path, eflag);
00759 }
00760
00761
00762
00763 void
00764 Url::setPathParams(const std::string ¶ms)
00765 {
00766 m_impl->setPathParams(params);
00767 }
00768
00769
00770
00771 void
00772 Url::setPathParamsVec(const zypp::url::ParamVec &pvec)
00773 {
00774 m_impl->setPathParamsVec(pvec);
00775 }
00776
00777
00778
00779 void
00780 Url::setPathParamsMap(const zypp::url::ParamMap &pmap)
00781 {
00782 m_impl->setPathParamsMap(pmap);
00783 }
00784
00785
00786
00787 void
00788 Url::setPathParam(const std::string ¶m, const std::string &value)
00789 {
00790 m_impl->setPathParam(param, value);
00791 }
00792
00793
00794
00795 void
00796 Url::setQueryStringVec(const zypp::url::ParamVec &pvec)
00797 {
00798 m_impl->setQueryStringVec(pvec);
00799 }
00800
00801
00802
00803 void
00804 Url::setQueryStringMap(const zypp::url::ParamMap &pmap)
00805 {
00806 m_impl->setQueryStringMap(pmap);
00807 }
00808
00809
00810 void
00811 Url::setQueryParam(const std::string ¶m, const std::string &value)
00812 {
00813 m_impl->setQueryParam(param, value);
00814 }
00815
00816
00817 ViewOptions
00818 Url::getViewOptions() const
00819 {
00820 return m_impl->getViewOptions();
00821 }
00822
00823
00824 void
00825 Url::setViewOptions(const ViewOptions &vopts)
00826 {
00827 m_impl->setViewOptions(vopts);
00828 }
00829
00830
00831 std::ostream & operator<<( std::ostream & str, const Url & url )
00832 {
00833 return str << url.asString();
00834 }
00835
00836 bool operator<( const Url &lhs, const Url &rhs )
00837 {
00838 return (lhs.asCompleteString() < rhs.asCompleteString());
00839 }
00840
00841 bool operator==( const Url &lhs, const Url &rhs )
00842 {
00843 return (lhs.asCompleteString() == rhs.asCompleteString());
00844 }
00845
00846 bool operator!=( const Url &lhs, const Url &rhs )
00847 {
00848 return (lhs.asCompleteString() != rhs.asCompleteString());
00849 }
00850
00852 }
00854
00855
00856