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>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <arpa/inet.h>
24 // ---------------------------------------------------------------
26 ** authority = //[user [:password] @ ] host [:port]
28 ** host = hostname | IPv4 | "[" IPv6-IP "]" | "[v...]"
30 #define RX_SPLIT_AUTHORITY \
31 "^(([^:@]*)([:]([^@]*))?@)?(\\[[^]]+\\]|[^:]+)?([:](.*))?"
33 #define RX_VALID_SCHEME "^[a-zA-Z][a-zA-Z0-9\\.+-]*$"
35 #define RX_VALID_PORT "^[0-9]{1,5}$"
37 #define RX_VALID_HOSTNAME "^[[:alnum:]]+([\\.-][[:alnum:]]+)*$"
39 #define RX_VALID_HOSTIPV4 \
40 "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$"
42 #define RX_VALID_HOSTIPV6 \
43 "^\\[[:a-fA-F0-9]+(:[0-9]{1,3}(\\.[0-9]{1,3}){3})?\\]$"
46 //////////////////////////////////////////////////////////////////////
48 { ////////////////////////////////////////////////////////////////////
50 ////////////////////////////////////////////////////////////////////
52 { //////////////////////////////////////////////////////////////////
55 // ---------------------------------------------------------------
57 ** URL asString() view option constants:
59 const ViewOption ViewOption::WITH_SCHEME = 0x0001;
60 const ViewOption ViewOption::WITH_USERNAME = 0x0002;
61 const ViewOption ViewOption::WITH_PASSWORD = 0x0004;
62 const ViewOption ViewOption::WITH_HOST = 0x0008;
63 const ViewOption ViewOption::WITH_PORT = 0x0010;
64 const ViewOption ViewOption::WITH_PATH_NAME = 0x0020;
65 const ViewOption ViewOption::WITH_PATH_PARAMS = 0x0040;
66 const ViewOption ViewOption::WITH_QUERY_STR = 0x0080;
67 const ViewOption ViewOption::WITH_FRAGMENT = 0x0100;
68 const ViewOption ViewOption::EMPTY_AUTHORITY = 0x0200;
69 const ViewOption ViewOption::EMPTY_PATH_NAME = 0x0400;
70 const ViewOption ViewOption::EMPTY_PATH_PARAMS = 0x0800;
71 const ViewOption ViewOption::EMPTY_QUERY_STR = 0x1000;
72 const ViewOption ViewOption::EMPTY_FRAGMENT = 0x2000;
73 const ViewOption ViewOption::DEFAULTS = 0x07bb;
75 const ViewOption ViewOption::DEFAULTS =
76 ViewOption::WITH_SCHEME +
77 ViewOption::WITH_USERNAME +
78 ViewOption::WITH_HOST +
79 ViewOption::WITH_PORT +
80 ViewOption::WITH_PATH_NAME +
81 ViewOption::WITH_QUERY_STR +
82 ViewOption::WITH_FRAGMENT +
83 ViewOption::EMPTY_AUTHORITY +
84 ViewOption::EMPTY_PATH_NAME;
87 // ---------------------------------------------------------------
88 ViewOption::ViewOption()
92 // ---------------------------------------------------------------
93 ViewOption::ViewOption(int option)
98 // ---------------------------------------------------------------
100 ** Behaviour configuration variables.
102 typedef std::map< std::string, std::string > UrlConfig;
105 // ---------------------------------------------------------------
107 * \brief Internal data used by UrlBase.
115 UrlBaseData(const UrlConfig &conf)
127 std::string pathname;
128 std::string pathparams;
129 std::string querystr;
130 std::string fragment;
134 // ---------------------------------------------------------------
136 ** Anonymous/internal utility namespace:
138 namespace // anonymous
141 // -------------------------------------------------------------
143 checkUrlData(const std::string &data,
144 const std::string &name,
145 const std::string ®x,
148 if( regx.empty() || regx == "^$")
150 ZYPP_THROW(UrlNotAllowedException(
151 str::form(_("Url scheme does not allow a %s"), name.c_str())
159 str::regex rex(regx);
160 valid = str::regex_match(data, rex);
169 ZYPP_THROW(UrlBadComponentException(
170 str::form(_("Invalid %s component '%s'"),
171 name.c_str(), data.c_str())
176 ZYPP_THROW(UrlBadComponentException(
177 str::form(_("Invalid %s component"), name.c_str())
187 // ---------------------------------------------------------------
195 // ---------------------------------------------------------------
197 : m_data( new UrlBaseData())
203 // ---------------------------------------------------------------
204 UrlBase::UrlBase(const UrlBase &url)
205 : m_data( new UrlBaseData( *(url.m_data)))
210 // ---------------------------------------------------------------
211 UrlBase::UrlBase(const std::string &scheme,
212 const std::string &authority,
213 const std::string &pathdata,
214 const std::string &querystr,
215 const std::string &fragment)
216 : m_data( new UrlBaseData())
219 init(scheme, authority, pathdata, querystr, fragment);
223 // ---------------------------------------------------------------
225 UrlBase::init(const std::string &scheme,
226 const std::string &authority,
227 const std::string &pathdata,
228 const std::string &querystr,
229 const std::string &fragment)
232 setAuthority(authority);
233 setPathData(pathdata);
234 setQueryString(querystr);
235 setFragment(fragment, zypp::url::E_ENCODED);
239 // ---------------------------------------------------------------
243 config("sep_pathparams", ";");
244 config("psep_pathparam", ",");
245 config("vsep_pathparam", "=");
247 config("psep_querystr", "&");
248 config("vsep_querystr", "=");
250 config("safe_username", "~!$&'()*+=,;");
251 config("safe_password", "~!$&'()*+=,:;");
252 config("safe_hostname", "[:]");
253 config("safe_pathname", "~!$&'()*+=,:@/");
254 config("safe_pathparams", "~!$&'()*+=,:;@/");
255 config("safe_querystr", "~!$&'()*+=,:;@/?");
256 config("safe_fragment", "~!$&'()*+=,:;@/?");
259 // n=no (disallowed, exception if !empty)
260 config("with_authority", "y");
261 config("with_port", "y");
263 // y=yes (required but don't throw if empty)
264 // n=no (not required, ignore if empty)
265 // m=mandatory (exception if empty)
266 config("require_host", "n");
267 config("require_pathname","n");
269 // y=yes (encode 2. slash even if authority present)
270 // n=no (don't encode 2. slash if authority present)
271 config("path_encode_slash2", "n");
273 config("rx_username", "^([a-zA-Z0-9!$&'\\(\\)*+=,;~\\._-]|%[a-fA-F0-9]{2})+$");
274 config("rx_password", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;~\\._-]|%[a-fA-F0-9]{2})+$");
276 config("rx_pathname", "^([a-zA-Z0-9!$&'\\(\\)*+=,:@/~\\._-]|%[a-fA-F0-9]{2})+$");
277 config("rx_pathparams", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/~\\._-]|%[a-fA-F0-9]{2})+$");
279 config("rx_querystr", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
280 config("rx_fragment", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
284 // ---------------------------------------------------------------
286 UrlBase::config(const std::string &opt, const std::string &val)
288 m_data->config[opt] = val;
292 // ---------------------------------------------------------------
294 UrlBase::config(const std::string &opt) const
296 UrlConfig::const_iterator v( m_data->config.find(opt));
297 if( v != m_data->config.end())
300 return std::string();
304 // ---------------------------------------------------------------
306 UrlBase::getViewOptions() const
308 return m_data->vopts;
312 // ---------------------------------------------------------------
314 UrlBase::setViewOptions(const ViewOptions &vopts)
316 m_data->vopts = vopts;
320 // ---------------------------------------------------------------
324 zypp::url::UrlConfig config(m_data->config);
325 zypp::url::ViewOptions vopts(m_data->vopts);
326 *m_data = UrlBaseData();
327 m_data->config = config;
328 m_data->vopts = vopts;
332 // ---------------------------------------------------------------
334 UrlBase::clone() const
336 return new UrlBase(*this);
340 // ---------------------------------------------------------------
341 zypp::url::UrlSchemes
342 UrlBase::getKnownSchemes() const
348 // ---------------------------------------------------------------
350 UrlBase::isKnownScheme(const std::string &scheme) const
352 std::string lscheme( str::toLower(scheme));
353 UrlSchemes schemes( getKnownSchemes());
354 UrlSchemes::const_iterator s;
356 for(s=schemes.begin(); s!=schemes.end(); ++s)
358 if( lscheme == str::toLower(*s))
365 // ---------------------------------------------------------------
367 UrlBase::isValidScheme(const std::string &scheme) const
372 str::regex rex(RX_VALID_SCHEME);
373 valid = str::regex_match(scheme, rex);
380 std::string lscheme( str::toLower(scheme));
381 UrlSchemes schemes( getKnownSchemes());
386 UrlSchemes::const_iterator s;
387 for(s=schemes.begin(); s!=schemes.end(); ++s)
389 if( lscheme == str::toLower(*s))
397 // ---------------------------------------------------------------
399 UrlBase::isValid() const
402 ** scheme is the only mandatory component
403 ** for all url's and is already verified,
404 ** (except for empty Url instances), so
405 ** Url with empty scheme is never valid.
407 if( getScheme().empty())
410 std::string host( getHost(zypp::url::E_ENCODED));
411 if( host.empty() && config("require_host") != "n")
414 std::string path( getPathName(zypp::url::E_ENCODED));
415 if( path.empty() && config("require_pathname") != "n")
419 ** path has to begin with "/" if authority avaliable
420 ** if host is set after the pathname, we can't throw
422 if( !host.empty() && !path.empty() && path.at(0) != '/')
429 // ---------------------------------------------------------------
431 UrlBase::asString() const
433 return asString(getViewOptions());
437 // ---------------------------------------------------------------
439 UrlBase::asString(const zypp::url::ViewOptions &opts) const
444 if( opts.has(ViewOptions::WITH_SCHEME))
446 tmp.scheme = getScheme();
447 if( !tmp.scheme.empty())
449 url += tmp.scheme + ":";
451 if( opts.has(ViewOptions::WITH_HOST))
453 tmp.host = getHost(zypp::url::E_ENCODED);
454 if( !tmp.host.empty())
458 if( opts.has(ViewOptions::WITH_USERNAME))
460 tmp.user = getUsername(zypp::url::E_ENCODED);
461 if( !tmp.user.empty())
465 if( opts.has(ViewOptions::WITH_PASSWORD))
467 tmp.pass = getPassword(zypp::url::E_ENCODED);
468 if( !tmp.pass.empty())
470 url += ":" + tmp.pass;
479 if( opts.has(ViewOptions::WITH_PORT))
481 tmp.port = getPort();
482 if( !tmp.port.empty())
484 url += ":" + tmp.port;
488 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
493 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
500 if( opts.has(ViewOptions::WITH_PATH_NAME))
502 tmp.pathname = getPathName(zypp::url::E_ENCODED);
503 if( !tmp.pathname.empty())
505 if(url.find("/") != std::string::npos)
507 // Url contains authority (that may be empty),
508 // we may need a rewrite of the encoded path.
509 tmp.pathname = cleanupPathName(tmp.pathname, true);
510 if(tmp.pathname.at(0) != '/')
517 if( opts.has(ViewOptions::WITH_PATH_PARAMS))
519 tmp.pathparams = getPathParams();
520 if( !tmp.pathparams.empty())
522 url += ";" + tmp.pathparams;
524 else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
530 else if( opts.has(ViewOptions::EMPTY_PATH_NAME)
531 && url.find("/") != std::string::npos)
534 if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
541 if( opts.has(ViewOptions::WITH_QUERY_STR))
543 tmp.querystr = getQueryString();
544 if( !tmp.querystr.empty())
546 url += "?" + tmp.querystr;
548 else if( opts.has(ViewOptions::EMPTY_QUERY_STR))
554 if( opts.has(ViewOptions::WITH_FRAGMENT))
556 tmp.fragment = getFragment(zypp::url::E_ENCODED);
557 if( !tmp.fragment.empty())
559 url += "#" + tmp.fragment;
561 else if( opts.has(ViewOptions::EMPTY_FRAGMENT))
571 // ---------------------------------------------------------------
573 UrlBase::getScheme() const
575 return m_data->scheme;
579 // ---------------------------------------------------------------
581 UrlBase::getAuthority() const
584 if( !getHost(zypp::url::E_ENCODED).empty())
586 if( !getUsername(zypp::url::E_ENCODED).empty())
588 str = getUsername(zypp::url::E_ENCODED);
589 if( !getPassword(zypp::url::E_ENCODED).empty())
591 str += ":" + getPassword(zypp::url::E_ENCODED);
596 str += getHost(zypp::url::E_ENCODED);
597 if( !getPort().empty())
599 str += ":" + getPort();
606 // ---------------------------------------------------------------
608 UrlBase::getPathData() const
610 return getPathName(zypp::url::E_ENCODED) +
611 config("sep_pathparams") +
616 // ---------------------------------------------------------------
618 UrlBase::getQueryString() const
620 return m_data->querystr;
624 // ---------------------------------------------------------------
626 UrlBase::getFragment(EEncoding eflag) const
628 if(eflag == zypp::url::E_DECODED)
629 return zypp::url::decode(m_data->fragment);
631 return m_data->fragment;
635 // ---------------------------------------------------------------
637 UrlBase::getUsername(EEncoding eflag) const
639 if(eflag == zypp::url::E_DECODED)
640 return zypp::url::decode(m_data->user);
646 // ---------------------------------------------------------------
648 UrlBase::getPassword(EEncoding eflag) const
650 if(eflag == zypp::url::E_DECODED)
651 return zypp::url::decode(m_data->pass);
657 // ---------------------------------------------------------------
659 UrlBase::getHost(EEncoding eflag) const
661 if(eflag == zypp::url::E_DECODED)
662 return zypp::url::decode(m_data->host);
668 // ---------------------------------------------------------------
670 UrlBase::getPort() const
676 // ---------------------------------------------------------------
678 UrlBase::getPathName(EEncoding eflag) const
680 if(eflag == zypp::url::E_DECODED)
681 return zypp::url::decode(m_data->pathname);
683 return cleanupPathName(m_data->pathname);
687 // ---------------------------------------------------------------
689 UrlBase::getPathParams() const
691 return m_data->pathparams;
695 // ---------------------------------------------------------------
697 UrlBase::getPathParamsVec() const
699 zypp::url::ParamVec pvec;
700 if( config("psep_pathparam").empty())
702 pvec.push_back(getPathParams());
709 config("psep_pathparam")
716 // ---------------------------------------------------------------
718 UrlBase::getPathParamsMap(EEncoding eflag) const
720 if( config("psep_pathparam").empty() ||
721 config("vsep_pathparam").empty())
723 ZYPP_THROW(UrlNotSupportedException(
724 _("Path parameter parsing not supported for this URL")
727 zypp::url::ParamMap pmap;
731 config("psep_pathparam"),
732 config("vsep_pathparam"),
739 // ---------------------------------------------------------------
741 UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const
743 zypp::url::ParamMap pmap( getPathParamsMap( eflag));
744 zypp::url::ParamMap::const_iterator i( pmap.find(param));
746 return i != pmap.end() ? i->second : std::string();
750 // ---------------------------------------------------------------
752 UrlBase::getQueryStringVec() const
754 zypp::url::ParamVec pvec;
755 if( config("psep_querystr").empty())
757 pvec.push_back(getQueryString());
764 config("psep_querystr")
771 // ---------------------------------------------------------------
773 UrlBase::getQueryStringMap(EEncoding eflag) const
775 if( config("psep_querystr").empty() ||
776 config("vsep_querystr").empty())
778 ZYPP_THROW(UrlNotSupportedException(
779 _("Query string parsing not supported for this URL")
782 zypp::url::ParamMap pmap;
786 config("psep_querystr"),
787 config("vsep_querystr"),
794 // ---------------------------------------------------------------
796 UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const
798 zypp::url::ParamMap pmap( getQueryStringMap( eflag));
799 zypp::url::ParamMap::const_iterator i( pmap.find(param));
801 return i != pmap.end() ? i->second : std::string();
805 // ---------------------------------------------------------------
807 UrlBase::setScheme(const std::string &scheme)
809 if( isValidScheme(scheme))
811 m_data->scheme = str::toLower(scheme);
816 ZYPP_THROW(UrlBadComponentException(
817 _("Url scheme is a required component")
822 ZYPP_THROW(UrlBadComponentException(
823 str::form(_("Invalid Url scheme '%s'"), scheme.c_str())
829 // ---------------------------------------------------------------
831 UrlBase::setAuthority(const std::string &authority)
838 str::regex rex(RX_SPLIT_AUTHORITY);
839 ret = str::regex_match(authority, out, rex);
844 if( ret && out.size() == 8)
846 setUsername(out[2].str(), zypp::url::E_ENCODED);
847 setPassword(out[4].str(), zypp::url::E_ENCODED);
848 setHost(out[5].str());
849 setPort(out[7].str());
853 ZYPP_THROW(UrlParsingException(
854 _("Unable to parse Url authority")
859 // ---------------------------------------------------------------
861 UrlBase::setPathData(const std::string &pathdata)
863 size_t pos = std::string::npos;
864 std::string sep(config("sep_pathparams"));
867 pos = pathdata.find(sep);
869 if( pos != std::string::npos)
871 setPathName(pathdata.substr(0, pos),
872 zypp::url::E_ENCODED);
873 setPathParams(pathdata.substr(pos + 1));
877 setPathName(pathdata,
878 zypp::url::E_ENCODED);
884 // ---------------------------------------------------------------
886 UrlBase::setQueryString(const std::string &querystr)
888 if( querystr.empty())
890 m_data->querystr = querystr;
894 checkUrlData(querystr, "query string", config("rx_querystr"));
896 m_data->querystr = querystr;
901 // ---------------------------------------------------------------
903 UrlBase::setFragment(const std::string &fragment,
906 if( fragment.empty())
908 m_data->fragment = fragment;
912 if(eflag == zypp::url::E_ENCODED)
914 checkUrlData(fragment, "fragment", config("rx_fragment"));
916 m_data->fragment = fragment;
920 m_data->fragment = zypp::url::encode(
921 fragment, config("safe_fragment")
928 // ---------------------------------------------------------------
930 UrlBase::setUsername(const std::string &user,
939 if( config("with_authority") != "y")
941 ZYPP_THROW(UrlNotAllowedException(
942 _("Url scheme does not allow a username")
946 if(eflag == zypp::url::E_ENCODED)
948 checkUrlData(user, "username", config("rx_username"));
954 m_data->user = zypp::url::encode(
955 user, config("safe_username")
962 // ---------------------------------------------------------------
964 UrlBase::setPassword(const std::string &pass,
973 if( config("with_authority") != "y")
975 ZYPP_THROW(UrlNotAllowedException(
976 _("Url scheme does not allow a password")
980 if(eflag == zypp::url::E_ENCODED)
982 checkUrlData(pass, "password", config("rx_password"), false);
988 m_data->pass = zypp::url::encode(
989 pass, config("safe_password")
996 // ---------------------------------------------------------------
998 UrlBase::setHost(const std::string &host)
1002 if(config("require_host") == "m")
1004 ZYPP_THROW(UrlNotAllowedException(
1005 _("Url scheme requires a host component")
1008 m_data->host = host;
1012 if( config("with_authority") != "y")
1014 ZYPP_THROW(UrlNotAllowedException(
1015 _("Url scheme does not allow a host component")
1019 if( isValidHost(host))
1023 // always decode in case isValidHost()
1024 // is reimplemented and supports also
1025 // the [v ... ] notation.
1026 if( host.at(0) == '[')
1028 temp = str::toUpper(zypp::url::decode(host));
1032 temp = str::toLower(zypp::url::decode(host));
1035 m_data->host = zypp::url::encode(
1036 temp, config("safe_hostname")
1041 ZYPP_THROW(UrlBadComponentException(
1042 str::form(_("Invalid host component '%s'"), host.c_str())
1049 // ---------------------------------------------------------------
1051 UrlBase::setPort(const std::string &port)
1055 m_data->port = port;
1059 if( config("with_authority") != "y" ||
1060 config("with_port") != "y")
1062 ZYPP_THROW(UrlNotAllowedException(
1063 _("Url scheme does not allow a port")
1067 if( isValidPort(port))
1069 m_data->port = port;
1073 ZYPP_THROW(UrlBadComponentException(
1074 str::form(_("Invalid port component '%s'"), port.c_str())
1081 // ---------------------------------------------------------------
1083 UrlBase::setPathName(const std::string &path,
1088 if(config("require_pathname") == "m")
1090 ZYPP_THROW(UrlNotAllowedException(
1091 _("Url scheme requires path name")
1094 m_data->pathname = path;
1098 if(eflag == zypp::url::E_ENCODED)
1100 checkUrlData(path, "path name", config("rx_pathname"));
1102 if( !getHost(zypp::url::E_ENCODED).empty())
1104 // has to begin with a "/". For consistency with
1105 // setPathName while the host is empty, we allow
1106 // it in encoded ("%2f") form - cleanupPathName()
1107 // will fix / decode the first slash if needed.
1108 if(!(path.at(0) == '/' || (path.size() >= 3 &&
1109 str::toLower(path.substr(0, 3)) == "%2f")))
1111 ZYPP_THROW(UrlNotAllowedException(
1112 _("Relative path not allowed if authority exists")
1117 m_data->pathname = cleanupPathName(path);
1119 else // zypp::url::E_DECODED
1121 if( !getHost(zypp::url::E_ENCODED).empty())
1123 if(path.at(0) != '/')
1125 ZYPP_THROW(UrlNotAllowedException(
1126 _("Relative path not allowed if authority exists")
1131 m_data->pathname = cleanupPathName(
1133 path, config("safe_pathname")
1141 // ---------------------------------------------------------------
1143 UrlBase::setPathParams(const std::string ¶ms)
1147 m_data->pathparams = params;
1151 checkUrlData(params, "path parameters", config("rx_pathparams"));
1153 m_data->pathparams = params;
1158 // ---------------------------------------------------------------
1160 UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec)
1165 config("psep_pathparam")
1171 // ---------------------------------------------------------------
1173 UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap)
1175 if( config("psep_pathparam").empty() ||
1176 config("vsep_pathparam").empty())
1178 ZYPP_THROW(UrlNotSupportedException(
1179 _("Path Parameter parsing not supported for this URL")
1185 config("psep_pathparam"),
1186 config("vsep_pathparam"),
1187 config("safe_pathparams")
1193 // ---------------------------------------------------------------
1195 UrlBase::setPathParam(const std::string ¶m, const std::string &value)
1197 zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED));
1198 pmap[param] = value;
1199 setPathParamsMap(pmap);
1203 // ---------------------------------------------------------------
1205 UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec)
1210 config("psep_querystr")
1216 // ---------------------------------------------------------------
1218 UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap)
1220 if( config("psep_querystr").empty() ||
1221 config("vsep_querystr").empty())
1223 ZYPP_THROW(UrlNotSupportedException(
1224 _("Query string parsing not supported for this URL")
1230 config("psep_querystr"),
1231 config("vsep_querystr"),
1232 config("safe_querystr")
1237 // ---------------------------------------------------------------
1239 UrlBase::setQueryParam(const std::string ¶m, const std::string &value)
1241 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
1242 pmap[param] = value;
1243 setQueryStringMap(pmap);
1247 // ---------------------------------------------------------------
1249 UrlBase::cleanupPathName(const std::string &path) const
1251 bool authority = !getHost(zypp::url::E_ENCODED).empty();
1252 return cleanupPathName(path, authority);
1255 // ---------------------------------------------------------------
1257 UrlBase::cleanupPathName(const std::string &path, bool authority) const
1259 std::string copy( path);
1261 // decode the first slash if it is encoded ...
1262 if(copy.size() >= 3 && copy.at(0) != '/' &&
1263 str::toLower(copy.substr(0, 3)) == "%2f")
1265 copy.replace(0, 3, "/");
1268 // if path begins with a double slash ("//"); encode the second
1269 // slash [minimal and IMO sufficient] before the first path
1270 // segment, to fulfill the path-absolute rule of RFC 3986
1271 // disallowing a "//" if no authority is present.
1275 // rewrite of "//" to "/%2f" not required, use config
1277 if(config("path_encode_slash2") == "y")
1279 // rewrite "//" ==> "/%2f"
1280 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1282 copy.replace(1, 1, "%2F");
1287 // rewrite "/%2f" ==> "//"
1288 if(copy.size() >= 4 && copy.at(0) == '/' &&
1289 str::toLower(copy.substr(1, 4)) == "%2f")
1291 copy.replace(1, 4, "/");
1297 // rewrite of "//" to "/%2f" is required (no authority)
1298 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1300 copy.replace(1, 1, "%2F");
1307 // ---------------------------------------------------------------
1309 UrlBase::isValidHost(const std::string &host) const
1313 str::regex regx(RX_VALID_HOSTIPV6);
1314 if( str::regex_match(host, regx))
1317 std::string temp( host.substr(1, host.size()-2));
1319 return inet_pton(AF_INET6, temp.c_str(), &ip) > 0;
1323 // matches also IPv4 dotted-decimal adresses...
1324 std::string temp( zypp::url::decode(host));
1325 str::regex regx(RX_VALID_HOSTNAME);
1326 return str::regex_match(temp, regx);
1336 // ---------------------------------------------------------------
1338 UrlBase::isValidPort(const std::string &port) const
1342 str::regex regx(RX_VALID_PORT);
1343 if( str::regex_match(port, regx))
1345 long pnum = str::strtonum<long>(port);
1346 return ( pnum >= 1 && pnum <= USHRT_MAX);
1356 //////////////////////////////////////////////////////////////////
1358 ////////////////////////////////////////////////////////////////////
1360 ////////////////////////////////////////////////////////////////////
1362 //////////////////////////////////////////////////////////////////////
1364 ** vim: set ts=2 sts=2 sw=2 ai et: