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"