1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
10 * \file zypp/url/UrlBase.cc
12 #include <zypp/url/UrlBase.h>
13 #include <zypp/base/String.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <arpa/inet.h>
23 // ---------------------------------------------------------------
25 ** authority = //[user [:password] @ ] host [:port]
27 ** host = hostname | IPv4 | "[" IPv6-IP "]" | "[v...]"
29 #define RX_SPLIT_AUTHORITY \
30 "^(([^:@]*)([:]([^@]*))?@)?(\\[[^]]+\\]|[^:]+)?([:](.*))?"
32 #define RX_VALID_SCHEME "^[a-zA-Z][a-zA-Z0-9\\.+-]*$"
34 #define RX_VALID_PORT "^[0-9]{1,5}$"
36 #define RX_VALID_HOSTNAME "^[[:alnum:]]+([\\.-][[:alnum:]]+)*$"
38 #define RX_VALID_HOSTIPV4 \
39 "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$"
41 #define RX_VALID_HOSTIPV6 \
42 "^\\[[:a-fA-F0-9]+(:[0-9]{1,3}(\\.[0-9]{1,3}){3})?\\]$"
45 //////////////////////////////////////////////////////////////////////
47 { ////////////////////////////////////////////////////////////////////
49 ////////////////////////////////////////////////////////////////////
51 { //////////////////////////////////////////////////////////////////
54 // ---------------------------------------------------------------
56 ** URL asString() view option constants:
58 const ViewOptions ViewOptions::WITH_SCHEME = 0x0001;
59 const ViewOptions ViewOptions::WITH_USERNAME = 0x0002;
60 const ViewOptions ViewOptions::WITH_PASSWORD = 0x0004;
61 const ViewOptions ViewOptions::WITH_HOST = 0x0008;
62 const ViewOptions ViewOptions::WITH_PORT = 0x0010;
63 const ViewOptions ViewOptions::WITH_PATH_NAME = 0x0020;
64 const ViewOptions ViewOptions::WITH_PATH_PARAMS = 0x0040;
65 const ViewOptions ViewOptions::WITH_QUERY_STR = 0x0080;
66 const ViewOptions ViewOptions::WITH_FRAGMENT = 0x0100;
67 const ViewOptions ViewOptions::EMPTY_AUTHORITY = 0x0200;
68 const ViewOptions ViewOptions::EMPTY_PATH_NAME = 0x0400;
69 const ViewOptions ViewOptions::EMPTY_PATH_PARAMS = 0x0800;
70 const ViewOptions ViewOptions::EMPTY_QUERY_STR = 0x1000;
71 const ViewOptions ViewOptions::EMPTY_FRAGMENT = 0x2000;
72 const ViewOptions ViewOptions::DEFAULTS = 0x07bb;
74 ViewOptions::WITH_SCHEME +
75 ViewOptions::WITH_USERNAME +
76 ViewOptions::WITH_HOST +
77 ViewOptions::WITH_PORT +
78 ViewOptions::WITH_PATH_NAME +
79 ViewOptions::WITH_QUERY_STR +
80 ViewOptions::WITH_FRAGMENT +
81 ViewOptions::EMPTY_AUTHORITY +
82 ViewOptions::EMPTY_PATH_NAME;
86 // ---------------------------------------------------------------
88 ** Behaviour configuration variables.
90 typedef std::map< std::string, std::string > UrlConfig;
93 // ---------------------------------------------------------------
95 * \brief Internal data used by UrlBase.
103 UrlBaseData(const UrlConfig &conf)
115 std::string pathname;
116 std::string pathparams;
117 std::string querystr;
118 std::string fragment;
122 // ---------------------------------------------------------------
124 ** Anonymous/internal utility namespace:
126 namespace // anonymous
129 // -------------------------------------------------------------
131 checkUrlData(const std::string &data,
132 const std::string &name,
133 const std::string ®x,
136 if( regx.empty() || regx == "^$")
138 ZYPP_THROW(UrlNotAllowedException(
139 std::string("Url scheme does not allow a " + name)
147 str::regex rex(regx);
148 valid = str::regex_match(data, rex);
157 ZYPP_THROW(UrlBadComponentException(
158 std::string("Invalid " + name + " component '" +
164 ZYPP_THROW(UrlBadComponentException(
165 std::string("Invalid " + name + " component")
175 // ---------------------------------------------------------------
183 // ---------------------------------------------------------------
185 : m_data( new UrlBaseData())
191 // ---------------------------------------------------------------
192 UrlBase::UrlBase(const UrlBase &url)
193 : m_data( new UrlBaseData( *(url.m_data)))
198 // ---------------------------------------------------------------
199 UrlBase::UrlBase(const std::string &scheme,
200 const std::string &authority,
201 const std::string &pathdata,
202 const std::string &querystr,
203 const std::string &fragment)
204 : m_data( new UrlBaseData())
207 init(scheme, authority, pathdata, querystr, fragment);
211 // ---------------------------------------------------------------
213 UrlBase::init(const std::string &scheme,
214 const std::string &authority,
215 const std::string &pathdata,
216 const std::string &querystr,
217 const std::string &fragment)
220 setAuthority(authority);
221 setPathData(pathdata);
222 setQueryString(querystr);
223 setFragment(fragment, zypp::url::E_ENCODED);
227 // ---------------------------------------------------------------
231 config("sep_pathparams", ";");
232 config("psep_pathparam", ",");
233 config("vsep_pathparam", "=");
235 config("psep_querystr", "&");
236 config("vsep_querystr", "=");
238 config("safe_username", "~!$&'()*+=,;");
239 config("safe_password", "~!$&'()*+=,:;");
240 config("safe_hostname", "[:]");
241 config("safe_pathname", "~!$&'()*+=,:@/");
242 config("safe_pathparams", "~!$&'()*+=,:;@/");
243 config("safe_querystr", "~!$&'()*+=,:;@/?");
244 config("safe_fragment", "~!$&'()*+=,:;@/?");
247 // n=no (disallowed, exception if !empty)
248 config("with_authority", "y");
249 config("with_port", "y");
251 // y=yes (required but don't throw if empty)
252 // n=no (not required, ignore if empty)
253 // m=mandatory (exception if empty)
254 config("require_host", "n");
255 config("require_pathname","n");
257 // y=yes (encode 2. slash even if authority present)
258 // n=no (don't encode 2. slash if authority present)
259 config("path_encode_slash2", "n");
261 config("rx_username", "^([a-zA-Z0-9!$&'\\(\\)*+=,;~\\._-]|%[a-fA-F0-9]{2})+$");
262 config("rx_password", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;~\\._-]|%[a-fA-F0-9]{2})+$");
264 config("rx_pathname", "^([a-zA-Z0-9!$&'\\(\\)*+=,:@/~\\._-]|%[a-fA-F0-9]{2})+$");
265 config("rx_pathparams", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/~\\._-]|%[a-fA-F0-9]{2})+$");
267 config("rx_querystr", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
268 config("rx_fragment", "^([a-zA-Z0-9!$&'\\(\\)*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
272 // ---------------------------------------------------------------
274 UrlBase::config(const std::string &opt, const std::string &val)
276 m_data->config[opt] = val;
280 // ---------------------------------------------------------------
282 UrlBase::config(const std::string &opt) const
284 UrlConfig::const_iterator v( m_data->config.find(opt));
285 if( v != m_data->config.end())
288 return std::string();
292 // ---------------------------------------------------------------
294 UrlBase::getViewOptions() const
296 return m_data->vopts;
300 // ---------------------------------------------------------------
302 UrlBase::setViewOptions(const ViewOptions &vopts)
304 m_data->vopts = vopts;
308 // ---------------------------------------------------------------
312 zypp::url::UrlConfig config(m_data->config);
313 zypp::url::ViewOptions vopts(m_data->vopts);
314 *m_data = UrlBaseData();
315 m_data->config = config;
316 m_data->vopts = vopts;
320 // ---------------------------------------------------------------
322 UrlBase::clone() const
324 return new UrlBase(*this);
328 // ---------------------------------------------------------------
329 zypp::url::UrlSchemes
330 UrlBase::getKnownSchemes() const
336 // ---------------------------------------------------------------
338 UrlBase::isKnownScheme(const std::string &scheme) const
340 std::string lscheme( str::toLower(scheme));
341 UrlSchemes schemes( getKnownSchemes());
342 UrlSchemes::const_iterator s;
344 for(s=schemes.begin(); s!=schemes.end(); ++s)
346 if( lscheme == str::toLower(*s))
353 // ---------------------------------------------------------------
355 UrlBase::isValidScheme(const std::string &scheme) const
360 str::regex rex(RX_VALID_SCHEME);
361 valid = str::regex_match(scheme, rex);
368 std::string lscheme( str::toLower(scheme));
369 UrlSchemes schemes( getKnownSchemes());
374 UrlSchemes::const_iterator s;
375 for(s=schemes.begin(); s!=schemes.end(); ++s)
377 if( lscheme == str::toLower(*s))
385 // ---------------------------------------------------------------
387 UrlBase::isValid() const
390 ** scheme is the only mandatory component
391 ** for all url's and is already verified,
392 ** (except for empty Url instances), so
393 ** Url with empty scheme is never valid.
395 if( getScheme().empty())
398 std::string host( getHost(zypp::url::E_ENCODED));
399 if( host.empty() && config("require_host") != "n")
402 std::string path( getPathName(zypp::url::E_ENCODED));
403 if( path.empty() && config("require_pathname") != "n")
407 ** path has to begin with "/" if authority avaliable
408 ** if host is set after the pathname, we can't throw
410 if( !host.empty() && !path.empty() && path.at(0) != '/')
417 // ---------------------------------------------------------------
419 UrlBase::asString() const
421 return asString(getViewOptions());
425 // ---------------------------------------------------------------
427 UrlBase::asString(const zypp::url::ViewOptions &opts) const
432 if( opts.has(ViewOptions::WITH_SCHEME))
434 tmp.scheme = getScheme();
435 if( !tmp.scheme.empty())
437 url += tmp.scheme + ":";
439 if( opts.has(ViewOptions::WITH_HOST))
441 tmp.host = getHost(zypp::url::E_ENCODED);
442 if( !tmp.host.empty())
446 if( opts.has(ViewOptions::WITH_USERNAME))
448 tmp.user = getUsername(zypp::url::E_ENCODED);
449 if( !tmp.user.empty())
453 if( opts.has(ViewOptions::WITH_PASSWORD))
455 tmp.pass = getPassword(zypp::url::E_ENCODED);
456 if( !tmp.pass.empty())
458 url += ":" + tmp.pass;
467 if( opts.has(ViewOptions::WITH_PORT))
469 tmp.port = getPort();
470 if( !tmp.port.empty())
472 url += ":" + tmp.port;
476 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
481 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
488 if( opts.has(ViewOptions::WITH_PATH_NAME))
490 tmp.pathname = getPathName(zypp::url::E_ENCODED);
491 if( !tmp.pathname.empty())
493 if(url.find("/") != std::string::npos)
495 // Url contains authority (that may be empty),
496 // we may need a rewrite of the encoded path.
497 tmp.pathname = cleanupPathName(tmp.pathname, true);
498 if(tmp.pathname.at(0) != '/')
505 if( opts.has(ViewOptions::WITH_PATH_PARAMS))
507 tmp.pathparams = getPathParams();
508 if( !tmp.pathparams.empty())
510 url += ";" + tmp.pathparams;
512 else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
518 else if( opts.has(ViewOptions::EMPTY_PATH_NAME)
519 && url.find("/") != std::string::npos)
522 if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
529 if( opts.has(ViewOptions::WITH_QUERY_STR))
531 tmp.querystr = getQueryString();
532 if( !tmp.querystr.empty())
534 url += "?" + tmp.querystr;
536 else if( opts.has(ViewOptions::EMPTY_QUERY_STR))
542 if( opts.has(ViewOptions::WITH_FRAGMENT))
544 tmp.fragment = getFragment(zypp::url::E_ENCODED);
545 if( !tmp.fragment.empty())
547 url += "#" + tmp.fragment;
549 else if( opts.has(ViewOptions::EMPTY_FRAGMENT))
559 // ---------------------------------------------------------------
561 UrlBase::getScheme() const
563 return m_data->scheme;
567 // ---------------------------------------------------------------
569 UrlBase::getAuthority() const
572 if( !getHost(zypp::url::E_ENCODED).empty())
574 if( !getUsername(zypp::url::E_ENCODED).empty())
576 str = getUsername(zypp::url::E_ENCODED);
577 if( !getPassword(zypp::url::E_ENCODED).empty())
579 str += ":" + getPassword(zypp::url::E_ENCODED);
584 str += getHost(zypp::url::E_ENCODED);
585 if( !getPort().empty())
587 str += ":" + getPort();
594 // ---------------------------------------------------------------
596 UrlBase::getPathData() const
598 return getPathName(zypp::url::E_ENCODED) +
599 config("sep_pathparams") +
604 // ---------------------------------------------------------------
606 UrlBase::getQueryString() const
608 return m_data->querystr;
612 // ---------------------------------------------------------------
614 UrlBase::getFragment(EEncoding eflag) const
616 if(eflag == zypp::url::E_DECODED)
617 return zypp::url::decode(m_data->fragment);
619 return m_data->fragment;
623 // ---------------------------------------------------------------
625 UrlBase::getUsername(EEncoding eflag) const
627 if(eflag == zypp::url::E_DECODED)
628 return zypp::url::decode(m_data->user);
634 // ---------------------------------------------------------------
636 UrlBase::getPassword(EEncoding eflag) const
638 if(eflag == zypp::url::E_DECODED)
639 return zypp::url::decode(m_data->pass);
645 // ---------------------------------------------------------------
647 UrlBase::getHost(EEncoding eflag) const
649 if(eflag == zypp::url::E_DECODED)
650 return zypp::url::decode(m_data->host);
656 // ---------------------------------------------------------------
658 UrlBase::getPort() const
664 // ---------------------------------------------------------------
666 UrlBase::getPathName(EEncoding eflag) const
668 if(eflag == zypp::url::E_DECODED)
669 return zypp::url::decode(m_data->pathname);
671 return cleanupPathName(m_data->pathname);
675 // ---------------------------------------------------------------
677 UrlBase::getPathParams() const
679 return m_data->pathparams;
683 // ---------------------------------------------------------------
685 UrlBase::getPathParamsVec() const
687 zypp::url::ParamVec pvec;
688 if( config("psep_pathparam").empty())
690 pvec.push_back(getPathParams());
697 config("psep_pathparam")
704 // ---------------------------------------------------------------
706 UrlBase::getPathParamsMap(EEncoding eflag) const
708 if( config("psep_pathparam").empty() ||
709 config("vsep_pathparam").empty())
711 ZYPP_THROW(UrlNotSupportedException(
712 "Path parameter parsing not supported for this URL"
715 zypp::url::ParamMap pmap;
719 config("psep_pathparam"),
720 config("vsep_pathparam"),
727 // ---------------------------------------------------------------
729 UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const
731 zypp::url::ParamMap pmap( getPathParamsMap( eflag));
732 zypp::url::ParamMap::const_iterator i( pmap.find(param));
734 return i != pmap.end() ? i->second : std::string();
738 // ---------------------------------------------------------------
740 UrlBase::getQueryStringVec() const
742 zypp::url::ParamVec pvec;
743 if( config("psep_querystr").empty())
745 pvec.push_back(getQueryString());
752 config("psep_querystr")
759 // ---------------------------------------------------------------
761 UrlBase::getQueryStringMap(EEncoding eflag) const
763 if( config("psep_querystr").empty() ||
764 config("vsep_querystr").empty())
766 ZYPP_THROW(UrlNotSupportedException(
767 "Query string parsing not supported for this URL"
770 zypp::url::ParamMap pmap;
774 config("psep_querystr"),
775 config("vsep_querystr"),
782 // ---------------------------------------------------------------
784 UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const
786 zypp::url::ParamMap pmap( getQueryStringMap( eflag));
787 zypp::url::ParamMap::const_iterator i( pmap.find(param));
789 return i != pmap.end() ? i->second : std::string();
793 // ---------------------------------------------------------------
795 UrlBase::setScheme(const std::string &scheme)
797 if( isValidScheme(scheme))
799 m_data->scheme = str::toLower(scheme);
804 ZYPP_THROW(UrlBadComponentException(
805 std::string("Url scheme is a required component")
810 ZYPP_THROW(UrlBadComponentException(
811 std::string("Invalid Url scheme '" + scheme + "'")
817 // ---------------------------------------------------------------
819 UrlBase::setAuthority(const std::string &authority)
826 str::regex rex(RX_SPLIT_AUTHORITY);
827 ret = str::regex_match(authority, out, rex);
832 if( ret && out.size() == 8)
834 setUsername(out[2].str(), zypp::url::E_ENCODED);
835 setPassword(out[4].str(), zypp::url::E_ENCODED);
836 setHost(out[5].str());
837 setPort(out[7].str());
841 ZYPP_THROW(UrlParsingException(
842 "Unable to parse Url authority"
847 // ---------------------------------------------------------------
849 UrlBase::setPathData(const std::string &pathdata)
851 size_t pos = std::string::npos;
852 std::string sep(config("sep_pathparams"));
855 pos = pathdata.find(sep);
857 if( pos != std::string::npos)
859 setPathName(pathdata.substr(0, pos),
860 zypp::url::E_ENCODED);
861 setPathParams(pathdata.substr(pos + 1));
865 setPathName(pathdata,
866 zypp::url::E_ENCODED);
872 // ---------------------------------------------------------------
874 UrlBase::setQueryString(const std::string &querystr)
876 if( querystr.empty())
878 m_data->querystr = querystr;
882 checkUrlData(querystr, "query string", config("rx_querystr"));
884 m_data->querystr = querystr;
889 // ---------------------------------------------------------------
891 UrlBase::setFragment(const std::string &fragment,
894 if( fragment.empty())
896 m_data->fragment = fragment;
900 if(eflag == zypp::url::E_ENCODED)
902 checkUrlData(fragment, "fragment", config("rx_fragment"));
904 m_data->fragment = fragment;
908 m_data->fragment = zypp::url::encode(
909 fragment, config("safe_password")
916 // ---------------------------------------------------------------
918 UrlBase::setUsername(const std::string &user,
927 if( config("with_authority") != "y")
929 ZYPP_THROW(UrlNotAllowedException(
930 std::string("Url scheme does not allow a username")
934 if(eflag == zypp::url::E_ENCODED)
936 checkUrlData(user, "username", config("rx_username"));
942 m_data->user = zypp::url::encode(
943 user, config("safe_username")
950 // ---------------------------------------------------------------
952 UrlBase::setPassword(const std::string &pass,
961 if( config("with_authority") != "y")
963 ZYPP_THROW(UrlNotAllowedException(
964 std::string("Url scheme does not allow a password")
968 if(eflag == zypp::url::E_ENCODED)
970 checkUrlData(pass, "password", config("rx_password"), false);
976 m_data->pass = zypp::url::encode(
977 pass, config("safe_password")
984 // ---------------------------------------------------------------
986 UrlBase::setHost(const std::string &host)
990 if(config("require_host") == "m")
992 ZYPP_THROW(UrlNotAllowedException(
993 std::string("Url scheme requires a host")
1000 if( config("with_authority") != "y")
1002 ZYPP_THROW(UrlNotAllowedException(
1003 std::string("Url scheme does not allow a host")
1007 if( isValidHost(host))
1011 // always decode in case isValidHost()
1012 // is reimplemented and supports also
1013 // the [v ... ] notation.
1014 if( host.at(0) == '[')
1016 temp = str::toUpper(zypp::url::decode(host));
1020 temp = str::toLower(zypp::url::decode(host));
1023 m_data->host = zypp::url::encode(
1024 temp, config("safe_hostname")
1029 ZYPP_THROW(UrlBadComponentException(
1030 std::string("Invalid host argument '" + host + "'")
1037 // ---------------------------------------------------------------
1039 UrlBase::setPort(const std::string &port)
1043 m_data->port = port;
1047 if( config("with_authority") != "y" ||
1048 config("with_port") != "y")
1050 ZYPP_THROW(UrlNotAllowedException(
1051 std::string("Url scheme does not allow a port")
1055 if( isValidPort(port))
1057 m_data->port = port;
1061 ZYPP_THROW(UrlBadComponentException(
1062 std::string("Invalid host argument '" + port + "'")
1069 // ---------------------------------------------------------------
1071 UrlBase::setPathName(const std::string &path,
1076 if(config("require_pathname") == "m")
1078 ZYPP_THROW(UrlNotAllowedException(
1079 std::string("Url scheme requires path name")
1082 m_data->pathname = path;
1086 if(eflag == zypp::url::E_ENCODED)
1088 checkUrlData(path, "path name", config("rx_pathname"));
1090 if( !getHost(zypp::url::E_ENCODED).empty())
1092 // has to begin with a "/". For consistency with
1093 // setPathName while the host is empty, we allow
1094 // it in encoded ("%2f") form - cleanupPathName()
1095 // will fix / decode the first slash if needed.
1096 if(!(path.at(0) == '/' || (path.size() >= 3 &&
1097 str::toLower(path.substr(0, 3)) == "%2f")))
1099 ZYPP_THROW(UrlNotAllowedException(
1100 std::string("Relative path not allowed if authority exists")
1105 m_data->pathname = cleanupPathName(path);
1107 else // zypp::url::E_DECODED
1109 if( !getHost(zypp::url::E_ENCODED).empty())
1111 if(path.at(0) != '/')
1113 ZYPP_THROW(UrlNotAllowedException(
1114 std::string("Relative path not allowed if authority exists")
1119 m_data->pathname = cleanupPathName(
1121 path, config("safe_pathname")
1129 // ---------------------------------------------------------------
1131 UrlBase::setPathParams(const std::string ¶ms)
1135 m_data->pathparams = params;
1139 checkUrlData(params, "path parameters", config("rx_pathparams"));
1141 m_data->pathparams = params;
1146 // ---------------------------------------------------------------
1148 UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec)
1153 config("psep_pathparam")
1159 // ---------------------------------------------------------------
1161 UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap)
1163 if( config("psep_pathparam").empty() ||
1164 config("vsep_pathparam").empty())
1166 ZYPP_THROW(UrlNotSupportedException(
1167 "Path Parameter parsing not supported for this URL"
1173 config("psep_pathparam"),
1174 config("vsep_pathparam"),
1175 config("safe_pathparams")
1181 // ---------------------------------------------------------------
1183 UrlBase::setPathParam(const std::string ¶m, const std::string &value)
1185 zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED));
1186 pmap[param] = value;
1187 setPathParamsMap(pmap);
1191 // ---------------------------------------------------------------
1193 UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec)
1198 config("psep_querystr")
1204 // ---------------------------------------------------------------
1206 UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap)
1208 if( config("psep_querystr").empty() ||
1209 config("vsep_querystr").empty())
1211 ZYPP_THROW(UrlNotSupportedException(
1212 "Query string parsing not supported for this URL"
1218 config("psep_querystr"),
1219 config("vsep_querystr"),
1220 config("safe_querystr")
1225 // ---------------------------------------------------------------
1227 UrlBase::setQueryParam(const std::string ¶m, const std::string &value)
1229 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
1230 pmap[param] = value;
1231 setQueryStringMap(pmap);
1235 // ---------------------------------------------------------------
1237 UrlBase::cleanupPathName(const std::string &path) const
1239 bool authority = !getHost(zypp::url::E_ENCODED).empty();
1240 return cleanupPathName(path, authority);
1243 // ---------------------------------------------------------------
1245 UrlBase::cleanupPathName(const std::string &path, bool authority) const
1247 std::string copy( path);
1249 // decode the first slash if it is encoded ...
1250 if(copy.size() >= 3 && copy.at(0) != '/' &&
1251 str::toLower(copy.substr(0, 3)) == "%2f")
1253 copy.replace(0, 3, "/");
1256 // if path begins with a double slash ("//"); encode the second
1257 // slash [minimal and IMO sufficient] before the first path
1258 // segment, to fulfill the path-absolute rule of RFC 3986
1259 // disallowing a "//" if no authority is present.
1263 // rewrite of "//" to "/%2f" not required, use config
1265 if(config("path_encode_slash2") == "y")
1267 // rewrite "//" ==> "/%2f"
1268 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1270 copy.replace(1, 1, "%2F");
1275 // rewrite "/%2f" ==> "//"
1276 if(copy.size() >= 4 && copy.at(0) == '/' &&
1277 str::toLower(copy.substr(1, 4)) == "%2f")
1279 copy.replace(1, 4, "/");
1285 // rewrite of "//" to "/%2f" is required (no authority)
1286 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1288 copy.replace(1, 1, "%2F");
1295 // ---------------------------------------------------------------
1297 UrlBase::isValidHost(const std::string &host) const
1301 str::regex regx(RX_VALID_HOSTIPV6);
1302 if( str::regex_match(host, regx))
1305 std::string temp( host.substr(1, host.size()-2));
1307 return inet_pton(AF_INET6, temp.c_str(), &ip) > 0;
1311 // matches also IPv4 dotted-decimal adresses...
1312 std::string temp( zypp::url::decode(host));
1313 str::regex regx(RX_VALID_HOSTNAME);
1314 return str::regex_match(temp, regx);
1324 // ---------------------------------------------------------------
1326 UrlBase::isValidPort(const std::string &port) const
1330 str::regex regx(RX_VALID_PORT);
1331 if( str::regex_match(port, regx))
1333 long pnum = str::strtonum<long>(port);
1334 return ( pnum >= 1 && pnum <= USHRT_MAX);
1344 //////////////////////////////////////////////////////////////////
1346 ////////////////////////////////////////////////////////////////////
1348 ////////////////////////////////////////////////////////////////////
1350 //////////////////////////////////////////////////////////////////////
1352 ** vim: set ts=2 sts=2 sw=2 ai et: