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