20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <arpa/inet.h>
28 #define a_zA_Z "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
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})?\\]$"
146 checkUrlData(
const std::string &data,
147 const std::string &name,
148 const std::string ®x,
151 if( regx.empty() || regx ==
"^$")
154 str::form(
_(
"Url scheme does not allow a %s"), name.c_str())
174 name.c_str(), data.c_str())
180 str::form(
_(
"Invalid %s component"), name.c_str())
215 const std::string &authority,
216 const std::string &pathdata,
217 const std::string &querystr,
218 const std::string &fragment)
222 init(scheme, authority, pathdata, querystr, fragment);
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() ==
'/' )
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",
"~!$&'()*+=,:;@/?");
267 config(
"with_authority",
"y");
273 config(
"require_host",
"n");
274 config(
"require_pathname",
"n");
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})+$");
307 return std::string();
361 UrlSchemes::const_iterator s;
363 for(s=schemes.begin(); s!=schemes.end(); ++s)
393 UrlSchemes::const_iterator s;
394 for(s=schemes.begin(); s!=schemes.end(); ++s)
418 if( host.empty() &&
config(
"require_host") !=
"n")
422 if( path.empty() &&
config(
"require_pathname") !=
"n")
429 if( !host.empty() && !path.empty() && path.at(0) !=
'/')
461 if( !tmp.
host.empty())
468 if( !tmp.
user.empty())
475 if( !tmp.
pass.empty())
477 url +=
":" + tmp.
pass;
489 if( !tmp.
port.empty())
491 url +=
":" + tmp.
port;
512 if(url.find(
"/") != std::string::npos)
538 && url.find(
"/") != std::string::npos)
618 config(
"sep_pathparams") +
707 if(
config(
"psep_pathparam").empty())
727 if(
config(
"psep_pathparam").empty() ||
728 config(
"vsep_pathparam").empty())
731 "Path parameter parsing not supported for this URL"
751 zypp::url::ParamMap::const_iterator i( pmap.find(param));
753 return i != pmap.end() ? i->second : std::string();
762 if(
config(
"psep_querystr").empty())
782 if(
config(
"psep_querystr").empty() ||
783 config(
"vsep_querystr").empty())
786 _(
"Query string parsing not supported for this URL")
806 zypp::url::ParamMap::const_iterator i( pmap.find(param));
808 return i != pmap.end() ? i->second : std::string();
824 _(
"Url scheme is a required component")
830 str::form(
_(
"Invalid Url scheme '%s'"), scheme.c_str())
840 std::string s = authority;
843 std::string username, password, host, port;
845 if ((p=s.find(
'@')) != std::string::npos)
848 if (q != std::string::npos && q < p)
857 if ((p = s.rfind(
':')) != std::string::npos && ( (q = s.rfind(
']')) == std::string::npos || q < p) )
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)
895 if( querystr.empty())
901 checkUrlData(querystr,
"query string",
config(
"rx_querystr"));
913 if( fragment.empty())
921 checkUrlData(fragment,
"fragment",
config(
"rx_fragment"));
928 fragment,
config(
"safe_fragment")
946 if(
config(
"with_authority") !=
"y")
949 _(
"Url scheme does not allow a username")
955 checkUrlData(user,
"username",
config(
"rx_username"));
962 user,
config(
"safe_username")
980 if(
config(
"with_authority") !=
"y")
983 _(
"Url scheme does not allow a password")
989 checkUrlData(pass,
"password",
config(
"rx_password"),
false);
996 pass,
config(
"safe_password")
1009 if(
config(
"require_host") ==
"m")
1012 _(
"Url scheme requires a host component")
1019 if(
config(
"with_authority") !=
"y")
1022 _(
"Url scheme does not allow a host component")
1033 if( host.at(0) ==
'[')
1043 temp,
config(
"safe_hostname")
1049 str::form(
_(
"Invalid host component '%s'"), host.c_str())
1066 if(
config(
"with_authority") !=
"y" ||
1067 config(
"with_port") !=
"y")
1070 _(
"Url scheme does not allow a port")
1081 str::form(
_(
"Invalid port component '%s'"), port.c_str())
1095 if(
config(
"require_pathname") ==
"m")
1098 _(
"Url scheme requires path name")
1107 checkUrlData(path,
"path name",
config(
"rx_pathname"));
1115 if(!(path.at(0) ==
'/' || (path.size() >= 3 &&
1119 _(
"Relative path not allowed if authority exists")
1130 if(path.at(0) !=
'/')
1133 _(
"Relative path not allowed if authority exists")
1140 path,
config(
"safe_pathname")
1158 checkUrlData(params,
"path parameters",
config(
"rx_pathparams"));
1182 if(
config(
"psep_pathparam").empty() ||
1183 config(
"vsep_pathparam").empty())
1186 "Path Parameter parsing not supported for this URL"
1192 config(
"psep_pathparam"),
1193 config(
"vsep_pathparam"),
1194 config(
"safe_pathparams")
1205 pmap[param] = value;
1227 if(
config(
"psep_querystr").empty() ||
1228 config(
"vsep_querystr").empty())
1231 _(
"Query string parsing not supported for this URL")
1249 pmap[param] = value;
1275 std::string
copy( path);
1278 if(copy.size() >= 3 && copy.at(0) !=
'/' &&
1281 copy.replace(0, 3,
"/");
1293 if(
config(
"path_encode_slash2") ==
"y")
1296 if(copy.size() >= 2 && copy.at(0) ==
'/' && copy.at(1) ==
'/')
1298 copy.replace(1, 1,
"%2F");
1304 if(copy.size() >= 4 && copy.at(0) ==
'/' &&
1307 copy.replace(1, 4,
"/");
1314 if(copy.size() >= 2 && copy.at(0) ==
'/' && copy.at(1) ==
'/')
1316 copy.replace(1, 1,
"%2F");
1333 std::string temp( host.substr(1, host.size()-2));
1335 return inet_pton(AF_INET6, temp.c_str(), &ip) > 0;
1361 long pnum = str::strtonum<long>(port);
1362 return ( pnum >= 1 && pnum <= USHRT_MAX);