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