From d2983aecee07161aba43ccd58ebbe50c9755641d Mon Sep 17 00:00:00 2001 From: Manjeet Dahiya Date: Sat, 5 Sep 2009 09:56:38 +0000 Subject: Fix Issue 2: problem when sending messages with < or > characters in body fields Fix Issue 3: QXmppClient::connected signal --- source/QXmppClient.cpp | 110 ++++++++++++++++++++++++++++++++++++++++-- source/QXmppClient.h | 33 ++++++++++++- source/QXmppConfiguration.cpp | 12 +---- source/QXmppConfiguration.h | 6 ++- source/QXmppMessage.cpp | 7 ++- source/QXmppPresence.cpp | 7 ++- source/QXmppPresence.h | 3 +- source/QXmppStream.cpp | 32 ++++++------ source/QXmppStream.h | 18 ++++++- source/source.pro | 6 ++- source/utils.cpp | 20 ++++++++ source/utils.h | 3 ++ 12 files changed, 213 insertions(+), 44 deletions(-) (limited to 'source') diff --git a/source/QXmppClient.cpp b/source/QXmppClient.cpp index 17370982..7fcfe1fb 100644 --- a/source/QXmppClient.cpp +++ b/source/QXmppClient.cpp @@ -26,9 +26,11 @@ #include "QXmppStream.h" #include "QXmppRoster.h" #include "QXmppMessage.h" +#include "QXmppReconnectionManager.h" QXmppClient::QXmppClient(QObject *parent) - : QObject(parent), m_stream(0) + : QObject(parent), m_stream(0), m_clientPrecence(QXmppPresence::Available), + m_reconnectionManager(0) { m_stream = new QXmppStream(this); @@ -42,6 +44,20 @@ QXmppClient::QXmppClient(QObject *parent) check = connect(m_stream, SIGNAL(iqReceived(const QXmppIq&)), this, SIGNAL(iqReceived(const QXmppIq&))); + + check = connect(m_stream, SIGNAL(disconnected()), this, + SIGNAL(disconnected())); + Q_ASSERT(check); + + check = connect(m_stream, SIGNAL(xmppConnected()), this, + SIGNAL(connected())); + Q_ASSERT(check); + + check = connect(m_stream, SIGNAL(error(QXmppClient::Error)), this, + SIGNAL(error(QXmppClient::Error))); + Q_ASSERT(check); + + check = setReconnectionManager(new QXmppReconnectionManager(this)); Q_ASSERT(check); } @@ -55,7 +71,7 @@ QXmppConfiguration& QXmppClient::getConfiguration() } void QXmppClient::connectToServer(const QString& host, const QString& user, const QString& passwd, - const QString& domain, int port) + const QString& domain, int port, const QXmppPresence& initialPresence) { m_config.setHost(host); m_config.setUser(user); @@ -63,13 +79,17 @@ void QXmppClient::connectToServer(const QString& host, const QString& user, cons m_config.setDomain(domain); m_config.setPort(port); + m_clientPrecence = initialPresence; + m_stream->connect(); } -void QXmppClient::connectToServer(const QXmppConfiguration& config) +void QXmppClient::connectToServer(const QXmppConfiguration& config, const QXmppPresence& initialPresence) { m_config = config; - + + m_clientPrecence = initialPresence; + m_stream->connect(); } @@ -83,11 +103,91 @@ void QXmppClient::sendPacket(const QXmppPacket& packet) void QXmppClient::disconnect() { + m_clientPrecence.setType(QXmppPresence::Unavailable); + m_clientPrecence.getStatus().setType(QXmppPresence::Status::Online); + m_clientPrecence.getStatus().setStatusText("Logged out"); + sendPacket(m_clientPrecence); if(m_stream) m_stream->disconnect(); } QXmppRoster& QXmppClient::getRoster() { - return m_stream->getRoster(); + if(m_stream) + return m_stream->getRoster(); +} + +void QXmppClient::sendMessage(const QString& bareJid, const QString& message) +{ + QStringList resources = getRoster().getResources(bareJid); + for(int i = 0; i < resources.size(); ++i) + { + sendPacket(QXmppMessage("", bareJid + "/" + resources.at(i), message)); + } +} + +// sets the new presence of the connected client +void QXmppClient::setClientPresence(const QXmppPresence& presence) +{ + m_clientPrecence = presence; + sendPacket(m_clientPrecence); +} + +// overloaded function, changes the status text +void QXmppClient::setClientPresence(const QString& statusText) +{ + m_clientPrecence.getStatus().setStatusText(statusText); + sendPacket(m_clientPrecence); +} + +// overloaded function, changes the presence type +void QXmppClient::setClientPresence(QXmppPresence::Type presenceType) +{ + if(presenceType == QXmppPresence::Unavailable) + { + disconnect(); + } + else + { + m_clientPrecence.setType(presenceType); + sendPacket(m_clientPrecence); + } +} + +// overloaded function, changes the status type +void QXmppClient::setClientPresence(QXmppPresence::Status::Type statusType) +{ + m_clientPrecence.getStatus().setType(statusType); + sendPacket(m_clientPrecence); +} + +// returnsn the referece to client presence object +const QXmppPresence& QXmppClient::getClientPresence() const +{ + return m_clientPrecence; +} + +QXmppReconnectionManager* QXmppClient::getReconnectionManager() +{ + return m_reconnectionManager; +} + +bool QXmppClient::setReconnectionManager(QXmppReconnectionManager* reconnectionManager) +{ + if(m_reconnectionManager) + delete m_reconnectionManager; + + m_reconnectionManager = reconnectionManager; + + bool check = connect(this, SIGNAL(connected()), m_reconnectionManager, SLOT(connected())); + Q_ASSERT(check); + + check = connect(this, SIGNAL(error(QXmppClient::Error)), m_reconnectionManager, + SLOT(error(QXmppClient::Error))); + Q_ASSERT(check); +} + +QAbstractSocket::SocketError QXmppClient::getSocketError() +{ + return m_stream->getSocketError(); } diff --git a/source/QXmppClient.h b/source/QXmppClient.h index cc9bcea6..69fd6006 100644 --- a/source/QXmppClient.h +++ b/source/QXmppClient.h @@ -26,7 +26,9 @@ #define QXMPPCLIENT_H #include +#include #include "QXmppConfiguration.h" +#include "QXmppPresence.h" class QXmppStream; class QXmppPresence; @@ -34,32 +36,59 @@ class QXmppMessage; class QXmppPacket; class QXmppIq; class QXmppRoster; +class QXmppReconnectionManager; class QXmppClient : public QObject { Q_OBJECT public: + enum Error + { + SocketError, + XmppStreamError, + XmppStanzaError + }; + QXmppClient(QObject *parent = 0); ~QXmppClient(); void connectToServer(const QString& host, const QString& user, const QString& passwd, - const QString& domain, int port = 5222); - void connectToServer(const QXmppConfiguration&); + const QString& domain, int port = 5222, + const QXmppPresence& initialPresence = QXmppPresence()); + void connectToServer(const QXmppConfiguration&, const QXmppPresence& initialPresence = QXmppPresence()); void disconnect(); QXmppRoster& getRoster(); QXmppConfiguration& getConfiguration(); + QXmppReconnectionManager* getReconnectionManager(); + bool setReconnectionManager(QXmppReconnectionManager*); + const QXmppPresence& getClientPresence() const; signals: + void connected(); + void disconnected(); + void error(QXmppClient::Error); void messageReceived(const QXmppMessage&); void presenceReceived(const QXmppPresence&); void iqReceived(const QXmppIq&); +public: + QAbstractSocket::SocketError getSocketError(); +// QXmppStanza::Error getXmppStreamError(); + public slots: void sendPacket(const QXmppPacket&); + void sendMessage(const QString& bareJid, const QString& message); + + void setClientPresence(const QXmppPresence&); + void setClientPresence(const QString& statusText); + void setClientPresence(QXmppPresence::Type presenceType); + void setClientPresence(QXmppPresence::Status::Type statusType); private: QXmppStream* m_stream; QXmppConfiguration m_config; + QXmppPresence m_clientPrecence; + QXmppReconnectionManager* m_reconnectionManager; }; #endif // QXMPPCLIENT_H diff --git a/source/QXmppConfiguration.cpp b/source/QXmppConfiguration.cpp index d4abb0b5..b42b0472 100644 --- a/source/QXmppConfiguration.cpp +++ b/source/QXmppConfiguration.cpp @@ -26,7 +26,7 @@ QXmppConfiguration::QXmppConfiguration():m_resource("QXmpp"), m_autoAcceptSubscriptions(true), m_sendIntialPresence(true), m_sendRosterRequest(true), m_port(5222), - m_keepAlivePingsInterval(100) + m_keepAlivePingsInterval(100), m_autoReconnectionEnabled(true) { } @@ -61,11 +61,6 @@ void QXmppConfiguration::setPasswd(const QString& str) m_passwd = str; } -void QXmppConfiguration::setStatus(const QString& str) -{ - m_status = str; -} - void QXmppConfiguration::setResource(const QString& str) { m_resource = str; @@ -95,11 +90,6 @@ QString QXmppConfiguration::getPasswd() const return m_passwd; } -QString QXmppConfiguration::getStatus() const -{ - return m_status; -} - QString QXmppConfiguration::getResource() const { return m_resource; diff --git a/source/QXmppConfiguration.h b/source/QXmppConfiguration.h index c57dadd6..82fcccea 100644 --- a/source/QXmppConfiguration.h +++ b/source/QXmppConfiguration.h @@ -38,7 +38,6 @@ public: void setPort(int); void setUser(const QString&); void setPasswd(const QString&); - void setStatus(const QString&); void setResource(const QString&); QString getHost() const; @@ -54,19 +53,22 @@ public: bool getAutoAcceptSubscriptions() const; void setAutoAcceptSubscriptions(bool); + bool getAutoReconnectionEnabled() const; + void setAutoReconnectionEnabled(bool); + private: QString m_host; int m_port; QString m_user; QString m_passwd; QString m_domain; - QString m_status; QString m_resource; bool m_autoAcceptSubscriptions; // default is true bool m_sendIntialPresence; // default is true bool m_sendRosterRequest; // default is true int m_keepAlivePingsInterval; // interval in seconds, if negative it won't ping + bool m_autoReconnectionEnabled; // will keep reconnecting if disconnected, default is true }; #endif // QXMPPCONFIGURATION_H diff --git a/source/QXmppMessage.cpp b/source/QXmppMessage.cpp index 3dc19ce5..42dd5308 100644 --- a/source/QXmppMessage.cpp +++ b/source/QXmppMessage.cpp @@ -28,9 +28,8 @@ QXmppMessage::QXmppMessage(const QString& from, const QString& to, const QString& body, const QString& thread) - : QXmppStanza(from, to), m_type(Chat), m_body(body), m_thread(thread) + : QXmppStanza(from, to), m_type(Chat), m_thread(thread), m_body(body) { - } QXmppMessage::~QXmppMessage() @@ -126,8 +125,8 @@ QByteArray QXmppMessage::toXml() const helperToXmlAddAttribute(stream, "from", getFrom()); helperToXmlAddAttribute(stream, "type", getTypeStr()); stream << ">"; - helperToXmlAddElement(stream, "subject", getSubject()); - helperToXmlAddElement(stream, "body", getBody()); + helperToXmlAddElement(stream, "subject", escapeString(getSubject())); + helperToXmlAddElement(stream, "body", escapeString(getBody())); helperToXmlAddElement(stream, "thread", getThread()); stream << getError().toXml(); stream << ""; diff --git a/source/QXmppPresence.cpp b/source/QXmppPresence.cpp index 16906bd3..72aeace7 100644 --- a/source/QXmppPresence.cpp +++ b/source/QXmppPresence.cpp @@ -47,7 +47,12 @@ void QXmppPresence::setType(QXmppPresence::Type type) m_type = type; } -QXmppPresence::Status QXmppPresence::getStatus() const +const QXmppPresence::Status& QXmppPresence::getStatus() const +{ + return m_status; +} + +QXmppPresence::Status& QXmppPresence::getStatus() { return m_status; } diff --git a/source/QXmppPresence.h b/source/QXmppPresence.h index 19b3aecb..f416f1ff 100644 --- a/source/QXmppPresence.h +++ b/source/QXmppPresence.h @@ -84,7 +84,8 @@ public: void setType(QXmppPresence::Type); void setTypeFromStr(const QString&); - QXmppPresence::Status getStatus() const; + QXmppPresence::Status& getStatus(); + const QXmppPresence::Status& getStatus() const; void setStatus(const QXmppPresence::Status&); QByteArray toXml() const; diff --git a/source/QXmppStream.cpp b/source/QXmppStream.cpp index e557387e..7216c4ed 100644 --- a/source/QXmppStream.cpp +++ b/source/QXmppStream.cpp @@ -105,12 +105,14 @@ void QXmppStream::socketHostFound() void QXmppStream::socketConnected() { log(QString("Connected")); + emit connected(); sendStartStream(); } void QXmppStream::socketDisconnected() { log(QString("Disconnected")); + emit disconnected(); } void QXmppStream::socketEncrypted() @@ -121,7 +123,9 @@ void QXmppStream::socketEncrypted() void QXmppStream::socketError(QAbstractSocket::SocketError ee) { - log(QString("Socket error")); + m_socketError = ee; + emit error(QXmppClient::SocketError); + log(QString("Socket error: " + m_socket.errorString())); } void QXmppStream::socketReadReady() @@ -237,6 +241,10 @@ void QXmppStream::parser(const QByteArray& data) { // get back add configuration whether to send roster and intial presence in beginning // process SessionIq + + // xmpp connection made + emit xmppConnected(); + sendRosterRequest(); sendInitialPresence(); @@ -325,8 +333,8 @@ void QXmppStream::parser(const QByteArray& data) QString from = nodeRecv.attribute("from"); QString to = nodeRecv.attribute("to"); QString type = nodeRecv.attribute("type"); - QString body = nodeRecv.firstChildElement("body").text(); - QString sub = nodeRecv.firstChildElement("subject").text(); + QString body = unescapeString(nodeRecv.firstChildElement("body").text()); + QString sub = unescapeString(nodeRecv.firstChildElement("subject").text()); QString thread = nodeRecv.firstChildElement("thread").text(); QXmppMessage message(from, to, body, thread); message.setSubject(sub); @@ -415,12 +423,8 @@ void QXmppStream::sendSessionIQ() void QXmppStream::sendInitialPresence() { - QString statusText = getConfiguration().getStatus(); - - QXmppPresence presence(QXmppPresence::Available); - presence.setStatus(QXmppPresence::Status(QXmppPresence::Status::Online, statusText)); - - sendPacket(presence); + if(m_client) + sendPacket(m_client->getClientPresence()); } void QXmppStream::acceptSubscriptionRequest(const QString& from, bool accept) @@ -456,12 +460,7 @@ void QXmppStream::sendRosterRequest() void QXmppStream::disconnect() { - QXmppPresence presence(QXmppPresence::Unavailable, - QXmppPresence::Status(QXmppPresence::Status::Online, "Logged out")); - sendPacket(presence); - sendEndStream(); - m_socket.disconnectFromHost(); } @@ -581,3 +580,8 @@ QXmppStanza::Error QXmppStream::parseStanzaError(QDomElement & errorElement) error.setText(text); return error; } + +QAbstractSocket::SocketError QXmppStream::getSocketError() +{ + return m_socketError; +} diff --git a/source/QXmppStream.h b/source/QXmppStream.h index 04bd6d58..7ea95be1 100644 --- a/source/QXmppStream.h +++ b/source/QXmppStream.h @@ -56,11 +56,22 @@ public: QXmppRoster& getRoster(); void sendPacket(const QXmppPacket&); + QAbstractSocket::SocketError getSocketError(); + signals: + // socket host found void hostFound(); + + // socket connected void connected(); + + // socket disconnected void disconnected(); - void streamError(); + + // xmpp connected + void xmppConnected(); + + void error(QXmppClient::Error); void subscriptionRequestReceived(const QString& from); void presenceReceived(const QXmppPresence&); void messageReceived(const QXmppMessage&); @@ -74,7 +85,7 @@ private slots: void socketConnected(); void socketDisconnected(); void socketError(QAbstractSocket::SocketError); - void socketSslErrors(const QList &); + void socketSslErrors(const QList&); private: QXmppClient* m_client; // reverse pointer @@ -85,6 +96,9 @@ private: QSslSocket m_socket; bool m_sessionAvaliable; + QAbstractSocket::SocketError m_socketError; +// m_xmppStreamError; +// m_xmppStanzaError; QXmppConfiguration& getConfiguration(); void parser(const QByteArray&); diff --git a/source/source.pro b/source/source.pro index ee82d6a6..7c314927 100644 --- a/source/source.pro +++ b/source/source.pro @@ -21,7 +21,8 @@ HEADERS += utils.h \ QXmppSession.h \ QXmppStanza.h \ QXmppStream.h \ - QXmppLogger.h + QXmppLogger.h \ + QXmppReconnectionManager.h # Source files SOURCES += utils.cpp \ @@ -38,4 +39,5 @@ SOURCES += utils.cpp \ QXmppSession.cpp \ QXmppStanza.cpp \ QXmppStream.cpp \ - QXmppLogger.cpp + QXmppLogger.cpp \ + QXmppReconnectionManager.cpp diff --git a/source/utils.cpp b/source/utils.cpp index abeab27b..0ee7cfaf 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -64,3 +64,23 @@ void log(const QByteArray& str) { QXmppLogger::getLogger()->log(str); } + +QString escapeString(const QString& str) +{ + QString strOut = str; + strOut.replace(QChar('&'), "&"); + strOut.replace(QChar('<'), "<"); + strOut.replace(QChar('>'), ">"); + strOut.replace(QChar('"'), """); + return strOut; +} + +QString unescapeString(const QString& str) +{ + QString strOut = str; + strOut.replace("<", QChar('<')); + strOut.replace(">", QChar('>')); + strOut.replace(""", QChar('"')); + strOut.replace("&", QChar('&')); + return strOut; +} diff --git a/source/utils.h b/source/utils.h index d7ae26b1..ba31f449 100644 --- a/source/utils.h +++ b/source/utils.h @@ -40,4 +40,7 @@ void helperToXmlAddElement(QTextStream& stream, const QString& name, int value); void log(const QString& str); void log(const QByteArray& str); +QString escapeString(const QString& str); +QString unescapeString(const QString& str); + #endif // UTILS_H -- cgit v1.2.3