File indexing completed on 2024-04-21 04:04:41

0001 
0002 /***************************************************************************
0003                 jabberclient.cpp - 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     Copyright 2006 by Tommi Rantala <tommi.rantala@cs.helsinki.fi>
0009 
0010          Kopete (C) 2001-2006 Kopete developers
0011          <kopete-devel@kde.org>.
0012  ***************************************************************************/
0013 
0014 /***************************************************************************
0015  *                                                                         *
0016  *   This program is free software; you can redistribute it and/or modify  *
0017  *   it under the terms of the GNU General Public License as published by  *
0018  *   the Free Software Foundation; either either version 2
0019    of the License, or (at your option) any later version.of the License, or     *
0020  *   (at your option) any later version.                                   *
0021  *                                                                         *
0022  ***************************************************************************/
0023 
0024 #include "jabberclient.h"
0025 #include "jabber_protocol_debug.h"
0026 
0027 #include <QTimer>
0028 #include <QRegExp>
0029 
0030 #include <bsocket.h>
0031 #include <filetransfer.h>
0032 #include <xmpp_tasks.h>
0033 
0034 #include "jabberconnector.h"
0035 #include "privacymanager.h"
0036 
0037 #define JABBER_PENALTY_TIME  2
0038 
0039 using namespace XMPP;
0040 
0041 class JabberClient::Private
0042 {
0043 public:
0044   Private()
0045   : jabberClient(nullptr), jabberClientStream(nullptr), jabberClientConnector(nullptr), jabberTLS(nullptr),
0046            jabberTLSHandler(nullptr), privacyManager(nullptr)
0047   {}
0048   ~Private()
0049   {
0050     if ( jabberClient )
0051     {
0052       jabberClient->close ();
0053     }
0054     
0055     delete jabberClient;
0056     delete jabberClientStream;
0057     delete jabberClientConnector;
0058     delete jabberTLSHandler;
0059     delete jabberTLS;
0060     // privacyManager will be deleted with jabberClient, its parent's parent
0061   }
0062 
0063   // connection details
0064   XMPP::Jid jid;
0065   QString password;
0066 
0067   // XMPP backend
0068   XMPP::Client *jabberClient;
0069   XMPP::ClientStream *jabberClientStream;
0070   JabberConnector *jabberClientConnector;
0071   QCA::TLS *jabberTLS;
0072   XMPP::QCATLSHandler *jabberTLSHandler;
0073   QCA::Initializer qcaInit;
0074   PrivacyManager *privacyManager;
0075 
0076   // ignore TLS warnings
0077   bool ignoreTLSWarnings;
0078 
0079   // current S5B server instance
0080   static XMPP::S5BServer *s5bServer;
0081   // address list being handled by the S5B server instance
0082   static QStringList s5bAddressList;
0083   // port of S5B server
0084   static int s5bServerPort;
0085 
0086   // local IP address
0087   QString localAddress;
0088 
0089   // whether TLS (or direct SSL in case of the old protocol) should be used
0090   bool forceTLS;
0091 
0092   // whether direct SSL connections should be used
0093   bool useSSL;
0094 
0095   // use XMPP 1.0 or the older protocol version
0096   bool useXMPP09;
0097 
0098   // whether SSL support should be probed in case the old protocol is used
0099   bool probeSSL;
0100 
0101   // override the default server name and port (only pre-XMPP 1.0)
0102   bool overrideHost;
0103   QString server;
0104   int port;
0105 
0106   // allow transmission of plaintext passwords
0107   bool allowPlainTextPassword;
0108 
0109   // enable file transfers
0110   bool fileTransfersEnabled;
0111 
0112   // current penalty time
0113   int currentPenaltyTime;
0114 
0115   // client information
0116   QString clientName, clientVersion, osName;
0117 
0118   // timezone information
0119   QString timeZoneName;
0120   int timeZoneOffset;
0121 
0122   // Caps(JEP-0115: Entity Capabilities) information
0123   QString capsNode, capsVersion;
0124   DiscoItem::Identity discoIdentity;
0125 };
0126 
0127 XMPP::S5BServer *JabberClient::Private::s5bServer = nullptr;
0128 QStringList JabberClient::Private::s5bAddressList;
0129 int JabberClient::Private::s5bServerPort = 8010;
0130 
0131 JabberClient::JabberClient ()
0132 {
0133   d = new Private();
0134 
0135   cleanUp ();
0136 
0137   // initiate penalty timer
0138   QTimer::singleShot ( JABBER_PENALTY_TIME * 1000, this, SLOT (slotUpdatePenaltyTime()) );
0139 
0140 }
0141 
0142 JabberClient::~JabberClient ()
0143 {
0144   delete d;
0145 }
0146 
0147 void JabberClient::cleanUp ()
0148 {
0149   if ( d->jabberClient )
0150   {
0151     d->jabberClient->close ();
0152   }
0153   
0154   delete d->jabberClient;
0155   delete d->jabberClientStream;
0156   delete d->jabberClientConnector;
0157   delete d->jabberTLSHandler;
0158   delete d->jabberTLS;
0159   // privacyManager will be deleted with jabberClient, its parent's parent
0160 
0161   d->jabberClient = nullptr;
0162   d->jabberClientStream = nullptr;
0163   d->jabberClientConnector = nullptr;
0164   d->jabberTLSHandler = nullptr;
0165   d->jabberTLS = nullptr;
0166   d->privacyManager = nullptr;
0167 
0168   d->currentPenaltyTime = 0;
0169 
0170   d->jid = XMPP::Jid ();
0171   d->password.clear();
0172 
0173   setForceTLS ( false );
0174   setUseSSL ( false );
0175   setUseXMPP09 ( false );
0176   setProbeSSL ( false );
0177 
0178   setOverrideHost ( false );
0179 
0180   setAllowPlainTextPassword ( true );
0181 
0182   setFileTransfersEnabled ( false );
0183   setS5BServerPort ( 8010 );
0184 
0185   setClientName ( QString() );
0186   setClientVersion ( QString() );
0187   setOSName ( QString() );
0188 
0189   setTimeZone ( "UTC", 0 );
0190 
0191   setIgnoreTLSWarnings ( false );
0192 
0193 }
0194 
0195 void JabberClient::slotUpdatePenaltyTime ()
0196 {
0197 
0198   if ( d->currentPenaltyTime >= JABBER_PENALTY_TIME )
0199     d->currentPenaltyTime -= JABBER_PENALTY_TIME;
0200   else
0201     d->currentPenaltyTime = 0;
0202 
0203   QTimer::singleShot ( JABBER_PENALTY_TIME * 1000, this, SLOT (slotUpdatePenaltyTime()) );
0204 
0205 }
0206 
0207 void JabberClient::setIgnoreTLSWarnings ( bool flag )
0208 {
0209 
0210   d->ignoreTLSWarnings = flag;
0211 
0212 }
0213 
0214 bool JabberClient::ignoreTLSWarnings ()
0215 {
0216 
0217   return d->ignoreTLSWarnings;
0218 
0219 }
0220 
0221 bool JabberClient::setS5BServerPort ( int port )
0222 {
0223 
0224   d->s5bServerPort = port;
0225 
0226   if ( fileTransfersEnabled () )
0227   {
0228     return s5bServer()->start ( port );
0229   }
0230 
0231   return true;
0232 
0233 }
0234 
0235 int JabberClient::s5bServerPort () const
0236 {
0237 
0238   return d->s5bServerPort;
0239 
0240 }
0241 
0242 XMPP::S5BServer *JabberClient::s5bServer ()
0243 {
0244 
0245   if ( !d->s5bServer )
0246   {
0247     d->s5bServer = new XMPP::S5BServer ();
0248     QObject::connect ( d->s5bServer, SIGNAL (destroyed()), this, SLOT (slotS5BServerGone()) );
0249 
0250     /*
0251      * Try to start the server at the default port here.
0252      * We have no way of notifying the caller of an error.
0253      * However, since the caller will usually also
0254      * use setS5BServerPort() to ensure the correct
0255      * port, we can return an error code there.
0256      */
0257     if ( fileTransfersEnabled () )
0258     {
0259       s5bServer()->start ( d->s5bServerPort );
0260     }
0261   }
0262 
0263   return d->s5bServer;
0264 
0265 }
0266 
0267 void JabberClient::slotS5BServerGone ()
0268 {
0269 
0270   d->s5bServer = nullptr;
0271 
0272   if ( d->jabberClient )
0273     d->jabberClient->s5bManager()->setServer( nullptr );
0274 
0275 }
0276 
0277 void JabberClient::addS5BServerAddress ( const QString &address )
0278 {
0279   QStringList newList;
0280 
0281   d->s5bAddressList.append ( address );
0282 
0283   // now filter the list without dupes
0284   foreach( QStringList::const_reference str, d->s5bAddressList )
0285   {
0286     if ( !newList.contains ( str ) )
0287       newList.append ( str );
0288   }
0289 
0290   s5bServer()->setHostList ( newList );
0291 
0292 }
0293 
0294 void JabberClient::removeS5BServerAddress ( const QString &address )
0295 {
0296   QStringList newList;
0297 
0298   int idx = d->s5bAddressList.indexOf( address );
0299 
0300   if ( idx != -1 )
0301     d->s5bAddressList.removeAt(idx);
0302 
0303   if ( d->s5bAddressList.isEmpty () )
0304   {
0305     delete d->s5bServer;
0306     d->s5bServer = nullptr;
0307   }
0308   else
0309   {
0310     // now filter the list without dupes
0311     foreach( QStringList::const_reference str, d->s5bAddressList )
0312     {
0313       if ( !newList.contains ( str ) )
0314         newList.append ( str );
0315     }
0316 
0317     s5bServer()->setHostList ( newList );
0318   }
0319 
0320 }
0321 
0322 void JabberClient::setForceTLS ( bool flag )
0323 {
0324 
0325   d->forceTLS = flag;
0326 
0327 }
0328 
0329 bool JabberClient::forceTLS () const
0330 {
0331 
0332   return d->forceTLS;
0333 
0334 }
0335 
0336 void JabberClient::setUseSSL ( bool flag )
0337 {
0338 
0339   d->useSSL = flag;
0340 
0341 }
0342 
0343 bool JabberClient::useSSL () const
0344 {
0345 
0346   return d->useSSL;
0347 
0348 }
0349 
0350 void JabberClient::setUseXMPP09 ( bool flag )
0351 {
0352 
0353   d->useXMPP09 = flag;
0354 
0355 }
0356 
0357 bool JabberClient::useXMPP09 () const
0358 {
0359 
0360   return d->useXMPP09;
0361 
0362 }
0363 
0364 void JabberClient::setProbeSSL ( bool flag )
0365 {
0366 
0367   d->probeSSL = flag;
0368 
0369 }
0370 
0371 bool JabberClient::probeSSL () const
0372 {
0373 
0374   return d->probeSSL;
0375 
0376 }
0377 
0378 void JabberClient::setOverrideHost ( bool flag, const QString &server, int port )
0379 {
0380 
0381   d->overrideHost = flag;
0382   d->server = server;
0383   d->port = port;
0384 
0385 }
0386 
0387 bool JabberClient::overrideHost () const
0388 {
0389 
0390   return d->overrideHost;
0391 
0392 }
0393 
0394 void JabberClient::setAllowPlainTextPassword ( bool flag )
0395 {
0396 
0397   d->allowPlainTextPassword = flag;
0398 
0399 }
0400 
0401 bool JabberClient::allowPlainTextPassword () const
0402 {
0403 
0404   return d->allowPlainTextPassword;
0405 
0406 }
0407 
0408 void JabberClient::setFileTransfersEnabled ( bool flag, const QString &localAddress )
0409 {
0410 
0411   d->fileTransfersEnabled = flag;
0412   d->localAddress = localAddress;
0413 
0414 }
0415 
0416 QString JabberClient::localAddress () const
0417 {
0418 
0419   return d->localAddress;
0420 
0421 }
0422 
0423 bool JabberClient::fileTransfersEnabled () const
0424 {
0425 
0426   return d->fileTransfersEnabled;
0427 
0428 }
0429 
0430 void JabberClient::setClientName ( const QString &clientName )
0431 {
0432 
0433   d->clientName = clientName;
0434 
0435 }
0436 
0437 QString JabberClient::clientName () const
0438 {
0439 
0440   return d->clientName;
0441 
0442 }
0443 
0444 void JabberClient::setClientVersion ( const QString &clientVersion )
0445 {
0446 
0447   d->clientVersion = clientVersion;
0448 
0449 }
0450 
0451 QString JabberClient::clientVersion () const
0452 {
0453 
0454   return d->clientVersion;
0455 
0456 }
0457 
0458 void JabberClient::setOSName ( const QString &osName )
0459 {
0460 
0461   d->osName = osName;
0462 
0463 }
0464 
0465 QString JabberClient::osName () const
0466 {
0467 
0468   return d->osName;
0469 
0470 }
0471 
0472 void JabberClient::setCapsNode( const QString &capsNode )
0473 {
0474   d->capsNode = capsNode;
0475 }
0476 
0477 QString JabberClient::capsNode() const
0478 {
0479   return d->capsNode;
0480 }
0481 
0482 void JabberClient::setCapsVersion( const QString &capsVersion )
0483 {
0484   d->capsVersion = capsVersion;
0485 }
0486 
0487 QString JabberClient::capsVersion() const
0488 {
0489   return d->capsVersion;
0490 }
0491 
0492 QString JabberClient::capsExt() const
0493 {
0494   if(d->jabberClient)
0495   {
0496     return d->jabberClient->capsExt();
0497   }
0498 
0499   return QString();
0500 }
0501 void JabberClient::setDiscoIdentity( DiscoItem::Identity identity )
0502 {
0503   d->discoIdentity = identity;
0504 }
0505 
0506 DiscoItem::Identity JabberClient::discoIdentity() const
0507 {
0508   return d->discoIdentity;
0509 }
0510 
0511 void JabberClient::setTimeZone ( const QString &timeZoneName, int timeZoneOffset )
0512 {
0513 
0514   d->timeZoneName = timeZoneName;
0515   d->timeZoneOffset = timeZoneOffset;
0516 
0517 }
0518 
0519 QString JabberClient::timeZoneName () const
0520 {
0521 
0522   return d->timeZoneName;
0523 
0524 }
0525 
0526 int JabberClient::timeZoneOffset () const
0527 {
0528 
0529   return d->timeZoneOffset;
0530 
0531 }
0532 
0533 int JabberClient::getPenaltyTime ()
0534 {
0535 
0536   int currentTime = d->currentPenaltyTime;
0537 
0538   d->currentPenaltyTime += JABBER_PENALTY_TIME;
0539 
0540   return currentTime;
0541 
0542 }
0543 
0544 XMPP::Client *JabberClient::client () const
0545 {
0546 
0547   return d->jabberClient;
0548 
0549 }
0550 
0551 XMPP::ClientStream *JabberClient::clientStream () const
0552 {
0553 
0554   return d->jabberClientStream;
0555 
0556 }
0557 
0558 JabberConnector *JabberClient::clientConnector () const
0559 {
0560 
0561   return d->jabberClientConnector;
0562 
0563 }
0564 
0565 XMPP::Task *JabberClient::rootTask () const
0566 {
0567 
0568   if ( client () )
0569   {
0570     return client()->rootTask ();
0571   }
0572   else
0573   {
0574     return nullptr;
0575   }
0576 
0577 }
0578 
0579 XMPP::FileTransferManager *JabberClient::fileTransferManager () const
0580 {
0581 
0582   if ( client () )
0583   {
0584     return client()->fileTransferManager ();
0585   }
0586   else
0587   {
0588     return nullptr;
0589   }
0590 
0591 }
0592 
0593 PrivacyManager *JabberClient::privacyManager () const
0594 {
0595   return d->privacyManager;
0596 }
0597 
0598 XMPP::Jid JabberClient::jid () const
0599 {
0600 
0601   return d->jid;
0602 
0603 }
0604 
0605 JabberClient::ErrorCode JabberClient::connect ( const XMPP::Jid &jid, const QString &password, bool auth )
0606 {
0607   /*
0608    * Close any existing connection.
0609    */
0610   if ( d->jabberClient )
0611   {
0612     d->jabberClient->close ();
0613   }
0614   d->jid = jid;
0615   d->password = password;
0616 
0617   /*
0618    * Return an error if we should force TLS but it's not available.
0619    */
0620   if ( ( forceTLS () || useSSL () || probeSSL () ) && !QCA::isSupported ("tls" ) )
0621   {
0622     qCDebug(JABBER_PROTOCOL_LOG) << "no TLS";
0623     return NoTLS;
0624   }
0625 
0626   /*
0627    * Instantiate connector, responsible for dealing with the socket.
0628    * This class uses KDE's socket code, which in turn makes use of
0629    * the global proxy settings.
0630    */
0631   if ( d->jabberClientConnector == nullptr)
0632   {
0633     d->jabberClientConnector = new JabberConnector;
0634   }
0635 
0636   d->jabberClientConnector->setOptSSL ( useSSL () );
0637 
0638   if ( useXMPP09 () )
0639   {
0640     if ( overrideHost () )
0641     {
0642       d->jabberClientConnector->setOptHostPort ( d->server, d->port );
0643     }
0644 
0645     d->jabberClientConnector->setOptProbe ( probeSSL () );
0646 
0647   }
0648 
0649   /*
0650    * Setup authentication layer
0651    */
0652   if ( QCA::isSupported ("tls") )
0653   {
0654     qCDebug(JABBER_PROTOCOL_LOG) << "QCA tls";
0655     if (d->jabberTLS == nullptr)
0656       d->jabberTLS = new QCA::TLS;
0657     d->jabberTLS->setTrustedCertificates(QCA::systemStore());
0658     if (d->jabberTLSHandler == nullptr)
0659       d->jabberTLSHandler = new QCATLSHandler(d->jabberTLS);
0660     d->jabberTLSHandler->setXMPPCertCheck(true);
0661 
0662     QObject::connect ( d->jabberTLSHandler, SIGNAL (tlsHandshaken()), SLOT (slotTLSHandshaken()) );
0663   }
0664 
0665   /*
0666    * Instantiate client stream which handles the network communication by referring
0667    * to a connector (proxying etc.) and a TLS handler (security layer)
0668    */
0669   if (d->jabberClientStream != nullptr)
0670     delete d->jabberClientStream;
0671   d->jabberClientStream = new XMPP::ClientStream ( d->jabberClientConnector, d->jabberTLSHandler );
0672 
0673   {
0674     using namespace XMPP;
0675     QObject::connect ( d->jabberClientStream, SIGNAL (needAuthParams(bool,bool,bool)),
0676            this, SLOT (slotCSNeedAuthParams(bool,bool,bool)) );
0677     QObject::connect ( d->jabberClientStream, SIGNAL (authenticated()),
0678            this, SLOT (slotCSAuthenticated()) );
0679     QObject::connect ( d->jabberClientStream, SIGNAL (connectionClosed()),
0680            this, SLOT (slotCSDisconnected()) );
0681     QObject::connect ( d->jabberClientStream, SIGNAL (delayedCloseFinished()),
0682            this, SLOT (slotCSDisconnected()) );
0683     QObject::connect ( d->jabberClientStream, SIGNAL (warning(int)),
0684            this, SLOT (slotCSWarning(int)) );
0685     QObject::connect ( d->jabberClientStream, SIGNAL (error(int)),
0686            this, SLOT (slotCSError(int)) );
0687   }
0688 
0689   d->jabberClientStream->setOldOnly ( useXMPP09 () );
0690 
0691   /*
0692    * Initiate anti-idle timer (will be triggered every 55 seconds).
0693    */
0694   d->jabberClientStream->setNoopTime ( 55000 );
0695 
0696   /*
0697    * Allow plaintext password authentication or not?
0698    */
0699   d->jabberClientStream->setAllowPlain( allowPlainTextPassword () ?  XMPP::ClientStream::AllowPlain : XMPP::ClientStream::NoAllowPlain );
0700 
0701   /*
0702    * Setup client layer.
0703    */
0704     qCDebug(JABBER_PROTOCOL_LOG) << "Setup client layer";
0705     if (d->jabberClient != nullptr)
0706       delete d->jabberClient;
0707     d->jabberClient = new XMPP::Client ( this );
0708   
0709   /*
0710    * Setup privacy manager
0711    */
0712   if (d->privacyManager == nullptr)
0713     d->privacyManager = new PrivacyManager ( rootTask() );
0714 
0715   /*
0716    * Enable file transfer (IP and server will be set after connection
0717    * has been established.
0718    */
0719   if ( fileTransfersEnabled () )
0720   {
0721     d->jabberClient->setFileTransferEnabled ( true );
0722 
0723     {
0724       using namespace XMPP;
0725       QObject::connect ( d->jabberClient->fileTransferManager(), SIGNAL (incomingReady()),
0726              this, SLOT (slotIncomingFileTransfer()) );
0727     }
0728   }
0729 
0730   /* This should only be done here to connect the signals, otherwise it is a
0731    * bad idea.
0732    */
0733   {
0734     using namespace XMPP;
0735     qCDebug(JABBER_PROTOCOL_LOG) << "Connecting subscription";
0736     QObject::connect ( d->jabberClient, SIGNAL (subscription(Jid,QString,QString)),
0737     this, SLOT (slotSubscription(Jid,QString)) );
0738     qCDebug(JABBER_PROTOCOL_LOG) << "Connecting rosterRequestFinished";
0739     QObject::connect ( d->jabberClient, SIGNAL (rosterRequestFinished(bool,int,QString)),
0740     this, SLOT (slotRosterRequestFinished(bool,int,QString)) );
0741     QObject::connect ( d->jabberClient, SIGNAL (rosterItemAdded(RosterItem)),
0742            this, SLOT (slotNewContact(RosterItem)) );
0743     QObject::connect ( d->jabberClient, SIGNAL (rosterItemUpdated(RosterItem)),
0744            this, SLOT (slotContactUpdated(RosterItem)) );
0745     QObject::connect ( d->jabberClient, SIGNAL (rosterItemRemoved(RosterItem)),
0746            this, SLOT (slotContactDeleted(RosterItem)) );
0747     QObject::connect ( d->jabberClient, SIGNAL (resourceAvailable(Jid,Resource)),
0748            this, SLOT (slotResourceAvailable(Jid,Resource)) );
0749     QObject::connect ( d->jabberClient, SIGNAL (resourceUnavailable(Jid,Resource)),
0750            this, SLOT (slotResourceUnavailable(Jid,Resource)) );
0751     QObject::connect ( d->jabberClient, SIGNAL (messageReceived(Message)),
0752            this, SLOT (slotReceivedMessage(Message)) );
0753     QObject::connect ( d->jabberClient, SIGNAL (groupChatJoined(Jid)),
0754            this, SLOT (slotGroupChatJoined(Jid)) );
0755     QObject::connect ( d->jabberClient, SIGNAL (groupChatLeft(Jid)),
0756            this, SLOT (slotGroupChatLeft(Jid)) );
0757     QObject::connect ( d->jabberClient, SIGNAL (groupChatPresence(Jid,Status)),
0758            this, SLOT (slotGroupChatPresence(Jid,Status)) );
0759     QObject::connect ( d->jabberClient, SIGNAL (groupChatError(Jid,int,QString)),
0760            this, SLOT (slotGroupChatError(Jid,int,QString)) );
0761     //QObject::connect ( d->jabberClient, SIGNAL (debugText(QString)),
0762     //       this, SLOT (slotPsiDebug(QString)) );
0763     QObject::connect ( d->jabberClient, SIGNAL (xmlIncoming(QString)),
0764            this, SLOT (slotIncomingXML(QString)) );
0765     QObject::connect ( d->jabberClient, SIGNAL (xmlOutgoing(QString)),
0766            this, SLOT (slotOutgoingXML(QString)) );
0767   }
0768 
0769   d->jabberClient->setClientName ( clientName () );
0770   d->jabberClient->setClientVersion ( clientVersion () );
0771   d->jabberClient->setOSName ( osName () );
0772 
0773   // Set caps information
0774   d->jabberClient->setCapsNode( capsNode() );
0775   d->jabberClient->setCapsVersion( capsVersion() );
0776   
0777   // Set Disco Identity
0778   d->jabberClient->setIdentity( discoIdentity() );
0779 
0780   d->jabberClient->setTimeZone ( timeZoneName (), timeZoneOffset () );
0781 
0782   qCDebug(JABBER_PROTOCOL_LOG) << "connect to server" << jid.domain() << jid.node() << jid.resource() << jid.bare() << jid.full() << auth;
0783   d->jabberClient->connectToServer ( d->jabberClientStream, jid, auth );
0784 
0785   return Ok;
0786 }
0787 
0788 void JabberClient::disconnect ()
0789 {
0790 
0791   if ( d->jabberClient )
0792   {
0793     d->jabberClient->close ();
0794   }
0795   else
0796   {
0797     cleanUp ();
0798   }
0799 
0800 }
0801 
0802 void JabberClient::disconnect( XMPP::Status &reason )
0803 {
0804     if ( d->jabberClient )
0805     {
0806         if ( d->jabberClientStream->isActive() )
0807         {
0808             XMPP::JT_Presence *pres = new JT_Presence(rootTask());
0809             reason.setIsAvailable( false );
0810             pres->pres( reason );
0811             pres->go();
0812 
0813             d->jabberClientStream->close();
0814             d->jabberClient->close();
0815         }
0816     }
0817     else
0818     {
0819         cleanUp();
0820     }
0821 }
0822 
0823 bool JabberClient::isConnected () const
0824 {
0825 
0826   if ( d->jabberClient )
0827   {
0828     return d->jabberClient->isActive ();
0829   }
0830 
0831   return false;
0832 
0833 }
0834 
0835 void JabberClient::joinGroupChat ( const QString &host, const QString &room, const QString &nick )
0836 {
0837 
0838   client()->groupChatJoin ( host, room, nick );
0839 
0840 }
0841 
0842 void JabberClient::joinGroupChat ( const QString &host, const QString &room, const QString &nick, const QString &password )
0843 {
0844   client()->groupChatJoin ( host, room, nick, password );
0845 
0846 }
0847 
0848 void JabberClient::leaveGroupChat ( const QString &host, const QString &room )
0849 {
0850 
0851   client()->groupChatLeave ( host, room );
0852 
0853 }
0854 
0855 void JabberClient::setGroupChatStatus( const QString & host, const QString & room, const XMPP::Status & status )
0856 {
0857   client()->groupChatSetStatus( host, room, status);
0858 }
0859 
0860 void JabberClient::changeGroupChatNick( const QString & host, const QString & room, const QString & nick, const XMPP::Status & status )
0861 {
0862   client()->groupChatChangeNick( host, room, nick, status );
0863 }
0864 
0865 
0866 void JabberClient::sendMessage ( const XMPP::Message &message )
0867 {
0868 
0869   client()->sendMessage ( message );
0870 
0871 }
0872 
0873 void JabberClient::send ( const QString &packet )
0874 {
0875 
0876   client()->send ( packet );
0877 
0878 }
0879 
0880 void JabberClient::requestRoster ()
0881 {
0882 
0883   client()->rosterRequest ();
0884 
0885 }
0886 
0887 void JabberClient::slotPsiDebug ( const QString & _msg )
0888 {
0889   QString msg = _msg;
0890 
0891   msg = msg.replace( QRegExp( "<password>[^<]*</password>\n" ), "<password>[Filtered]</password>\n" );
0892   msg = msg.replace( QRegExp( "<digest>[^<]*</digest>\n" ), "<digest>[Filtered]</digest>\n" );
0893 
0894   emit debugMessage ( "Psi: " + msg );
0895 
0896 }
0897 
0898 void JabberClient::slotIncomingXML ( const QString & _msg )
0899 {
0900   QString msg = _msg;
0901 
0902   msg = msg.replace( QRegExp( "<password>[^<]*</password>\n" ), "<password>[Filtered]</password>\n" );
0903   msg = msg.replace( QRegExp( "<digest>[^<]*</digest>\n" ), "<digest>[Filtered]</digest>\n" );
0904 
0905   emit debugMessage ( "XML IN: " + msg );
0906   emit incomingXML ( msg );
0907 }
0908 
0909 void JabberClient::slotOutgoingXML ( const QString & _msg )
0910 {
0911   QString msg = _msg;
0912 
0913   msg = msg.replace( QRegExp( "<password>[^<]*</password>\n" ), "<password>[Filtered]</password>\n" );
0914   msg = msg.replace( QRegExp( "<digest>[^<]*</digest>\n" ), "<digest>[Filtered]</digest>\n" );
0915 
0916   emit debugMessage ( "XML OUT: " + msg );
0917   emit outgoingXML ( msg );
0918 }
0919 
0920 void JabberClient::slotTLSHandshaken ()
0921 {
0922 
0923   emit debugMessage ( "TLS handshake done, testing certificate validity..." );
0924 
0925   // FIXME: in the future, this should be handled by KDE, not QCA
0926 
0927   QCA::TLS::IdentityResult identityResult = d->jabberTLS->peerIdentityResult();
0928   QCA::Validity            validityResult = d->jabberTLS->peerCertificateValidity();
0929 
0930   if ( identityResult == QCA::TLS::Valid && validityResult == QCA::ValidityGood )
0931   {
0932     emit debugMessage ( "Identity and certificate valid, continuing." );
0933 
0934     // valid certificate, continue
0935     d->jabberTLSHandler->continueAfterHandshake ();
0936   }
0937   else
0938   {
0939     emit debugMessage ( "Certificate is not valid, asking user what to do next." );
0940 
0941     // certificate is not valid, query the user
0942     if ( ignoreTLSWarnings () )
0943     {
0944       emit debugMessage ( "We are supposed to ignore TLS warnings, continuing." );
0945       d->jabberTLSHandler->continueAfterHandshake ();
0946     }
0947 
0948     emit tlsWarning ( identityResult, validityResult );
0949   }
0950 
0951 }
0952 
0953 void JabberClient::continueAfterTLSWarning ()
0954 {
0955 
0956   if ( d->jabberTLSHandler )
0957   {
0958     d->jabberTLSHandler->continueAfterHandshake ();
0959   }
0960 
0961 }
0962 
0963 void JabberClient::slotCSNeedAuthParams ( bool user, bool pass, bool realm )
0964 {
0965   emit debugMessage ( "Sending auth credentials..." );
0966 
0967   if ( user )
0968   {
0969     d->jabberClientStream->setUsername ( jid().node () );
0970   }
0971 
0972   if ( pass )
0973   {
0974     d->jabberClientStream->setPassword ( d->password );
0975   }
0976 
0977   if ( realm )
0978   {
0979     d->jabberClientStream->setRealm ( jid().domain () );
0980   }
0981 
0982   d->jabberClientStream->continueAfterParams ();
0983 
0984 }
0985 
0986 void JabberClient::slotCSAuthenticated ()
0987 {
0988   qCDebug(JABBER_PROTOCOL_LOG);
0989   emit debugMessage ( "Connected to Jabber server." );
0990 
0991   /*
0992    * Determine local IP address.
0993    * FIXME: This is ugly!
0994    */
0995   if ( localAddress().isEmpty () )
0996   {
0997     // code for Iris-type bytestreams
0998     ByteStream *irisByteStream = d->jabberClientConnector->stream();
0999     if ( irisByteStream->inherits ( "BSocket" ) || irisByteStream->inherits ( "XMPP::BSocket" ) )
1000     {
1001       d->localAddress = ( (BSocket *)irisByteStream )->address().toString ();
1002     }
1003 
1004     // code for the KDE-type bytestream
1005     JabberByteStream *kdeByteStream = dynamic_cast<JabberByteStream*>(d->jabberClientConnector->stream());
1006     if ( kdeByteStream )
1007     {
1008       d->localAddress = kdeByteStream->socket()->peerName();
1009     }
1010   }
1011 
1012   if ( fileTransfersEnabled () )
1013   {
1014     // setup file transfer
1015     addS5BServerAddress ( localAddress () );
1016     d->jabberClient->s5bManager()->setServer ( s5bServer () );
1017   }
1018 
1019   // start the client operation
1020   d->jabberClient->start ( jid().domain (), jid().node (), d->password, jid().resource () );
1021 
1022   emit connected ();
1023 }
1024 
1025 void JabberClient::slotCSDisconnected ()
1026 {
1027 
1028   /* FIXME:
1029    * We should delete the XMPP::Client instance here,
1030    * but timers etc prevent us from doing so. (Psi does
1031    * not like to be deleted from a slot).
1032    */
1033 
1034   emit debugMessage ( "Disconnected, freeing up file transfer port..." );
1035 
1036   // delete local address from S5B server
1037   removeS5BServerAddress ( localAddress () );
1038 
1039   emit csDisconnected ();
1040 
1041 }
1042 
1043 void JabberClient::slotCSWarning ( int warning )
1044 {
1045 
1046   emit debugMessage ( "Client stream warning." );
1047 
1048   /*
1049    * FIXME: process all other warnings
1050    */
1051   switch ( warning )
1052   {
1053     //case XMPP::ClientStream::WarnOldVersion:
1054     case XMPP::ClientStream::WarnNoTLS:
1055       if ( forceTLS () )
1056       {
1057         disconnect ();
1058         emit error ( NoTLS );
1059         return;
1060       }
1061       break;
1062   }
1063 
1064   d->jabberClientStream->continueAfterWarning ();
1065 
1066 }
1067 
1068 void JabberClient::slotCSError ( int error )
1069 {
1070 
1071   emit debugMessage ( "Client stream error." );
1072 
1073   emit csError ( error );
1074 
1075 }
1076 
1077 void JabberClient::slotRosterRequestFinished ( bool success, int /*statusCode*/, const QString &/*statusString*/ )
1078 {
1079 
1080   emit rosterRequestFinished ( success );
1081 
1082 }
1083 
1084 void JabberClient::slotIncomingFileTransfer ()
1085 {
1086 
1087   emit incomingFileTransfer ();
1088 
1089 }
1090 
1091 void JabberClient::slotNewContact ( const XMPP::RosterItem &item )
1092 {
1093 
1094   emit newContact ( item );
1095 
1096 }
1097 
1098 void JabberClient::slotContactDeleted ( const RosterItem &item )
1099 {
1100 
1101   emit contactDeleted ( item );
1102 
1103 }
1104 
1105 void JabberClient::slotContactUpdated ( const RosterItem &item )
1106 {
1107 
1108   emit contactUpdated ( item );
1109 
1110 }
1111 
1112 void JabberClient::slotResourceAvailable ( const Jid &jid, const Resource &resource )
1113 {
1114 
1115   emit resourceAvailable ( jid, resource );
1116 
1117 }
1118 
1119 void JabberClient::slotResourceUnavailable ( const Jid &jid, const Resource &resource )
1120 {
1121 
1122   emit resourceUnavailable ( jid, resource );
1123 
1124 }
1125 
1126 void JabberClient::slotReceivedMessage ( const Message &message )
1127 {
1128 
1129   emit messageReceived ( message );
1130 
1131 }
1132 
1133 void JabberClient::slotGroupChatJoined ( const Jid &jid )
1134 {
1135 
1136   emit groupChatJoined ( jid );
1137 
1138 }
1139 
1140 void JabberClient::slotGroupChatLeft ( const Jid &jid )
1141 {
1142 
1143   emit groupChatLeft ( jid );
1144 
1145 }
1146 
1147 void JabberClient::slotGroupChatPresence ( const Jid &jid, const Status &status)
1148 {
1149 
1150   emit groupChatPresence ( jid, status );
1151 
1152 }
1153 
1154 void JabberClient::slotGroupChatError ( const Jid &jid, int error, const QString &reason)
1155 {
1156 
1157   emit groupChatError ( jid, error, reason );
1158 
1159 }
1160 
1161 void JabberClient::slotSubscription(const XMPP::Jid& jid, const QString& type)
1162 {
1163 
1164   emit subscription ( jid, type );
1165 
1166 }
1167 
1168 #include "moc_jabberclient.cpp"