00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <zypp/url/UrlBase.h>
00013 #include <zypp/base/String.h>
00014 #include <zypp/base/Gettext.h>
00015 #include <stdexcept>
00016 #include <climits>
00017 #include <errno.h>
00018 #include <sys/types.h>
00019 #include <sys/socket.h>
00020 #include <arpa/inet.h>
00021
00022
00023
00024
00025
00026
00027
00028
00029 #define RX_VALID_SCHEME "^[a-zA-Z][a-zA-Z0-9\\.+-]*$"
00030
00031 #define RX_VALID_PORT "^[0-9]{1,5}$"
00032
00033 #define RX_VALID_HOSTNAME "^[[:alnum:]]+([\\.-][[:alnum:]]+)*$"
00034
00035 #define RX_VALID_HOSTIPV4 \
00036 "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$"
00037
00038 #define RX_VALID_HOSTIPV6 \
00039 "^\\[[:a-fA-F0-9]+(:[0-9]{1,3}(\\.[0-9]{1,3}){3})?\\]$"
00040
00041
00043 namespace zypp
00044 {
00045
00047 namespace url
00048 {
00049
00050
00051
00052
00053
00054
00055 const ViewOption ViewOption::WITH_SCHEME = 0x0001;
00056 const ViewOption ViewOption::WITH_USERNAME = 0x0002;
00057 const ViewOption ViewOption::WITH_PASSWORD = 0x0004;
00058 const ViewOption ViewOption::WITH_HOST = 0x0008;
00059 const ViewOption ViewOption::WITH_PORT = 0x0010;
00060 const ViewOption ViewOption::WITH_PATH_NAME = 0x0020;
00061 const ViewOption ViewOption::WITH_PATH_PARAMS = 0x0040;
00062 const ViewOption ViewOption::WITH_QUERY_STR = 0x0080;
00063 const ViewOption ViewOption::WITH_FRAGMENT = 0x0100;
00064 const ViewOption ViewOption::EMPTY_AUTHORITY = 0x0200;
00065 const ViewOption ViewOption::EMPTY_PATH_NAME = 0x0400;
00066 const ViewOption ViewOption::EMPTY_PATH_PARAMS = 0x0800;
00067 const ViewOption ViewOption::EMPTY_QUERY_STR = 0x1000;
00068 const ViewOption ViewOption::EMPTY_FRAGMENT = 0x2000;
00069 const ViewOption ViewOption::DEFAULTS = 0x07bb;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 ViewOption::ViewOption()
00085 : opt(0x07bb)
00086 {}
00087
00088
00089 ViewOption::ViewOption(int option)
00090 : opt(option)
00091 {}
00092
00093
00094
00095
00096
00097
00098 typedef std::map< std::string, std::string > UrlConfig;
00099
00100
00101
00105 class UrlBaseData
00106 {
00107 public:
00108 UrlBaseData()
00109 {}
00110
00111 UrlBaseData(const UrlConfig &conf)
00112 : config(conf)
00113 {}
00114
00115 UrlConfig config;
00116 ViewOptions vopts;
00117
00118 std::string scheme;
00119 std::string user;
00120 std::string pass;
00121 std::string host;
00122 std::string port;
00123 std::string pathname;
00124 std::string pathparams;
00125 std::string querystr;
00126 std::string fragment;
00127 };
00128
00129
00130
00131
00132
00133
00134 namespace
00135 {
00136
00137
00138 inline void
00139 checkUrlData(const std::string &data,
00140 const std::string &name,
00141 const std::string ®x,
00142 bool show=true)
00143 {
00144 if( regx.empty() || regx == "^$")
00145 {
00146 ZYPP_THROW(UrlNotAllowedException(
00147 str::form(_("Url scheme does not allow a %s"), name.c_str())
00148 ));
00149 }
00150 else
00151 {
00152 bool valid = false;
00153 try
00154 {
00155 str::regex rex(regx);
00156 valid = str::regex_match(data, rex);
00157 }
00158 catch( ... )
00159 {}
00160
00161 if( !valid)
00162 {
00163 if( show)
00164 {
00165 ZYPP_THROW(UrlBadComponentException(
00166 str::form(_("Invalid %s component '%s'"),
00167 name.c_str(), data.c_str())
00168 ));
00169 }
00170 else
00171 {
00172 ZYPP_THROW(UrlBadComponentException(
00173 str::form(_("Invalid %s component"), name.c_str())
00174 ));
00175 }
00176 }
00177 }
00178 }
00179
00180 }
00181
00182
00183
00184 UrlBase::~UrlBase()
00185 {
00186 delete m_data;
00187 m_data = NULL;
00188 }
00189
00190
00191
00192 UrlBase::UrlBase()
00193 : m_data( new UrlBaseData())
00194 {
00195 configure();
00196 }
00197
00198
00199
00200 UrlBase::UrlBase(const UrlBase &url)
00201 : m_data( new UrlBaseData( *(url.m_data)))
00202 {
00203 }
00204
00205
00206
00207 UrlBase::UrlBase(const std::string &scheme,
00208 const std::string &authority,
00209 const std::string &pathdata,
00210 const std::string &querystr,
00211 const std::string &fragment)
00212 : m_data( new UrlBaseData())
00213 {
00214 configure();
00215 init(scheme, authority, pathdata, querystr, fragment);
00216 }
00217
00218
00219
00220 void
00221 UrlBase::init(const std::string &scheme,
00222 const std::string &authority,
00223 const std::string &pathdata,
00224 const std::string &querystr,
00225 const std::string &fragment)
00226 {
00227 setScheme(scheme);
00228 setAuthority(authority);
00229 setPathData(pathdata);
00230 setQueryString(querystr);
00231 setFragment(fragment, zypp::url::E_ENCODED);
00232 }
00233
00234
00235
00236 void
00237 UrlBase::configure()
00238 {
00239 config("sep_pathparams", ";");
00240 config("psep_pathparam", ",");
00241 config("vsep_pathparam", "=");
00242
00243 config("psep_querystr", "&");
00244 config("vsep_querystr", "=");
00245
00246 config("safe_username", "~!$&'()*+=,;");
00247 config("safe_password", "~!$&'()*+=,:;");
00248 config("safe_hostname", "[:]");
00249 config("safe_pathname", "~!$&'()*+=,:@/");
00250 config("safe_pathparams", "~!$&'()*+=,:;@/");
00251 config("safe_querystr", "~!$&'()*+=,:;@/?");
00252 config("safe_fragment", "~!$&'()*+=,:;@/?");
00253
00254
00255
00256 config("with_authority", "y");
00257 config("with_port", "y");
00258
00259
00260
00261
00262 config("require_host", "n");
00263 config("require_pathname","n");
00264
00265
00266
00267 config("path_encode_slash2", "n");
00268
00269 config("rx_username", "^([a-zA-Z0-9!$&'\\(\\)*+=,;~\\._-]|%[a-fA-F0-9]{2})+$");
00270 config("rx_password", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;~\\._-]|%[a-fA-F0-9]{2})+$");
00271
00272 config("rx_pathname", "^([a-zA-Z0-9!$&'\\(\\)*+=,:@/~\\._-]|%[a-fA-F0-9]{2})+$");
00273 config("rx_pathparams", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/~\\._-]|%[a-fA-F0-9]{2})+$");
00274
00275 config("rx_querystr", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
00276 config("rx_fragment", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
00277 }
00278
00279
00280
00281 void
00282 UrlBase::config(const std::string &opt, const std::string &val)
00283 {
00284 m_data->config[opt] = val;
00285 }
00286
00287
00288
00289 std::string
00290 UrlBase::config(const std::string &opt) const
00291 {
00292 UrlConfig::const_iterator v( m_data->config.find(opt));
00293 if( v != m_data->config.end())
00294 return v->second;
00295 else
00296 return std::string();
00297 }
00298
00299
00300
00301 ViewOptions
00302 UrlBase::getViewOptions() const
00303 {
00304 return m_data->vopts;
00305 }
00306
00307
00308
00309 void
00310 UrlBase::setViewOptions(const ViewOptions &vopts)
00311 {
00312 m_data->vopts = vopts;
00313 }
00314
00315
00316
00317 void
00318 UrlBase::clear()
00319 {
00320 zypp::url::UrlConfig config(m_data->config);
00321 zypp::url::ViewOptions vopts(m_data->vopts);
00322 *m_data = UrlBaseData();
00323 m_data->config = config;
00324 m_data->vopts = vopts;
00325 }
00326
00327
00328
00329 UrlBase *
00330 UrlBase::clone() const
00331 {
00332 return new UrlBase(*this);
00333 }
00334
00335
00336
00337 zypp::url::UrlSchemes
00338 UrlBase::getKnownSchemes() const
00339 {
00340 return UrlSchemes();
00341 }
00342
00343
00344
00345 bool
00346 UrlBase::isKnownScheme(const std::string &scheme) const
00347 {
00348 std::string lscheme( str::toLower(scheme));
00349 UrlSchemes schemes( getKnownSchemes());
00350 UrlSchemes::const_iterator s;
00351
00352 for(s=schemes.begin(); s!=schemes.end(); ++s)
00353 {
00354 if( lscheme == str::toLower(*s))
00355 return true;
00356 }
00357 return false;
00358 }
00359
00360
00361
00362 bool
00363 UrlBase::isValidScheme(const std::string &scheme) const
00364 {
00365 bool valid = false;
00366 try
00367 {
00368 str::regex rex(RX_VALID_SCHEME);
00369 valid = str::regex_match(scheme, rex);
00370 }
00371 catch( ... )
00372 {}
00373
00374 if(valid)
00375 {
00376 std::string lscheme( str::toLower(scheme));
00377 UrlSchemes schemes( getKnownSchemes());
00378
00379 if( schemes.empty())
00380 return true;
00381
00382 UrlSchemes::const_iterator s;
00383 for(s=schemes.begin(); s!=schemes.end(); ++s)
00384 {
00385 if( lscheme == str::toLower(*s))
00386 return true;
00387 }
00388 }
00389 return false;
00390 }
00391
00392
00393
00394 bool
00395 UrlBase::isValid() const
00396 {
00397
00398
00399
00400
00401
00402
00403 if( getScheme().empty())
00404 return false;
00405
00406 std::string host( getHost(zypp::url::E_ENCODED));
00407 if( host.empty() && config("require_host") != "n")
00408 return false;
00409
00410 std::string path( getPathName(zypp::url::E_ENCODED));
00411 if( path.empty() && config("require_pathname") != "n")
00412 return false;
00413
00414
00415
00416
00417
00418 if( !host.empty() && !path.empty() && path.at(0) != '/')
00419 return false;
00420
00421 return true;
00422 }
00423
00424
00425
00426 std::string
00427 UrlBase::asString() const
00428 {
00429 return asString(getViewOptions());
00430 }
00431
00432
00433
00434 std::string
00435 UrlBase::asString(const zypp::url::ViewOptions &opts) const
00436 {
00437 std::string url;
00438 UrlBaseData tmp;
00439
00440 if( opts.has(ViewOptions::WITH_SCHEME))
00441 {
00442 tmp.scheme = getScheme();
00443 if( !tmp.scheme.empty())
00444 {
00445 url += tmp.scheme + ":";
00446
00447 if( opts.has(ViewOptions::WITH_HOST))
00448 {
00449 tmp.host = getHost(zypp::url::E_ENCODED);
00450 if( !tmp.host.empty())
00451 {
00452 url += "//";
00453
00454 if( opts.has(ViewOptions::WITH_USERNAME))
00455 {
00456 tmp.user = getUsername(zypp::url::E_ENCODED);
00457 if( !tmp.user.empty())
00458 {
00459 url += tmp.user;
00460
00461 if( opts.has(ViewOptions::WITH_PASSWORD))
00462 {
00463 tmp.pass = getPassword(zypp::url::E_ENCODED);
00464 if( !tmp.pass.empty())
00465 {
00466 url += ":" + tmp.pass;
00467 }
00468 }
00469 url += "@";
00470 }
00471 }
00472
00473 url += tmp.host;
00474
00475 if( opts.has(ViewOptions::WITH_PORT))
00476 {
00477 tmp.port = getPort();
00478 if( !tmp.port.empty())
00479 {
00480 url += ":" + tmp.port;
00481 }
00482 }
00483 }
00484 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
00485 {
00486 url += "//";
00487 }
00488 }
00489 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
00490 {
00491 url += "//";
00492 }
00493 }
00494 }
00495
00496 if( opts.has(ViewOptions::WITH_PATH_NAME))
00497 {
00498 tmp.pathname = getPathName(zypp::url::E_ENCODED);
00499 if( !tmp.pathname.empty())
00500 {
00501 if(url.find("/") != std::string::npos)
00502 {
00503
00504
00505 tmp.pathname = cleanupPathName(tmp.pathname, true);
00506 if(tmp.pathname.at(0) != '/')
00507 {
00508 url += "/";
00509 }
00510 }
00511 url += tmp.pathname;
00512
00513 if( opts.has(ViewOptions::WITH_PATH_PARAMS))
00514 {
00515 tmp.pathparams = getPathParams();
00516 if( !tmp.pathparams.empty())
00517 {
00518 url += ";" + tmp.pathparams;
00519 }
00520 else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
00521 {
00522 url += ";";
00523 }
00524 }
00525 }
00526 else if( opts.has(ViewOptions::EMPTY_PATH_NAME)
00527 && url.find("/") != std::string::npos)
00528 {
00529 url += "/";
00530 if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
00531 {
00532 url += ";";
00533 }
00534 }
00535 }
00536
00537 if( opts.has(ViewOptions::WITH_QUERY_STR))
00538 {
00539 tmp.querystr = getQueryString();
00540 if( !tmp.querystr.empty())
00541 {
00542 url += "?" + tmp.querystr;
00543 }
00544 else if( opts.has(ViewOptions::EMPTY_QUERY_STR))
00545 {
00546 url += "?";
00547 }
00548 }
00549
00550 if( opts.has(ViewOptions::WITH_FRAGMENT))
00551 {
00552 tmp.fragment = getFragment(zypp::url::E_ENCODED);
00553 if( !tmp.fragment.empty())
00554 {
00555 url += "#" + tmp.fragment;
00556 }
00557 else if( opts.has(ViewOptions::EMPTY_FRAGMENT))
00558 {
00559 url += "#";
00560 }
00561 }
00562
00563 return url;
00564 }
00565
00566
00567
00568 std::string
00569 UrlBase::getScheme() const
00570 {
00571 return m_data->scheme;
00572 }
00573
00574
00575
00576 std::string
00577 UrlBase::getAuthority() const
00578 {
00579 std::string str;
00580 if( !getHost(zypp::url::E_ENCODED).empty())
00581 {
00582 if( !getUsername(zypp::url::E_ENCODED).empty())
00583 {
00584 str = getUsername(zypp::url::E_ENCODED);
00585 if( !getPassword(zypp::url::E_ENCODED).empty())
00586 {
00587 str += ":" + getPassword(zypp::url::E_ENCODED);
00588 }
00589 str += "@";
00590 }
00591
00592 str += getHost(zypp::url::E_ENCODED);
00593 if( !getPort().empty())
00594 {
00595 str += ":" + getPort();
00596 }
00597 }
00598 return str;
00599 }
00600
00601
00602
00603 std::string
00604 UrlBase::getPathData() const
00605 {
00606 return getPathName(zypp::url::E_ENCODED) +
00607 config("sep_pathparams") +
00608 getPathParams();
00609 }
00610
00611
00612
00613 std::string
00614 UrlBase::getQueryString() const
00615 {
00616 return m_data->querystr;
00617 }
00618
00619
00620
00621 std::string
00622 UrlBase::getFragment(EEncoding eflag) const
00623 {
00624 if(eflag == zypp::url::E_DECODED)
00625 return zypp::url::decode(m_data->fragment);
00626 else
00627 return m_data->fragment;
00628 }
00629
00630
00631
00632 std::string
00633 UrlBase::getUsername(EEncoding eflag) const
00634 {
00635 if(eflag == zypp::url::E_DECODED)
00636 return zypp::url::decode(m_data->user);
00637 else
00638 return m_data->user;
00639 }
00640
00641
00642
00643 std::string
00644 UrlBase::getPassword(EEncoding eflag) const
00645 {
00646 if(eflag == zypp::url::E_DECODED)
00647 return zypp::url::decode(m_data->pass);
00648 else
00649 return m_data->pass;
00650 }
00651
00652
00653
00654 std::string
00655 UrlBase::getHost(EEncoding eflag) const
00656 {
00657 if(eflag == zypp::url::E_DECODED)
00658 return zypp::url::decode(m_data->host);
00659 else
00660 return m_data->host;
00661 }
00662
00663
00664
00665 std::string
00666 UrlBase::getPort() const
00667 {
00668 return m_data->port;
00669 }
00670
00671
00672
00673 std::string
00674 UrlBase::getPathName(EEncoding eflag) const
00675 {
00676 if(eflag == zypp::url::E_DECODED)
00677 return zypp::url::decode(m_data->pathname);
00678 else
00679 return cleanupPathName(m_data->pathname);
00680 }
00681
00682
00683
00684 std::string
00685 UrlBase::getPathParams() const
00686 {
00687 return m_data->pathparams;
00688 }
00689
00690
00691
00692 zypp::url::ParamVec
00693 UrlBase::getPathParamsVec() const
00694 {
00695 zypp::url::ParamVec pvec;
00696 if( config("psep_pathparam").empty())
00697 {
00698 pvec.push_back(getPathParams());
00699 }
00700 else
00701 {
00702 zypp::url::split(
00703 pvec,
00704 getPathParams(),
00705 config("psep_pathparam")
00706 );
00707 }
00708 return pvec;
00709 }
00710
00711
00712
00713 zypp::url::ParamMap
00714 UrlBase::getPathParamsMap(EEncoding eflag) const
00715 {
00716 if( config("psep_pathparam").empty() ||
00717 config("vsep_pathparam").empty())
00718 {
00719 ZYPP_THROW(UrlNotSupportedException(
00720 _("Path parameter parsing not supported for this URL")
00721 ));
00722 }
00723 zypp::url::ParamMap pmap;
00724 zypp::url::split(
00725 pmap,
00726 getPathParams(),
00727 config("psep_pathparam"),
00728 config("vsep_pathparam"),
00729 eflag
00730 );
00731 return pmap;
00732 }
00733
00734
00735
00736 std::string
00737 UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const
00738 {
00739 zypp::url::ParamMap pmap( getPathParamsMap( eflag));
00740 zypp::url::ParamMap::const_iterator i( pmap.find(param));
00741
00742 return i != pmap.end() ? i->second : std::string();
00743 }
00744
00745
00746
00747 zypp::url::ParamVec
00748 UrlBase::getQueryStringVec() const
00749 {
00750 zypp::url::ParamVec pvec;
00751 if( config("psep_querystr").empty())
00752 {
00753 pvec.push_back(getQueryString());
00754 }
00755 else
00756 {
00757 zypp::url::split(
00758 pvec,
00759 getQueryString(),
00760 config("psep_querystr")
00761 );
00762 }
00763 return pvec;
00764 }
00765
00766
00767
00768 zypp::url::ParamMap
00769 UrlBase::getQueryStringMap(EEncoding eflag) const
00770 {
00771 if( config("psep_querystr").empty() ||
00772 config("vsep_querystr").empty())
00773 {
00774 ZYPP_THROW(UrlNotSupportedException(
00775 _("Query string parsing not supported for this URL")
00776 ));
00777 }
00778 zypp::url::ParamMap pmap;
00779 zypp::url::split(
00780 pmap,
00781 getQueryString(),
00782 config("psep_querystr"),
00783 config("vsep_querystr"),
00784 eflag
00785 );
00786 return pmap;
00787 }
00788
00789
00790
00791 std::string
00792 UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const
00793 {
00794 zypp::url::ParamMap pmap( getQueryStringMap( eflag));
00795 zypp::url::ParamMap::const_iterator i( pmap.find(param));
00796
00797 return i != pmap.end() ? i->second : std::string();
00798 }
00799
00800
00801
00802 void
00803 UrlBase::setScheme(const std::string &scheme)
00804 {
00805 if( isValidScheme(scheme))
00806 {
00807 m_data->scheme = str::toLower(scheme);
00808 }
00809 else
00810 if( scheme.empty())
00811 {
00812 ZYPP_THROW(UrlBadComponentException(
00813 _("Url scheme is a required component")
00814 ));
00815 }
00816 else
00817 {
00818 ZYPP_THROW(UrlBadComponentException(
00819 str::form(_("Invalid Url scheme '%s'"), scheme.c_str())
00820 ));
00821 }
00822 }
00823
00824
00825
00826 void
00827 UrlBase::setAuthority(const std::string &authority)
00828 {
00829 std::string s = authority;
00830 std::string::size_type p,q;
00831
00832 std::string username, password, host, port;
00833
00834 if ((p=s.find('@')) != std::string::npos)
00835 {
00836 q = s.find(':');
00837 if (q != std::string::npos && q < p)
00838 {
00839 setUsername(s.substr(0, q), zypp::url::E_ENCODED);
00840 setPassword(s.substr(q+1, p-q-1), zypp::url::E_ENCODED);
00841 }
00842 else
00843 setUsername(s.substr(0, p), zypp::url::E_ENCODED);
00844 s = s.substr(p+1);
00845 }
00846 q = s.rfind(']');
00847 if ((p = s.rfind(':')) != std::string::npos && p > q+1)
00848 {
00849
00850 setHost(s.substr(0, p));
00851 setPort(s.substr(p+1));
00852 }
00853 else
00854 setHost(s);
00855 }
00856
00857
00858 void
00859 UrlBase::setPathData(const std::string &pathdata)
00860 {
00861 size_t pos = std::string::npos;
00862 std::string sep(config("sep_pathparams"));
00863
00864 if( !sep.empty())
00865 pos = pathdata.find(sep);
00866
00867 if( pos != std::string::npos)
00868 {
00869 setPathName(pathdata.substr(0, pos),
00870 zypp::url::E_ENCODED);
00871 setPathParams(pathdata.substr(pos + 1));
00872 }
00873 else
00874 {
00875 setPathName(pathdata,
00876 zypp::url::E_ENCODED);
00877 setPathParams("");
00878 }
00879 }
00880
00881
00882
00883 void
00884 UrlBase::setQueryString(const std::string &querystr)
00885 {
00886 if( querystr.empty())
00887 {
00888 m_data->querystr = querystr;
00889 }
00890 else
00891 {
00892 checkUrlData(querystr, "query string", config("rx_querystr"));
00893
00894 m_data->querystr = querystr;
00895 }
00896 }
00897
00898
00899
00900 void
00901 UrlBase::setFragment(const std::string &fragment,
00902 EEncoding eflag)
00903 {
00904 if( fragment.empty())
00905 {
00906 m_data->fragment = fragment;
00907 }
00908 else
00909 {
00910 if(eflag == zypp::url::E_ENCODED)
00911 {
00912 checkUrlData(fragment, "fragment", config("rx_fragment"));
00913
00914 m_data->fragment = fragment;
00915 }
00916 else
00917 {
00918 m_data->fragment = zypp::url::encode(
00919 fragment, config("safe_fragment")
00920 );
00921 }
00922 }
00923 }
00924
00925
00926
00927 void
00928 UrlBase::setUsername(const std::string &user,
00929 EEncoding eflag)
00930 {
00931 if( user.empty())
00932 {
00933 m_data->user = user;
00934 }
00935 else
00936 {
00937 if( config("with_authority") != "y")
00938 {
00939 ZYPP_THROW(UrlNotAllowedException(
00940 _("Url scheme does not allow a username")
00941 ));
00942 }
00943
00944 if(eflag == zypp::url::E_ENCODED)
00945 {
00946 checkUrlData(user, "username", config("rx_username"));
00947
00948 m_data->user = user;
00949 }
00950 else
00951 {
00952 m_data->user = zypp::url::encode(
00953 user, config("safe_username")
00954 );
00955 }
00956 }
00957 }
00958
00959
00960
00961 void
00962 UrlBase::setPassword(const std::string &pass,
00963 EEncoding eflag)
00964 {
00965 if( pass.empty())
00966 {
00967 m_data->pass = pass;
00968 }
00969 else
00970 {
00971 if( config("with_authority") != "y")
00972 {
00973 ZYPP_THROW(UrlNotAllowedException(
00974 _("Url scheme does not allow a password")
00975 ));
00976 }
00977
00978 if(eflag == zypp::url::E_ENCODED)
00979 {
00980 checkUrlData(pass, "password", config("rx_password"), false);
00981
00982 m_data->pass = pass;
00983 }
00984 else
00985 {
00986 m_data->pass = zypp::url::encode(
00987 pass, config("safe_password")
00988 );
00989 }
00990 }
00991 }
00992
00993
00994
00995 void
00996 UrlBase::setHost(const std::string &host)
00997 {
00998 if( host.empty())
00999 {
01000 if(config("require_host") == "m")
01001 {
01002 ZYPP_THROW(UrlNotAllowedException(
01003 _("Url scheme requires a host component")
01004 ));
01005 }
01006 m_data->host = host;
01007 }
01008 else
01009 {
01010 if( config("with_authority") != "y")
01011 {
01012 ZYPP_THROW(UrlNotAllowedException(
01013 _("Url scheme does not allow a host component")
01014 ));
01015 }
01016
01017 if( isValidHost(host))
01018 {
01019 std::string temp;
01020
01021
01022
01023
01024 if( host.at(0) == '[')
01025 {
01026 temp = str::toUpper(zypp::url::decode(host));
01027 }
01028 else
01029 {
01030 temp = str::toLower(zypp::url::decode(host));
01031 }
01032
01033 m_data->host = zypp::url::encode(
01034 temp, config("safe_hostname")
01035 );
01036 }
01037 else
01038 {
01039 ZYPP_THROW(UrlBadComponentException(
01040 str::form(_("Invalid host component '%s'"), host.c_str())
01041 ));
01042 }
01043 }
01044 }
01045
01046
01047
01048 void
01049 UrlBase::setPort(const std::string &port)
01050 {
01051 if( port.empty())
01052 {
01053 m_data->port = port;
01054 }
01055 else
01056 {
01057 if( config("with_authority") != "y" ||
01058 config("with_port") != "y")
01059 {
01060 ZYPP_THROW(UrlNotAllowedException(
01061 _("Url scheme does not allow a port")
01062 ));
01063 }
01064
01065 if( isValidPort(port))
01066 {
01067 m_data->port = port;
01068 }
01069 else
01070 {
01071 ZYPP_THROW(UrlBadComponentException(
01072 str::form(_("Invalid port component '%s'"), port.c_str())
01073 ));
01074 }
01075 }
01076 }
01077
01078
01079
01080 void
01081 UrlBase::setPathName(const std::string &path,
01082 EEncoding eflag)
01083 {
01084 if( path.empty())
01085 {
01086 if(config("require_pathname") == "m")
01087 {
01088 ZYPP_THROW(UrlNotAllowedException(
01089 _("Url scheme requires path name")
01090 ));
01091 }
01092 m_data->pathname = path;
01093 }
01094 else
01095 {
01096 if(eflag == zypp::url::E_ENCODED)
01097 {
01098 checkUrlData(path, "path name", config("rx_pathname"));
01099
01100 if( !getHost(zypp::url::E_ENCODED).empty())
01101 {
01102
01103
01104
01105
01106 if(!(path.at(0) == '/' || (path.size() >= 3 &&
01107 str::toLower(path.substr(0, 3)) == "%2f")))
01108 {
01109 ZYPP_THROW(UrlNotAllowedException(
01110 _("Relative path not allowed if authority exists")
01111 ));
01112 }
01113 }
01114
01115 m_data->pathname = cleanupPathName(path);
01116 }
01117 else
01118 {
01119 if( !getHost(zypp::url::E_ENCODED).empty())
01120 {
01121 if(path.at(0) != '/')
01122 {
01123 ZYPP_THROW(UrlNotAllowedException(
01124 _("Relative path not allowed if authority exists")
01125 ));
01126 }
01127 }
01128
01129 m_data->pathname = cleanupPathName(
01130 zypp::url::encode(
01131 path, config("safe_pathname")
01132 )
01133 );
01134 }
01135 }
01136 }
01137
01138
01139
01140 void
01141 UrlBase::setPathParams(const std::string ¶ms)
01142 {
01143 if( params.empty())
01144 {
01145 m_data->pathparams = params;
01146 }
01147 else
01148 {
01149 checkUrlData(params, "path parameters", config("rx_pathparams"));
01150
01151 m_data->pathparams = params;
01152 }
01153 }
01154
01155
01156
01157 void
01158 UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec)
01159 {
01160 setPathParams(
01161 zypp::url::join(
01162 pvec,
01163 config("psep_pathparam")
01164 )
01165 );
01166 }
01167
01168
01169
01170 void
01171 UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap)
01172 {
01173 if( config("psep_pathparam").empty() ||
01174 config("vsep_pathparam").empty())
01175 {
01176 ZYPP_THROW(UrlNotSupportedException(
01177 _("Path Parameter parsing not supported for this URL")
01178 ));
01179 }
01180 setPathParams(
01181 zypp::url::join(
01182 pmap,
01183 config("psep_pathparam"),
01184 config("vsep_pathparam"),
01185 config("safe_pathparams")
01186 )
01187 );
01188 }
01189
01190
01191
01192 void
01193 UrlBase::setPathParam(const std::string ¶m, const std::string &value)
01194 {
01195 zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED));
01196 pmap[param] = value;
01197 setPathParamsMap(pmap);
01198 }
01199
01200
01201
01202 void
01203 UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec)
01204 {
01205 setQueryString(
01206 zypp::url::join(
01207 pvec,
01208 config("psep_querystr")
01209 )
01210 );
01211 }
01212
01213
01214
01215 void
01216 UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap)
01217 {
01218 if( config("psep_querystr").empty() ||
01219 config("vsep_querystr").empty())
01220 {
01221 ZYPP_THROW(UrlNotSupportedException(
01222 _("Query string parsing not supported for this URL")
01223 ));
01224 }
01225 setQueryString(
01226 zypp::url::join(
01227 pmap,
01228 config("psep_querystr"),
01229 config("vsep_querystr"),
01230 config("safe_querystr")
01231 )
01232 );
01233 }
01234
01235
01236 void
01237 UrlBase::setQueryParam(const std::string ¶m, const std::string &value)
01238 {
01239 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
01240 pmap[param] = value;
01241 setQueryStringMap(pmap);
01242 }
01243
01244
01245
01246 std::string
01247 UrlBase::cleanupPathName(const std::string &path) const
01248 {
01249 bool authority = !getHost(zypp::url::E_ENCODED).empty();
01250 return cleanupPathName(path, authority);
01251 }
01252
01253
01254 std::string
01255 UrlBase::cleanupPathName(const std::string &path, bool authority) const
01256 {
01257 std::string copy( path);
01258
01259
01260 if(copy.size() >= 3 && copy.at(0) != '/' &&
01261 str::toLower(copy.substr(0, 3)) == "%2f")
01262 {
01263 copy.replace(0, 3, "/");
01264 }
01265
01266
01267
01268
01269
01270 if( authority)
01271 {
01272
01273
01274
01275 if(config("path_encode_slash2") == "y")
01276 {
01277
01278 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
01279 {
01280 copy.replace(1, 1, "%2F");
01281 }
01282 }
01283 else
01284 {
01285
01286 if(copy.size() >= 4 && copy.at(0) == '/' &&
01287 str::toLower(copy.substr(1, 4)) == "%2f")
01288 {
01289 copy.replace(1, 4, "/");
01290 }
01291 }
01292 }
01293 else
01294 {
01295
01296 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
01297 {
01298 copy.replace(1, 1, "%2F");
01299 }
01300 }
01301 return copy;
01302 }
01303
01304
01305
01306 bool
01307 UrlBase::isValidHost(const std::string &host) const
01308 {
01309 try
01310 {
01311 str::regex regx(RX_VALID_HOSTIPV6);
01312 if( str::regex_match(host, regx))
01313 {
01314 struct in6_addr ip;
01315 std::string temp( host.substr(1, host.size()-2));
01316
01317 return inet_pton(AF_INET6, temp.c_str(), &ip) > 0;
01318 }
01319 else
01320 {
01321
01322 std::string temp( zypp::url::decode(host));
01323 str::regex regx(RX_VALID_HOSTNAME);
01324 return str::regex_match(temp, regx);
01325 }
01326 }
01327 catch( ... )
01328 {}
01329
01330 return false;
01331 }
01332
01333
01334
01335 bool
01336 UrlBase::isValidPort(const std::string &port) const
01337 {
01338 try
01339 {
01340 str::regex regx(RX_VALID_PORT);
01341 if( str::regex_match(port, regx))
01342 {
01343 long pnum = str::strtonum<long>(port);
01344 return ( pnum >= 1 && pnum <= USHRT_MAX);
01345 }
01346 }
01347 catch( ... )
01348 {}
01349
01350 return false;
01351 }
01352
01353
01355 }
01357
01359 }
01361
01362
01363