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)
234 if ( scheme.empty() && *pathdata.c_str() == '/' )
239 setAuthority(authority);
240 setPathData(pathdata);
241 setQueryString(querystr);
242 setFragment(fragment, zypp::url::E_ENCODED);
246 // ---------------------------------------------------------------
250 config("sep_pathparams", ";");
251 config("psep_pathparam", ",");
252 config("vsep_pathparam", "=");
254 config("psep_querystr", "&");
255 config("vsep_querystr", "=");
257 config("safe_username", "~!$&'()*+=,;");
258 config("safe_password", "~!$&'()*+=,:;");
259 config("safe_hostname", "[:]");
260 config("safe_pathname", "~!$&'()*+=,:@/");
261 config("safe_pathparams", "~!$&'()*+=,:;@/");
262 config("safe_querystr", "~!$&'()*+=,:;@/?");
263 config("safe_fragment", "~!$&'()*+=,:;@/?");
266 // n=no (disallowed, exception if !empty)
267 config("with_authority", "y");
268 config("with_port", "y");
270 // y=yes (required but don't throw if empty)
271 // n=no (not required, ignore if empty)
272 // m=mandatory (exception if empty)
273 config("require_host", "n");
274 config("require_pathname","n");
276 // y=yes (encode 2. slash even if authority present)
277 // n=no (don't encode 2. slash if authority present)
278 config("path_encode_slash2", "n");
280 config("rx_username", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,;~\\._-]|%[a-fA-F0-9]{2})+$");
281 config("rx_password", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,:;~\\._-]|%[a-fA-F0-9]{2})+$");
283 config("rx_pathname", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:@/~\\._-]|%[a-fA-F0-9]{2})+$");
284 config("rx_pathparams", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:;@/~\\._-]|%[a-fA-F0-9]{2})+$");
286 config("rx_querystr", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
287 config("rx_fragment", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$");
291 // ---------------------------------------------------------------
293 UrlBase::config(const std::string &opt, const std::string &val)
295 m_data->config[opt] = val;
299 // ---------------------------------------------------------------
301 UrlBase::config(const std::string &opt) const
303 UrlConfig::const_iterator v( m_data->config.find(opt));
304 if( v != m_data->config.end())
307 return std::string();
311 // ---------------------------------------------------------------
313 UrlBase::getViewOptions() const
315 return m_data->vopts;
319 // ---------------------------------------------------------------
321 UrlBase::setViewOptions(const ViewOptions &vopts)
323 m_data->vopts = vopts;
327 // ---------------------------------------------------------------
331 zypp::url::UrlConfig config(m_data->config);
332 zypp::url::ViewOptions vopts(m_data->vopts);
333 *m_data = UrlBaseData();
334 m_data->config = config;
335 m_data->vopts = vopts;
339 // ---------------------------------------------------------------
341 UrlBase::clone() const
343 return new UrlBase(*this);
347 // ---------------------------------------------------------------
348 zypp::url::UrlSchemes
349 UrlBase::getKnownSchemes() const
355 // ---------------------------------------------------------------
357 UrlBase::isKnownScheme(const std::string &scheme) const
359 std::string lscheme( str::toLower(scheme));
360 UrlSchemes schemes( getKnownSchemes());
361 UrlSchemes::const_iterator s;
363 for(s=schemes.begin(); s!=schemes.end(); ++s)
365 if( lscheme == str::toLower(*s))
372 // ---------------------------------------------------------------
374 UrlBase::isValidScheme(const std::string &scheme) const
379 str::regex rex(RX_VALID_SCHEME);
380 valid = str::regex_match(scheme, rex);
387 std::string lscheme( str::toLower(scheme));
388 UrlSchemes schemes( getKnownSchemes());
393 UrlSchemes::const_iterator s;
394 for(s=schemes.begin(); s!=schemes.end(); ++s)
396 if( lscheme == str::toLower(*s))
404 // ---------------------------------------------------------------
406 UrlBase::isValid() const
409 ** scheme is the only mandatory component
410 ** for all url's and is already verified,
411 ** (except for empty Url instances), so
412 ** Url with empty scheme is never valid.
414 if( getScheme().empty())
417 std::string host( getHost(zypp::url::E_ENCODED));
418 if( host.empty() && config("require_host") != "n")
421 std::string path( getPathName(zypp::url::E_ENCODED));
422 if( path.empty() && config("require_pathname") != "n")
426 ** path has to begin with "/" if authority avaliable
427 ** if host is set after the pathname, we can't throw
429 if( !host.empty() && !path.empty() && path.at(0) != '/')
436 // ---------------------------------------------------------------
438 UrlBase::asString() const
440 return asString(getViewOptions());
444 // ---------------------------------------------------------------
446 UrlBase::asString(const zypp::url::ViewOptions &opts) const
451 if( opts.has(ViewOptions::WITH_SCHEME))
453 tmp.scheme = getScheme();
454 if( !tmp.scheme.empty())
456 url += tmp.scheme + ":";
458 if( opts.has(ViewOptions::WITH_HOST))
460 tmp.host = getHost(zypp::url::E_ENCODED);
461 if( !tmp.host.empty())
465 if( opts.has(ViewOptions::WITH_USERNAME))
467 tmp.user = getUsername(zypp::url::E_ENCODED);
468 if( !tmp.user.empty())
472 if( opts.has(ViewOptions::WITH_PASSWORD))
474 tmp.pass = getPassword(zypp::url::E_ENCODED);
475 if( !tmp.pass.empty())
477 url += ":" + tmp.pass;
486 if( opts.has(ViewOptions::WITH_PORT))
488 tmp.port = getPort();
489 if( !tmp.port.empty())
491 url += ":" + tmp.port;
495 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
500 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
507 if( opts.has(ViewOptions::WITH_PATH_NAME))
509 tmp.pathname = getPathName(zypp::url::E_ENCODED);
510 if( !tmp.pathname.empty())
512 if(url.find("/") != std::string::npos)
514 // Url contains authority (that may be empty),
515 // we may need a rewrite of the encoded path.
516 tmp.pathname = cleanupPathName(tmp.pathname, true);
517 if(tmp.pathname.at(0) != '/')
524 if( opts.has(ViewOptions::WITH_PATH_PARAMS))
526 tmp.pathparams = getPathParams();
527 if( !tmp.pathparams.empty())
529 url += ";" + tmp.pathparams;
531 else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
537 else if( opts.has(ViewOptions::EMPTY_PATH_NAME)
538 && url.find("/") != std::string::npos)
541 if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
548 if( opts.has(ViewOptions::WITH_QUERY_STR))
550 tmp.querystr = getQueryString();
551 if( !tmp.querystr.empty())
553 url += "?" + tmp.querystr;
555 else if( opts.has(ViewOptions::EMPTY_QUERY_STR))
561 if( opts.has(ViewOptions::WITH_FRAGMENT))
563 tmp.fragment = getFragment(zypp::url::E_ENCODED);
564 if( !tmp.fragment.empty())
566 url += "#" + tmp.fragment;
568 else if( opts.has(ViewOptions::EMPTY_FRAGMENT))
578 // ---------------------------------------------------------------
580 UrlBase::getScheme() const
582 return m_data->scheme;
586 // ---------------------------------------------------------------
588 UrlBase::getAuthority() const
591 if( !getHost(zypp::url::E_ENCODED).empty())
593 if( !getUsername(zypp::url::E_ENCODED).empty())
595 str = getUsername(zypp::url::E_ENCODED);
596 if( !getPassword(zypp::url::E_ENCODED).empty())
598 str += ":" + getPassword(zypp::url::E_ENCODED);
603 str += getHost(zypp::url::E_ENCODED);
604 if( !getPort().empty())
606 str += ":" + getPort();
613 // ---------------------------------------------------------------
615 UrlBase::getPathData() const
617 return getPathName(zypp::url::E_ENCODED) +
618 config("sep_pathparams") +
623 // ---------------------------------------------------------------
625 UrlBase::getQueryString() const
627 return m_data->querystr;
631 // ---------------------------------------------------------------
633 UrlBase::getFragment(EEncoding eflag) const
635 if(eflag == zypp::url::E_DECODED)
636 return zypp::url::decode(m_data->fragment);
638 return m_data->fragment;
642 // ---------------------------------------------------------------
644 UrlBase::getUsername(EEncoding eflag) const
646 if(eflag == zypp::url::E_DECODED)
647 return zypp::url::decode(m_data->user);
653 // ---------------------------------------------------------------
655 UrlBase::getPassword(EEncoding eflag) const
657 if(eflag == zypp::url::E_DECODED)
658 return zypp::url::decode(m_data->pass);
664 // ---------------------------------------------------------------
666 UrlBase::getHost(EEncoding eflag) const
668 if(eflag == zypp::url::E_DECODED)
669 return zypp::url::decode(m_data->host);
675 // ---------------------------------------------------------------
677 UrlBase::getPort() const
683 // ---------------------------------------------------------------
685 UrlBase::getPathName(EEncoding eflag) const
687 if(eflag == zypp::url::E_DECODED)
688 return zypp::url::decode(m_data->pathname);
690 return cleanupPathName(m_data->pathname);
694 // ---------------------------------------------------------------
696 UrlBase::getPathParams() const
698 return m_data->pathparams;
702 // ---------------------------------------------------------------
704 UrlBase::getPathParamsVec() const
706 zypp::url::ParamVec pvec;
707 if( config("psep_pathparam").empty())
709 pvec.push_back(getPathParams());
716 config("psep_pathparam")
723 // ---------------------------------------------------------------
725 UrlBase::getPathParamsMap(EEncoding eflag) const
727 if( config("psep_pathparam").empty() ||
728 config("vsep_pathparam").empty())
730 ZYPP_THROW(UrlNotSupportedException(
731 "Path parameter parsing not supported for this URL"
734 zypp::url::ParamMap pmap;
738 config("psep_pathparam"),
739 config("vsep_pathparam"),
746 // ---------------------------------------------------------------
748 UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const
750 zypp::url::ParamMap pmap( getPathParamsMap( eflag));
751 zypp::url::ParamMap::const_iterator i( pmap.find(param));
753 return i != pmap.end() ? i->second : std::string();
757 // ---------------------------------------------------------------
759 UrlBase::getQueryStringVec() const
761 zypp::url::ParamVec pvec;
762 if( config("psep_querystr").empty())
764 pvec.push_back(getQueryString());
771 config("psep_querystr")
778 // ---------------------------------------------------------------
780 UrlBase::getQueryStringMap(EEncoding eflag) const
782 if( config("psep_querystr").empty() ||
783 config("vsep_querystr").empty())
785 ZYPP_THROW(UrlNotSupportedException(
786 _("Query string parsing not supported for this URL")
789 zypp::url::ParamMap pmap;
793 config("psep_querystr"),
794 config("vsep_querystr"),
801 // ---------------------------------------------------------------
803 UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const
805 zypp::url::ParamMap pmap( getQueryStringMap( eflag));
806 zypp::url::ParamMap::const_iterator i( pmap.find(param));
808 return i != pmap.end() ? i->second : std::string();
812 // ---------------------------------------------------------------
814 UrlBase::setScheme(const std::string &scheme)
816 if( isValidScheme(scheme))
818 m_data->scheme = str::toLower(scheme);
823 ZYPP_THROW(UrlBadComponentException(
824 _("Url scheme is a required component")
829 ZYPP_THROW(UrlBadComponentException(
830 str::form(_("Invalid Url scheme '%s'"), scheme.c_str())
836 // ---------------------------------------------------------------
838 UrlBase::setAuthority(const std::string &authority)
840 std::string s = authority;
841 std::string::size_type p,q;
843 std::string username, password, host, port;
845 if ((p=s.find('@')) != std::string::npos)
848 if (q != std::string::npos && q < p)
850 setUsername(s.substr(0, q), zypp::url::E_ENCODED);
851 setPassword(s.substr(q+1, p-q-1), zypp::url::E_ENCODED);
854 setUsername(s.substr(0, p), zypp::url::E_ENCODED);
857 if ((p = s.rfind(':')) != std::string::npos && ( (q = s.rfind(']')) == std::string::npos || q < p) )
859 setHost(s.substr(0, p));
860 setPort(s.substr(p+1));
866 // ---------------------------------------------------------------
868 UrlBase::setPathData(const std::string &pathdata)
870 size_t pos = std::string::npos;
871 std::string sep(config("sep_pathparams"));
874 pos = pathdata.find(sep);
876 if( pos != std::string::npos)
878 setPathName(pathdata.substr(0, pos),
879 zypp::url::E_ENCODED);
880 setPathParams(pathdata.substr(pos + 1));
884 setPathName(pathdata,
885 zypp::url::E_ENCODED);
891 // ---------------------------------------------------------------
893 UrlBase::setQueryString(const std::string &querystr)
895 if( querystr.empty())
897 m_data->querystr = querystr;
901 checkUrlData(querystr, "query string", config("rx_querystr"));
903 m_data->querystr = querystr;
908 // ---------------------------------------------------------------
910 UrlBase::setFragment(const std::string &fragment,
913 if( fragment.empty())
915 m_data->fragment = fragment;
919 if(eflag == zypp::url::E_ENCODED)
921 checkUrlData(fragment, "fragment", config("rx_fragment"));
923 m_data->fragment = fragment;
927 m_data->fragment = zypp::url::encode(
928 fragment, config("safe_fragment")
935 // ---------------------------------------------------------------
937 UrlBase::setUsername(const std::string &user,
946 if( config("with_authority") != "y")
948 ZYPP_THROW(UrlNotAllowedException(
949 _("Url scheme does not allow a username")
953 if(eflag == zypp::url::E_ENCODED)
955 checkUrlData(user, "username", config("rx_username"));
961 m_data->user = zypp::url::encode(
962 user, config("safe_username")
969 // ---------------------------------------------------------------
971 UrlBase::setPassword(const std::string &pass,
980 if( config("with_authority") != "y")
982 ZYPP_THROW(UrlNotAllowedException(
983 _("Url scheme does not allow a password")
987 if(eflag == zypp::url::E_ENCODED)
989 checkUrlData(pass, "password", config("rx_password"), false);
995 m_data->pass = zypp::url::encode(
996 pass, config("safe_password")
1003 // ---------------------------------------------------------------
1005 UrlBase::setHost(const std::string &host)
1009 if(config("require_host") == "m")
1011 ZYPP_THROW(UrlNotAllowedException(
1012 _("Url scheme requires a host component")
1015 m_data->host = host;
1019 if( config("with_authority") != "y")
1021 ZYPP_THROW(UrlNotAllowedException(
1022 _("Url scheme does not allow a host component")
1026 if( isValidHost(host))
1030 // always decode in case isValidHost()
1031 // is reimplemented and supports also
1032 // the [v ... ] notation.
1033 if( host.at(0) == '[')
1035 temp = str::toUpper(zypp::url::decode(host));
1039 temp = str::toLower(zypp::url::decode(host));
1042 m_data->host = zypp::url::encode(
1043 temp, config("safe_hostname")
1048 ZYPP_THROW(UrlBadComponentException(
1049 str::form(_("Invalid host component '%s'"), host.c_str())
1056 // ---------------------------------------------------------------
1058 UrlBase::setPort(const std::string &port)
1062 m_data->port = port;
1066 if( config("with_authority") != "y" ||
1067 config("with_port") != "y")
1069 ZYPP_THROW(UrlNotAllowedException(
1070 _("Url scheme does not allow a port")
1074 if( isValidPort(port))
1076 m_data->port = port;
1080 ZYPP_THROW(UrlBadComponentException(
1081 str::form(_("Invalid port component '%s'"), port.c_str())
1088 // ---------------------------------------------------------------
1090 UrlBase::setPathName(const std::string &path,
1095 if(config("require_pathname") == "m")
1097 ZYPP_THROW(UrlNotAllowedException(
1098 _("Url scheme requires path name")
1101 m_data->pathname = path;
1105 if(eflag == zypp::url::E_ENCODED)
1107 checkUrlData(path, "path name", config("rx_pathname"));
1109 if( !getHost(zypp::url::E_ENCODED).empty())
1111 // has to begin with a "/". For consistency with
1112 // setPathName while the host is empty, we allow
1113 // it in encoded ("%2f") form - cleanupPathName()
1114 // will fix / decode the first slash if needed.
1115 if(!(path.at(0) == '/' || (path.size() >= 3 &&
1116 str::toLower(path.substr(0, 3)) == "%2f")))
1118 ZYPP_THROW(UrlNotAllowedException(
1119 _("Relative path not allowed if authority exists")
1124 m_data->pathname = cleanupPathName(path);
1126 else // zypp::url::E_DECODED
1128 if( !getHost(zypp::url::E_ENCODED).empty())
1130 if(path.at(0) != '/')
1132 ZYPP_THROW(UrlNotAllowedException(
1133 _("Relative path not allowed if authority exists")
1138 m_data->pathname = cleanupPathName(
1140 path, config("safe_pathname")
1148 // ---------------------------------------------------------------
1150 UrlBase::setPathParams(const std::string ¶ms)
1154 m_data->pathparams = params;
1158 checkUrlData(params, "path parameters", config("rx_pathparams"));
1160 m_data->pathparams = params;
1165 // ---------------------------------------------------------------
1167 UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec)
1172 config("psep_pathparam")
1178 // ---------------------------------------------------------------
1180 UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap)
1182 if( config("psep_pathparam").empty() ||
1183 config("vsep_pathparam").empty())
1185 ZYPP_THROW(UrlNotSupportedException(
1186 "Path Parameter parsing not supported for this URL"
1192 config("psep_pathparam"),
1193 config("vsep_pathparam"),
1194 config("safe_pathparams")
1200 // ---------------------------------------------------------------
1202 UrlBase::setPathParam(const std::string ¶m, const std::string &value)
1204 zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED));
1205 pmap[param] = value;
1206 setPathParamsMap(pmap);
1210 // ---------------------------------------------------------------
1212 UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec)
1217 config("psep_querystr")
1223 // ---------------------------------------------------------------
1225 UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap)
1227 if( config("psep_querystr").empty() ||
1228 config("vsep_querystr").empty())
1230 ZYPP_THROW(UrlNotSupportedException(
1231 _("Query string parsing not supported for this URL")
1237 config("psep_querystr"),
1238 config("vsep_querystr"),
1239 config("safe_querystr")
1244 // ---------------------------------------------------------------
1246 UrlBase::setQueryParam(const std::string ¶m, const std::string &value)
1248 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
1249 pmap[param] = value;
1250 setQueryStringMap(pmap);
1253 // ---------------------------------------------------------------
1255 UrlBase::delQueryParam(const std::string ¶m)
1257 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
1259 setQueryStringMap(pmap);
1263 // ---------------------------------------------------------------
1265 UrlBase::cleanupPathName(const std::string &path) const
1267 bool authority = !getHost(zypp::url::E_ENCODED).empty();
1268 return cleanupPathName(path, authority);
1271 // ---------------------------------------------------------------
1273 UrlBase::cleanupPathName(const std::string &path, bool authority) const
1275 std::string copy( path);
1277 // decode the first slash if it is encoded ...
1278 if(copy.size() >= 3 && copy.at(0) != '/' &&
1279 str::toLower(copy.substr(0, 3)) == "%2f")
1281 copy.replace(0, 3, "/");
1284 // if path begins with a double slash ("//"); encode the second
1285 // slash [minimal and IMO sufficient] before the first path
1286 // segment, to fulfill the path-absolute rule of RFC 3986
1287 // disallowing a "//" if no authority is present.
1291 // rewrite of "//" to "/%2f" not required, use config
1293 if(config("path_encode_slash2") == "y")
1295 // rewrite "//" ==> "/%2f"
1296 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1298 copy.replace(1, 1, "%2F");
1303 // rewrite "/%2f" ==> "//"
1304 if(copy.size() >= 4 && copy.at(0) == '/' &&
1305 str::toLower(copy.substr(1, 4)) == "%2f")
1307 copy.replace(1, 4, "/");
1313 // rewrite of "//" to "/%2f" is required (no authority)
1314 if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
1316 copy.replace(1, 1, "%2F");
1323 // ---------------------------------------------------------------
1325 UrlBase::isValidHost(const std::string &host) const
1329 str::regex regx(RX_VALID_HOSTIPV6);
1330 if( str::regex_match(host, regx))
1333 std::string temp( host.substr(1, host.size()-2));
1335 return inet_pton(AF_INET6, temp.c_str(), &ip) > 0;
1339 // matches also IPv4 dotted-decimal adresses...
1340 std::string temp( zypp::url::decode(host));
1341 str::regex regx(RX_VALID_HOSTNAME);
1342 return str::regex_match(temp, regx);
1352 // ---------------------------------------------------------------
1354 UrlBase::isValidPort(const std::string &port) const
1358 str::regex regx(RX_VALID_PORT);
1359 if( str::regex_match(port, regx))
1361 long pnum = str::strtonum<long>(port);
1362 return ( pnum >= 1 && pnum <= USHRT_MAX);
1371 //////////////////////////////////////////////////////////////////
1373 ////////////////////////////////////////////////////////////////////
1375 ////////////////////////////////////////////////////////////////////
1377 //////////////////////////////////////////////////////////////////////
1379 ** vim: set ts=2 sts=2 sw=2 ai et: