35 #include <boost/algorithm/string.hpp>
36 #include <boost/array.hpp>
37 #include <boost/assign.hpp>
38 #include <boost/filesystem.hpp>
39 #include <boost/lexical_cast.hpp>
40 #include <boost/tokenizer.hpp>
41 #include <boost/xpressive/xpressive_static.hpp>
43 using namespace boost;
45 using namespace boost::xpressive;
47 namespace bx = boost::xpressive;
55 template<
typename S,
typename I> S
join_r(
const I & beg,
const I & end,
const S & sep) {
57 for (I it = beg; it != end; ++it) {
68 template<
typename TipusStr>
74 static boost::array<char,15> NO_SEGURS = { {
'{',
'}',
'|',
'\\',
'^',
'~',
'[',
']',
'.',
76 '/',
'?',
':',
'@',
'=',
'&'
79 (c < 0x1F) || (c == 0x7F) ||
80 (NO_SEGURS.end() != find(NO_SEGURS.begin(), NO_SEGURS.end(), c))
87 if (cal_codificar(c)) {
88 string hex = utils::to_string<int>(c, std::hex);
90 desti.append(
"%"+hex);
101 const string & ruta,
const string &
params,
105 if (!esquema.empty()) {
106 ss << esquema <<
":";
109 if (!autoritat.empty()) {
110 ss <<
"//" << autoritat;
115 if (!params.empty()) {
119 if (!query.empty()) {
123 if (!fragment.empty()) {
187 namespace RFC2068_Sintaxi_URIs {
190 const sregex
unsafe = imbue(locale::classic())(bx::set[ cntrl | char(32) |
'"'
191 |
'#' |
'%' |
'<' |
'>' ])
193 ,
safe = bx::set[ as_xpr(
'$') |
'-' |
'_' |
'.' ]
195 ,
extra = bx::set[ as_xpr(
'!') |
'*' |
'\'' |
'(' |
')' |
',' ]
197 ,
reserved = bx::set[ as_xpr(
';') |
'/' |
'?' |
':' |
'@' |
'&' |
'=' |
'+' ]
201 ,
national = imbue(locale::classic())(~bx::set[ alpha | digit
202 |
';' |
'/' |
'?' |
':' |
'@' |
'&' |
'=' |
'+'
203 |
'!' |
'*' |
'\'' |
'(' |
')' |
','
204 |
'$' |
'-' |
'_' |
'.'
205 | cntrl | char(32) |
'"' |
'#' |
'%' |
'<' |
'>'
213 const sregex
pchar = (
uchar |
':' |
'@' |
'&' |
'=' |
'+' ) ;
219 ,
scheme = +( alpha | digit |
'+' |
'-' |
'.' )
267 using namespace RFC2068_Sintaxi_URIs;
269 if (!regex_match(uri,
URI)) {
273 regex_match(uri, m,
ex_URI);
274 const string esquema = m[1], relativa = m[2],
fragment = m[3];
276 bool es_net_path = regex_match(relativa,
net_path),
277 es_abs_path = regex_match(relativa,
abs_path),
278 es_rel_path = regex_match(relativa,
rel_path);
279 assert( es_net_path | es_abs_path | es_rel_path );
280 string netloc, abspath, relpath;
286 else if (es_abs_path) {
289 else if (es_rel_path) {
292 if (!abspath.empty()) {
293 assert( abspath[0] ==
'/' );
294 relpath = abspath.substr(1);
297 if (!relpath.empty()) {
303 if (!abspath.empty()) {
330 bool Uri::operator==(
const Uri & u)
const {
334 return str() == u.
str();
337 bool Uri::es_uri_absoluta()
const {
338 return esquema_.length() != 0 && autoritat_.length() != 0;
341 bool Uri::te_ruta_absoluta()
const {
342 return ruta_.empty() || ruta_.at(0) ==
'/';
345 string Uri::str()
const {
358 if (p.empty() || p ==
"/") {
368 const sregex dblbarra = as_xpr(
'/') >> +as_xpr(
'/');
369 p = regex_replace(p, dblbarra,
"/");
376 const char_separator<char> sepdir(
"/");
377 tokenizer< char_separator<char> > tokens(p, sepdir);
380 for (
auto it = tokens.begin(); it != tokens.end(); ++it) {
381 const string & elem = *it;
384 comp.push_back(
string());
394 comp.push_back(elem);
397 string nova_ruta =
join_r(comp.begin(), comp.end(), string(
"/"));
399 if (nova_ruta.empty() && !p.empty() && p.at(0) ==
'/') {
406 return Uri(nova_url);
412 ret.reserve(s.length());
416 using namespace boost::xpressive;
417 const sregex hex_re = xdigit >> xdigit;
418 string::size_type idx = 0, percent;
419 while (string::npos != (percent = s.find(
'%', idx))) {
420 assert( s.at(percent) ==
'%' );
422 ret.append(s, idx, percent-idx);
425 if (s.length() < (percent+3)) {
428 ret.append(1, s.at(percent));
431 assert( s.length() >= (percent+3) );
432 const string hex(s.substr(percent+1, percent+3), 0, 2);
433 assert( hex.length() == 2 );
434 if (!regex_match(hex, hex_re)) {
438 ret.append(1, s.at(percent));
441 const int C = tfc::utils::from_string<int>(hex, std::hex);
443 const char c =
static_cast<char>(C);
448 ret.append(s.substr(idx));
465 ret.reserve(s.length());
466 for_each(s.begin(), s.end(), FunctorCodificacio<string>(ret));
474 <<
", " << u.
ruta() <<
", " << u.
query() <<
", "
477 return os << string(u);