diff --git a/src/amqp_client.cpp b/src/amqp_client.cpp index c041fc3..8df9b11 100644 --- a/src/amqp_client.cpp +++ b/src/amqp_client.cpp @@ -34,7 +34,7 @@ ClientPrivate::~ClientPrivate() { } -void ClientPrivate::init(const QUrl &connectionString) +void ClientPrivate::init() { Q_Q(Client); initSocket(); @@ -43,11 +43,6 @@ void ClientPrivate::init(const QUrl &connectionString) authenticator = QSharedPointer( new AMQPlainAuthenticator(QString::fromLatin1(AMQP_LOGIN), QString::fromLatin1(AMQP_PSWD))); - - if (connectionString.isValid()) { - parseConnectionString(connectionString); - _q_connect(); - } } void ClientPrivate::initSocket() @@ -61,24 +56,54 @@ void ClientPrivate::initSocket() q, SLOT(_q_socketError(QAbstractSocket::SocketError))); } -void ClientPrivate::parseConnectionString(const QUrl &connectionString) +void ClientPrivate::setUsername(const QString &username) { - Q_Q(Client); + Authenticator *auth = authenticator.data(); + if (auth && auth->type() == QLatin1String("AMQPLAIN")) { + AMQPlainAuthenticator *a = static_cast(auth); + a->setLogin(username); + } +} + +void ClientPrivate::setPassword(const QString &password) +{ + Authenticator *auth = authenticator.data(); + if (auth && auth->type() == QLatin1String("AMQPLAIN")) { + AMQPlainAuthenticator *a = static_cast(auth); + a->setPassword(password); + } +} + +void ClientPrivate::parseConnectionString(const QString &uri) +{ +#if QT_VERSION > 0x040801 + QUrl connectionString = QUrl::fromUserInput(uri); +#else + QUrl connectionString(uri, QUrl::TolerantMode); +#endif + if (connectionString.scheme() != AMQP_SCHEME && connectionString.scheme() != AMQP_SSCHEME) { qAmqpDebug() << Q_FUNC_INFO << "invalid scheme: " << connectionString.scheme(); return; } - q->setPassword(connectionString.password()); - q->setUsername(connectionString.userName()); - q->setPort(connectionString.port(AMQP_PORT)); - q->setHost(connectionString.host()); + + port = connectionString.port(AMQP_PORT); + host = connectionString.host(); QString vhost = connectionString.path(); if (vhost.startsWith("/")) vhost = vhost.mid(1); - q->setVirtualHost(vhost); +#if QT_VERSION <= 0x050200 + virtualHost = QUrl::fromPercentEncoding(vhost.toUtf8()); + setPassword(QUrl::fromPercentEncoding(connectionString.password().toUtf8())); + setUsername(QUrl::fromPercentEncoding(connectionString.userName().toUtf8())); +#else + virtualHost = vhost; + setPassword(connectionString.password()); + setUsername(connectionString.userName()); +#endif } void ClientPrivate::_q_connect() @@ -506,14 +531,6 @@ Client::Client(QObject *parent) d->init(); } -Client::Client(const QUrl &connectionString, QObject *parent) - : QObject(parent), - d_ptr(new ClientPrivate(this)) -{ - Q_D(Client); - d->init(connectionString); -} - Client::Client(ClientPrivate *dd, QObject *parent) : QObject(parent), d_ptr(dd) @@ -583,12 +600,8 @@ QString Client::username() const void Client::setUsername(const QString &username) { - Q_D(const Client); - Authenticator *auth = d->authenticator.data(); - if (auth && auth->type() == QLatin1String("AMQPLAIN")) { - AMQPlainAuthenticator *a = static_cast(auth); - a->setLogin(username); - } + Q_D(Client); + d->setUsername(username); } QString Client::password() const @@ -606,11 +619,7 @@ QString Client::password() const void Client::setPassword(const QString &password) { Q_D(Client); - Authenticator *auth = d->authenticator.data(); - if (auth && auth->type() == QLatin1String("AMQPLAIN")) { - AMQPlainAuthenticator *a = static_cast(auth); - a->setPassword(password); - } + d->setPassword(password); } Exchange *Client::createExchange(int channelNumber) @@ -753,15 +762,15 @@ QString Client::errorString() const return d->errorString; } -void Client::connectToHost(const QString &connectionString) +void Client::connectToHost(const QString &uri) { Q_D(Client); - if (connectionString.isEmpty()) { + if (uri.isEmpty()) { d->_q_connect(); return; } - d->parseConnectionString(QUrl::fromUserInput(connectionString)); + d->parseConnectionString(uri); d->_q_connect(); } @@ -829,13 +838,6 @@ SslClient::SslClient(QObject *parent) { } -SslClient::SslClient(const QUrl &connectionString, QObject *parent) - : Client(new SslClientPrivate(this), parent) -{ - Q_D(SslClient); - d->init(connectionString); -} - SslClient::~SslClient() { } diff --git a/src/amqp_client.h b/src/amqp_client.h index aaad61c..10e8557 100644 --- a/src/amqp_client.h +++ b/src/amqp_client.h @@ -33,8 +33,7 @@ class QAMQP_EXPORT Client : public QObject Q_PROPERTY(qint16 heartbeatDelay READ heartbeatDelay() WRITE setHeartbeatDelay) public: - Client(QObject *parent = 0); - Client(const QUrl &connectionString, QObject *parent = 0); + explicit Client(QObject *parent = 0); ~Client(); // properties @@ -84,7 +83,7 @@ public: Queue *createQueue(const QString &name, int channelNumber = -1); // methods - void connectToHost(const QString &connectionString = QString()); + void connectToHost(const QString &uri = QString()); void connectToHost(const QHostAddress &address, quint16 port = AMQP_PORT); void disconnectFromHost(); diff --git a/src/amqp_client_p.h b/src/amqp_client_p.h index 38d29a8..916070e 100644 --- a/src/amqp_client_p.h +++ b/src/amqp_client_p.h @@ -35,9 +35,11 @@ public: ClientPrivate(Client *q); virtual ~ClientPrivate(); - virtual void init(const QUrl &connectionString = QUrl()); + virtual void init(); virtual void initSocket(); - void parseConnectionString(const QUrl &connectionString); + void setUsername(const QString &username); + void setPassword(const QString &password); + void parseConnectionString(const QString &uri); void sendFrame(const Frame::Base &frame); // private slots @@ -69,7 +71,7 @@ public: void close(const Frame::Method &frame); void closeOk(); - quint32 port; + quint16 port; QString host; QString virtualHost; diff --git a/tests/auto/qamqpclient/tst_qamqpclient.cpp b/tests/auto/qamqpclient/tst_qamqpclient.cpp index 9155c81..9901bfc 100644 --- a/tests/auto/qamqpclient/tst_qamqpclient.cpp +++ b/tests/auto/qamqpclient/tst_qamqpclient.cpp @@ -3,6 +3,7 @@ #include #include "amqp_client.h" +#include "amqp_client_p.h" #include "amqp_authenticator.h" using namespace QAMQP; @@ -15,6 +16,9 @@ private Q_SLOTS: void invalidAuthenticationMechanism(); void tune(); + void validateUri_data(); + void validateUri(); + private: void autoReconnect(); @@ -85,5 +89,58 @@ void tst_QAMQPClient::tune() QVERIFY(waitForSignal(&client, SIGNAL(disconnected()))); } +void tst_QAMQPClient::validateUri_data() +{ + QTest::addColumn("uri"); + QTest::addColumn("expectedUsername"); + QTest::addColumn("expectedPassword"); + QTest::addColumn("expectedHost"); + QTest::addColumn("expectedPort"); + QTest::addColumn("expectedVirtualHost"); + + QTest::newRow("standard") << "amqp://user:pass@host:10000/vhost" + << "user" << "pass" << "host" << quint16(10000) << "vhost"; +#if QT_VERSION >= 0x040806 + QTest::newRow("urlencoded") << "amqp://user%61:%61pass@ho%61st:10000/v%2fhost" + << "usera" << "apass" << "hoast" << quint16(10000) << "v/host"; +#endif + QTest::newRow("empty") << "amqp://" << "" << "" << "" << quint16(AMQP_PORT) << ""; + QTest::newRow("empty2") << "amqp://:@/" << "" << "" << "" << quint16(AMQP_PORT) << ""; + QTest::newRow("onlyuser") << "amqp://user@" << "user" << "" << "" << quint16(AMQP_PORT) << ""; + QTest::newRow("userpass") << "amqp://user:pass@" << "user" << "pass" << "" << quint16(AMQP_PORT) << ""; + QTest::newRow("onlyhost") << "amqp://host" << "" << "" << "host" << quint16(AMQP_PORT) << ""; + QTest::newRow("onlyport") << "amqp://:10000" << "" << "" << "" << quint16(10000) << ""; + QTest::newRow("onlyvhost") << "amqp:///vhost" << "" << "" << "" << quint16(AMQP_PORT) << "vhost"; + QTest::newRow("urlencodedvhost") << "amqp://host/%2f" + << "" << "" << "host" << quint16(AMQP_PORT) << "/"; + QTest::newRow("ipv6") << "amqp://[::1]" << "" << "" << "::1" << quint16(AMQP_PORT) << ""; +} + +void tst_QAMQPClient::validateUri() +{ + QFETCH(QString, uri); + QFETCH(QString, expectedUsername); + QFETCH(QString, expectedPassword); + QFETCH(QString, expectedHost); + QFETCH(quint16, expectedPort); + QFETCH(QString, expectedVirtualHost); + + ClientPrivate clientPrivate(0); + // fake init + clientPrivate.authenticator = QSharedPointer( + new AMQPlainAuthenticator(QString::fromLatin1(AMQP_LOGIN), QString::fromLatin1(AMQP_PSWD))); + + // test parsing + clientPrivate.parseConnectionString(uri); + AMQPlainAuthenticator *auth = + static_cast(clientPrivate.authenticator.data()); + + QCOMPARE(auth->login(), expectedUsername); + QCOMPARE(auth->password(), expectedPassword); + QCOMPARE(clientPrivate.host, expectedHost); + QCOMPARE(clientPrivate.port, expectedPort); + QCOMPARE(clientPrivate.virtualHost, expectedVirtualHost); +} + QTEST_MAIN(tst_QAMQPClient) #include "tst_qamqpclient.moc"