File indexing completed on 2024-12-08 03:47:59

0001 
0002 /***************************************************************************
0003                 jabberclient.h - Generic Jabber Client Class
0004                              -------------------
0005     begin                : Sat May 25 2005
0006     copyright            : (C) 2005 by Till Gerken <till@tantalo.net>
0007                            (C) 2006 by Michaƫl Larouche <larouche@kde.org>
0008 
0009     Copyright 2006 by Tommi Rantala <tommi.rantala@cs.helsinki.fi>
0010 
0011                Kopete (C) 2001-2006 Kopete developers
0012                <kopete-devel@kde.org>.
0013  ***************************************************************************/
0014 
0015 /***************************************************************************
0016  *                                                                         *
0017  *   This program is free software; you can redistribute it and/or modify  *
0018  *   it under the terms of the GNU General Public License as published by  *
0019  *   the Free Software Foundation; either either version 2
0020    of the License, or (at your option) any later version.of the License, or     *
0021  *   (at your option) any later version.                                   *
0022  *                                                                         *
0023  ***************************************************************************/
0024 
0025 #ifndef JABBERCLIENT_H
0026 #define JABBERCLIENT_H
0027 
0028 
0029 #include <QObject>
0030 
0031 // include these because of namespace reasons
0032 #include <im.h>
0033 #include <xmpp.h>
0034 #include <xmpp_discoitem.h>
0035 #include <s5b.h>
0036 
0037 #include <QtCrypto>
0038 
0039 class JabberConnector;
0040 namespace XMPP { class PrivacyManager; }
0041 
0042 using namespace XMPP;
0043 /**
0044  * This class provides an interface to the Iris subsystem. The goal is to
0045  * abstract the Iris layer and manage it via a single, simple to use class.
0046  * By default, @ref JabberClient will attempt to establish a connection
0047  * using XMPP 1.0. This means that apart from the JID and password, no
0048  * further details are necessary to connect. The server and port will be
0049  * determined using a SRV lookup. If TLS is possible (meaning, the TLS
0050  * plugin is available and the server supports TLS) it will automatically
0051  * be used. Otherwise, a non-encrypted connection will be established.
0052  * If XMPP 1.0 is not possible, the connection will fall back to the old
0053  * protocol. By default, this connection is not encrypted. You can, however,
0054  * use @ref setUseSSL to immediately attempt an SSL connection. This is
0055  * most useful if you want to establish an SSL connection to a non-standard
0056  * port, in which case you will also have to use @ref setOverrideHost. In case
0057  * XMPP 1.0 does not work, an automatic attempt to connect to the standard port
0058  * 5223 with SSL can be made with @ref setProbeSSL. If the attempt is not
0059  * sucessful, the connection will fall back to an unencrypted attempt
0060  * at port 5222.
0061  * @brief Provides a Jabber client
0062  * @author Till Gerken
0063  */
0064 class JabberClient : public QObject
0065 {
0066 
0067 Q_OBJECT
0068 
0069 public:
0070     /**
0071      * Error codes indicating problems during operation.
0072      */
0073     enum ErrorCode
0074     {
0075         Ok,                 /** No error. */
0076         InvalidPassword,    /** Password used to connect to the server was incorrect. */
0077         AlreadyConnected,   /** A new connection was attempted while the previous one hasn't been closed. */
0078         NoTLS,              /** Use of TLS has been forced (see @ref forceTLS) but TLS is not available, either server- or client-side. */
0079         InvalidPasswordForMUC = 401,    /** A password is require to enter on this Multi-User Chat */
0080         NicknameConflict = 409,     /** There is already someone with that nick connected to the Multi-User Chat */
0081         BannedFromThisMUC = 403,    /** You can't join this Multi-User Chat because you were bannished */
0082         MaxUsersReachedForThisMuc = 503 /** You can't join this Multi-User Chat because it is full */
0083     };
0084 
0085     JabberClient();
0086     ~JabberClient() override;
0087 
0088     /**
0089      * Connect to a Jabber server.
0090      * @param jid JID to connect to.
0091      * @param password Password to authenticate with.
0092      * @param auth True if authentication should be done, false if not.
0093      */
0094     ErrorCode connect ( const Jid &jid, const QString &password, bool auth = true );
0095 
0096     /**
0097      * Disconnect from Jabber server.
0098      */
0099     void disconnect ();
0100     
0101     /**
0102      * Disconnect from Jabber server with reason
0103      * @param reason The reason for disconnecting
0104      */
0105     void disconnect (Status &reason);
0106 
0107     /**
0108      * Returns if this instance is connected to a server.
0109      */
0110     bool isConnected () const;
0111 
0112     /**
0113      * Returns the JID associated with this instance.
0114      */
0115     Jid jid () const;
0116 
0117     /**
0118      * Set flag to ignore TLS warnings. If TLS
0119      * warnings are not ignored, the class will emit
0120      * @ref tlsWarning and wait for the user to
0121      * call @ref continueAfterTLSWarning or
0122      * @ref disconnect. Default is false.
0123      */
0124     void setIgnoreTLSWarnings ( bool flag );
0125     /**
0126      * Return if TLS warnings are being ignored.
0127      */
0128     bool ignoreTLSWarnings ();
0129 
0130     /**
0131      * Continue after a @ref tlsWarning signal.
0132      */
0133     void continueAfterTLSWarning ();
0134 
0135     /**
0136      * Set the port on which the S5B server should listen.
0137      * This is only taken into account if @ref setFileTransfersEnabled
0138      * is set to true.
0139      * @return True if port could be bound, false if not.
0140      */
0141     bool setS5BServerPort ( int port );
0142     /**
0143      * Returns the port the S5B server listens on.
0144      */
0145     int s5bServerPort () const;
0146 
0147     /**
0148      * Force the use of TLS. If TLS connections are forced,
0149      * unencrypted connections will not be established.
0150      * Default is false.
0151      */
0152     void setForceTLS ( bool flag );
0153     /**
0154      * Returns if TLS connections are forced.
0155      */
0156     bool forceTLS () const;
0157     
0158     /**
0159      * Force direct SSL connection, also for the
0160      * handshake. This is only useful if you know
0161      * the server supports it or you want to use
0162      * a non-standard port, in which case @ref setOverrideHost
0163      * will be useful. Default is false.
0164      */
0165     void setUseSSL ( bool flag );
0166     /**
0167      * Returns if an SSL connection attempt should be made.
0168      */
0169     bool useSSL () const;
0170 
0171     /**
0172      * Use only the old protocol (pre-XMPP 1.0). This should only
0173      * be used with servers not supporting XMPP 1.0 or with servers
0174      * that have a broken login procedure. Default is false. If
0175      * a connection attempt is not possible, Iris will automatically
0176      * fall back to the old protocol.
0177      */
0178     void setUseXMPP09 ( bool flag );
0179     /**
0180      * Returns if the old protocol should be used.
0181      */
0182     bool useXMPP09 () const;
0183 
0184     /**
0185      * Probe port 5223 if an SSL connection is possible. If
0186      * a connection is not possible, an unencrypted connection
0187      * will be attempted at port 5222. This is only meaningful
0188      * if @ref useXMPP09 is true. Default is false.
0189      */
0190     void setProbeSSL ( bool flag );
0191     /**
0192      * Returns if SSL support will be probed.
0193      */
0194     bool probeSSL () const;
0195 
0196     /**
0197      * Override the name and port of the server to connect to.
0198      * This only has an effect if the old protocol (@ref useXMPP09)
0199      * has been enabled. Default is false.
0200      */
0201     void setOverrideHost ( bool flag, const QString &server = "", int port = 5222 );
0202     /**
0203      * Returns if the server name and port are overridden.
0204      */
0205     bool overrideHost () const;
0206 
0207     /**
0208      * Allow the transmission of a plain text password. If digested
0209      * passwords are supported by the server, they will still be preferred.
0210      * Defaults to true.
0211      */
0212     void setAllowPlainTextPassword ( bool flag );
0213     /**
0214      * Returns if plain text passwords are allowed.
0215      */
0216     bool allowPlainTextPassword () const;
0217 
0218     /**
0219      * Enable file transfers. Default is false.
0220      * @param flag Whether to enable file transfers.
0221      * @param localAddress Local address to receive file transfers at. Will be determined automatically if not specified.
0222      */
0223     void setFileTransfersEnabled ( bool flag, const QString &localAddress = QString() );
0224 
0225     /**
0226      * Returns the address of the local interface.
0227      */
0228     QString localAddress () const;
0229 
0230     /**
0231      * Returns if file transfers are enabled.
0232      */
0233     bool fileTransfersEnabled () const;
0234 
0235     /**
0236      * Set client name.
0237      */
0238     void setClientName ( const QString &clientName );
0239     /**
0240      * Return client name.
0241      */
0242     QString clientName () const;
0243 
0244     /**
0245      * Set client version.
0246      */
0247     void setClientVersion ( const QString &clientVersion );
0248     /**
0249      * Return client version.
0250      */
0251     QString clientVersion () const;
0252 
0253     /**
0254      * Set operating system name.
0255      */
0256     void setOSName ( const QString &osName );
0257     /**
0258      * Return operating system name.
0259      */
0260     QString osName () const;
0261 
0262     /**
0263      * Set the caps(JEP-0115: Entity capabilities) node name.
0264      * @param node Node name.
0265      */
0266     void setCapsNode( const QString &capsNode );
0267     /**
0268      * Return the caps node name for this client.
0269      * @return the caps node name.
0270      */
0271     QString capsNode() const;
0272     
0273     /**
0274      * Set the caps(JEP-0115: Entity capabilities) node version.
0275      * @param capsVersion the node version.
0276      */
0277     void setCapsVersion( const QString &capsVersion );
0278     /**
0279      * Return the caps version for this client.
0280      * @return the caps version.
0281      */
0282     QString capsVersion() const;
0283 
0284     /**
0285      * Return the caps extension list for this client.
0286      * @return A string containing all extensions separated by space.
0287      */
0288     QString capsExt() const;
0289 
0290     /**
0291      * Set the disco Identity information for this client.
0292      * Create a Disco identity like this:
0293      * @code
0294      * DiscoItem::Identity identity;
0295      * identity.category = "client";
0296      * identity.type = "pc";
0297      * identity.name = "Kopete";
0298      * @endcode
0299      *
0300      * @param identity DiscoItem::Identity for the client.
0301      */
0302     void setDiscoIdentity(DiscoItem::Identity identity);
0303     /**
0304      * Get the disco Identity information for this client.
0305      * @return the DiscoItem::Identity for this client.
0306      */
0307     DiscoItem::Identity discoIdentity() const;
0308 
0309     /**
0310      * Set timezone information. Default is UTC.
0311      */
0312     void setTimeZone ( const QString &timeZoneName, int timeZoneOffset );
0313     /**
0314      * Return timezone name.
0315      */
0316     QString timeZoneName () const;
0317     /**
0318      * Return timezone offset.
0319      */
0320     int timeZoneOffset () const;
0321 
0322     /**
0323      * This method can be used to implement a penalty
0324      * system when a lot of queries need to be sent to the
0325      * server. Using the time returned by this method,
0326      * the caller can determine a delay until the next
0327      * operation in the queue can be carried out.
0328      * @brief Return current penalty time in seconds.
0329      */
0330     int getPenaltyTime ();
0331 
0332     /**
0333      * Return the XMPP client instance.
0334      */
0335     Client *client () const;
0336 
0337     /**
0338      * Return client stream instance.
0339      */
0340     ClientStream *clientStream () const;
0341 
0342     /**
0343      * Return client connector instance.
0344      */
0345     JabberConnector *clientConnector () const;
0346 
0347     /**
0348      * Get the root task for this connection.
0349      * You need this instance for every task
0350      * you want to start.
0351      */
0352     Task *rootTask () const;
0353 
0354     /**
0355      * Returns the file transfer manager
0356      * instance that deals with current file
0357      * transfers.
0358      */
0359     FileTransferManager *fileTransferManager () const;
0360     
0361     /**
0362      * Returns the privacy lists manager
0363      */
0364     PrivacyManager *privacyManager () const;
0365 
0366     /**
0367      * Join a groupchat.
0368      * @param host Node to join the room at.
0369      * @param room Name of room to join.
0370      * @param nick Nick name you want to join with.
0371      */
0372     void joinGroupChat ( const QString &host, const QString &room, const QString &nick );
0373 
0374     /**
0375      * Join a groupchat that require a password.
0376      * @param host Node to join the room at.
0377      * @param room Name of room to join.
0378      * @param nick Nick name you want to join with.
0379      * @param password The password to join the room.
0380      */
0381     void joinGroupChat ( const QString &host, const QString &room, const QString &nick, const QString &password );
0382 
0383     /**
0384      * Leave a groupchat.
0385      * @param host Node to leave room at.
0386      * @param room Name of room to leave.
0387      */
0388     void leaveGroupChat ( const QString &host, const QString &room );
0389     
0390     /**
0391      * change the status of a groupchat
0392      */
0393     void setGroupChatStatus(const QString &host, const QString &room, const Status &);
0394     /**
0395      * change the nick in a groupchat
0396      */
0397     void changeGroupChatNick(const QString &host, const QString &room, const QString &nick, const Status &status =Status());
0398 
0399     /**
0400      * Send a message.
0401      */
0402     void sendMessage ( const Message &message );
0403 
0404     /**
0405      * Send raw packet to the server.
0406      */
0407     void send ( const QString &packet );
0408 
0409     /**
0410      * Request the roster from the Jabber server.
0411      */
0412     void requestRoster ();
0413 
0414 signals:
0415     /**
0416      * Connected successfully.
0417      */
0418     void connected ();
0419 
0420     /**
0421      * Client stream authenticated. This
0422      * signal is emitted when the socket
0423      * connection has been successfully
0424      * established, before sending the login
0425      * packet.
0426      */
0427     void csAuthenticated ();
0428 
0429     /**
0430      * Client stream error.
0431      */
0432     void csError ( int error );
0433 
0434     /**
0435      * Client stream was disconnected.
0436      */
0437     void csDisconnected ();
0438 
0439     /**
0440      * TLS problem encountered.
0441      */
0442     void tlsWarning ( QCA::TLS::IdentityResult, QCA::Validity );
0443 
0444     /**
0445      * A new file transfer needs to be handled.
0446      * The file transfer can be dealt with by
0447      * querying the file transfer manager from
0448      * @ref client.
0449      */
0450     void incomingFileTransfer ();
0451 
0452     /**
0453      * Fatal error has been encountered,
0454      * further operations are not possible.
0455      */
0456     void error ( JabberClient::ErrorCode code );
0457 
0458     /**
0459      * Roster has been transmitted and processed.
0460      */
0461     void rosterRequestFinished ( bool success );
0462 
0463     /**
0464      * A new contact appeared on the roster.
0465      */
0466     void newContact ( const RosterItem &item );
0467 
0468     /**
0469      * A contact has been removed from the roster.
0470      */
0471     void contactDeleted ( const RosterItem &item );
0472 
0473     /**
0474      * A roster item has changed.
0475      */
0476     void contactUpdated ( const RosterItem &item );
0477 
0478     /**
0479      * New resource is available for a contact.
0480      */
0481     void resourceAvailable ( const Jid &jid, const Resource &resource );
0482 
0483     /**
0484      * An existing resource has been removed.
0485      */
0486     void resourceUnavailable ( const Jid &jid, const Resource &resource );
0487 
0488     /**
0489      * A new message has been received.
0490      */
0491     void messageReceived ( const XMPP::Message &message );
0492 
0493     /**
0494      * Group chat has been joined.
0495      */
0496     void groupChatJoined ( const XMPP::Jid &jid );
0497 
0498     /**
0499      * Group chat has been left.
0500      */
0501     void groupChatLeft ( const XMPP::Jid &jid );
0502 
0503     /**
0504      * A presence to a groupchat has been signalled.
0505      */
0506     void groupChatPresence ( const XMPP::Jid &jid, const XMPP::Status &status );
0507 
0508     /**
0509      * An error was encountered joining or processing a groupchat.
0510      */
0511     void groupChatError ( const XMPP::Jid &jid, int error, const QString &reason );
0512 
0513     /**
0514      * New subscription request.
0515      */
0516     void subscription ( const Jid &jid, const QString &type );
0517     
0518     /**
0519      * Dispatches a debug message. Debug messages
0520      * include incoming and outgoing XML packets
0521      * as well as internal status messages.
0522      */
0523     void debugMessage ( const QString &message );
0524     void incomingXML (const QString &msg);
0525     void outgoingXML (const QString &msg);
0526 
0527 private:
0528     class Private;
0529     Private *d;
0530 
0531     /**
0532      * Delete all member classes and reset the class to a predefined state.
0533      */
0534     void cleanUp ();
0535 
0536     /** 
0537      * Return current instance of the S5B server.
0538      */
0539     S5BServer *s5bServer ();
0540     /** 
0541      * Add an address that the S5B server should handle.
0542      */
0543     void addS5BServerAddress ( const QString &address );
0544     /** 
0545      * Remove an address that the S5B server currently handles.
0546      */
0547     void removeS5BServerAddress ( const QString &address );
0548 
0549 private slots:
0550     /* S5B server object has been destroyed. */
0551     void slotS5BServerGone ();
0552 
0553     /* update the penalty timer */
0554     void slotUpdatePenaltyTime ();
0555 
0556     /* Login if the connection was OK. */
0557     void slotCSNeedAuthParams (bool user, bool pass, bool realm);
0558 
0559     /* Called from Psi: tells us when we're logged in OK. */
0560     void slotCSAuthenticated ();
0561 
0562     /* Called from Psi: tells us when we've been disconnected from the server. */
0563     void slotCSDisconnected ();
0564 
0565     /* Called from Psi: alerts us to a protocol warning. */
0566     void slotCSWarning (int);
0567 
0568     /* Called from Psi: alerts us to a protocol error. */
0569     void slotCSError (int);
0570 
0571     /* Called from Psi: report certificate status */
0572     void slotTLSHandshaken ();
0573 
0574     /* Called from Psi: roster request finished */
0575     void slotRosterRequestFinished ( bool success, int statusCode, const QString &statusString );
0576 
0577     /* Called from Psi: incoming file transfer */
0578     void slotIncomingFileTransfer ();
0579 
0580     /* A new item appeared in our roster */
0581     void slotNewContact (const RosterItem &);
0582 
0583     /* An item has been deleted from our roster. */
0584     void slotContactDeleted (const RosterItem &);
0585 
0586     /* Update a contact's details. */
0587     void slotContactUpdated (const RosterItem &);
0588 
0589     /* Someone on our contact list had (another) resource come online. */
0590     void slotResourceAvailable (const Jid &, const Resource &);
0591 
0592     /* Someone on our contact list had a resource go offline. */
0593     void slotResourceUnavailable (const Jid &, const Resource &);
0594 
0595     /* Incoming message. */
0596     void slotReceivedMessage (const Message &);
0597     
0598     /* Called from Psi: debug messages from the backend. */
0599     void slotPsiDebug (const QString & msg);
0600     void slotIncomingXML (const QString &msg);
0601     void slotOutgoingXML (const QString &msg);
0602 
0603     /* Slots for handling groupchats. */
0604     void slotGroupChatJoined (const Jid & jid);
0605   void slotGroupChatLeft (const Jid & jid);
0606   void slotGroupChatPresence (const Jid & jid, const Status & status);
0607   void slotGroupChatError (const Jid & jid, int error, const QString & reason);
0608 
0609     /* Incoming subscription request. */
0610     void slotSubscription (const Jid& jid, const QString& type);
0611 
0612 };
0613 
0614 #endif