fixed issue with parsing the password in a amqp:// string

This commit is contained in:
Emiel Bruijntjes 2017-05-01 21:59:45 +02:00
parent 2bb1300bc0
commit 2a249ae7ea
2 changed files with 80 additions and 22 deletions

View File

@ -50,65 +50,82 @@ private:
public:
/**
* Constructor to parse an address string
* The address should be in "amqp://
* @param address
* The address should start with "amqp://
* @param data
* @param size
* @throws std::runtime_error
*/
Address(const char *address) : _vhost("/")
Address(const char *data, size_t size) : _vhost("/")
{
// position of the last byte
const char *last = data + size;
// must start with amqp://
if (strncmp(address, "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 being parsed
const char *begin = address + 7;
// begin of the string was parsed
data += 7;
// do we have a '@' to split user-data and hostname?
const char *at = strchr(begin, '@');
const char *at = (const char *)memchr(data, '@', last - data);
// do we have one?
if (at != nullptr)
{
// size of the user:password
size_t loginsize = at - data;
// colon could split username and password
const char *colon = (const char *)memchr(begin, ':', at - begin);
const char *colon = (const char *)memchr(data, ':', loginsize);
// assign the login
_login = Login(
std::string(begin, colon ? colon - begin : at - begin),
std::string(data, colon ? colon - data : loginsize),
std::string(colon ? colon + 1 : "", colon ? at - colon - 1 : 0)
);
// set begin to the start of the hostname
begin = at + 1;
// set data to the start of the hostname
data = at + 1;
}
// find out where the vhost is set (starts with a slash)
const char *slash = strchr(begin, '/');
const char *slash = (const char *)memchr(data, '/', last - data);
// was a vhost set?
if (slash != nullptr && slash[1]) _vhost = slash + 1;
if (slash != nullptr && last - data > 1) _vhost.assign(slash + 1, last - data - 1);
// the hostname is everything until the slash, check is portnumber was set
const char *colon = strchr(begin, ':');
const char *colon = (const char *)memchr(data, ':', last - data);
// was a portnumber specified (colon must appear before the slash of the vhost)
if (colon && (!slash || colon < slash))
{
// a portnumber was set to
_hostname.assign(begin, colon - begin);
_port = atoi(colon + 1);
_hostname.assign(data, colon - data);
// calculate the port
_port = atoi(std::string(colon + 1, slash ? slash - colon - 1 : last - colon - 1).data());
}
else
{
// no portnumber was set
_hostname.assign(begin, slash ? slash - begin : strlen(begin));
_hostname.assign(data, slash ? slash - data : last - data);
}
}
/**
* Constructor to parse an address string
* The address should start with "amqp://
* @param data
* @throws std::runtime_error
*/
Address(const char *data) : Address(data, strlen(data)) {}
/**
* Constructor based on std::string
* @param address
*/
Address(const std::string &address) : Address(address.data()) {}
Address(const std::string &address) : Address(address.data(), address.size()) {}
/**
* Constructor based on already known properties
@ -117,14 +134,16 @@ public:
* @param login
* @param vhost
*/
Address(std::string host, uint16_t port, Login login, std::string vhost) : _login(std::move(login)),
_hostname(std::move(host)),
_port(port), _vhost(std::move(vhost)) {}
Address(std::string host, uint16_t port, Login login, std::string vhost) :
_login(std::move(login)),
_hostname(std::move(host)),
_port(port),
_vhost(std::move(vhost)) {}
/**
* Destructor
*/
virtual ~Address() {}
virtual ~Address() = default;
/**
* Expose the login data

39
tests/address.cpp Normal file
View File

@ -0,0 +1,39 @@
/**
* Address.cpp
*
* Test program to parse address strings
*
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
* @copyright 2017 Copernica BV
*/
/**
* Dependencies
*/
#include <amqpcpp.h>
/**
* Main procedure
* @param argc
* @param argv
* @return int
*/
int main(int argc, const char *argv[])
{
// iterate over the arguments
for (int i = 1; i < argc; ++i)
{
// parse address
AMQP::Address address(argv[i]);
// output all properties
std::cout << "user: " << address.login().user() << std::endl;
std::cout << "password: " << address.login().password() << std::endl;
std::cout << "hostname: " << address.hostname() << std::endl;
std::cout << "port: " << address.port() << std::endl;
std::cout << "vhost: " << address.vhost() << std::endl;
}
// done
return 0;
}