198 lines
4.9 KiB
C++
198 lines
4.9 KiB
C++
#include <fc/network/url.hpp>
|
|
#include <fc/io/sstream.hpp>
|
|
#include <fc/exception/exception.hpp>
|
|
#include <fc/log/logger.hpp>
|
|
#include <sstream>
|
|
|
|
namespace fc
|
|
{
|
|
namespace detail
|
|
{
|
|
class url_impl
|
|
{
|
|
public:
|
|
void parse( const std::string& s )
|
|
{
|
|
std::stringstream ss(s);
|
|
std::string skip,_lpath,_largs,luser,lpass;
|
|
std::getline( ss, _proto, ':' );
|
|
std::getline( ss, skip, '/' );
|
|
std::getline( ss, skip, '/' );
|
|
|
|
if( s.find('@') != size_t(std::string::npos) ) {
|
|
std::string user_pass;
|
|
std::getline( ss, user_pass, '@' );
|
|
std::stringstream upss(user_pass);
|
|
if( user_pass.find( ':' ) != size_t(std::string::npos) ) {
|
|
std::getline( upss, luser, ':' );
|
|
std::getline( upss, lpass, ':' );
|
|
_user = std::move(luser);
|
|
_pass = std::move(lpass);
|
|
} else {
|
|
_user = std::move(user_pass);
|
|
}
|
|
}
|
|
std::string host_port;
|
|
std::getline( ss, host_port, '/' );
|
|
auto pos = host_port.find( ':' );
|
|
if( pos != std::string::npos ) {
|
|
try {
|
|
_port = static_cast<uint16_t>(to_uint64( host_port.substr( pos+1 ) ));
|
|
} catch ( ... ) {
|
|
FC_THROW_EXCEPTION( parse_error_exception, "Unable to parse port field in url",( "url", s ) );
|
|
}
|
|
_host = host_port.substr(0,pos);
|
|
} else {
|
|
_host = std::move(host_port);
|
|
}
|
|
std::getline( ss, _lpath, '?' );
|
|
#ifdef WIN32
|
|
// On windows, a URL like file:///c:/autoexec.bat would result in _lpath = c:/autoexec.bat
|
|
// which is what we really want (it's already an absolute path)
|
|
if (!stricmp(_proto.c_str(), "file"))
|
|
_path = _lpath;
|
|
else
|
|
_path = fc::path( "/" ) / _lpath; // let other schemes behave like unix
|
|
#else
|
|
// On unix, a URL like file:///etc/rc.local would result in _lpath = etc/rc.local
|
|
// but we really want to make it the absolute path /etc/rc.local
|
|
_path = fc::path( "/" ) / _lpath;
|
|
#endif
|
|
std::getline( ss, _largs );
|
|
if( _args.valid() && _args->size() )
|
|
{
|
|
// TODO: args = std::move(_args);
|
|
}
|
|
}
|
|
|
|
string _proto;
|
|
ostring _host;
|
|
ostring _user;
|
|
ostring _pass;
|
|
opath _path;
|
|
ovariant_object _args;
|
|
fc::optional<uint16_t> _port;
|
|
};
|
|
}
|
|
|
|
void to_variant( const url& u, fc::variant& v, uint32_t max_depth )
|
|
{
|
|
v = std::string(u);
|
|
}
|
|
void from_variant( const fc::variant& v, url& u, uint32_t max_depth )
|
|
{
|
|
u = url( v.as_string() );
|
|
}
|
|
|
|
url::operator string()const
|
|
{
|
|
std::stringstream ss;
|
|
ss<<my->_proto<<"://";
|
|
if( my->_user.valid() ) {
|
|
ss << *my->_user;
|
|
if( my->_pass.valid() ) {
|
|
ss<<":"<<*my->_pass;
|
|
}
|
|
ss<<"@";
|
|
}
|
|
if( my->_host.valid() ) ss<<*my->_host;
|
|
if( my->_port.valid() ) ss<<":"<<*my->_port;
|
|
if( my->_path.valid() ) ss<<my->_path->generic_string();
|
|
return ss.str();
|
|
}
|
|
|
|
url::url( const std::string& u )
|
|
:my( std::make_shared<detail::url_impl>() )
|
|
{
|
|
my->parse(u);
|
|
}
|
|
|
|
std::shared_ptr<detail::url_impl> get_null_url()
|
|
{
|
|
static auto u = std::make_shared<detail::url_impl>();
|
|
return u;
|
|
}
|
|
|
|
url::url()
|
|
:my( get_null_url() )
|
|
{ }
|
|
|
|
url::url( const url& u )
|
|
:my(u.my){}
|
|
|
|
url::url( url&& u )
|
|
:my( std::move(u.my) )
|
|
{
|
|
u.my = get_null_url();
|
|
}
|
|
|
|
url::url( const mutable_url& mu )
|
|
:my( std::make_shared<detail::url_impl>(*mu.my) )
|
|
{
|
|
|
|
}
|
|
url::url( mutable_url&& mu )
|
|
:my( std::move( mu.my ) )
|
|
{ }
|
|
|
|
url::~url(){}
|
|
|
|
url& url::operator=(const url& u )
|
|
{
|
|
my = u.my;
|
|
return *this;
|
|
}
|
|
|
|
url& url::operator=(url&& u )
|
|
{
|
|
if( this != &u )
|
|
{
|
|
my = std::move(u.my);
|
|
u.my= get_null_url();
|
|
}
|
|
return *this;
|
|
}
|
|
url& url::operator=(const mutable_url& u )
|
|
{
|
|
my = std::make_shared<detail::url_impl>(*u.my);
|
|
return *this;
|
|
}
|
|
url& url::operator=(mutable_url&& u )
|
|
{
|
|
my = std::move(u.my);
|
|
return *this;
|
|
}
|
|
|
|
string url::proto()const
|
|
{
|
|
return my->_proto;
|
|
}
|
|
ostring url::host()const
|
|
{
|
|
return my->_host;
|
|
}
|
|
ostring url::user()const
|
|
{
|
|
return my->_user;
|
|
}
|
|
ostring url::pass()const
|
|
{
|
|
return my->_pass;
|
|
}
|
|
opath url::path()const
|
|
{
|
|
return my->_path;
|
|
}
|
|
ovariant_object url::args()const
|
|
{
|
|
return my->_args;
|
|
}
|
|
fc::optional<uint16_t> url::port()const
|
|
{
|
|
return my->_port;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|