1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
10 * \file zypp/url/UrlBase.cc
12 #include "zypp/url/UrlBase.h"
13 #include "zypp/base/String.h"
14 #include "zypp/base/Gettext.h"
15 #include "zypp/base/Regex.h"
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <arpa/inet.h>
26 // in the Estonian locale, a-z excludes t, for example. #302525
27 // http://en.wikipedia.org/wiki/Estonian_alphabet
28 #define a_zA_Z "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
30 // ---------------------------------------------------------------
32 ** authority = //[user [:password] @ ] host [:port]
34 ** host = hostname | IPv4 | "[" IPv6-IP "]" | "[v...]"
36 #define RX_VALID_SCHEME "^[" a_zA_Z "][" a_zA_Z "0-9\\.+-]*$"
38 #define RX_VALID_PORT "^[0-9]{1,5}$"
40 #define RX_VALID_HOSTNAME "^[[:alnum:]]+([\\.-][[:alnum:]]+)*$"
42 #define RX_VALID_HOSTIPV4 \
43 "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$"
45 #define RX_VALID_HOSTIPV6 \
46 "^\\[[:a-fA-F0-9]+(:[0-9]{1,3}(\\.[0-9]{1,3}){3})?\\]$"
49 //////////////////////////////////////////////////////////////////////
51 { ////////////////////////////////////////////////////////////////////
53 ////////////////////////////////////////////////////////////////////
55 { //////////////////////////////////////////////////////////////////
58 // ---------------------------------------------------------------
60 ** URL asString() view option constants:
62 const ViewOption ViewOption::WITH_SCHEME = 0x0001;
63 const ViewOption ViewOption::WITH_USERNAME = 0x0002;
64 const ViewOption ViewOption::WITH_PASSWORD = 0x0004;
65 const ViewOption ViewOption::WITH_HOST = 0x0008;
66 const ViewOption ViewOption::WITH_PORT = 0x0010;
67 const ViewOption ViewOption::WITH_PATH_NAME = 0x0020;
68 const ViewOption ViewOption::WITH_PATH_PARAMS = 0x0040;
69 const ViewOption ViewOption::WITH_QUERY_STR = 0x0080;
70 const ViewOption ViewOption::WITH_FRAGMENT = 0x0100;
71 const ViewOption ViewOption::EMPTY_AUTHORITY = 0x0200;
72 const ViewOption ViewOption::EMPTY_PATH_NAME = 0x0400;
73 const ViewOption ViewOption::EMPTY_PATH_PARAMS = 0x0800;
74 const ViewOption ViewOption::EMPTY_QUERY_STR = 0x1000;
75 const ViewOption ViewOption::EMPTY_FRAGMENT = 0x2000;
76 const ViewOption ViewOption::DEFAULTS = 0x07bb;
78 const ViewOption ViewOption::DEFAULTS =
79 ViewOption::WITH_SCHEME +
80 ViewOption::WITH_USERNAME +
81 ViewOption::WITH_HOST +
82 ViewOption::WITH_PORT +
83 ViewOption::WITH_PATH_NAME +
84 ViewOption::WITH_QUERY_STR +
85 ViewOption::WITH_FRAGMENT +
86 ViewOption::EMPTY_AUTHORITY +
87 ViewOption::EMPTY_PATH_NAME;
90 // ---------------------------------------------------------------
91 ViewOption::ViewOption()
95 // ---------------------------------------------------------------
96 ViewOption::ViewOption(int option)
101 // ---------------------------------------------------------------
103 ** Behaviour configuration variables.
105 typedef std::map< std::string, std::string > UrlConfig;
108 // ---------------------------------------------------------------
110 * \brief Internal data used by UrlBase.
118 UrlBaseData(const UrlConfig &conf)
130 std::string pathname;
131 std::string pathparams;
132 std::string querystr;
133 std::string fragment;
137 // ---------------------------------------------------------------
139 ** Anonymous/internal utility namespace:
141 namespace // anonymous
144 // -------------------------------------------------------------
146 checkUrlData(const std::string &data,
147 const std::string &name,
148 const std::string ®x,
151 if( regx.empty() || regx == "^$")
153 ZYPP_THROW(UrlNotAllowedException(
154 str::form(_("Url scheme does not allow a %s"), name.c_str())
162 str::regex rex(regx);
163 valid = str::regex_match(data, rex);
172 ZYPP_THROW(UrlBadComponentException(
173 str::form(_("Invalid %s component '%s'"),
174 name.c_str(), data.c_str())
179 ZYPP_THROW(UrlBadComponentException(
180 str::form(_("Invalid %s component"), name.c_str())
190 // ---------------------------------------------------------------
198 // ---------------------------------------------------------------
200 : m_data( new UrlBaseData())
206 // ---------------------------------------------------------------
207 UrlBase::UrlBase(const UrlBase &url)
208 : m_data( new UrlBaseData( *(url.m_data)))
213 // ---------------------------------------------------------------
214 UrlBase::UrlBase(const std::string &scheme,
215 const std::string &authority,
216 const std::string &pathdata,
217 const std::string &querystr,
218 const std::string &fragment)
219 : m_data( new UrlBaseData())
222 init(scheme, authority, pathdata, querystr, fragment);
226 // ---------------------------------------------------------------
228 UrlBase::init(const std::string &scheme,
229 const std::string &authority,
230 const std::string &pathdata,
231 const std::string &querystr,
232 const std::string &fragment)
235 setAuthority(authority);
236 setPathData(pathdata);
237 setQueryString(querystr);
238 setFragment(fragment, zypp::url::E_ENCODED);
242 // ---------------------------------------------------------------
246 config("sep_pathparams", ";");
247 config("psep_pathparam", ",");
248 config("vsep_pathparam", "=");
250 config("psep_querystr", "&");
251 config("vsep_querystr", "=");
253 config("safe_username", "~!$&'()*+=,;");
254 config("safe_password", "~!$&'()*+=,:;");
255 config("safe_hostname", "[:]");
256 config("safe_pathname", "~!$&'()*+=,:@/");
257 config("safe_pathparams", "~!$&'()*+=,:;@/");
258 config("safe_querystr", "~!$&'()*+=,:;@/?");
259 config("safe_fragment", "~!$&'()*+=,:;@/?");
262 // n=no (disallowed, exception if !empty)
263 config("with_authority", "y");
264 config("with_port", "y");
266 // y=yes (required but don't throw if empty)
267 // n=no (not required, ignore if empty)
268 // m=mandatory (exception if empty)
269 config("require_host", "n");
270 config("require_pathname","n");
272 // y=yes (encode 2. slash even if authority present)
273 // n=no (don't encode 2. slash if authority present)
274 config("path_encode_slash2", "n");
276 config("rx_username", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,;~\\._-]|%[a-fA-F0-9]{2})+$");
277 config("rx_password", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,:;~\\._-]|%[a-fA-F0-9]{2})+$");
279 config("rx_pathname", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,:@/~\\._-]|%[a-fA-F0-9]{2})+$");
280 config("rx_pathparams", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,:;@/~\\._-]|%[a-fA-F0-9]{2})+$");
282 config("rx_querystr", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
283 config("rx_fragment", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
287 // ---------------------------------------------------------------
289 UrlBase::config(const std::string &opt, const std::string &val)
291 m_data->config[opt] = val;
295 // ---------------------------------------------------------------
297 UrlBase::config(const std::string &opt) const
299 UrlConfig::const_iterator v( m_data->config.find(opt));
300 if( v != m_data->config.end())
303 return std::string();
307 // ---------------------------------------------------------------
309 UrlBase::getViewOptions() const
311 return m_data->vopts;
315 // ---------------------------------------------------------------
317 UrlBase::setViewOptions(const ViewOptions &vopts)
319 m_data->vopts = vopts;
323 // ---------------------------------------------------------------
327 zypp::url::UrlConfig config(m_data->config);
328 zypp::url::ViewOptions vopts(m_data->vopts);
329 *m_data = UrlBaseData();
330 m_data->config = config;
331 m_data->vopts = vopts;
335 // ---------------------------------------------------------------
337 UrlBase::clone() const
339 return new UrlBase(*this);
343 // ---------------------------------------------------------------
344 zypp::url::UrlSchemes
345 UrlBase::getKnownSchemes() const
351 // ---------------------------------------------------------------
353 UrlBase::isKnownScheme(const std::string &scheme) const
355 std::string lscheme( str::toLower(scheme));
356 UrlSchemes schemes( getKnownSchemes());
357 UrlSchemes::const_iterator s;
359 for(s=schemes.begin(); s!=schemes.end(); ++s)
361 if( lscheme == str::toLower(*s))
368 // ---------------------------------------------------------------
370 UrlBase::isValidScheme(const std::string &scheme) const
375 str::regex rex(RX_VALID_SCHEME);
376 valid = str::regex_match(scheme, rex);
383 std::string lscheme( str::toLower(scheme));
384 UrlSchemes schemes( getKnownSchemes());
389 UrlSchemes::const_iterator s;
390 for(s=schemes.begin(); s!=schemes.end(); ++s)
392 if( lscheme == str::toLower(*s))
400 // ---------------------------------------------------------------
402 UrlBase::isValid() const
405 ** scheme is the only mandatory component
406 ** for all url's and is already verified,
407 ** (except for empty Url instances), so
408 ** Url with empty scheme is never valid.
410 if( getScheme().empty())
413 std::string host( getHost(zypp::url::E_ENCODED));
414 if( host.empty() && config("require_host") != "n")
417 std::string path( getPathName(zypp::url::E_ENCODED));
418 if( path.empty() && config("require_pathname") != "n")
422 ** path has to begin with "/" if authority avaliable
423 ** if host is set after the pathname, we can't throw
425 if( !host.empty() && !path.empty() && path.at(0) != '/')
432 // ---------------------------------------------------------------
434 UrlBase::asString() const
436 return asString(getViewOptions());
440 // ---------------------------------------------------------------
442 UrlBase::asString(const zypp::url::ViewOptions &opts) const
447 if( opts.has(ViewOptions::WITH_SCHEME))
449 tmp.scheme = getScheme();
450 if( !tmp.scheme.empty())
452 url += tmp.scheme + ":";
454 if( opts.has(ViewOptions::WITH_HOST))
456 tmp.host = getHost(zypp::url::E_ENCODED);
457 if( !tmp.host.empty())
461 if( opts.has(ViewOptions::WITH_USERNAME))
463 tmp.user = getUsername(zypp::url::E_ENCODED);
464 if( !tmp.user.empty())
468 if( opts.has(ViewOptions::WITH_PASSWORD))
470 tmp.pass = getPassword(zypp::url::E_ENCODED);
471 if( !tmp.pass.empty())
473 url += ":" + tmp.pass;
482 if( opts.has(ViewOptions::WITH_PORT))
484 tmp.port = getPort();
485 if( !tmp.port.empty())
487 url += ":" + tmp.port;
491 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
496 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
503 if( opts.has(ViewOptions::WITH_PATH_NAME))
505 tmp.pathname = getPathName(zypp::url::E_ENCODED);
506 if( !tmp.pathname.empty())
508 if(url.find("/") != std::string::npos)
510 // Url contains authority (that may be empty),
511 // we may need a rewrite of the encoded path.
512 tmp.pathname = cleanupPathName(tmp.pathname, true);
513 if(tmp.pathname.at(0) != '/')
520 if( opts.has(ViewOptions::WITH_PATH_PARAMS))
522 tmp.pathparams = getPathParams();
523 if( !tmp.pathparams.empty())
525 url += ";" + tmp.pathparams;
527 else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
533 else if( opts.has(ViewOptions::EMPTY_PATH_NAME)
534 && url.find("/") != std::string::npos)
537 if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
544 if( opts.has(ViewOptions::WITH_QUERY_STR))
546 tmp.querystr = getQueryString();
547 if( !tmp.querystr.empty())
549 url += "?" + tmp.querystr;
551 else if( opts.has(ViewOptions::EMPTY_QUERY_STR))
557 if( opts.has(ViewOptions::WITH_FRAGMENT))
559 tmp.fragment = getFragment(zypp::url::E_ENCODED);
560 if( !tmp.fragment.empty())
562 url += "#" + tmp.fragment;
564 else if( opts.has(ViewOptions::EMPTY_FRAGMENT))
574 // ---------------------------------------------------------------
576 UrlBase::getScheme() const
578 return m_data->scheme;
582 // ---------------------------------------------------------------
584 UrlBase::getAuthority() const
587 if( !getHost(zypp::url::E_ENCODED).empty())
589 if( !getUsername(zypp::url::E_ENCODED).empty())
591 str = getUsername(zypp::url::E_ENCODED);
592 if( !getPassword(zypp::url::E_ENCODED).empty())
594 str += ":" + getPassword(zypp::url::E_ENCODED);
599 str += getHost(zypp::url::E_ENCODED);
600 if( !getPort().empty())
602 str += ":" + getPort();
609 // ---------------------------------------------------------------
611 UrlBase::getPathData() const
613 return getPathName(zypp::url::E_ENCODED) +
614 config("sep_pathparams") +
619 // ---------------------------------------------------------------
621 UrlBase::getQueryString() const
623 return m_data->querystr;
627 // ---------------------------------------------------------------
629 UrlBase::getFragment(EEncoding eflag) const
631 if(eflag == zypp::url::E_DECODED)
632 return zypp::url::decode(m_data->fragment);
634 return m_data->fragment;
638 // ---------------------------------------------------------------
640 UrlBase::getUsername(EEncoding eflag) const
642 if(eflag == zypp::url::E_DECODED)
643 return zypp::url::decode(m_data->user);
649 // ---------------------------------------------------------------
651 UrlBase::getPassword(EEncoding eflag) const
653 if(eflag == zypp::url::E_DECODED)
654 return zypp::url::decode(m_data->pass);
660 // ---------------------------------------------------------------
662 UrlBase::getHost(EEncoding eflag) const
664 if(eflag == zypp::url::E_DECODED)
665 return zypp::url::decode(m_data->host);
671 // ---------------------------------------------------------------
673 UrlBase::getPort() const
679 // ---------------------------------------------------------------
681 UrlBase::getPathName(EEncoding eflag) const
683 if(eflag == zypp::url::E_DECODED)
684 return zypp::url::decode(m_data->pathname);
686 return cleanupPathName(m_data->pathname);
690 // ---------------------------------------------------------------
692 UrlBase::getPathParams() const
694 return m_data->pathparams;
698 // ---------------------------------------------------------------
700 UrlBase::getPathParamsVec() const
702 zypp::url::ParamVec pvec;
703 if( config("psep_pathparam").empty())
705 pvec.push_back(getPathParams());
712 config("psep_pathparam")
719 // ---------------------------------------------------------------
721 UrlBase::getPathParamsMap(EEncoding eflag) const
723 if( config("psep_pathparam").empty() ||
724 config("vsep_pathparam").empty())
726 ZYPP_THROW(UrlNotSupportedException(
727 "Path parameter parsing not supported for this URL"
730 zypp::url::ParamMap pmap;
734 config("psep_pathparam"),
735 config("vsep_pathparam"),
742 // ---------------------------------------------------------------
744 UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const
746 zypp::url::ParamMap pmap( getPathParamsMap( eflag));
747 zypp::url::ParamMap::const_iterator i( pmap.find(param));
749 return i != pmap.end() ? i->second : std::string();
753 // ---------------------------------------------------------------
755 UrlBase::getQueryStringVec() const
757 zypp::url::ParamVec pvec;
758 if( config("psep_querystr").empty())
760 pvec.push_back(getQueryString());
767 config("psep_querystr")
774 // ---------------------------------------------------------------
776 UrlBase::getQueryStringMap(EEncoding eflag) const
778 if( config("psep_querystr").empty() ||
779 config("vsep_querystr").empty())
781 ZYPP_THROW(UrlNotSupportedException(
782 _("Query string parsing not supported for this URL")
785 zypp::url::ParamMap pmap;
789 config("psep_querystr"),
790 config("vsep_querystr"),
797 // ---------------------------------------------------------------
799 UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const
801 zypp::url::ParamMap pmap( getQueryStringMap( eflag));
802 zypp::url::ParamMap::const_iterator i( pmap.find(param));
804 return i != pmap.end() ? i->second : std::string();
808 // ---------------------------------------------------------------
810 UrlBase::setScheme(const std::string &scheme)
812 if( isValidScheme(scheme))
814 m_data->scheme = str::toLower(scheme);
819 ZYPP_THROW(UrlBadComponentException(
820 _("Url scheme is a required component")
825 ZYPP_THROW(UrlBadComponentException(
826 str::form(_("Invalid Url scheme '%s'"), scheme.c_str())
832 // ---------------------------------------------------------------
834 UrlBase::setAuthority(const std::string &authority)
836 std::string s = authority;
837 std::string::size_type p,q;
839 std::string username, password, host, port;
841 if ((p=s.find('@')) != std::string::npos)
844 if (q != std::string::npos && q < p)
846 setUsername(s.substr(0, q), zypp::url::E_ENCODED);
847 setPassword(s.substr(q+1, p-q-1), zypp::url::E_ENCODED);
850 setUsername(s.substr(0, p), zypp::url::E_ENCODED);
853 if ((p = s.rfind(':')) != std::string::npos && ( (q = s.rfind(']')) == std::string::npos || q < p) )
855 setHost(s.substr(0, p));
856 setPort(s.substr(p+1));
862 // ---------------------------------------------------------------
864 UrlBase::setPathData(const std::string &pathdata)
866 size_t pos = std::string::npos;
867 std::string sep(config("sep_pathparams"));
870 pos = pathdata.find(sep);
872 if( pos != std::string::npos)
874 setPathName(pathdata.substr(0, pos),
875 zypp::url::E_ENCODED);
876 setPathParams(pathdata.substr(pos + 1));
880 setPathName(pathdata,
881 zypp::url::E_ENCODED);
887 // ---------------------------------------------------------------
889 UrlBase::setQueryString(const std::string &querystr)
891 if( querystr.empty())
893 m_data->querystr = querystr;
897 checkUrlData(querystr, "query string", config("rx_querystr"));
899 m_data->querystr = querystr;
904 // ---------------------------------------------------------------
906 UrlBase::setFragment(const std::string &fragment,
909 if( fragment.empty())
911 m_data->fragment = fragment;
915 if(eflag == zypp::url::E_ENCODED)
917 checkUrlData(fragment, "fragment", config("rx_fragment"));
919 m_data->fragment = fragment;
923 m_data->fragment = zypp::url::encode(
924 fragment, config("safe_fragment")
931 // ---------------------------------------------------------------
933 UrlBase::setUsername(const std::string &user,
942 if( config("with_authority") != "y")
944 ZYPP_THROW(UrlNotAllowedException(
945 _("Url scheme does not allow a username")
949 if(eflag == zypp::url::E_ENCODED)
951 checkUrlData(user, "username", config("rx_username"));
957 m_data->user = zypp::url::encode(
958 user, config("safe_username")
965 // ---------------------------------------------------------------
967 UrlBase::setPassword(const std::string &pass,
976 if( config("with_authority") != "y")
978 ZYPP_THROW(UrlNotAllowedException(
979 _("Url scheme does not allow a password")
983 if(eflag == zypp::url::E_ENCODED)
985 checkUrlData(pass, "password", config("rx_password"), false);
991 m_data->pass = zypp::url::encode(
992 pass, config("safe_password")
999 // ---------------------------------------------------------------
1001 UrlBase::setHost(const std::string &host)
1005 if(config("require_host") == "m")
1007 ZYPP_THROW(UrlNotAllowedException(
1008 _("Url scheme requires a host component")
1011 m_data->host = host;
1015 if( config("with_authority") != "y")
1017 ZYPP_THROW(UrlNotAllowedException(
1018 _("Url scheme does not allow a host component")
1022 if( isValidHost(host))
1026 // always decode in case isValidHost()
1027 // is reimplemented and supports also
1028 // the [v ... ] notation.
1029 if( host.at(0) == '[')
1031 temp = str::toUpper(zypp::url::decode(host));
1035 temp = str::toLower(zypp::url::decode(host));
1038 m_data->host = zypp::url::encode(
1039 temp, config("safe_hostname")
1044 ZYPP_THROW(UrlBadComponentException(
1045 str::form(_("Invalid host component '%s'"), host.c_str())
1052 // ---------------------------------------------------------------
1054 UrlBase::setPort(const std::string &port)
1058 m_data->port = port;
1062 if( config("with_authority") != "y" ||
1063 config("with_port") != "y")
1065 ZYPP_THROW(UrlNotAllowedException(
1066 _("Url scheme does not allow a port")
1070 if( isValidPort(port))
1072 m_data->port = port;
1076 ZYPP_THROW(UrlBadComponentException(
1077 str::form(_("Invalid port component '%s'"), port.c_str())
1084 // ---------------------------------------------------------------
1086 UrlBase::setPathName(const std::string &path,
1091 if(config("require_pathname") == "m")
1093 ZYPP_THROW(UrlNotAllowedException(
1094 _("Url scheme requires path name")
1097 m_data->pathname = path;
1101 if(eflag == zypp::url::E_ENCODED)
1103 checkUrlData(path, "path name", config("rx_pathname"));
1105 if( !getHost(zypp::url::E_ENCODED).empty())
1107 // has to begin with a "/". For consistency with
1108 // setPathName while the host is empty, we allow
1109 // it in encoded ("%2f") form - cleanupPathName()
1110 // will fix / decode the first slash if needed.
1111 if(!(path.at(0) == '/' || (path.size() >= 3 &&
1112 str::toLower(path.substr(0, 3)) == "%2f")))
1114 ZYPP_THROW(UrlNotAllowedException(
1115 _("Relative path not allowed if authority exists")
1120 m_data->pathname = cleanupPathName(path);
1122 else // zypp::url::E_DECODED
1124 if( !getHost(zypp::url::E_ENCODED).empty())
1126 if(path.at(0) != '/')
1128 ZYPP_THROW(UrlNotAllowedException(
1129 _("Relative path not allowed if authority exists")
1134 m_data->pathname = cleanupPathName(
1136 path, config("safe_pathname")
1144 // ---------------------------------------------------------------
1146 UrlBase::setPathParams(const std::string ¶ms)
1150 m_data->pathparams = params;
1154 checkUrlData(params, "path parameters", config("rx_pathparams"));
1156 m_data->pathparams = params;
1161 // ---------------------------------------------------------------
1163 UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec)
1168 config("psep_pathparam")
1174 // ---------------------------------------------------------------
1176 UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap)
1178 if( config("psep_pathparam").empty() ||
1179 config("vsep_pathparam").empty())
1181 ZYPP_THROW(UrlNotSupportedException(
1182 "Path Parameter parsing not supported for this URL"
1188 config("psep_pathparam"),
1189 config("vsep_pathparam"),
1190 config("safe_pathparams")
1196 // ---------------------------------------------------------------
1198 UrlBase::setPathParam(const std::string ¶m, const std::string &value)
1200 zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED));
1201 pmap[param] = value;
1202 setPathParamsMap(pmap);
1206 // ---------------------------------------------------------------
1208 UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec)
1213 config("psep_querystr")
1219 // ---------------------------------------------------------------
1221 UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap)
1223 if( config("psep_querystr").empty() ||
1224 config("vsep_querystr").empty())
1226 ZYPP_THROW(UrlNotSupportedException(
1227 _("Query string parsing not supported for this URL")
1233 config("psep_querystr"),
1234 config("vsep_querystr"),
1235 config("safe_querystr")
1240 // ---------------------------------------------------------------
1242 UrlBase::setQueryParam(const std::string ¶m, const std::string &value)
1244 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
1245 pmap[param] = value;
1246 setQueryStringMap(pmap);
1249 // ---------------------------------------------------------------
1251 UrlBase::delQueryParam(const std::string ¶m)
1253 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
1255 setQueryStringMap(pmap);
1259 // ---------------------------------------------------------------
1261 UrlBase::cleanupPathName(const std::string &path) const
1263 bool authority = !getHost(zypp::url::E_ENCODED).empty();
1264 return cleanupPathName(path, authority);
1267 // ---------------------------------------------------------------
1269 UrlBase::cleanupPathName(const std::string &path, bool authority) const
1271 std::string copy( path);
1273 // decode the first slash if it is encoded ...
1274 if(copy.size() >= 3 && copy.at(0) != '/' &&
1275 str::toLower(copy.substr(0, 3)) == "%2f")
1277 copy.replace(0, 3, "/");
1280 // if path begins with a double slash ("//"); encode the second
1281 // slash [minimal and IMO sufficient] before the first path
1282 // segment, to fulfill the path-absolute rule of RFC 3986
1283 // disallowing a "//" if no authority is present.
1287 // rewrite of "//" to "/%2f" not required, use config
1289 if(config("path_encode_slash2") == "y")
1291 // rewrite "//" ==> "/%2f"
1292 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1294 copy.replace(1, 1, "%2F");
1299 // rewrite "/%2f" ==> "//"
1300 if(copy.size() >= 4 && copy.at(0) == '/' &&
1301 str::toLower(copy.substr(1, 4)) == "%2f")
1303 copy.replace(1, 4, "/");
1309 // rewrite of "//" to "/%2f" is required (no authority)
1310 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1312 copy.replace(1, 1, "%2F");
1319 // ---------------------------------------------------------------
1321 UrlBase::isValidHost(const std::string &host) const
1325 str::regex regx(RX_VALID_HOSTIPV6);
1326 if( str::regex_match(host, regx))
1329 std::string temp( host.substr(1, host.size()-2));
1331 return inet_pton(AF_INET6, temp.c_str(), &ip) > 0;
1335 // matches also IPv4 dotted-decimal adresses...
1336 std::string temp( zypp::url::decode(host));
1337 str::regex regx(RX_VALID_HOSTNAME);
1338 return str::regex_match(temp, regx);
1348 // ---------------------------------------------------------------
1350 UrlBase::isValidPort(const std::string &port) const
1354 str::regex regx(RX_VALID_PORT);
1355 if( str::regex_match(port, regx))
1357 long pnum = str::strtonum<long>(port);
1358 return ( pnum >= 1 && pnum <= USHRT_MAX);
1367 //////////////////////////////////////////////////////////////////
1369 ////////////////////////////////////////////////////////////////////
1371 ////////////////////////////////////////////////////////////////////
1373 //////////////////////////////////////////////////////////////////////
1375 ** vim: set ts=2 sts=2 sw=2 ai et: