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