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;
47 ViewOptions::WITH_SCHEME +
48 ViewOptions::WITH_USERNAME +
49 ViewOptions::WITH_HOST +
50 ViewOptions::WITH_PORT +
51 ViewOptions::WITH_PATH_NAME +
52 ViewOptions::WITH_QUERY_STR +
53 ViewOptions::WITH_FRAGMENT +
54 ViewOptions::EMPTY_AUTHORITY +
55 ViewOptions::EMPTY_PATH_NAME;
59 // ---------------------------------------------------------------
61 * authority = //[user [:password] @ ] host [:port]
63 * host = hostname | IPv4 | "[" IPv6-IP "]" | "[v...]"
65 #define RX_SPLIT_AUTHORITY \
66 "^(([^:@]*)" "([:]([^@]*))?" "@)?" "(\\[[^]]+\\]|[^:]+)?" "([:](.*))?"
69 // ---------------------------------------------------------------
70 namespace // anonymous
73 // -------------------------------------------------------------
75 checkUrlData(const std::string &data,
76 const std::string &name,
77 const std::string ®x)
79 if( regx.empty() || regx == "^$")
81 throw std::invalid_argument(
82 std::string("Url scheme does not allow a " +
87 if( !str::regex_match(data, str::regex(regx)))
89 throw std::invalid_argument(
90 std::string("Invalid " + name + " argument '" +
99 // ---------------------------------------------------------------
107 // ---------------------------------------------------------------
109 : m_data( new UrlData())
115 // ---------------------------------------------------------------
116 UrlBase::UrlBase(const UrlBase &url)
117 : m_data( new UrlData( *(url.m_data)))
122 // ---------------------------------------------------------------
123 UrlBase::UrlBase(const std::string &scheme,
124 const std::string &authority,
125 const std::string &pathdata,
126 const std::string &querystr,
127 const std::string &fragment)
128 : m_data( new UrlData())
131 init(scheme, authority, pathdata, querystr, fragment);
135 // ---------------------------------------------------------------
137 UrlBase::init(const std::string &scheme,
138 const std::string &authority,
139 const std::string &pathdata,
140 const std::string &querystr,
141 const std::string &fragment)
144 setAuthority(authority);
145 setPathData(pathdata);
146 setQueryString(querystr);
147 setFragment(fragment);
151 // ---------------------------------------------------------------
155 config("sep_pathparams", ";");
156 config("psep_pathparam", ",");
157 config("vsep_pathparam", "=");
159 config("psep_querystr", "&");
160 config("vsep_querystr", "=");
162 config("safe_username", "");
163 config("safe_password", "");
164 config("safe_hostname", "[:]");
165 config("safe_pathname", "/");
166 config("safe_pathparams", "");
167 config("safe_querystr", "");
168 config("safe_fragment", "");
170 config("rx_scheme", "^[a-zA-Z][a-zA-Z0-9\\._-]*$");
171 config("rx_username", ".*");
172 config("rx_password", ".*");
173 config("rx_hostname", ".*"); // FIXME
174 config("rx_port", "^[0-9]{1,5}$");
175 config("rx_pathname", ".*");
176 config("rx_pathparams", ".*");
177 config("rx_querystr", ".*");
178 config("rx_fragment", ".*");
182 // ---------------------------------------------------------------
184 UrlBase::config(const std::string &opt, const std::string &val)
186 m_data->config[opt] = val;
190 // ---------------------------------------------------------------
192 UrlBase::config(const std::string &opt) const
194 UrlConfig::const_iterator v( m_data->config.find(opt));
195 if( v != m_data->config.end())
198 return std::string();
202 // ---------------------------------------------------------------
204 UrlBase::getViewOptions() const
206 return m_data->vopts;
210 // ---------------------------------------------------------------
212 UrlBase::setViewOptions(const ViewOptions &vopts)
214 m_data->vopts = vopts;
218 // ---------------------------------------------------------------
222 zypp::url::UrlConfig config(m_data->config);
223 zypp::url::ViewOptions vopts(m_data->vopts);
225 m_data->config = config;
226 m_data->vopts = vopts;
230 // ---------------------------------------------------------------
232 UrlBase::clone() const
234 return new UrlBase(*this);
238 // ---------------------------------------------------------------
240 UrlBase::cleanupPathName(const std::string &path)
244 while( pos < path.length() && path.at(pos) == '/')
249 // make sure, there is not more than
250 // _one_ leading "/" in the path name.
251 return path.substr(pos - 1);
254 return std::string(path);
258 // ---------------------------------------------------------------
259 zypp::url::UrlSchemes
260 UrlBase::getKnownSchemes() const
266 // ---------------------------------------------------------------
268 UrlBase::isKnownScheme(const std::string &scheme) const
270 std::string lscheme( str::toLower(scheme));
271 UrlSchemes schemes( getKnownSchemes());
272 UrlSchemes::const_iterator s;
274 for(s=schemes.begin(); s!=schemes.end(); ++s)
276 if( lscheme == str::toLower(*s))
283 // ---------------------------------------------------------------
285 UrlBase::isValidScheme(const std::string &scheme) const
288 str::regex_match(scheme, str::regex(config("rx_scheme"))))
290 std::string lscheme( str::toLower(scheme));
291 UrlSchemes schemes( getKnownSchemes());
296 UrlSchemes::const_iterator s;
297 for(s=schemes.begin(); s!=schemes.end(); ++s)
299 if( lscheme == str::toLower(*s))
307 // ---------------------------------------------------------------
309 UrlBase::isValid() const
311 return !getScheme().empty();
315 // ---------------------------------------------------------------
317 UrlBase::toString() const
319 return toString(getViewOptions());
323 // ---------------------------------------------------------------
325 UrlBase::toString(const zypp::url::ViewOptions &opts) const
330 if( opts.has(ViewOptions::WITH_SCHEME))
332 tmp.scheme = getScheme();
333 if( !tmp.scheme.empty())
335 url += tmp.scheme + ":";
337 if( opts.has(ViewOptions::WITH_HOST))
339 tmp.host = getHost(zypp::url::E_ENCODED);
340 if( !tmp.host.empty())
344 if( opts.has(ViewOptions::WITH_USERNAME))
346 tmp.user = getUsername(zypp::url::E_ENCODED);
347 if( !tmp.user.empty())
351 if( opts.has(ViewOptions::WITH_PASSWORD))
353 tmp.pass = getPassword(zypp::url::E_ENCODED);
354 if( !tmp.pass.empty())
356 url += ":" + tmp.pass;
365 if( opts.has(ViewOptions::WITH_PORT))
367 tmp.port = getPort();
368 if( !tmp.port.empty())
370 url += ":" + tmp.port;
375 else if( opts.has(ViewOptions::EMPTY_AUTHORITY))
382 if( opts.has(ViewOptions::WITH_PATH_NAME))
384 tmp.pathname = getPathName(zypp::url::E_ENCODED);
385 if( !tmp.pathname.empty())
387 if( (!tmp.host.empty() || opts.has(ViewOptions::EMPTY_AUTHORITY))
388 && (tmp.pathname.at(0) != '/'))
394 if( opts.has(ViewOptions::WITH_PATH_PARAMS))
396 tmp.pathparams = getPathParams();
397 if( !tmp.pathparams.empty())
399 url += ";" + tmp.pathparams;
401 else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
407 else if( opts.has(ViewOptions::EMPTY_PATH_NAME))
410 if( opts.has(ViewOptions::EMPTY_PATH_PARAMS))
417 if( opts.has(ViewOptions::WITH_QUERY_STR))
419 tmp.querystr = getQueryString();
420 if( !tmp.querystr.empty())
422 url += "?" + tmp.querystr;
424 else if( opts.has(ViewOptions::EMPTY_QUERY_STR))
430 if( opts.has(ViewOptions::WITH_FRAGMENT))
432 tmp.fragment = getFragment(zypp::url::E_ENCODED);
433 if( !tmp.fragment.empty())
435 url += "#" + tmp.fragment;
437 else if( opts.has(ViewOptions::EMPTY_FRAGMENT))
447 // ---------------------------------------------------------------
449 UrlBase::getScheme() const
451 return m_data->scheme;
455 // ---------------------------------------------------------------
457 UrlBase::getAuthority() const
460 if( !getHost(zypp::url::E_ENCODED).empty())
462 if( !getUsername(zypp::url::E_ENCODED).empty())
464 str = getUsername(zypp::url::E_ENCODED);
465 if( !getPassword(zypp::url::E_ENCODED).empty())
467 str += ":" + getPassword(zypp::url::E_ENCODED);
472 str += getHost(zypp::url::E_ENCODED);
473 if( !getPort().empty())
475 str += ":" + getPort();
482 // ---------------------------------------------------------------
484 UrlBase::getPathData() const
486 return getPathName(zypp::url::E_ENCODED) +
487 config("sep_pathparams") +
492 // ---------------------------------------------------------------
494 UrlBase::getQueryString() const
496 return m_data->querystr;
500 // ---------------------------------------------------------------
502 UrlBase::getFragment(EEncoding eflag) const
504 if(eflag == zypp::url::E_DECODED)
505 return zypp::url::decode(m_data->fragment);
507 return m_data->fragment;
511 // ---------------------------------------------------------------
513 UrlBase::getUsername(EEncoding eflag) const
515 if(eflag == zypp::url::E_DECODED)
516 return zypp::url::decode(m_data->user);
522 // ---------------------------------------------------------------
524 UrlBase::getPassword(EEncoding eflag) const
526 if(eflag == zypp::url::E_DECODED)
527 return zypp::url::decode(m_data->pass);
533 // ---------------------------------------------------------------
535 UrlBase::getHost(EEncoding eflag) const
537 if(eflag == zypp::url::E_DECODED)
538 return zypp::url::decode(m_data->host);
544 // ---------------------------------------------------------------
546 UrlBase::getPort() const
552 // ---------------------------------------------------------------
554 UrlBase::getPathName(EEncoding eflag) const
556 if(eflag == zypp::url::E_DECODED)
557 return zypp::url::decode(m_data->pathname);
559 return m_data->pathname;
563 // ---------------------------------------------------------------
565 UrlBase::getPathParams() const
567 return m_data->pathparams;
571 // ---------------------------------------------------------------
573 UrlBase::getPathParamsVec() const
575 zypp::url::ParamVec pvec;
579 config("psep_pathparam")
585 // ---------------------------------------------------------------
587 UrlBase::getPathParamsMap(EEncoding eflag) const
589 zypp::url::ParamMap pmap;
593 config("psep_pathparam"),
594 config("vsep_pathparam"),
601 // ---------------------------------------------------------------
603 UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const
605 zypp::url::ParamMap pmap( getPathParamsMap( eflag));
606 zypp::url::ParamMap::const_iterator i( pmap.find(param));
608 return i != pmap.end() ? i->second : std::string();
612 // ---------------------------------------------------------------
614 UrlBase::getQueryStringVec() const
616 zypp::url::ParamVec pvec;
620 config("psep_querystr")
626 // ---------------------------------------------------------------
628 UrlBase::getQueryStringMap(EEncoding eflag) const
630 zypp::url::ParamMap pmap;
634 config("psep_querystr"),
635 config("vsep_querystr"),
642 // ---------------------------------------------------------------
644 UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const
646 zypp::url::ParamMap pmap( getQueryStringMap( eflag));
647 zypp::url::ParamMap::const_iterator i( pmap.find(param));
649 return i != pmap.end() ? i->second : std::string();
653 // ---------------------------------------------------------------
655 UrlBase::setScheme(const std::string &scheme)
657 if( isValidScheme(scheme))
659 m_data->scheme = str::toLower(scheme);
663 throw std::invalid_argument(
664 std::string("Invalid Url scheme '" + scheme + "'")
670 // ---------------------------------------------------------------
672 UrlBase::setAuthority(const std::string &authority)
674 str::regex rex(RX_SPLIT_AUTHORITY);
676 bool ret = str::regex_match(authority, out, rex);
679 #if defined(WITH_URL_PARSE_DEBUG)
680 std::cerr << "Regex parsed URL authority("
681 << out.size() << "):" << std::endl;
682 std::cerr << "==> " << authority << std::endl;
683 for(size_t n=0; n < out.size(); n++)
685 std::cerr << "[" << n << "] " << out[n].str() << std::endl;
689 if( ret && out.size() == 8)
691 setUsername(out[2].str());
692 setPassword(out[4].str());
693 setHost(out[5].str());
694 setPort(out[7].str());
698 throw std::invalid_argument(
699 "Unable to parse Url authority"
705 // ---------------------------------------------------------------
707 UrlBase::setPathData(const std::string &pathdata)
710 pos = pathdata.find(config("sep_pathparams"));
711 if( pos != std::string::npos)
713 setPathName(pathdata.substr(0, pos));
714 setPathParams(pathdata.substr(pos + 1));
718 setPathName(pathdata);
724 // ---------------------------------------------------------------
726 UrlBase::setQueryString(const std::string &querystr)
728 if( querystr.empty())
730 m_data->querystr = querystr;
734 checkUrlData(querystr, "query string", config("rx_querystr"));
736 // FIXME: split & recode?
737 m_data->querystr = querystr;
742 // ---------------------------------------------------------------
744 UrlBase::setFragment(const std::string &fragment)
746 if( fragment.empty())
748 m_data->fragment = fragment;
752 std::string data( zypp::url::decode(fragment));
754 checkUrlData(data, "fragment", config("rx_fragment"));
756 m_data->fragment = zypp::url::encode(
757 data, config("safe_fragment")
763 // ---------------------------------------------------------------
765 UrlBase::setUsername(const std::string &user)
773 std::string data( zypp::url::decode(user));
775 checkUrlData(data, "username", config("rx_username"));
777 m_data->user = zypp::url::encode(
778 data, config("safe_username")
784 // ---------------------------------------------------------------
786 UrlBase::setPassword(const std::string &pass)
794 std::string data( zypp::url::decode(pass));
796 checkUrlData(data, "password", config("rx_password"));
798 m_data->pass = zypp::url::encode(
799 data, config("safe_password")
805 // ---------------------------------------------------------------
807 UrlBase::setHost(const std::string &host)
815 std::string data( zypp::url::decode(host));
817 checkUrlData(data, "hostname", config("rx_hostname"));
819 m_data->host = zypp::url::encode(
820 data, config("safe_hostname")
826 // ---------------------------------------------------------------
828 UrlBase::setPort(const std::string &port)
836 std::string data( zypp::url::decode(port));
838 checkUrlData(data, "port", config("rx_port"));
845 // ---------------------------------------------------------------
847 UrlBase::setPathName(const std::string &path)
851 m_data->pathname = path;
855 std::string data( cleanupPathName(zypp::url::decode(path)));
857 checkUrlData(data, "path", config("rx_pathname"));
859 m_data->pathname = zypp::url::encode(
860 data, config("safe_pathname")
866 // ---------------------------------------------------------------
868 UrlBase::setPathParams(const std::string ¶ms)
872 m_data->pathparams = params;
876 checkUrlData(params, "path parameters", config("rx_pathparams"));
878 // FIXME: split & recode?
879 m_data->pathparams = params;
884 // ---------------------------------------------------------------
886 UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec)
891 config("psep_pathparam")
897 // ---------------------------------------------------------------
899 UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap)
904 config("psep_pathparam"),
905 config("vsep_pathparam"),
906 config("safe_pathparams")
912 // ---------------------------------------------------------------
914 UrlBase::setPathParam(const std::string ¶m, const std::string &value)
916 std::string raw_param( zypp::url::decode(param));
917 std::string raw_value( zypp::url::decode(value));
919 zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED));
920 pmap[raw_param] = raw_value;
922 setPathParamsMap(pmap);
926 // ---------------------------------------------------------------
928 UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec)
933 config("psep_querystr")
939 // ---------------------------------------------------------------
941 UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap)
946 config("psep_querystr"),
947 config("vsep_querystr"),
948 config("safe_querystr")
953 // ---------------------------------------------------------------
955 UrlBase::setQueryParam(const std::string ¶m, const std::string &value)
957 std::string raw_param( zypp::url::decode(param));
958 std::string raw_value( zypp::url::decode(value));
960 zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED));
961 pmap[raw_param] = raw_value;
963 setQueryStringMap(pmap);
967 //////////////////////////////////////////////////////////////////
969 ////////////////////////////////////////////////////////////////////
971 ////////////////////////////////////////////////////////////////////
973 //////////////////////////////////////////////////////////////////////
975 ** vim: set ts=2 sts=2 sw=2 ai et: