|
|
|
/*
|
|
|
|
* xmpp.h - XMPP "core" library API
|
|
|
|
* Copyright (C) 2003 Justin Karneges
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef XMPP_H
|
|
|
|
#define XMPP_H
|
|
|
|
|
|
|
|
#include<qobject.h>
|
|
|
|
#include<qstring.h>
|
|
|
|
#include<qhostaddress.h>
|
|
|
|
#include<qstring.h>
|
|
|
|
#include<qcstring.h>
|
|
|
|
#include<qxml.h>
|
|
|
|
#include<qdom.h>
|
|
|
|
|
|
|
|
namespace QCA
|
|
|
|
{
|
|
|
|
class TLS;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef CS_XMPP
|
|
|
|
class ByteStream;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace XMPP
|
|
|
|
{
|
|
|
|
// CS_IMPORT_BEGIN cutestuff/bytestream.h
|
|
|
|
#ifdef CS_XMPP
|
|
|
|
class ByteStream;
|
|
|
|
#endif
|
|
|
|
// CS_IMPORT_END
|
|
|
|
|
|
|
|
class Debug
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~Debug();
|
|
|
|
|
|
|
|
virtual void msg(const QString &)=0;
|
|
|
|
virtual void outgoingTag(const QString &)=0;
|
|
|
|
virtual void incomingTag(const QString &)=0;
|
|
|
|
virtual void outgoingXml(const QDomElement &)=0;
|
|
|
|
virtual void incomingXml(const QDomElement &)=0;
|
|
|
|
};
|
|
|
|
|
|
|
|
void setDebug(Debug *);
|
|
|
|
|
|
|
|
class Connector : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
Connector(QObject *parent=0);
|
|
|
|
virtual ~Connector();
|
|
|
|
|
|
|
|
virtual void connectToServer(const QString &server)=0;
|
|
|
|
virtual ByteStream *stream() const=0;
|
|
|
|
virtual void done()=0;
|
|
|
|
|
|
|
|
bool useSSL() const;
|
|
|
|
bool havePeerAddress() const;
|
|
|
|
QHostAddress peerAddress() const;
|
|
|
|
Q_UINT16 peerPort() const;
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void connected();
|
|
|
|
void error();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void setUseSSL(bool b);
|
|
|
|
void setPeerAddressNone();
|
|
|
|
void setPeerAddress(const QHostAddress &addr, Q_UINT16 port);
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool ssl;
|
|
|
|
bool haveaddr;
|
|
|
|
QHostAddress addr;
|
|
|
|
Q_UINT16 port;
|
|
|
|
};
|
|
|
|
|
|
|
|
class AdvancedConnector : public Connector
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
enum Error { ErrConnectionRefused, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth, ErrStream };
|
|
|
|
AdvancedConnector(QObject *parent=0);
|
|
|
|
virtual ~AdvancedConnector();
|
|
|
|
|
|
|
|
class Proxy
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum { None, HttpConnect, HttpPoll, Socks };
|
|
|
|
Proxy();
|
|
|
|
~Proxy();
|
|
|
|
|
|
|
|
int type() const;
|
|
|
|
QString host() const;
|
|
|
|
Q_UINT16 port() const;
|
|
|
|
QString url() const;
|
|
|
|
QString user() const;
|
|
|
|
QString pass() const;
|
|
|
|
int pollInterval() const;
|
|
|
|
|
|
|
|
void setHttpConnect(const QString &host, Q_UINT16 port);
|
|
|
|
void setHttpPoll(const QString &host, Q_UINT16 port, const QString &url);
|
|
|
|
void setSocks(const QString &host, Q_UINT16 port);
|
|
|
|
void setUserPass(const QString &user, const QString &pass);
|
|
|
|
void setPollInterval(int secs);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int t;
|
|
|
|
QString v_host, v_url;
|
|
|
|
Q_UINT16 v_port;
|
|
|
|
QString v_user, v_pass;
|
|
|
|
int v_poll;
|
|
|
|
};
|
|
|
|
|
|
|
|
void setProxy(const Proxy &proxy);
|
|
|
|
void setOptHostPort(const QString &host, Q_UINT16 port);
|
|
|
|
void setOptProbe(bool);
|
|
|
|
void setOptSSL(bool);
|
|
|
|
|
|
|
|
void changePollInterval(int secs);
|
|
|
|
|
|
|
|
void connectToServer(const QString &server);
|
|
|
|
ByteStream *stream() const;
|
|
|
|
void done();
|
|
|
|
|
|
|
|
int errorCode() const;
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void srvLookup(const QString &server);
|
|
|
|
void srvResult(bool success);
|
|
|
|
void httpSyncStarted();
|
|
|
|
void httpSyncFinished();
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void dns_done();
|
|
|
|
void srv_done();
|
|
|
|
void bs_connected();
|
|
|
|
void bs_error(int);
|
|
|
|
void http_syncStarted();
|
|
|
|
void http_syncFinished();
|
|
|
|
|
|
|
|
private:
|
|
|
|
class Private;
|
|
|
|
Private *d;
|
|
|
|
|
|
|
|
void cleanup();
|
|
|
|
void do_resolve();
|
|
|
|
void do_connect();
|
|
|
|
void tryNextSrv();
|
|
|
|
};
|
|
|
|
|
|
|
|
class TLSHandler : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
TLSHandler(QObject *parent=0);
|
|
|
|
virtual ~TLSHandler();
|
|
|
|
|
|
|
|
virtual void reset()=0;
|
|
|
|
virtual void startClient(const QString &host)=0;
|
|
|
|
virtual void write(const QByteArray &a)=0;
|
|
|
|
virtual void writeIncoming(const QByteArray &a)=0;
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void success();
|
|
|
|
void fail();
|
|
|
|
void closed();
|
|
|
|
void readyRead(const QByteArray &a);
|
|
|
|
void readyReadOutgoing(const QByteArray &a, int plainBytes);
|
|
|
|
};
|
|
|
|
|
|
|
|
class QCATLSHandler : public TLSHandler
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
QCATLSHandler(QCA::TLS *parent);
|
|
|
|
~QCATLSHandler();
|
|
|
|
|
|
|
|
QCA::TLS *tls() const;
|
|
|
|
int tlsError() const;
|
|
|
|
|
|
|
|
void reset();
|
|
|
|
void startClient(const QString &host);
|
|
|
|
void write(const QByteArray &a);
|
|
|
|
void writeIncoming(const QByteArray &a);
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void tlsHandshaken();
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
void continueAfterHandshake();
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void tls_handshaken();
|
|
|
|
void tls_readyRead();
|
|
|
|
void tls_readyReadOutgoing(int);
|
|
|
|
void tls_closed();
|
|
|
|
void tls_error(int);
|
|
|
|
|
|
|
|
private:
|
|
|
|
class Private;
|
|
|
|
Private *d;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Jid
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Jid();
|
|
|
|
~Jid();
|
|
|
|
|
|
|
|
Jid(const QString &s);
|
|
|
|
Jid(const char *s);
|
|
|
|
Jid & operator=(const QString &s);
|
|
|
|
Jid & operator=(const char *s);
|
|
|
|
|
|
|
|
void set(const QString &s);
|
|
|
|
void set(const QString &domain, const QString &node, const QString &resource="");
|
|
|
|
|
|
|
|
void setDomain(const QString &s);
|
|
|
|
void setNode(const QString &s);
|
|
|
|
void setResource(const QString &s);
|
|
|
|
|
|
|
|
const QString & domain() const { return d; }
|
|
|
|
const QString & node() const { return n; }
|
|
|
|
const QString & resource() const { return r; }
|
|
|
|
const QString & bare() const { return b; }
|
|
|
|
const QString & full() const { return f; }
|
|
|
|
|
|
|
|
Jid withNode(const QString &s) const;
|
|
|
|
Jid withResource(const QString &s) const;
|
|
|
|
|
|
|
|
bool isValid() const;
|
|
|
|
bool isEmpty() const;
|
|
|
|
bool compare(const Jid &a, bool compareRes=true) const;
|
|
|
|
|
|
|
|
static bool validDomain(const QString &s, QString *norm=0);
|
|
|
|
static bool validNode(const QString &s, QString *norm=0);
|
|
|
|
static bool validResource(const QString &s, QString *norm=0);
|
|
|
|
|
|
|
|
// TODO: kill these later
|
|
|
|
const QString & host() const { return d; }
|
|
|
|
const QString & user() const { return n; }
|
|
|
|
const QString & userHost() const { return b; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
void reset();
|
|
|
|
void update();
|
|
|
|
|
|
|
|
QString f, b, d, n, r;
|
|
|
|
bool valid;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Stream;
|
|
|
|
class Stanza
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum Kind { Message, Presence, IQ };
|
|
|
|
enum ErrorType { Cancel, Continue, Modify, Auth, Wait };
|
|
|
|
enum ErrorCond
|
|
|
|
{
|
|
|
|
BadRequest,
|
|
|
|
Conflict,
|
|
|
|
FeatureNotImplemented,
|
|
|
|
Forbidden,
|
|
|
|
InternalServerError,
|
|
|
|
ItemNotFound,
|
|
|
|
JidMalformed,
|
|
|
|
NotAllowed,
|
|
|
|
PaymentRequired,
|
|
|
|
RecipientUnavailable,
|
|
|
|
RegistrationRequired,
|
|
|
|
ServerNotFound,
|
|
|
|
ServerTimeout,
|
|
|
|
ResourceConstraint,
|
|
|
|
ServiceUnavailable,
|
|
|
|
SubscriptionRequired,
|
|
|
|
UndefinedCondition,
|
|
|
|
UnexpectedRequest
|
|
|
|
};
|
|
|
|
|
|
|
|
Stanza();
|
|
|
|
Stanza(const Stanza &from);
|
|
|
|
Stanza & operator=(const Stanza &from);
|
|
|
|
virtual ~Stanza();
|
|
|
|
|
|
|
|
class Error
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Error(int type=Cancel, int condition=UndefinedCondition, const QString &text="", const QDomElement &appSpec=QDomElement());
|
|
|
|
|
|
|
|
int type;
|
|
|
|
int condition;
|
|
|
|
QString text;
|
|
|
|
QDomElement appSpec;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool isNull() const;
|
|
|
|
|
|
|
|
QDomElement element() const;
|
|
|
|
QString toString() const;
|
|
|
|
|
|
|
|
QDomDocument & doc() const;
|
|
|
|
QString baseNS() const;
|
|
|
|
QString xhtmlImNS() const;
|
|
|
|
QString xhtmlNS() const;
|
|
|
|
QDomElement createElement(const QString &ns, const QString &tagName);
|
|
|
|
QDomElement createTextElement(const QString &ns, const QString &tagName, const QString &text);
|
|
|
|
QDomElement createXHTMLElement(const QString &xHTML);
|
|
|
|
void appendChild(const QDomElement &e);
|
|
|
|
|
|
|
|
Kind kind() const;
|
|
|
|
void setKind(Kind k);
|
|
|
|
|
|
|
|
Jid to() const;
|
|
|
|
Jid from() const;
|
|
|
|
QString id() const;
|
|
|
|
QString type() const;
|
|
|
|
QString lang() const;
|
|
|
|
|
|
|
|
void setTo(const Jid &j);
|
|
|
|
void setFrom(const Jid &j);
|
|
|
|
void setId(const QString &id);
|
|
|
|
void setType(const QString &type);
|
|
|
|
void setLang(const QString &lang);
|
|
|
|
|
|
|
|
Error error() const;
|
|
|
|
void setError(const Error &err);
|
|
|
|
void clearError();
|
|
|
|
|
|
|
|
private:
|
|
|
|
friend class Stream;
|
|
|
|
Stanza(Stream *s, Kind k, const Jid &to, const QString &type, const QString &id);
|
|
|
|
Stanza(Stream *s, const QDomElement &e);
|
|
|
|
|
|
|
|
class Private;
|
|
|
|
Private *d;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Stream : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
enum Error { ErrParse, ErrProtocol, ErrStream, ErrCustom = 10 };
|
|
|
|
enum StreamCond {
|
|
|
|
GenericStreamError,
|
|
|
|
Conflict,
|
|
|
|
ConnectionTimeout,
|
|
|
|
InternalServerError,
|
|
|
|
InvalidFrom,
|
|
|
|
InvalidXml,
|
|
|
|
PolicyViolation,
|
|
|
|
ResourceConstraint,
|
|
|
|
SystemShutdown
|
|
|
|
};
|
|
|
|
|
|
|
|
Stream(QObject *parent=0);
|
|
|
|
virtual ~Stream();
|
|
|
|
|
|
|
|
virtual QDomDocument & doc() const=0;
|
|
|
|
virtual QString baseNS() const=0;
|
|
|
|
virtual QString xhtmlImNS() const=0;
|
|
|
|
virtual QString xhtmlNS() const=0;
|
|
|
|
virtual bool old() const=0;
|
|
|
|
|
|
|
|
virtual void close()=0;
|
|
|
|
virtual bool stanzaAvailable() const=0;
|
|
|
|
virtual Stanza read()=0;
|
|
|
|
virtual void write(const Stanza &s)=0;
|
|
|
|
|
|
|
|
virtual int errorCondition() const=0;
|
|
|
|
virtual QString errorText() const=0;
|
|
|
|
virtual QDomElement errorAppSpec() const=0;
|
|
|
|
|
|
|
|
Stanza createStanza(Stanza::Kind k, const Jid &to="", const QString &type="", const QString &id="");
|
|
|
|
Stanza createStanza(const QDomElement &e);
|
|
|
|
|
|
|
|
static QString xmlToString(const QDomElement &e, bool clip=false);
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void connectionClosed();
|
|
|
|
void delayedCloseFinished();
|
|
|
|
void readyRead();
|
|
|
|
void stanzaWritten();
|
|
|
|
void error(int);
|
|
|
|
};
|
|
|
|
|
|
|
|
class ClientStream : public Stream
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
enum Error {
|
|
|
|
ErrConnection = ErrCustom, // Connection error, ask Connector-subclass what's up
|
|
|
|
ErrNeg, // Negotiation error, see condition
|
|
|
|
ErrTLS, // TLS error, see condition
|
|
|
|
ErrAuth, // Auth error, see condition
|
|
|
|
ErrSecurityLayer, // broken SASL security layer
|
|
|
|
ErrBind // Resource binding error
|
|
|
|
};
|
|
|
|
enum Warning {
|
|
|
|
WarnOldVersion, // server uses older XMPP/Jabber "0.9" protocol
|
|
|
|
WarnNoTLS // there is no chance for TLS at this point
|
|
|
|
};
|
|
|
|
enum NegCond {
|
|
|
|
HostGone, // host no longer hosted
|
|
|
|
HostUnknown, // unknown host
|
|
|
|
RemoteConnectionFailed, // unable to connect to a required remote resource
|
|
|
|
SeeOtherHost, // a 'redirect', see errorText() for other host
|
|
|
|
UnsupportedVersion // unsupported XMPP version
|
|
|
|
};
|
|
|
|
enum TLSCond {
|
|
|
|
TLSStart, // server rejected STARTTLS
|
|
|
|
TLSFail // TLS failed, ask TLSHandler-subclass what's up
|
|
|
|
};
|
|
|
|
enum SecurityLayer {
|
|
|
|
LayerTLS,
|
|
|
|
LayerSASL
|
|
|
|
};
|
|
|
|
enum AuthCond {
|
|
|
|
GenericAuthError, // all-purpose "can't login" error
|
|
|
|
NoMech, // No appropriate auth mech available
|
|
|
|
BadProto, // Bad SASL auth protocol
|
|
|
|
BadServ, // Server failed mutual auth
|
|
|
|
EncryptionRequired, // can't use mech without TLS
|
|
|
|
InvalidAuthzid, // bad input JID
|
|
|
|
InvalidMech, // bad mechanism
|
|
|
|
InvalidRealm, // bad realm
|
|
|
|
MechTooWeak, // can't use mech with this authzid
|
|
|
|
NotAuthorized, // bad user, bad password, bad creditials
|
|
|
|
TemporaryAuthFailure // please try again later!
|
|
|
|
};
|
|
|
|
enum BindCond {
|
|
|
|
BindNotAllowed, // not allowed to bind a resource
|
|
|
|
BindConflict // resource in-use
|
|
|
|
};
|
|
|
|
|
|
|
|
ClientStream(Connector *conn, TLSHandler *tlsHandler=0, QObject *parent=0);
|
|
|
|
ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls=0, QObject *parent=0); // server
|
|
|
|
~ClientStream();
|
|
|
|
|
|
|
|
Jid jid() const;
|
|
|
|
void connectToServer(const Jid &jid, bool auth=true);
|
|
|
|
void accept(); // server
|
|
|
|
bool isActive() const;
|
|
|
|
bool isAuthenticated() const;
|
|
|
|
|
|
|
|
// login params
|
|
|
|
void setUsername(const QString &s);
|
|
|
|
void setPassword(const QString &s);
|
|
|
|
void setRealm(const QString &s);
|
|
|
|
void continueAfterParams();
|
|
|
|
|
|
|
|
// SASL information
|
|
|
|
QString saslMechanism() const;
|
|
|
|
int saslSSF() const;
|
|
|
|
|
|
|
|
// binding
|
|
|
|
void setResourceBinding(bool);
|
|
|
|
|
|
|
|
// security options (old protocol only uses the first !)
|
|
|
|
void setAllowPlain(bool);
|
|
|
|
void setRequireMutualAuth(bool);
|
|
|
|
void setSSFRange(int low, int high);
|
|
|
|
void setOldOnly(bool);
|
|
|
|
void setSASLMechanism(const QString &s);
|
|
|
|
void setLocalAddr(const QHostAddress &addr, Q_UINT16 port);
|
|
|
|
|
|
|
|
// reimplemented
|
|
|
|
QDomDocument & doc() const;
|
|
|
|
QString baseNS() const;
|
|
|
|
QString xhtmlImNS() const;
|
|
|
|
QString xhtmlNS() const;
|
|
|
|
bool old() const;
|
|
|
|
|
|
|
|
void close();
|
|
|
|
bool stanzaAvailable() const;
|
|
|
|
Stanza read();
|
|
|
|
void write(const Stanza &s);
|
|
|
|
|
|
|
|
int errorCondition() const;
|
|
|
|
QString errorText() const;
|
|
|
|
QDomElement errorAppSpec() const;
|
|
|
|
|
|
|
|
// extra
|
|
|
|
void writeDirect(const QString &s);
|
|
|
|
void setNoopTime(int mills);
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void connected();
|
|
|
|
void securityLayerActivated(int);
|
|
|
|
void needAuthParams(bool user, bool pass, bool realm);
|
|
|
|
void authenticated();
|
|
|
|
void warning(int);
|
|
|
|
void incomingXml(const QString &s);
|
|
|
|
void outgoingXml(const QString &s);
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
void continueAfterWarning();
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void cr_connected();
|
|
|
|
void cr_error();
|
|
|
|
|
|
|
|
void bs_connectionClosed();
|
|
|
|
void bs_delayedCloseFinished();
|
|
|
|
void bs_error(int); // server only
|
|
|
|
|
|
|
|
void ss_readyRead();
|
|
|
|
void ss_bytesWritten(int);
|
|
|
|
void ss_tlsHandshaken();
|
|
|
|
void ss_tlsClosed();
|
|
|
|
void ss_error(int);
|
|
|
|
|
|
|
|
void sasl_clientFirstStep(const QString &mech, const QByteArray *clientInit);
|
|
|
|
void sasl_nextStep(const QByteArray &stepData);
|
|
|
|
void sasl_needParams(bool user, bool authzid, bool pass, bool realm);
|
|
|
|
void sasl_authCheck(const QString &user, const QString &authzid);
|
|
|
|
void sasl_authenticated();
|
|
|
|
void sasl_error(int);
|
|
|
|
|
|
|
|
void doNoop();
|
|
|
|
void doReadyRead();
|
|
|
|
|
|
|
|
private:
|
|
|
|
class Private;
|
|
|
|
Private *d;
|
|
|
|
|
|
|
|
void reset(bool all=false);
|
|
|
|
void processNext();
|
|
|
|
int convertedSASLCond() const;
|
|
|
|
bool handleNeed();
|
|
|
|
void handleError();
|
|
|
|
void srvProcessNext();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|