#include "url_parser.hh"
|
|
|
|
#include <stdexcept>
|
|
#include <boost/spirit/include/qi.hpp>
|
|
#include <boost/spirit/include/phoenix.hpp>
|
|
|
|
|
|
namespace qi = boost::spirit::qi;
|
|
|
|
BOOST_FUSION_ADAPT_STRUCT(
|
|
pEp::URL,
|
|
(std::string, schema)
|
|
(std::string, username)
|
|
(std::string, password)
|
|
(std::string, host)
|
|
(unsigned , port)
|
|
(std::string, path_and_query)
|
|
(std::string, fragment)
|
|
)
|
|
|
|
|
|
namespace pEp
|
|
{
|
|
|
|
|
|
template <typename Iterator>
|
|
struct UriGrammar : qi::grammar<Iterator, URL()>
|
|
{
|
|
typedef unsigned long ulong;
|
|
UriGrammar() : UriGrammar::base_type(url)
|
|
{
|
|
schema = *(qi::char_ - ':' - '/');
|
|
username = *(qi::char_ - ':' - '@');
|
|
password = *(qi::char_ - '@');
|
|
host = *(qi::char_ - '/' - ':');
|
|
path_and_query = *(qi::char_ - '#');
|
|
fragment = *(qi::char_);
|
|
|
|
url = schema
|
|
>> "://" >> -( username
|
|
>> -(':' >> password) >> '@'
|
|
)
|
|
>> host
|
|
>> (':' >> qi::uint_[ boost::phoenix::at_c<4>(qi::_val) = qi::_1 ])
|
|
>> -(path_and_query) // >> -('?' >> params[ boost::phoenix::at_c<6>(qi::_val) = qi::_1 ] )
|
|
>> -('#' >> fragment);
|
|
};
|
|
|
|
qi::rule<Iterator, URL()> url;
|
|
qi::rule<Iterator, std::string()> schema, username, password, host, path_and_query, fragment;
|
|
};
|
|
|
|
|
|
URL parse_url(const char* begin, const char* end)
|
|
{
|
|
static const UriGrammar<const char*> G;
|
|
|
|
URL url;
|
|
const char* begin2 = begin;
|
|
const bool okay = boost::spirit::qi::parse(begin2, end, G, url);
|
|
if(!okay)
|
|
{
|
|
throw std::runtime_error("Cannot parse URL <" + std::string(begin,end) + "> !");
|
|
}
|
|
|
|
// stolen from pEpMIME's ascii_tolower():
|
|
for(char& c : url.schema)
|
|
{
|
|
if(c>='A' && c<='Z')
|
|
{
|
|
c += 32;
|
|
}
|
|
}
|
|
|
|
return url;
|
|
}
|
|
|
|
} // end of namespace pEp
|