1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
10 * \file zypp/url/UrlBase.cc
12 #include <zypp/url/UrlBase.h>
13 #include <zypp/base/String.h>
17 #if defined(WITH_URL_PARSE_DEBUG)
21 //////////////////////////////////////////////////////////////////////
23 { ////////////////////////////////////////////////////////////////////
25 ////////////////////////////////////////////////////////////////////
27 { //////////////////////////////////////////////////////////////////
30 // ---------------------------------------------------------------
31 const ViewOptions ViewOptions::WITH_SCHEME = 0x0001;
32 const ViewOptions ViewOptions::WITH_USERNAME = 0x0002;
33 const ViewOptions ViewOptions::WITH_PASSWORD = 0x0004;
34 const ViewOptions ViewOptions::WITH_HOST = 0x0008;
35 const ViewOptions ViewOptions::WITH_PORT = 0x0010;
36 const ViewOptions ViewOptions::WITH_PATH_NAME = 0x0020;
37 const ViewOptions ViewOptions::WITH_PATH_PARAMS = 0x0040;
38 const ViewOptions ViewOptions::WITH_QUERY_STR = 0x0080;
39 const ViewOptions ViewOptions::WITH_FRAGMENT = 0x0100;
40 const ViewOptions ViewOptions::EMPTY_AUTHORITY = 0x0200;
41 const ViewOptions ViewOptions::EMPTY_PATH_NAME = 0x0400;
42 const ViewOptions ViewOptions::EMPTY_PATH_PARAMS = 0x0800;
43 const ViewOptions ViewOptions::EMPTY_QUERY_STR = 0x1000;
44 const ViewOptions ViewOptions::EMPTY_FRAGMENT = 0x2000;
45 const ViewOptions ViewOptions::DEFAULTS = //0x07bb;
46 ViewOptions::WITH_SCHEME +
47 ViewOptions::WITH_USERNAME +
48 ViewOptions::WITH_HOST +
49 ViewOptions::WITH_PORT +
50 ViewOptions::WITH_PATH_NAME +
51 ViewOptions::WITH_QUERY_STR +
52 ViewOptions::WITH_FRAGMENT +
53 ViewOptions::EMPTY_AUTHORITY +
54 ViewOptions::EMPTY_PATH_NAME;
57 // ---------------------------------------------------------------
59 * authority = //[user [:password] @ ] host [:port]
61 * host = hostname | IPv4 | "[" IPv6-IP "]" | "[v...]"
63 #define RX_SPLIT_AUTHORITY \
64 "^(([^:@]*)" "([:]([^@]*))?" "@)?" "(\\[[^]]+\\]|[^:]+)?" "([:](.*))?"
67 // ---------------------------------------------------------------
68 namespace // anonymous
71 // -------------------------------------------------------------
73 checkUrlData(const std::string &data,
74 const std::string &name,
75 const std::string ®x)
77 if( regx.empty() || regx == "^$")
79 throw std::invalid_argument(
80 std::string("Url scheme does not allow a " +
85 if( !str::regex_match(data, str::regex(regx)))
87 throw std::invalid_argument(
88 std::string("Invalid " + name + " argument '" +
97 // ---------------------------------------------------------------
105 // ---------------------------------------------------------------
107 : m_data( new UrlData())
113 // ---------------------------------------------------------------
114 UrlBase::UrlBase(const UrlBase &url)
115 : m_data( new UrlData( *(url.m_data)))
120 // ---------------------------------------------------------------
121 UrlBase::UrlBase(const std::string &scheme,
122 const std::string &authority,
123 const std::string &pathdata,
124 const std::string &querystr,
125 const std::string &fragment)
126 : m_data( new UrlData())
129 init(scheme, authority, pathdata, querystr, fragment);
133 // ---------------------------------------------------------------
135 UrlBase::init(const std::string &scheme,
136 const std::string &authority,
137 const std::string &pathdata,
138 const std::string &querystr,
139 const std::string &fragment)
142 setAuthority(authority);
143 setPathData(pathdata);
144 setQueryString(querystr);
145 setFragment(fragment);
149 // ---------------------------------------------------------------
153 config("sep_pathparams", ";");
154 config("psep_pathparam", ",");
155 config("vsep_pathparam", "=");
157 config("psep_querystr", "&");
158 config("vsep_querystr", "=");
160 config("safe_username", "");
161 config("safe_password", "");
162 config("safe_hostname", "[:]");
163 config("safe_pathname", "/");
164 config("safe_pathparams", "");
165 config("safe_querystr", "");
166 config("safe_fragment", "");
168 config("rx_scheme", "^[a-zA-Z][a-zA-Z0-9\\._-]*$");
169 config("rx_username", ".*");
170 config("rx_password", ".*");
171 config("rx_hostname", ".*"); // FIXME
172 config("rx_port", ".*"); // FIXME
173 config("rx_pathname", ".*");
174 config("rx_pathparams", ".*");
175 config("rx_querystr", ".*");
176 config("rx_fragment", ".*");
180 // ---------------------------------------------------------------
182 UrlBase::config(const std::string &opt, const std::string &val)
184 m_data->config[opt] = val;
188 // ---------------------------------------------------------------
190 UrlBase::config(const std::string &opt) const
192 UrlConfig::const_iterator v( m_data->config.find(opt));
193 if( v != m_data->config.end())
196 return std::string();
200 // ---------------------------------------------------------------
202 UrlBase::getViewOptions() const
204 return m_data->vopts;
208 // ---------------------------------------------------------------
210 UrlBase::setViewOptions(const ViewOptions &vopts)
212 m_data->vopts = vopts;
216 // ---------------------------------------------------------------
220 zypp::url::UrlConfig config(m_data->config);
221 zypp::url::ViewOptions vopts(m_data->vopts);
223 m_data->config = config;
224 m_data->vopts = vopts;
228 // ---------------------------------------------------------------
230 UrlBase::clone() const
232 return new UrlBase(*this);
236 // ---------------------------------------------------------------
238 UrlBase::cleanupPathName(const std::string &path)
242 while( pos < path.length() && path.at(pos) == '/')
247 // make sure, there is not more than
248 // _one_ leading "/" in the path name.
249 return path.substr(pos - 1);
252 return std::string(path);
256 // ---------------------------------------------------------------
258 UrlBase::getKnownSchemes() const
264 // ---------------------------------------------------------------
266 UrlBase::isKnownScheme(const std::string &scheme) const
268 std::string lscheme( str::toLower(scheme));
269 Schemes schemes( getKnownSchemes());
270 Schemes::const_iterator s;
272 for(s=schemes.begin(); s!=schemes.end(); ++s)
274 if( lscheme == str::toLower(*s))
281 // ---------------------------------------------------------------
283 UrlBase::isValidScheme(const std::string &scheme) const
286 str::regex_match(scheme, str::regex(config("rx_scheme"))))
288 std::string lscheme( str::toLower(scheme));
289 Schemes schemes( getKnownSchemes());
294 Schemes::const_iterator s;
295 for(s=schemes.begin(); s!=schemes.end(); ++s)
297 if( scheme == str::toLower(*s))
305 // ---------------------------------------------------------------
307 UrlBase::isValid() const
309 return !getScheme().empty();
313 // ---------------------------------------------------------------
315 UrlBase::toString() const
317 return toString(getViewOptions());
321 // ---------------------------------------------------------------
323 UrlBase::toString(const zypp::url::ViewOptions &opts) const
328 if( opts.has(ViewOptions::WITH_SCHEME))
330 tmp.scheme = getScheme();
331 if( !tmp.scheme.empty())
333 url += tmp.scheme + ":";
335 if( opts.has(ViewOptions::WITH_HOST))
337 tmp.host = getHost(zypp::url::E_ENCODED);
338 if( !tmp.host.empty())
342 if( opts.has(ViewOptions::WITH_USERNAME))
344 tmp.user = getUsername(zypp::url::E_ENCODED);
345 if( !tmp.user.empty())
349 if( opts.has(ViewOptions::WITH_PASSWORD))
351 tmp.pass = getPassword(zypp::url::E_ENCODED);
352 if( !tmp.pass.empty())
354 url += ":" + tmp.pass;
363 if( opts.has(ViewOptions::WITH_PORT))
365 tmp.port = getPort();
366 if( !tmp.port.empty())
368 url += ":" + tmp.port;
373 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
380 if( opts.has(ViewOptions::WITH_PATH_NAME))
382 tmp.pathname = getPathName(zypp::url::E_ENCODED);
383 if( !tmp.pathname.empty())
385 if( (!tmp.host.empty() || opts.has(ViewOptions::EMPTY_AUTHORITY))
386 && (tmp.pathname.at(0) != '/'))
392 if( opts.has(ViewOptions::WITH_PATH_PARAMS))
394 tmp.pathparams = getPathParams();
395 if( !tmp.pathparams.empty())
397 url += ";" + tmp.pathparams;
399 else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
405 else if( opts.has(ViewOptions::EMPTY_PATH_NAME))
408 if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
415 if( opts.has(ViewOptions::WITH_QUERY_STR))
417 tmp.querystr = getQueryString();
418 if( !tmp.querystr.empty())
420 url += "?" + tmp.querystr;
422 else if( opts.has(ViewOptions::EMPTY_QUERY_STR))
428 if( opts.has(ViewOptions::WITH_FRAGMENT))
430 tmp.fragment = getFragment(zypp::url::E_ENCODED);
431 if( !tmp.fragment.empty())
433 url += "#" + tmp.fragment;
435 else if( opts.has(ViewOptions::EMPTY_FRAGMENT))
445 // ---------------------------------------------------------------
447 UrlBase::getScheme() const
449 return m_data->scheme;
453 // ---------------------------------------------------------------
455 UrlBase::getAuthority() const
458 if( !getHost(zypp::url::E_ENCODED).empty())
460 if( !getUsername(zypp::url::E_ENCODED).empty())
462 str = getUsername(zypp::url::E_ENCODED);
463 if( !getPassword(zypp::url::E_ENCODED).empty())
465 str += ":" + getPassword(zypp::url::E_ENCODED);
470 str += getHost(zypp::url::E_ENCODED);
471 if( !getPort().empty())
473 str += ":" + getPort();
480 // ---------------------------------------------------------------
482 UrlBase::getPathData() const
484 return getPathName(zypp::url::E_ENCODED) +
485 config("sep_pathparams") +
490 // ---------------------------------------------------------------
492 UrlBase::getQueryString() const
494 return m_data->querystr;
498 // ---------------------------------------------------------------
500 UrlBase::getFragment(EEncoding eflag) const
502 if(eflag == zypp::url::E_DECODED)
503 return zypp::url::decode(m_data->fragment);
505 return m_data->fragment;
509 // ---------------------------------------------------------------
511 UrlBase::getUsername(EEncoding eflag) const
513 if(eflag == zypp::url::E_DECODED)
514 return zypp::url::decode(m_data->user);
520 // ---------------------------------------------------------------
522 UrlBase::getPassword(EEncoding eflag) const
524 if(eflag == zypp::url::E_DECODED)
525 return zypp::url::decode(m_data->pass);
531 // ---------------------------------------------------------------
533 UrlBase::getHost(EEncoding eflag) const
535 if(eflag == zypp::url::E_DECODED)
536 return zypp::url::decode(m_data->host);
542 // ---------------------------------------------------------------
544 UrlBase::getPort() const
550 // ---------------------------------------------------------------
552 UrlBase::getPathName(EEncoding eflag) const
554 if(eflag == zypp::url::E_DECODED)
555 return zypp::url::decode(m_data->pathname);
557 return m_data->pathname;
561 // ---------------------------------------------------------------
563 UrlBase::getPathParams() const
565 return m_data->pathparams;
569 // ---------------------------------------------------------------
571 UrlBase::getPathParamsVec() const
573 zypp::url::ParamVec pvec;
577 config("psep_pathparam")
583 // ---------------------------------------------------------------
585 UrlBase::getPathParamsMap(EEncoding eflag) const
587 zypp::url::ParamMap pmap;
591 config("psep_pathparam"),
592 config("vsep_pathparam"),
599 // ---------------------------------------------------------------
601 UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const
603 zypp::url::ParamMap pmap( getPathParamsMap( eflag));
604 zypp::url::ParamMap::const_iterator i( pmap.find(param));
606 return i != pmap.end() ? i->second : std::string();
610 // ---------------------------------------------------------------
612 UrlBase::getQueryStringVec() const
614 zypp::url::ParamVec pvec;
618 config("psep_querystr")
624 // ---------------------------------------------------------------
626 UrlBase::getQueryStringMap(EEncoding eflag) const
628 zypp::url::ParamMap pmap;
632 config("psep_querystr"),
633 config("vsep_querystr"),
640 // ---------------------------------------------------------------
642 UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const
644 zypp::url::ParamMap pmap( getQueryStringMap( eflag));
645 zypp::url::ParamMap::const_iterator i( pmap.find(param));
647 return i != pmap.end() ? i->second : std::string();
651 // ---------------------------------------------------------------
653 UrlBase::setScheme(const std::string &scheme)
655 if( isValidScheme(scheme))
657 m_data->scheme = str::toLower(scheme);
661 throw std::invalid_argument(
662 std::string("Invalid Url scheme '" + scheme + "'")
668 // ---------------------------------------------------------------
670 UrlBase::setAuthority(const std::string &authority)
672 str::regex rex(RX_SPLIT_AUTHORITY);
674 bool ret = str::regex_match(authority, out, rex);
677 #if defined(WITH_URL_PARSE_DEBUG)
678 std::cerr << "Regex parsed URL authority("
679 << out.size() << "):" << std::endl;
680 std::cerr << "==> " << authority << std::endl;
681 for(size_t n=0; n < out.size(); n++)
683 std::cerr << "[" << n << "] " << out[n].str() << std::endl;
687 if( ret && out.size() == 8)
689 setUsername(out[2].str());
690 setPassword(out[4].str());
691 setHost(out[5].str());
692 setPort(out[7].str());
696 throw std::invalid_argument(
697 "Unable to parse Url authority"
703 // ---------------------------------------------------------------
705 UrlBase::setPathData(const std::string &pathdata)
708 pos = pathdata.find(config("sep_pathparams"));
709 if( pos != std::string::npos)
711 setPathName(pathdata.substr(0, pos));
712 setPathParams(pathdata.substr(pos + 1));
716 setPathName(pathdata);
722 // ---------------------------------------------------------------
724 UrlBase::setQueryString(const std::string &querystr)
726 if( querystr.empty())
728 m_data->querystr = querystr;
732 checkUrlData(querystr, "query string", config("rx_querystr"));
734 // FIXME: split & recode?
735 m_data->querystr = querystr;
740 // ---------------------------------------------------------------
742 UrlBase::setFragment(const std::string &fragment)
744 if( fragment.empty())
746 m_data->fragment = fragment;
750 std::string data( zypp::url::decode(fragment));
752 checkUrlData(data, "fragment", config("rx_fragment"));
754 m_data->fragment = zypp::url::encode(
755 data, config("safe_fragment")
761 // ---------------------------------------------------------------
763 UrlBase::setUsername(const std::string &user)
771 std::string data( zypp::url::decode(user));
773 checkUrlData(data, "username", config("rx_username"));
775 m_data->user = zypp::url::encode(
776 data, config("safe_username")
782 // ---------------------------------------------------------------
784 UrlBase::setPassword(const std::string &pass)
792 std::string data( zypp::url::decode(pass));
794 checkUrlData(data, "password", config("rx_password"));
796 m_data->pass = zypp::url::encode(
797 data, config("safe_password")
803 // ---------------------------------------------------------------
805 UrlBase::setHost(const std::string &host)
813 std::string data( zypp::url::decode(host));
815 checkUrlData(data, "hostname", config("rx_hostname"));
817 m_data->host = zypp::url::encode(
818 data, config("safe_hostname")
824 // ---------------------------------------------------------------
826 UrlBase::setPort(const std::string &port)
834 std::string data( zypp::url::decode(port));
836 checkUrlData(data, "port", config("rx_port"));
843 // ---------------------------------------------------------------
845 UrlBase::setPathName(const std::string &path)
849 m_data->pathname = path;
853 std::string data( cleanupPathName(zypp::url::decode(path)));
855 checkUrlData(data, "path", config("rx_pathname"));
857 m_data->pathname = zypp::url::encode(
858 data, config("safe_pathname")
864 // ---------------------------------------------------------------
866 UrlBase::setPathParams(const std::string ¶ms)
870 m_data->pathparams = params;
874 checkUrlData(params, "path parameters", config("rx_pathparams"));
876 // FIXME: split & recode?
877 m_data->pathparams = params;
882 // ---------------------------------------------------------------
884 UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec)
889 config("psep_pathparam")
895 // ---------------------------------------------------------------
897 UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap)
902 config("psep_pathparam"),
903 config("vsep_pathparam"),
904 config("safe_pathparams")
910 // ---------------------------------------------------------------
912 UrlBase::setPathParam(const std::string ¶m, const std::string &value)
914 std::string raw_param( zypp::url::decode(param));
915 std::string raw_value( zypp::url::decode(value));
917 zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED));
918 pmap[raw_param] = raw_value;
920 setPathParamsMap(pmap);
924 // ---------------------------------------------------------------
926 UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec)
931 config("psep_querystr")
937 // ---------------------------------------------------------------
939 UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap)
944 config("psep_querystr"),
945 config("vsep_querystr"),
946 config("safe_querystr")
951 // ---------------------------------------------------------------
953 UrlBase::setQueryParam(const std::string ¶m, const std::string &value)
955 std::string raw_param( zypp::url::decode(param));
956 std::string raw_value( zypp::url::decode(value));
958 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
959 pmap[raw_param] = raw_value;
961 setQueryStringMap(pmap);
965 //////////////////////////////////////////////////////////////////
967 ////////////////////////////////////////////////////////////////////
969 ////////////////////////////////////////////////////////////////////
971 //////////////////////////////////////////////////////////////////////
973 ** vim: set ts=2 sts=2 sw=2 ai et: