fix new bug in parsing amqp:// address where the default vhost was incorrectly overwritten

This commit is contained in:
Daan Mulder 2017-05-11 13:59:07 +02:00
parent 8501f19c0b
commit b2877434cf
1 changed files with 34 additions and 34 deletions

View File

@ -28,19 +28,19 @@ private:
* @var Login * @var Login
*/ */
Login _login; Login _login;
/** /**
* The hostname * The hostname
* @var std::string * @var std::string
*/ */
std::string _hostname; std::string _hostname;
/** /**
* Port number * Port number
* @var uint16_t * @var uint16_t
*/ */
uint16_t _port = 5672; uint16_t _port = 5672;
/** /**
* The vhost * The vhost
* @var std::string * @var std::string
@ -62,47 +62,47 @@ public:
// must start with amqp:// // must start with amqp://
if (size < 7 || strncmp(data, "amqp://", 7) != 0) throw std::runtime_error("AMQP address should start with \"amqp://\""); if (size < 7 || strncmp(data, "amqp://", 7) != 0) throw std::runtime_error("AMQP address should start with \"amqp://\"");
// begin of the string was parsed // begin of the string was parsed
data += 7; data += 7;
// do we have a '@' to split user-data and hostname? // do we have a '@' to split user-data and hostname?
const char *at = (const char *)memchr(data, '@', last - data); const char *at = (const char *)memchr(data, '@', last - data);
// do we have one? // do we have one?
if (at != nullptr) if (at != nullptr)
{ {
// size of the user:password // size of the user:password
size_t loginsize = at - data; size_t loginsize = at - data;
// colon could split username and password // colon could split username and password
const char *colon = (const char *)memchr(data, ':', loginsize); const char *colon = (const char *)memchr(data, ':', loginsize);
// assign the login // assign the login
_login = Login( _login = Login(
std::string(data, colon ? colon - data : loginsize), std::string(data, colon ? colon - data : loginsize),
std::string(colon ? colon + 1 : "", colon ? at - colon - 1 : 0) std::string(colon ? colon + 1 : "", colon ? at - colon - 1 : 0)
); );
// set data to the start of the hostname // set data to the start of the hostname
data = at + 1; data = at + 1;
} }
// find out where the vhost is set (starts with a slash) // find out where the vhost is set (starts with a slash)
const char *slash = (const char *)memchr(data, '/', last - data); const char *slash = (const char *)memchr(data, '/', last - data);
// was a vhost set? // was a vhost set?
if (slash != nullptr && last - data > 1) _vhost.assign(slash + 1, last - slash - 1); if (slash != nullptr && last - slash > 1) _vhost.assign(slash + 1, last - slash - 1);
// the hostname is everything until the slash, check is portnumber was set // the hostname is everything until the slash, check is portnumber was set
const char *colon = (const char *)memchr(data, ':', last - data); const char *colon = (const char *)memchr(data, ':', last - data);
// was a portnumber specified (colon must appear before the slash of the vhost) // was a portnumber specified (colon must appear before the slash of the vhost)
if (colon && (!slash || colon < slash)) if (colon && (!slash || colon < slash))
{ {
// a portnumber was set to // a portnumber was set to
_hostname.assign(data, colon - data); _hostname.assign(data, colon - data);
// calculate the port // calculate the port
_port = atoi(std::string(colon + 1, slash ? slash - colon - 1 : last - colon - 1).data()); _port = atoi(std::string(colon + 1, slash ? slash - colon - 1 : last - colon - 1).data());
} }
@ -120,7 +120,7 @@ public:
* @throws std::runtime_error * @throws std::runtime_error
*/ */
Address(const char *data) : Address(data, strlen(data)) {} Address(const char *data) : Address(data, strlen(data)) {}
/** /**
* Constructor based on std::string * Constructor based on std::string
* @param address * @param address
@ -134,17 +134,17 @@ public:
* @param login * @param login
* @param vhost * @param vhost
*/ */
Address(std::string host, uint16_t port, Login login, std::string vhost) : Address(std::string host, uint16_t port, Login login, std::string vhost) :
_login(std::move(login)), _login(std::move(login)),
_hostname(std::move(host)), _hostname(std::move(host)),
_port(port), _port(port),
_vhost(std::move(vhost)) {} _vhost(std::move(vhost)) {}
/** /**
* Destructor * Destructor
*/ */
virtual ~Address() = default; virtual ~Address() = default;
/** /**
* Expose the login data * Expose the login data
* @return Login * @return Login
@ -153,7 +153,7 @@ public:
{ {
return _login; return _login;
} }
/** /**
* Host name * Host name
* @return std::string * @return std::string
@ -162,7 +162,7 @@ public:
{ {
return _hostname; return _hostname;
} }
/** /**
* Port number * Port number
* @return uint16_t * @return uint16_t
@ -171,7 +171,7 @@ public:
{ {
return _port; return _port;
} }
/** /**
* The vhost to connect to * The vhost to connect to
* @return std::string * @return std::string
@ -180,7 +180,7 @@ public:
{ {
return _vhost; return _vhost;
} }
/** /**
* Cast to a string * Cast to a string
* @return std:string * @return std:string
@ -189,23 +189,23 @@ public:
{ {
// result object // result object
std::string str("amqp://"); std::string str("amqp://");
// append login // append login
str.append(_login.user()).append(":").append(_login.password()).append("@").append(_hostname); str.append(_login.user()).append(":").append(_login.password()).append("@").append(_hostname);
// do we need a special portnumber? // do we need a special portnumber?
if (_port != 5672) str.append(":").append(std::to_string(_port)); if (_port != 5672) str.append(":").append(std::to_string(_port));
// append default vhost // append default vhost
str.append("/"); str.append("/");
// do we have a special vhost? // do we have a special vhost?
if (_vhost != "/") str.append(_vhost); if (_vhost != "/") str.append(_vhost);
// done // done
return str; return str;
} }
/** /**
* Comparison operator * Comparison operator
* @param that * @param that
@ -215,17 +215,17 @@ public:
{ {
// logins must match // logins must match
if (_login != that._login) return false; if (_login != that._login) return false;
// hostname must match, but are nt case sensitive // hostname must match, but are nt case sensitive
if (strcasecmp(_hostname.data(), that._hostname.data()) != 0) return false; if (strcasecmp(_hostname.data(), that._hostname.data()) != 0) return false;
// portnumber must match // portnumber must match
if (_port != that._port) return false; if (_port != that._port) return false;
// and finally the vhosts, they must match too // and finally the vhosts, they must match too
return _vhost == that._vhost; return _vhost == that._vhost;
} }
/** /**
* Comparison operator * Comparison operator
* @param that * @param that