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