26
#include"psiaccount.h"
28
#include<qinputdialog.h>
32
#include<qmessagebox.h>
33
#include<qguardedptr.h>
34
#include<qapplication.h>
35
#include<qpushbutton.h>
37
#include<qobjectlist.h>
46
//#include"xmpp_client.h"
47
//#include"xmpp_stream.h"
48
//#include"xmpp_message.h"
49
#include"xmpp_tasks.h"
50
#include"xmpp_jidlink.h"
52
#include"filetransfer.h"
53
#include"accountdlg.h"
54
#include"changepwdlg.h"
55
#include"xmlconsole.h"
59
#include"contactview.h"
60
#include"groupchatdlg.h"
63
#include"adduserdlg.h"
64
#include"historydlg.h"
65
#include"servicesdlg.h"
69
#include"passphrasedlg.h"
70
#include"vcardfactory.h"
72
#include"sslcertdlg.h"
75
#include"fancylabel.h"
76
#include"iconwidget.h"
78
#include"filetransdlg.h"
26
#include <QFileDialog>
27
#include <qinputdialog.h>
29
#include <qmessagebox.h>
31
#include <qapplication.h>
32
#include <qpushbutton.h>
37
#include <qfileinfo.h>
43
#include "psiaccount.h"
44
#include "psiiconset.h"
47
#include "xmpp_tasks.h"
48
#include "xmpp_xmlcommon.h"
50
#include "filetransfer.h"
51
#include "pgpkeydlg.h"
52
#include "psioptions.h"
54
#include "httpauthmanager.h"
56
#include "applicationinfo.h"
57
#include "pgptransaction.h"
58
#include "accountmanagedlg.h"
59
#include "changepwdlg.h"
60
#include "xmlconsole.h"
65
#include "privacymanager.h"
66
#include "rosteritemexchangetask.h"
68
#include "contactview.h"
72
#include "tunecontroller.h"
74
#include "groupchatdlg.h"
75
#include "statusdlg.h"
77
#include "adduserdlg.h"
78
#include "historydlg.h"
79
#include "capsmanager.h"
80
#include "registrationdlg.h"
81
#include "searchdlg.h"
84
#include "accountmodifydlg.h"
85
#include "passphrasedlg.h"
86
#include "voicecaller.h"
87
#include "voicecalldlg.h"
89
#include "jinglevoicecaller.h"
92
#include "googleftmanager.h"
94
#include "pepmanager.h"
95
#include "serverinfomanager.h"
97
#include "wbmanager.h"
99
#include "bookmarkmanager.h"
100
#include "vcardfactory.h"
102
#include "sslcertdlg.h"
104
#include "qwextend.h"
105
#include "geolocation.h"
106
#include "physicallocation.h"
107
#include "psipopup.h"
109
#include "translationmanager.h"
110
#include "iconwidget.h"
111
#include "filetransdlg.h"
112
#include "systeminfo.h"
114
#include "ahcommanddlg.h"
115
#include "mucjoindlg.h"
116
#include "ahcservermanager.h"
119
#include "certutil.h"
121
#include "psicontactlist.h"
124
#include "pluginmanager.h"
82
129
#if defined(Q_WS_MAC) && defined(HAVE_GROWL)
83
130
#include "psigrowlnotifier.h"
89
136
typedef int socklen_t;
91
#include<sys/socket.h>
92
#include<netinet/in.h>
138
#include <sys/socket.h>
139
#include <netinet/in.h>
95
//----------------------------------------------------------------------------
97
//----------------------------------------------------------------------------
98
AccountLabel::AccountLabel(PsiAccount *_pa, QWidget *par, bool smode)
103
setFrameStyle( QFrame::Panel | QFrame::Sunken );
106
connect(pa, SIGNAL(updatedAccount()), this, SLOT(updateName()));
107
connect(pa, SIGNAL(destroyed()), this, SLOT(deleteMe()));
110
AccountLabel::~AccountLabel()
114
void AccountLabel::updateName()
116
setText(simpleMode ? pa->name() : pa->nameWithJid());
119
void AccountLabel::deleteMe()
125
//----------------------------------------------------------------------------
127
//----------------------------------------------------------------------------
128
static int transid = 0;
129
class PGPTransaction::Private
142
using namespace XMPP;
140
PGPTransaction::PGPTransaction(OpenPGP::Engine *pgp)
141
:OpenPGP::Request(pgp)
147
PGPTransaction::~PGPTransaction()
152
int PGPTransaction::id() const
157
void PGPTransaction::setMessage(const Message &m)
162
const Message & PGPTransaction::message() const
167
const QDomElement & PGPTransaction::xml() const
172
void PGPTransaction::setXml(const QDomElement &e)
177
Jid PGPTransaction::jid() const
182
void PGPTransaction::setJid(const Jid &j)
187
150
//----------------------------------------------------------------------------
188
151
// BlockTransportPopup -- blocks popups on transport status changes
189
152
//----------------------------------------------------------------------------
313
265
Status lastStatus, origStatus;
314
266
bool nickFromVCard;
315
QString cur_pgpSecretKeyID;
316
QPtrList<Message> messageQueue;
267
QCA::PGPKey cur_pgpSecretKey;
268
QList<Message*> messageQueue;
317
269
BlockTransportPopupList *blockTransportPopupList;
271
PrivacyManager* privacyManager;
272
CapsManager* capsManager;
273
RosterItemExchangeTask* rosterItemExchangeTask;
280
AHCServerManager* ahcManager;
281
RCSetStatusServer* rcSetStatusServer;
282
RCSetOptionsServer* rcSetOptionsServer;
283
RCForwardServer* rcForwardServer;
321
286
AvatarFactory* avatarFactory;
324
PassphraseDlg *ppdlg;
325
QGuardedPtr<OpenPGP::Request> ppreq;
327
QPtrList<GCContact> gcbank;
289
VoiceCaller* voiceCaller;
292
// Google file transfer manager
293
GoogleFTManager* googleFTManager;
298
WbManager* wbManager;
302
ServerInfoManager* serverInfoManager;
303
PEPManager* pepManager;
306
BookmarkManager* bookmarkManager;
309
HttpAuthManager* httpAuthManager;
311
QList<GCContact*> gcbank;
328
312
QStringList groupchats;
330
314
AdvancedConnector *conn;
331
315
ClientStream *stream;
333
317
QCATLSHandler *tlsHandler;
334
QPtrList<QCA::Cert> certList;
373
355
account->enabledChanged();
374
356
account->updatedAccount();
366
QList<item_dialog2*> dialogList;
368
bool compareJids(const Jid& j1, const Jid& j2, bool compareResource) const
370
return j1.compare(j2, compareResource);
374
QWidget* findDialog(const QMetaObject& mo, const Jid& jid, bool compareResource) const
376
foreach(item_dialog2* i, dialogList) {
377
if (mo.cast(i->widget) && compareJids(i->jid, jid, compareResource))
383
void findDialogs(const QMetaObject& mo, const Jid& jid, bool compareResource, QList<void*>* list) const
385
foreach(item_dialog2* i, dialogList) {
386
if (mo.cast(i->widget) && compareJids(i->jid, jid, compareResource))
387
list->append(i->widget);
391
void dialogRegister(QWidget* w, const Jid& jid)
393
connect(w, SIGNAL(destroyed(QObject*)), SLOT(forceDialogUnregister(QObject*)));
394
item_dialog2 *i = new item_dialog2;
397
dialogList.append(i);
400
void dialogUnregister(QWidget* w)
402
foreach(item_dialog2 *i, dialogList) {
403
if (i->widget == w) {
404
dialogList.removeAll(i);
411
void deleteDialogList()
413
while (!dialogList.isEmpty()) {
414
item_dialog2* i = dialogList.takeFirst();
415
ChatDlg* chat = qobject_cast<ChatDlg*>(i->widget);
417
if (psi->isChatTabbed(chat)) {
418
psi->getManagingTabs(chat)->close(chat);
427
void forceDialogUnregister(QObject* obj)
429
dialogUnregister(static_cast<QWidget*>(obj));
378
PsiAccount::PsiAccount(const UserAccount &acc, PsiCon *parent)
433
PsiAccount::PsiAccount(const UserAccount &acc, PsiContactList *parent)
381
436
d = new Private( this );
437
d->contactList = parent;
438
d->psi = parent->psi();
439
d->options = PsiOptions::instance();
385
442
d->userCounter = 0;
388
d->avatarFactory = new AvatarFactory(this);
443
d->avatarFactory = 0;
391
445
d->blockTransportPopupList = new BlockTransportPopupList();
393
447
d->doPopups = true;
431
475
d->tlsHandler = 0;
433
d->certList.setAutoDelete(true);
434
477
d->usingSSL = false;
436
479
// create Jabber::Client
437
480
d->client = new Client;
438
d->client->setOSName(getOSName());
439
d->client->setTimeZone(getTZString(), getTZOffset());
440
d->client->setClientName(PROG_NAME);
441
d->client->setClientVersion(PROG_VERSION);
481
d->client->setOSName(SystemInfo::instance()->os());
482
d->client->setTimeZone(SystemInfo::instance()->timezoneString(), SystemInfo::instance()->timezoneOffset());
483
d->client->setClientName(ApplicationInfo::name());
484
d->client->setClientVersion(ApplicationInfo::version());
485
d->client->setCapsNode(ApplicationInfo::capsNode());
486
d->client->setCapsVersion(ApplicationInfo::capsVersion());
488
DiscoItem::Identity identity;
489
identity.category = "client";
490
identity.type = "pc";
491
identity.name = ApplicationInfo::name();
492
d->client->setIdentity(identity);
494
QStringList features;
495
features << "http://jabber.org/protocol/commands";
496
features << "http://jabber.org/protocol/rosterx";
497
features << "http://jabber.org/protocol/muc";
498
features << "jabber:x:data";
499
d->client->setFeatures(Features(features));
443
501
d->client->setFileTransferEnabled(true);
503
setSendChatState(option.messageEvents);
445
505
//connect(d->client, SIGNAL(connected()), SLOT(client_connected()));
446
506
//connect(d->client, SIGNAL(handshaken()), SLOT(client_handshaken()));
457
517
connect(d->client, SIGNAL(resourceUnavailable(const Jid &, const Resource &)), SLOT(client_resourceUnavailable(const Jid &, const Resource &)));
458
518
connect(d->client, SIGNAL(presenceError(const Jid &, int, const QString &)), SLOT(client_presenceError(const Jid &, int, const QString &)));
459
519
connect(d->client, SIGNAL(messageReceived(const Message &)), SLOT(client_messageReceived(const Message &)));
460
connect(d->client, SIGNAL(subscription(const Jid &, const QString &)), SLOT(client_subscription(const Jid &, const QString &)));
520
connect(d->client, SIGNAL(subscription(const Jid &, const QString &, const QString&)), SLOT(client_subscription(const Jid &, const QString &, const QString&)));
461
521
connect(d->client, SIGNAL(debugText(const QString &)), SLOT(client_debugText(const QString &)));
462
522
connect(d->client, SIGNAL(groupChatJoined(const Jid &)), SLOT(client_groupChatJoined(const Jid &)));
463
523
connect(d->client, SIGNAL(groupChatLeft(const Jid &)), SLOT(client_groupChatLeft(const Jid &)));
464
524
connect(d->client, SIGNAL(groupChatPresence(const Jid &, const Status &)), SLOT(client_groupChatPresence(const Jid &, const Status &)));
465
525
connect(d->client, SIGNAL(groupChatError(const Jid &, int, const QString &)), SLOT(client_groupChatError(const Jid &, int, const QString &)));
466
connect(d->client, SIGNAL(incomingJidLink()), SLOT(client_incomingJidLink()));
467
526
connect(d->client->fileTransferManager(), SIGNAL(incomingReady()), SLOT(client_incomingFileTransfer()));
529
d->privacyManager = new PrivacyManager(d->client->rootTask());
532
d->capsManager = new CapsManager(d->client);
533
d->capsManager->setEnabled(option.useCaps);
535
// Roster item exchange task
536
d->rosterItemExchangeTask = new RosterItemExchangeTask(d->client->rootTask());
537
connect(d->rosterItemExchangeTask,SIGNAL(rosterItemExchange(const Jid&, const RosterExchangeItems&)),SLOT(actionRecvRosterExchange(const Jid&,const RosterExchangeItems&)));
469
539
// contactprofile context
470
540
d->cp = new ContactProfile(this, acc.name, d->psi->contactView());
471
541
connect(d->cp, SIGNAL(actionDefault(const Jid &)),SLOT(actionDefault(const Jid &)));
472
542
connect(d->cp, SIGNAL(actionRecvEvent(const Jid &)),SLOT(actionRecvEvent(const Jid &)));
473
543
connect(d->cp, SIGNAL(actionSendMessage(const Jid &)),SLOT(actionSendMessage(const Jid &)));
474
connect(d->cp, SIGNAL(actionSendMessage(const JidList &)),SLOT(actionSendMessage(const JidList &)));
544
connect(d->cp, SIGNAL(actionSendMessage(const QList<XMPP::Jid> &)),SLOT(actionSendMessage(const QList<XMPP::Jid> &)));
475
545
connect(d->cp, SIGNAL(actionSendUrl(const Jid &)),SLOT(actionSendUrl(const Jid &)));
476
546
connect(d->cp, SIGNAL(actionRemove(const Jid &)),SLOT(actionRemove(const Jid &)));
477
547
connect(d->cp, SIGNAL(actionRename(const Jid &, const QString &)),SLOT(actionRename(const Jid &, const QString &)));
487
561
connect(d->cp, SIGNAL(actionAdd(const Jid &)),SLOT(actionAdd(const Jid &)));
488
562
connect(d->cp, SIGNAL(actionGroupAdd(const Jid &, const QString &)),SLOT(actionGroupAdd(const Jid &, const QString &)));
489
563
connect(d->cp, SIGNAL(actionGroupRemove(const Jid &, const QString &)),SLOT(actionGroupRemove(const Jid &, const QString &)));
490
connect(d->cp, SIGNAL(actionTest(const Jid &)),SLOT(actionTest(const Jid &)));
564
connect(d->cp, SIGNAL(actionVoice(const Jid &)),SLOT(actionVoice(const Jid &)));
491
565
connect(d->cp, SIGNAL(actionSendFile(const Jid &)),SLOT(actionSendFile(const Jid &)));
492
566
connect(d->cp, SIGNAL(actionSendFiles(const Jid &, const QStringList&)),SLOT(actionSendFiles(const Jid &, const QStringList&)));
567
connect(d->cp, SIGNAL(actionExecuteCommand(const Jid &, const QString&)),SLOT(actionExecuteCommand(const Jid &, const QString&)));
568
connect(d->cp, SIGNAL(actionExecuteCommandSpecific(const Jid &, const QString&)),SLOT(actionExecuteCommandSpecific(const Jid &, const QString&)));
569
connect(d->cp, SIGNAL(actionSetMood()),SLOT(actionSetMood()));
570
connect(d->cp, SIGNAL(actionSetAvatar()),SLOT(actionSetAvatar()));
571
connect(d->cp, SIGNAL(actionUnsetAvatar()),SLOT(actionUnsetAvatar()));
493
572
connect(d->cp, SIGNAL(actionDisco(const Jid &, const QString &)),SLOT(actionDisco(const Jid &, const QString &)));
494
573
connect(d->cp, SIGNAL(actionInvite(const Jid &, const QString &)),SLOT(actionInvite(const Jid &, const QString &)));
495
574
connect(d->cp, SIGNAL(actionAssignKey(const Jid &)),SLOT(actionAssignKey(const Jid &)));
496
575
connect(d->cp, SIGNAL(actionUnassignKey(const Jid &)),SLOT(actionUnassignKey(const Jid &)));
577
// Initialize server info stuff
578
d->serverInfoManager = new ServerInfoManager(d->client);
579
connect(d->serverInfoManager,SIGNAL(featuresChanged()),SLOT(serverFeaturesChanged()));
581
// Initialize PubSub stuff
582
d->pepManager = new PEPManager(d->client, d->serverInfoManager);
583
connect(d->pepManager,SIGNAL(itemPublished(const Jid&, const QString&, const PubSubItem&)),SLOT(itemPublished(const Jid&, const QString&, const PubSubItem&)));
584
connect(d->pepManager,SIGNAL(itemRetracted(const Jid&, const QString&, const PubSubRetraction&)),SLOT(itemRetracted(const Jid&, const QString&, const PubSubRetraction&)));
585
d->pepAvailable = false;
588
// Initialize Whiteboard manager
589
d->wbManager = new WbManager(d->client, this);
593
d->avatarFactory = new AvatarFactory(this);
594
d->self.setAvatarFactory(avatarFactory());
597
d->bookmarkManager = new BookmarkManager(d->client);
601
connect(d->psi->tuneController(), SIGNAL(stopped()), SLOT(tuneStopped()));
602
connect(d->psi->tuneController(), SIGNAL(playing(const Tune&)),SLOT(tunePlaying(const Tune&)));
606
d->httpAuthManager = new HttpAuthManager(d->client->rootTask());
607
connect(d->httpAuthManager, SIGNAL(confirmationRequest(const PsiHttpAuthRequest &)), SLOT(incomingHttpAuthRequest(const PsiHttpAuthRequest &)));
609
// Initialize Adhoc Commands server
610
d->ahcManager = new AHCServerManager(this);
611
d->rcSetStatusServer = 0;
612
d->rcSetOptionsServer = 0;
613
d->rcForwardServer = 0;
614
setRCEnabled(option.useRC);
618
PluginManager::instance()->addAccount(this, d->client);
622
if(PsiOptions::instance()->getOption("options.html.chat.render").toBool())
623
d->client->addExtension("html",Features("http://jabber.org/protocol/xhtml-im"));
498
625
// restore cached roster
499
626
for(Roster::ConstIterator it = acc.roster.begin(); it != acc.roster.end(); ++it)
500
627
client_rosterItemUpdated(*it);
512
639
setUserAccount(acc);
641
d->contactList->link(this);
515
642
connect(d->psi, SIGNAL(emitOptionsUpdate()), SLOT(optionsUpdate()));
516
connect(d->psi, SIGNAL(pgpToggled(bool)), SLOT(pgpToggled(bool)));
517
connect(d->psi, SIGNAL(pgpKeysUpdated()), SLOT(pgpKeysUpdated()));
643
//connect(d->psi, SIGNAL(pgpToggled(bool)), SLOT(pgpToggled(bool)));
644
connect(&PGPUtil::instance(), SIGNAL(pgpKeysUpdated()), SLOT(pgpKeysUpdated()));
519
646
d->psi->setToggles(d->acc.tog_offline, d->acc.tog_away, d->acc.tog_agents, d->acc.tog_hidden,d->acc.tog_self);
521
648
d->setEnabled(d->acc.opt_enabled);
524
if(d->acc.opt_auto && d->acc.opt_enabled)
525
setStatus(Status("", "", d->acc.priority));
650
// Listen to the capabilities manager
651
connect(capsManager(),SIGNAL(capsChanged(const Jid&)),SLOT(capsChanged(const Jid&)));
527
653
//printf("PsiAccount: [%s] loaded\n", name().latin1());
528
654
d->xmlConsole = new XmlConsole(this);
529
655
if(option.xmlConsoleOnLogin && d->acc.opt_enabled) {
530
656
this->showXmlConsole();
531
657
d->xmlConsole->enable();
662
d->voiceCaller = new JingleVoiceCaller(this);
664
if (d->voiceCaller) {
665
d->client->addExtension("voice-v1", Features(QString("http://www.google.com/xmpp/protocol/voice/v1")));
666
connect(d->voiceCaller,SIGNAL(incoming(const Jid&)),SLOT(incomingVoiceCall(const Jid&)));
670
d->googleFTManager = new GoogleFTManager(client());
671
d->client->addExtension("share-v1", Features(QString("http://www.google.com/xmpp/protocol/share/v1")));
672
connect(d->googleFTManager,SIGNAL(incomingFileTransfer(GoogleFileTransfer*)),SLOT(incomingGoogleFileTransfer(GoogleFileTransfer*)));
676
if (d->options->getOption("options.extended-presence.notify").toBool()) {
677
QStringList pepNodes;
678
pepNodes += "http://jabber.org/protocol/mood+notify";
679
pepNodes += "http://jabber.org/protocol/tune+notify";
680
pepNodes += "http://jabber.org/protocol/physloc+notify";
681
pepNodes += "http://jabber.org/protocol/geoloc+notify";
682
pepNodes += "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify";
683
d->client->addExtension("ep-notify",Features(pepNodes));
534
686
// load event queue from disk
535
687
QTimer::singleShot(0, d, SLOT(loadQueue()));
538
690
PsiAccount::~PsiAccount()
693
#warning "Uncomment these"
696
// PluginManager::instance()->removeClient(this);
698
// nuke all related dialogs
541
702
QString str = name();
543
d->messageQueue.clear();
545
// nuke all related dialogs
704
while (!d->messageQueue.isEmpty())
705
delete d->messageQueue.takeFirst();
548
707
d->psi->ftdlg()->killTransfers(this);
710
delete d->voiceCaller;
712
delete d->ahcManager;
714
delete d->privacyManager;
715
delete d->capsManager;
716
delete d->pepManager;
717
delete d->serverInfoManager;
721
delete d->bookmarkManager;
551
722
delete d->client;
723
delete d->httpAuthManager;
553
725
delete d->eventQueue;
726
delete d->avatarFactory;
555
728
delete d->blockTransportPopupList;
557
d->psi->unlink(this);
730
d->contactList->unlink(this);
560
733
//printf("PsiAccount: [%s] unloaded\n", str.latin1());
759
948
QString PsiAccount::nameWithJid() const
761
return (name() + " (" + jid().full() + ')');
764
static QCA::Cert readCertXml(const QDomElement &e)
767
// there should be one child data tag
768
QDomElement data = e.elementsByTagName("data").item(0).toElement();
770
cert.fromDER(Base64::stringToArray(data.text()));
774
static QPtrList<QCA::Cert> getRootCerts(const QStringList &stores)
776
QPtrList<QCA::Cert> list;
778
for(QStringList::ConstIterator dit = stores.begin(); dit != stores.end(); ++dit) {
782
dir.setNameFilter("*.xml");
783
QStringList entries = dir.entryList();
784
for(QStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it) {
785
QFile f(dir.filePath(*it));
786
if(!f.open(IO_ReadOnly))
789
bool ok = doc.setContent(&f);
794
QDomElement base = doc.documentElement();
795
if(base.tagName() != "store")
797
QDomNodeList cl = base.elementsByTagName("certificate");
800
for(int n = 0; n < (int)cl.count(); ++n) {
801
QCA::Cert *cert = new QCA::Cert(readCertXml(cl.item(n).toElement()));
950
return (name() + " (" + JIDUtil::toString(jid(),true) + ')');
953
// Moved out of constructor to have all accounts loaded
954
// when we ask for passwords.
955
void PsiAccount::autoLogin()
958
if(d->acc.opt_auto && d->acc.opt_enabled)
959
setStatus(Status("", "", d->acc.priority));
816
962
// logs on with the active account settings
878
1019
d->conn = new AdvancedConnector;
880
QStringList certDirs;
881
certDirs += g.pathHome + "/certs";
882
certDirs += g.pathBase + "/certs";
883
d->certList = getRootCerts(certDirs);
1020
if(d->acc.ssl != UserAccount::SSL_No && QCA::isSupported("tls")) {
885
1021
d->tls = new QCA::TLS;
886
d->tls->setCertificateStore(d->certList);
1022
d->tls->setTrustedCertificates(CertUtil::allCertificates());
887
1023
d->tlsHandler = new QCATLSHandler(d->tls);
1024
d->tlsHandler->setXMPPCertCheck(true);
888
1025
connect(d->tlsHandler, SIGNAL(tlsHandshaken()), SLOT(tls_handshaken()));
890
1027
d->conn->setProxy(p);
891
d->conn->setOptHostPort(host, port);
892
d->conn->setOptSSL(d->acc.opt_ssl);
1029
d->conn->setOptHostPort(host, port);
1030
d->conn->setOptSSL(d->acc.ssl == UserAccount::SSL_Legacy);
1032
else if (QCA::isSupported("tls")) {
1033
d->conn->setOptProbe(d->acc.legacy_ssl_probe && d->acc.ssl != UserAccount::SSL_No);
894
1036
d->stream = new ClientStream(d->conn, d->tlsHandler);
895
d->stream->setOldOnly(true);
896
d->stream->setAllowPlain(d->acc.opt_plain);
1037
d->stream->setRequireMutualAuth(d->acc.req_mutual_auth);
1038
d->stream->setSSFRange(d->acc.security_level,256);
1039
d->stream->setAllowPlain(d->acc.allow_plain);
1040
d->stream->setCompress(d->acc.opt_compress);
1041
d->stream->setLang(TranslationManager::instance()->currentXMLLanguage());
897
1042
if(d->acc.opt_keepAlive)
898
1043
d->stream->setNoopTime(55000); // prevent NAT timeouts every minute
900
1045
d->stream->setNoopTime(0);
901
1046
connect(d->stream, SIGNAL(connected()), SLOT(cs_connected()));
902
connect(d->stream, SIGNAL(securityLayerActivated(int)), SLOT(cs_securityLayerActivated()));
1047
connect(d->stream, SIGNAL(securityLayerActivated(int)), SLOT(cs_securityLayerActivated(int)));
903
1048
connect(d->stream, SIGNAL(needAuthParams(bool, bool, bool)), SLOT(cs_needAuthParams(bool, bool, bool)));
904
1049
connect(d->stream, SIGNAL(authenticated()), SLOT(cs_authenticated()));
905
connect(d->stream, SIGNAL(connectionClosed()), SLOT(cs_connectionClosed()));
1050
connect(d->stream, SIGNAL(connectionClosed()), SLOT(cs_connectionClosed()), Qt::QueuedConnection);
906
1051
connect(d->stream, SIGNAL(delayedCloseFinished()), SLOT(cs_delayedCloseFinished()));
907
1052
connect(d->stream, SIGNAL(warning(int)), SLOT(cs_warning(int)));
908
connect(d->stream, SIGNAL(error(int)), SLOT(cs_error(int)));
1053
connect(d->stream, SIGNAL(error(int)), SLOT(cs_error(int)), Qt::QueuedConnection);
910
Jid j = d->jid.withResource(d->acc.resource);
1055
Jid j = d->jid.withResource((d->acc.opt_automatic_resource ? localHostName() : d->acc.resource ));
911
1056
d->client->connectToServer(d->stream, j);
954
1107
void PsiAccount::tls_handshaken()
956
QCA::Cert cert = d->tls->peerCertificate();
957
int r = d->tls->certificateValidityResult();
1109
QCA::Certificate cert = d->tls->peerCertificateChain().primary();
1110
int r = d->tls->peerIdentityResult();
1111
if (r == QCA::TLS::Valid && !d->tlsHandler->certMatchesHostname()) r = QCA::TLS::HostMismatch;
958
1112
if(r != QCA::TLS::Valid && !d->acc.opt_ignoreSSLWarnings) {
959
QString str = resultToString(r);
961
int n = QMessageBox::warning(0,
962
tr("%1: Server Authentication").arg(name()),
963
tr("The %1 certificate failed the authenticity test.").arg(d->jid.host()) + '\n' + tr("Reason: %1").arg(str),
966
tr("&Cancel"), 0, 2);
968
SSLCertDlg::showCert(cert, r);
1113
QCA::Validity validity = d->tls->peerCertificateValidity();
1114
QString str = CertUtil::resultToString(r,validity);
1115
QMessageBox msgBox(QMessageBox::Warning,
1116
(d->psi->contactList()->enabledAccounts().count() > 1 ? QString("%1: ").arg(name()) : "") + tr("Server Authentication"),
1117
tr("The %1 certificate failed the authenticity test.").arg(d->jid.host()) + '\n' + tr("Reason: %1.").arg(str));
1118
QPushButton *detailsButton = msgBox.addButton(tr("&Details..."), QMessageBox::ActionRole);
1119
QPushButton *continueButton = msgBox.addButton(tr("Co&ntinue"), QMessageBox::AcceptRole);
1120
QPushButton *cancelButton = msgBox.addButton(QMessageBox::Cancel);
1121
msgBox.setDefaultButton(detailsButton);
1122
msgBox.setResult(QDialog::Accepted);
1124
connect(this, SIGNAL(disconnected()), &msgBox, SLOT(reject()));
1125
connect(this, SIGNAL(reconnecting()), &msgBox, SLOT(reject()));
1127
while (msgBox.result() != QDialog::Rejected) {
1129
if (msgBox.clickedButton() == detailsButton) {
1130
msgBox.setResult(QDialog::Accepted);
1131
SSLCertDlg::showCert(cert, r, validity);
1133
else if (msgBox.clickedButton() == continueButton) {
971
1134
d->tlsHandler->continueAfterHandshake();
1137
else if (msgBox.clickedButton() == cancelButton) {
1141
else { // msgBox was hidden because connection was closed
981
1147
d->tlsHandler->continueAfterHandshake();
1150
void PsiAccount::showCert()
1152
if (!d->tls || !d->tls->isHandshaken()) return;
1153
QCA::Certificate cert = d->tls->peerCertificateChain().primary();
1154
int r = d->tls->peerIdentityResult();
1155
if (r == QCA::TLS::Valid && !d->tlsHandler->certMatchesHostname()) r = QCA::TLS::HostMismatch;
1156
QCA::Validity validity = d->tls->peerCertificateValidity();
1157
SSLCertDlg::showCert(cert, r, validity);
984
1161
void PsiAccount::cs_connected()
986
1163
// get IP address
987
1164
ByteStream *bs = d->conn->stream();
988
1165
if(bs->inherits("BSocket") || bs->inherits("XMPP::BSocket")) {
989
//#if QT_VERSION >= 0x030300
990
1166
d->localAddress = ((BSocket *)bs)->address();
992
int s = ((BSocket *)bs)->socket();
993
struct sockaddr addr;
994
socklen_t size = sizeof(struct sockaddr);
995
if(!getsockname(s, &addr, &size)) {
997
struct sockaddr_in *in = (struct sockaddr_in *)&addr;
998
memcpy(&ipv4addr, &in->sin_addr.s_addr, 4);
999
ipv4addr = ntohl(ipv4addr);
1000
d->localAddress = QHostAddress(ipv4addr);
1006
void PsiAccount::cs_securityLayerActivated()
1012
void PsiAccount::cs_needAuthParams(bool, bool pass, bool)
1170
void PsiAccount::cs_securityLayerActivated(int layer)
1172
if ((layer == ClientStream::LayerSASL) && (d->stream->saslSSF() <= 1)) {
1173
// integrity protected only
1180
void PsiAccount::cs_needAuthParams(bool user, bool pass, bool realm)
1183
if (d->acc.customAuth && !d->acc.authid.isEmpty())
1184
d->stream->setUsername(d->acc.authid);
1186
d->stream->setUsername(d->jid.user());
1188
else if (d->acc.customAuth && !d->acc.authid.isEmpty())
1189
qWarning("Custom authentication user not used");
1015
1192
d->stream->setPassword(d->acc.pass);
1195
if (d->acc.customAuth && !d->acc.realm.isEmpty()) {
1196
d->stream->setRealm(d->acc.realm);
1199
d->stream->setRealm(d->jid.domain());
1202
else if (d->acc.customAuth && !d->acc.realm.isEmpty())
1203
qWarning("Custom authentication realm not used");
1205
if(d->acc.customAuth)
1206
d->stream->setAuthzid(d->jid.bare());
1016
1207
d->stream->continueAfterParams();
1019
1210
void PsiAccount::cs_authenticated()
1212
//printf("PsiAccount: [%s] authenticated\n", name().latin1());
1021
1213
d->conn->changePollInterval(10); // for http poll, slow down after login
1023
d->client->start(d->jid.host(), d->jid.user(), d->acc.pass, d->acc.resource);
1025
//printf("PsiAccount: [%s] authenticated\n", name().latin1());
1215
// Update our jid (if necessary)
1216
if (!d->stream->jid().isEmpty()) {
1217
d->jid = d->stream->jid().bare();
1220
QString resource = (d->stream->jid().resource().isEmpty() ? ( d->acc.opt_automatic_resource ? localHostName() : d->acc.resource) : d->stream->jid().resource());
1222
d->client->start(d->jid.host(), d->jid.user(), d->acc.pass, resource);
1223
if (!d->stream->old()) {
1224
JT_Session *j = new JT_Session(d->client->rootTask());
1225
connect(j,SIGNAL(finished()),SLOT(sessionStart_finished()));
1233
void PsiAccount::sessionStart_finished()
1235
JT_Session *j = (JT_Session*)sender();
1236
if ( j->success() ) {
1245
void PsiAccount::sessionStarted()
1248
d->voiceCaller->initialize();
1027
1250
// flag roster for delete
1028
1251
UserListIt it(d->userList);
1514
void PsiAccount::serverFeaturesChanged()
1516
setPEPAvailable(d->serverInfoManager->hasPEP());
1519
void PsiAccount::setPEPAvailable(bool b)
1521
if (d->pepAvailable == b)
1524
d->pepAvailable = b;
1528
if (b && !d->client->extensions().contains("ep")) {
1529
QStringList pepNodes;
1530
pepNodes += "http://jabber.org/protocol/mood";
1531
pepNodes += "http://jabber.org/protocol/tune";
1532
pepNodes += "http://jabber.org/protocol/physloc";
1533
pepNodes += "http://jabber.org/protocol/geoloc";
1534
pepNodes += "http://www.xmpp.org/extensions/xep-0084.html#ns-data";
1535
pepNodes += "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata";
1536
d->client->addExtension("ep",Features(pepNodes));
1537
setStatusActual(d->loginStatus);
1539
else if (!b && d->client->extensions().contains("ep")) {
1540
d->client->removeExtension("ep");
1541
setStatusActual(d->loginStatus);
1544
// Publish current tune information
1545
if (b && d->psi->tuneController() && d->options->getOption("options.extended-presence.tune.publish").toBool()) {
1546
Tune current = d->psi->tuneController()->currentTune();
1547
if (!current.isNull())
1548
publishTune(current);
1553
void PsiAccount::getBookmarks_success(const QList<URLBookmark>&, const QList<ConferenceBookmark>& conferences)
1555
QObject::disconnect(d->bookmarkManager,SIGNAL(getBookmarks_success(const QList<URLBookmark>&, const QList<ConferenceBookmark>&)),this,SLOT(getBookmarks_success(const QList<URLBookmark>&, const QList<ConferenceBookmark>&)));
1557
foreach(ConferenceBookmark c, conferences) {
1558
if (!findDialog<GCMainDlg*>(Jid(c.jid().userHost())) && c.autoJoin()) {
1559
QString nick = c.nick();
1561
nick = d->jid.node();
1563
MUCJoinDlg *w = new MUCJoinDlg(psi(), this);
1564
w->le_host->setText(c.jid().domain());
1565
w->le_room->setText(c.jid().node());
1566
w->le_nick->setText(nick);
1567
w->le_pass->setText(c.password());
1574
void PsiAccount::incomingHttpAuthRequest(const PsiHttpAuthRequest &req)
1576
HttpAuthEvent *e = new HttpAuthEvent(req, this);
1261
1580
void PsiAccount::client_rosterItemAdded(const RosterItem &r)
1263
1582
if ( r.isPush() && r.name().isEmpty() && option.autoResolveNicksOnAdd ) {
1264
1583
// automatically resolve nickname from vCard, if newly added item doesn't have any
1265
VCardFactory::getVCard(r.jid(), d->client->rootTask(), this, SLOT(resolveContactName()));
1584
VCardFactory::instance()->getVCard(r.jid(), d->client->rootTask(), this, SLOT(resolveContactName()));
2165
void PsiAccount::capsChanged(const Jid& j)
2170
QString name = capsManager()->clientName(j);
2171
QString version = (name.isEmpty() ? QString() : capsManager()->clientVersion(j));
2173
foreach(UserListItem *u, findRelevant(j)) {
2174
UserResourceList::Iterator rit = u->userResourceList().find(j.resource());
2175
bool found = (rit == u->userResourceList().end()) ? false: true;
2178
(*rit).setClient(name,version,"");
2183
void PsiAccount::tuneStopped()
2185
if (loggedIn() && d->options->getOption("options.extended-presence.tune.publish").toBool()) {
2186
publishTune(Tune());
2190
void PsiAccount::tunePlaying(const Tune& tune)
2192
if (loggedIn() && d->options->getOption("options.extended-presence.tune.publish").toBool()) {
2197
void PsiAccount::publishTune(const Tune& tune)
2199
QDomDocument* doc = d->client->rootTask()->doc();
2200
QDomElement t = doc->createElement("tune");
2201
t.setAttribute("xmlns", "http://jabber.org/protocol/tune");
2202
if (!tune.artist().isEmpty())
2203
t.appendChild(textTag(doc, "artist", tune.artist()));
2204
if (!tune.name().isEmpty())
2205
t.appendChild(textTag(doc, "title", tune.name()));
2206
if (!tune.album().isEmpty())
2207
t.appendChild(textTag(doc, "source", tune.album()));
2208
if (!tune.track().isEmpty())
2209
t.appendChild(textTag(doc, "track", tune.track()));
2210
if (tune.time() != 0)
2211
t.appendChild(textTag(doc, "length", QString::number(tune.time())));
2214
d->pepManager->publish("http://jabber.org/protocol/tune",PubSubItem("current",t));
1792
2217
void PsiAccount::secondsIdle(int x)
1794
2219
if(!loggedIn())
1865
2294
d->psi->playSound(str);
1868
QWidget *PsiAccount::dialogFind(const char *className, const Jid &j)
1870
QPtrListIterator<item_dialog2> it(d->dialogList);
1871
for(item_dialog2 *i; (i = it.current()); ++it) {
1872
// does the classname and jid match?
1873
if(i->className == className && i->jid.compare(j)) {
2297
QString PsiAccount::localHostName()
2299
QString hostname = QHostInfo::localHostName();
2300
int i = hostname.indexOf('.');
2302
return hostname.left(hostname.indexOf('.'));
2307
bool PsiAccount::validRosterExchangeItem(const RosterExchangeItem& item)
2309
if (item.action() == RosterExchangeItem::Add) {
2310
return (d->client->roster().find(item.jid(),true) == d->client->roster().end());
2312
else if (item.action() == RosterExchangeItem::Delete) {
2313
LiveRoster::ConstIterator i = d->client->roster().find(item.jid(),true);
2314
if (i == d->client->roster().end())
2317
foreach(QString group, item.groups()) {
2318
if (!(*i).groups().contains(group))
2323
else if (item.action() == RosterExchangeItem::Modify) {
2330
QWidget* PsiAccount::findDialog(const QMetaObject& mo, const Jid& jid, bool compareResource) const
2332
return d->findDialog(mo, jid, compareResource);
2335
void PsiAccount::findDialogs(const QMetaObject& mo, const Jid& jid, bool compareResource, QList<void*>* list) const
2337
d->findDialogs(mo, jid, compareResource, list);
1880
2340
void PsiAccount::dialogRegister(QWidget *w, const Jid &j)
1882
item_dialog2 *i = new item_dialog2;
1884
i->className = w->className();
1886
d->dialogList.append(i);
2342
d->dialogRegister(w, j);
1889
2345
void PsiAccount::dialogUnregister(QWidget *w)
1891
QPtrListIterator<item_dialog2> it(d->dialogList);
1892
for(item_dialog2 *i; (i = it.current()); ++it) {
1893
if(i->widget == w) {
1894
d->dialogList.removeRef(i);
2347
d->dialogUnregister(w);
1900
2350
void PsiAccount::deleteAllDialogs()
1902
QPtrListIterator<item_dialog2> it(d->dialogList);
1903
for(item_dialog2 *i; (i = it.current());)
1905
d->dialogList.clear();
2352
delete d->xmlConsole;
2353
d->deleteDialogList();
1908
2356
bool PsiAccount::checkConnected(QWidget *par)
2095
2545
notifyOnlineOk = true;
2098
void PsiAccount::slotClientVersionFinished()
2100
JT_ClientVersion *j = (JT_ClientVersion *)sender();
2102
QPtrList<UserListItem> list = findRelavent(j->jid());
2103
QPtrListIterator<UserListItem> it(list);
2104
for(UserListItem *u; (u = it.current()); ++it) {
2105
UserResourceList::Iterator rit = u->userResourceList().find(j->jid().resource());
2106
bool found = (rit == u->userResourceList().end()) ? false: true;
2110
(*rit).setClient(j->name(),j->version(),j->os());
2115
d->cp->updateSelf(*u);
2118
d->cp->updateEntry(*u);*/
2123
QPtrList<UserListItem> PsiAccount::findRelavent(const Jid &j) const
2125
QPtrList<UserListItem> list;
2549
void PsiAccount::itemRetracted(const Jid& j, const QString& n, const PubSubRetraction& item)
2552
if (n == "http://jabber.org/protocol/tune") {
2554
foreach(UserListItem* u, findRelevant(j)) {
2555
// FIXME: try to find the right resource using JEP-33 'replyto'
2556
//UserResourceList::Iterator rit = u->userResourceList().find(<resource>);
2557
//bool found = (rit == u->userResourceList().end()) ? false: true;
2559
// (*rit).setTune(tune);
2560
u->setTune(QString());
2564
else if (n == "http://jabber.org/protocol/mood") {
2565
foreach(UserListItem* u, findRelevant(j)) {
2570
else if (n == "http://jabber.org/protocol/geoloc") {
2571
// FIXME: try to find the right resource using JEP-33 'replyto'
2572
// see tune case above
2573
foreach(UserListItem* u, findRelevant(j)) {
2574
u->setGeoLocation(GeoLocation());
2578
else if (n == "http://jabber.org/protocol/physloc") {
2579
// FIXME: try to find the right resource using JEP-33 'replyto'
2580
// see tune case above
2581
foreach(UserListItem* u, findRelevant(j)) {
2582
u->setPhysicalLocation(PhysicalLocation());
2588
void PsiAccount::itemPublished(const Jid& j, const QString& n, const PubSubItem& item)
2591
if (n == "http://jabber.org/protocol/tune") {
2593
QDomElement element = item.payload();
2598
e = findSubTag(element, "artist", &found);
2600
tune += e.text() + " - ";
2602
e = findSubTag(element, "title", &found);
2606
foreach(UserListItem* u, findRelevant(j)) {
2607
// FIXME: try to find the right resource using JEP-33 'replyto'
2608
//UserResourceList::Iterator rit = u->userResourceList().find(<resource>);
2609
//bool found = (rit == u->userResourceList().end()) ? false: true;
2611
// (*rit).setTune(tune);
2616
else if (n == "http://jabber.org/protocol/mood") {
2617
Mood mood(item.payload());
2618
foreach(UserListItem* u, findRelevant(j)) {
2623
else if (n == "http://jabber.org/protocol/geoloc") {
2624
// FIXME: try to find the right resource using JEP-33 'replyto'
2625
// see tune case above
2626
GeoLocation geoloc(item.payload());
2627
foreach(UserListItem* u, findRelevant(j)) {
2628
u->setGeoLocation(geoloc);
2632
else if (n == "http://jabber.org/protocol/physloc") {
2633
// FIXME: try to find the right resource using JEP-33 'replyto'
2634
// see tune case above
2635
PhysicalLocation physloc(item.payload());
2636
foreach(UserListItem* u, findRelevant(j)) {
2637
u->setPhysicalLocation(physloc);
2643
QList<UserListItem*> PsiAccount::findRelevant(const Jid &j) const
2645
QList<UserListItem*> list;
2128
2648
if(j.compare(d->self.jid(), false))
2129
2649
list.append(&d->self);
2131
QPtrListIterator<UserListItem> it(d->userList);
2132
for(UserListItem *u; (u = it.current()); ++it) {
2651
foreach(UserListItem* u, d->userList) {
2133
2652
if(!u->jid().compare(j, false))
2136
2655
if(!u->jid().resource().isEmpty()) {
2137
2656
if(u->jid().resource() != j.resource())
2659
// skip status changes from muc participants
2660
// if the MUC somehow got into userList.
2661
if (!j.resource().isEmpty() && d->groupchats.contains(j.bare())) continue;
2140
2663
list.append(u);
2201
2718
connect(w, SIGNAL(aReply(const Jid &, const QString &, const QString &, const QString &)), SLOT(dj_composeMessage(const Jid &, const QString &, const QString &, const QString &)));
2202
2719
connect(w, SIGNAL(aAuth(const Jid &)), SLOT(dj_addAuth(const Jid &)));
2203
2720
connect(w, SIGNAL(aDeny(const Jid &)), SLOT(dj_deny(const Jid &)));
2721
connect(w, SIGNAL(aHttpConfirm(const PsiHttpAuthRequest &)), SLOT(dj_confirmHttpAuth(const PsiHttpAuthRequest &)));
2722
connect(w, SIGNAL(aHttpDeny(const PsiHttpAuthRequest &)), SLOT(dj_denyHttpAuth(const PsiHttpAuthRequest &)));
2723
connect(w, SIGNAL(aRosterExchange(const RosterExchangeItems &)), SLOT(dj_rosterExchange(const RosterExchangeItems &)));
2204
2724
connect(d->psi, SIGNAL(emitOptionsUpdate()), w, SLOT(optionsUpdate()));
2205
2725
connect(this, SIGNAL(updateContact(const Jid &)), w, SLOT(updateContact(const Jid &)));
2726
connect(w, SIGNAL(aFormSubmit(const XData&, const QString&, const Jid&)), SLOT(dj_formSubmit(const XData&, const QString&, const Jid&)));
2727
connect(w, SIGNAL(aFormCancel(const XData&, const QString&, const Jid&)), SLOT(dj_formCancel(const XData&, const QString&, const Jid&)));
2271
2797
StatusSetDlg *w = new StatusSetDlg(this, makeStatus(x, ""));
2272
connect(w, SIGNAL(set(const Status &)), SLOT(setStatus(const Status &)));
2798
connect(w, SIGNAL(set(const XMPP::Status &, bool)), SLOT(setStatus(const XMPP::Status &, bool)));
2278
void PsiAccount::actionTest(const Jid &j)
2280
UserListItem *u = find(j);
2284
if(j.resource().isEmpty()) {
2285
if(u->isAvailable())
2286
j2.setResource((*u->userResourceList().priority()).name());
2289
//S5BConnection *c = new S5BConnection(d->client->s5bManager());
2290
//c->connectToJid(j2, d->client->s5bManager()->genUniqueSID(j2));
2291
JLTestDlg *w = new JLTestDlg(j2, this);
2295
void PsiAccount::actionSendFile(const Jid &j)
2298
actionSendFiles(j, l);
2301
void PsiAccount::actionSendFiles(const Jid &j, const QStringList& l)
2804
void PsiAccount::actionVoice(const Jid &j)
2806
Q_ASSERT(voiceCaller() != NULL);
2809
if (j.resource().isEmpty()) {
2811
UserListItem *u = find(j);
2813
const UserResourceList &rl = u->userResourceList();
2814
for (UserResourceList::ConstIterator it = rl.begin(); it != rl.end() && !found; ++it) {
2815
if (capsManager()->features(j.withResource((*it).name())).canVoice()) {
2816
jid = j.withResource((*it).name());
2829
VoiceCallDlg* vc = new VoiceCallDlg(jid,voiceCaller());
2834
void PsiAccount::sendFiles(const Jid& j, const QStringList& l, bool direct)
2304
2837
if(j.resource().isEmpty()) {
2312
2845
if (!l.isEmpty()) {
2313
2846
for (QStringList::ConstIterator f = l.begin(); f != l.end(); ++f ) {
2314
2847
QStringList fl(*f);
2315
FileRequestDlg *w = new FileRequestDlg(j2, d->psi, this, fl);
2848
FileRequestDlg *w = new FileRequestDlg(j2, d->psi, this, fl, direct);
2320
FileRequestDlg *w = new FileRequestDlg(j2, d->psi, this, l);
2853
FileRequestDlg *w = new FileRequestDlg(j2, d->psi, this, l, direct);
2858
void PsiAccount::actionSendFile(const Jid &j)
2864
void PsiAccount::actionSendFiles(const Jid &j, const QStringList& l)
2869
void PsiAccount::actionExecuteCommand(const Jid& j, const QString& node)
2872
if(j.resource().isEmpty()) {
2873
UserListItem *u = find(j);
2874
if(u && u->isAvailable())
2875
j2.setResource((*u->userResourceList().priority()).name());
2878
actionExecuteCommandSpecific(j2, node);
2881
void PsiAccount::actionExecuteCommandSpecific(const Jid& j, const QString& node)
2883
if (node.isEmpty()) {
2884
AHCommandDlg *w = new AHCommandDlg(this,j);
2888
AHCommandDlg::executeCommand(d->client,j,node);
2892
void PsiAccount::actionSetMood()
2894
MoodDlg *w = new MoodDlg(this);
2898
void PsiAccount::actionSetAvatar()
2901
if(option.lastPath.isEmpty())
2902
option.lastPath = QDir::homeDirPath();
2903
QString str = QFileDialog::getOpenFileName(0,tr("Choose a file"),option.lastPath, tr("Images (*.png *.xpm *.jpg *.PNG *.XPM *.JPG)"));
2904
if(!str.isEmpty()) {
2907
QMessageBox::critical(0, tr("Error"), tr("The file specified does not exist."));
2910
option.lastPath = fi.dirPath();
2911
avatarFactory()->setSelfAvatar(str);
2917
void PsiAccount::actionUnsetAvatar()
2919
avatarFactory()->setSelfAvatar("");
2325
2922
void PsiAccount::actionDefault(const Jid &j)
3084
3839
openNextEvent(*u);
3842
int PsiAccount::forwardPendingEvents(const Jid &jid)
3844
QList<PsiEvent*> chatList;
3845
d->eventQueue->extractMessages(&chatList);
3846
foreach(PsiEvent* e, chatList) {
3847
MessageEvent *me = (MessageEvent *) e;
3848
Message m = me->message();
3850
AddressList oFrom = m.findAddresses(Address::OriginalFrom);
3851
AddressList oTo = m.findAddresses(Address::OriginalTo);
3853
if (oFrom.count() == 0)
3854
m.addAddress(Address(Address::OriginalFrom, m.from()));
3855
if (oTo.count() == 0)
3856
m.addAddress(Address(Address::OriginalTo, m.to()));
3858
m.setTimeStamp(m.timeStamp(), true);
3862
d->client->sendMessage(m);
3864
// update the eventdlg
3865
UserListItem *u = find(e->jid());
3868
// update the contact
3872
updateReadNext(u->jid());
3874
return chatList.count();
3087
3877
void PsiAccount::updateReadNext(const Jid &j)
3089
3879
// update eventdlg's read-next
3090
EventDlg *w = (EventDlg *)dialogFind("EventDlg", j);
3880
EventDlg *w = findDialog<EventDlg*>(j);
3882
PsiIcon *nextAnim = 0;
3093
3883
int nextAmount = d->eventQueue->count(j);
3094
3884
if(nextAmount > 0)
3095
nextAnim = is->event2icon(d->eventQueue->peek(j));
3885
nextAnim = PsiIconset::instance()->event2icon(d->eventQueue->peek(j));
3096
3886
w->updateReadNext(nextAnim, nextAmount);
3231
4024
d->groupchats += str;
3233
4026
GCMainDlg *w = new GCMainDlg(this, j);
4027
w->setPassword(d->client->groupChatPassword(j.user(),j.host()));
3234
4028
connect(w, SIGNAL(aSend(const Message &)), SLOT(dj_sendMessage(const Message &)));
3235
4029
connect(d->psi, SIGNAL(emitOptionsUpdate()), w, SLOT(optionsUpdate()));
3239
bool PsiAccount::groupChatJoin(const QString &host, const QString &room, const QString &nick)
4033
bool PsiAccount::groupChatJoin(const QString &host, const QString &room, const QString &nick, const QString& pass, bool nohistory)
3241
return d->client->groupChatJoin(host, room, nick);
4036
return d->client->groupChatJoin(host, room, nick, pass, 0);
4038
Status s = d->loginStatus;
4040
return d->client->groupChatJoin(host, room, nick, pass, d->options->getOption("options.muc.context.maxchars").toInt(),d->options->getOption("options.muc.context.maxstanzas").toInt(),d->options->getOption("options.muc.context.seconds").toInt(),s);
3244
4044
void PsiAccount::groupChatChangeNick(const QString &host, const QString &room, const QString& nick, const Status &s)
3396
4196
return d->self.name();
3399
void PsiAccount::pgpToggled(bool b)
3401
QString oldkey = d->cur_pgpSecretKeyID;
3405
d->cur_pgpSecretKeyID = d->acc.pgpSecretKeyID;
3408
d->cur_pgpSecretKeyID = "";
3411
if(oldkey != d->cur_pgpSecretKeyID) {
3413
// resend status if online
3415
setStatusDirect(d->loginStatus);
4199
//void PsiAccount::pgpToggled(bool b)
4201
// QCA::PGPKey oldkey = d->cur_pgpSecretKey;
4205
// d->cur_pgpSecretKey = d->acc.pgpSecretKey;
4208
// d->cur_pgpSecretKey = QCA::PGPKey();
4211
// if(!PGPUtil::instance().equals(oldkey,d->cur_pgpSecretKey)) {
4213
// // resend status if online
4215
// setStatusDirect(d->loginStatus);
3419
4219
void PsiAccount::pgpKeysUpdated()
3421
OpenPGP::KeyList list = d->psi->pgp()->publicKeys();
3423
4221
// are there any sigs that need verifying?
3424
QPtrListIterator<UserListItem> it(d->userList);
3425
for(UserListItem *u; (u = it.current()); ++it) {
4222
foreach(UserListItem* u, d->userList) {
3426
4223
UserResourceList &rl = u->userResourceList();
3427
4224
for(UserResourceList::Iterator rit = rl.begin(); rit != rl.end(); ++rit) {
3428
4225
UserResource &r = *rit;
3429
if(!r.status().xsigned().isEmpty() && r.pgpVerifyStatus() == OpenPGP::VerifyNoKey) {
3430
bool haveKey = false;
3431
QString key = r.publicKeyID();
3432
for(OpenPGP::KeyList::ConstIterator kit = list.begin(); kit != list.end(); ++kit) {
3433
if((*kit).keyID() == key) {
4226
if(!r.status().xsigned().isEmpty() && r.pgpVerifyStatus() == QCA::SecureMessageSignature::NoKey) {
4227
QCA::KeyStoreEntry e = PGPUtil::instance().getPublicKeyStoreEntry(r.publicKeyID());
3439
4229
tryVerify(u, &r);
4235
void PsiAccount::trySignPresence()
4237
QCA::SecureMessageKey skey;
4238
skey.setPGPSecretKey(d->cur_pgpSecretKey);
4239
QByteArray plain = d->loginStatus.status().utf8();
4241
PGPTransaction *t = new PGPTransaction(new QCA::OpenPGP());
4242
connect(t, SIGNAL(finished()), SLOT(pgp_signFinished()));
4243
t->setFormat(QCA::SecureMessage::Ascii);
4245
t->startSign(QCA::SecureMessage::Detached);
4250
void PsiAccount::pgp_signFinished()
4252
PGPTransaction *t = (PGPTransaction*) sender();
4254
Status s = d->loginStatus;
4255
s.setXSigned(PGPUtil::instance().stripHeaderFooter(QString(t->signature())));
4259
// Clear passphrase from cache
4260
if (t->errorCode() == QCA::SecureMessage::ErrorPassphrase) {
4261
QCA::KeyStoreEntry ke = PGPUtil::instance().getSecretKeyStoreEntry(d->cur_pgpSecretKey.keyId());
4263
PGPUtil::instance().removePassphrase(ke.id());
4266
QMessageBox::critical(0, tr("Error"), tr("There was an error trying to sign your status.\nReason: %1.").arg(PGPUtil::instance().messageErrorString(t->errorCode())));
3445
4275
void PsiAccount::verifyStatus(const Jid &j, const Status &s)
3447
PGPTransaction *t = new PGPTransaction(d->psi->pgp());
4277
PGPTransaction *t = new PGPTransaction(new QCA::OpenPGP());
3449
connect(t, SIGNAL(finished(bool)), SLOT(pgp_verifyFinished(bool)));
3450
QCString cs = s.status().utf8();
3451
QByteArray buf(cs.length());
3452
memcpy(buf.data(), cs.data(), buf.size());
3453
t->verify(buf, OpenPGP::addHeaderFooter(s.xsigned(), 1));
3455
//printf("%s: verifying\n", j.full().latin1());
3458
void PsiAccount::trySignPresence()
3460
OpenPGP::Request *r = new OpenPGP::Request(d->psi->pgp());
3461
connect(r, SIGNAL(finished(bool)), SLOT(pgp_signFinished(bool)));
3462
connect(r, SIGNAL(needPassphrase()), SLOT(pgp_needPassphrase()));
3463
QCString cs = d->loginStatus.status().utf8();
3464
QByteArray buf(cs.length());
3465
memcpy(buf.data(), cs.data(), buf.size());
3466
r->sign(buf, d->cur_pgpSecretKeyID);
3469
void PsiAccount::pgp_needPassphrase()
3471
OpenPGP::Request *r = (OpenPGP::Request *)sender();
3474
if(pgp_passphrases.contains(d->cur_pgpSecretKeyID))
3475
r->submitPassphrase(pgp_passphrases[d->cur_pgpSecretKeyID]);
3480
void PsiAccount::promptPassphrase()
3483
d->ppdlg->unblock();
3485
PassphraseDlg *w = new PassphraseDlg(0);
3486
connect(w, SIGNAL(submitPassphrase(const QString &)), SLOT(submitPassphrase(const QString &)));
3487
connect(w, SIGNAL(rejectPassphrase()), SLOT(rejectPassphrase()));
3488
w->setCaption(tr("%1: OpenPGP Passphrase").arg(name()));
3495
void PsiAccount::submitPassphrase(const QString &pp)
3497
d->ppreq->submitPassphrase(pp);
3500
void PsiAccount::rejectPassphrase()
3506
d->ppreq->deleteLater();
3511
void PsiAccount::pgp_signFinished(bool ok)
3513
OpenPGP::Request *r = (OpenPGP::Request *)sender();
3514
bool badPassphrase = r->badPassphrase();
3517
sig = r->signature();
3519
pgp_passphrases[d->cur_pgpSecretKeyID] = d->ppdlg->passphrase();
3524
Status s = d->loginStatus;
3525
s.setXSigned(OpenPGP::stripHeaderFooter(sig));
3530
pgp_passphrases.erase(d->cur_pgpSecretKeyID);
3531
QMessageBox::information(d->ppdlg ? d->ppdlg : 0, CAP(tr("Error")), tr("You entered a bad passphrase. Please try again."));
3532
QTimer::singleShot(0, this, SLOT(trySignPresence()));
3536
QMessageBox::information(d->ppdlg ? d->ppdlg : 0, CAP(tr("Error")), tr("There was an error during OpenPGP processing. Check your settings and try again."));
3541
// remove the dialog if it is there
3543
d->ppdlg->deleteLater();
3548
void PsiAccount::pgp_verifyFinished(bool b)
3550
PGPTransaction *t = (PGPTransaction *)sender();
4279
connect(t, SIGNAL(finished()), SLOT(pgp_verifyFinished()));
4280
t->startVerify(PGPUtil::instance().addHeaderFooter(s.xsigned(),1).utf8());
4281
t->update(s.status().utf8());
4286
void PsiAccount::pgp_verifyFinished()
4288
PGPTransaction *t = (PGPTransaction*) sender();
3552
4289
Jid j = t->jid();
3553
//printf("%s: verify complete\n", j.full().latin1());
3554
QPtrList<UserListItem> list = findRelavent(j);
3555
QPtrListIterator<UserListItem> it(list);
3556
for(UserListItem *u; (u = it.current()); ++it) {
4290
foreach(UserListItem *u, findRelevant(j)) {
3557
4291
UserResourceList::Iterator rit = u->userResourceList().find(j.resource());
3558
4292
bool found = (rit == u->userResourceList().end()) ? false: true;
3561
4295
UserResource &ur = *rit;
3564
//printf("vergood\n");
3565
ur.setPublicKeyID(t->keyID());
3566
ur.setPGPVerifyStatus(t->verifyResult());
3567
ur.setSigTimestamp(t->timestamp());
4297
QCA::SecureMessageSignature signer;
4299
signer = t->signer();
4301
ur.setPublicKeyID(signer.key().pgpPublicKey().keyId());
4302
ur.setPGPVerifyStatus(signer.identityResult());
4303
ur.setSigTimestamp(signer.timestamp());
3569
4305
// if the key doesn't match the assigned key, unassign it
3570
if(t->keyID() != u->publicKeyID())
4306
if(signer.key().pgpPublicKey().keyId() != u->publicKeyID())
3571
4307
u->setPublicKeyID("");
3574
//QMessageBox::information(0, "sig verify error", QString("error verifying [%1]").arg(u->jid().full()));
3575
ur.setPGPVerifyStatus(OpenPGP::VerifyError);
4310
ur.setPGPVerifyStatus(-1);
3578
//printf("updating [%s]\n", u->jid().full().latin1());
3587
4320
if(!ensureKey(_m.to()))
3589
QString key = findFirstRelavent(_m.to())->publicKeyID();
3591
PGPTransaction *pt = new PGPTransaction(d->psi->pgp());
3593
pt->setMessage(m); // keep a copy
3594
//QByteArray a = m.generateEncryptablePayload(d->client->doc());
3595
QCString cs = m.body().utf8();
3596
QByteArray a(cs.length());
3597
memcpy(a.data(), cs.data(), a.size());
3602
connect(pt, SIGNAL(finished(bool)), SLOT(pgp_finished(bool)));
3603
pt->encrypt(a, rcpt);
4323
QString keyID = findFirstRelevant(_m.to())->publicKeyID();
4324
QCA::KeyStoreEntry keyEntry = PGPUtil::instance().getPublicKeyStoreEntry(keyID);
4325
if (keyEntry.isNull())
4328
QCA::SecureMessageKey key;
4329
key.setPGPPublicKey(keyEntry.pgpPublicKey());
4331
PGPTransaction *t = new PGPTransaction(new QCA::OpenPGP());
4333
connect(t, SIGNAL(finished()), SLOT(pgp_encryptFinished()));
4334
t->setFormat(QCA::SecureMessage::Ascii);
4335
t->setRecipient(key);
4337
t->update(_m.body().utf8());
3608
void PsiAccount::pgp_finished(bool b)
4343
void PsiAccount::pgp_encryptFinished()
3610
4345
PGPTransaction *pt = (PGPTransaction *)sender();
3612
4346
int x = pt->id();
3613
if(pt->type() == OpenPGP::Encrypt) {
3615
Message m = pt->message();
3616
// log the message here, before we encrypt it
3617
if(d->acc.opt_log) {
3618
MessageEvent *me = new MessageEvent(m, this);
3619
me->setOriginLocal(true);
3620
me->setTimeStamp(QDateTime::currentDateTime());
3621
logEvent(m.to(), me);
3626
mwrap.setTo(m.to());
3627
mwrap.setType(m.type());
3628
QString enc = OpenPGP::stripHeaderFooter(pt->encrypted());
3629
mwrap.setBody(tr("[ERROR: This message is encrypted, and you are unable to decrypt it.]"));
3630
mwrap.setXEncrypted(enc);
3631
mwrap.setWasEncrypted(true);
3632
// FIXME: Should be done cleaner, with an extra method in Iris
3633
if (m.containsEvent(OfflineEvent)) mwrap.addEvent(OfflineEvent);
3634
if (m.containsEvent(DeliveredEvent)) mwrap.addEvent(DeliveredEvent);
3635
if (m.containsEvent(DisplayedEvent)) mwrap.addEvent(DisplayedEvent);
3636
if (m.containsEvent(ComposingEvent)) mwrap.addEvent(ComposingEvent);
3637
if (m.containsEvent(CancelEvent)) mwrap.addEvent(CancelEvent);
3638
dj_sendMessage(mwrap);
4349
Message m = pt->message();
4350
// log the message here, before we encrypt it
4351
if(d->acc.opt_log) {
4352
MessageEvent *me = new MessageEvent(m, this);
4353
me->setOriginLocal(true);
4354
me->setTimeStamp(QDateTime::currentDateTime());
4355
logEvent(m.to(), me);
3640
encryptedMessageSent(x, b);
4360
mwrap.setTo(m.to());
4361
mwrap.setType(m.type());
4362
QString enc = PGPUtil::instance().stripHeaderFooter(pt->read());
4363
mwrap.setBody(tr("[ERROR: This message is encrypted, and you are unable to decrypt it.]"));
4364
mwrap.setXEncrypted(enc);
4365
mwrap.setWasEncrypted(true);
4366
// FIXME: Should be done cleaner, with an extra method in Iris
4367
if (m.containsEvent(OfflineEvent)) mwrap.addEvent(OfflineEvent);
4368
if (m.containsEvent(DeliveredEvent)) mwrap.addEvent(DeliveredEvent);
4369
if (m.containsEvent(DisplayedEvent)) mwrap.addEvent(DisplayedEvent);
4370
if (m.containsEvent(ComposingEvent)) mwrap.addEvent(ComposingEvent);
4371
if (m.containsEvent(CancelEvent)) mwrap.addEvent(CancelEvent);
4372
mwrap.setChatState(m.chatState());
4373
dj_sendMessage(mwrap);
4375
emit encryptedMessageSent(x, pt->success(), pt->errorCode());
3643
4376
pt->deleteLater();
3646
void PsiAccount::pgp_decryptFinished(bool b)
3648
PGPTransaction *pt = (PGPTransaction *)sender();
4380
void PsiAccount::processEncryptedMessage(const Message &m)
4382
PGPTransaction *t = new PGPTransaction(new QCA::OpenPGP());
4384
connect(t, SIGNAL(finished()), SLOT(pgp_decryptFinished()));
4385
t->setFormat(QCA::SecureMessage::Ascii);
4387
t->update(PGPUtil::instance().addHeaderFooter(m.xencrypted(),0).utf8());
4392
void PsiAccount::pgp_decryptFinished()
4394
PGPTransaction *pt = (PGPTransaction*) sender();
3650
4395
bool tryAgain = false;
4396
if (pt->success()) {
3652
4397
Message m = pt->message();
3653
//if(m.applyDecryptedPayload(pt->decrypted(), d->client->doc()))
3654
QByteArray buf = pt->decrypted();
3655
QCString cs(buf.size()+1);
3656
memcpy(cs.data(), buf.data(), buf.size());
3657
QString str = QString::fromUtf8(cs);
4398
m.setBody(QString::fromUtf8(pt->read()));
3659
4399
m.setXEncrypted("");
3660
4400
m.setWasEncrypted(true);
3661
4401
processIncomingMessage(m);
3664
// QMessageBox::information(0, CAP(tr("Error")), tr("A successful decryption operation resulted in an invalid message, so it has been ignored."));
3669
4406
m.setTo(pt->message().from());
3670
4407
m.setType("error");
4408
if (!pt->message().id().isEmpty())
4409
m.setId(pt->message().id());
3671
4410
m.setBody(pt->message().body());
3673
err.condition = 500;
3674
err.text = "Unable to decrypt";
4411
m.setError(Stanza::Error(Stanza::Error::Wait,
4412
Stanza::Error::NotAcceptable,
4413
"Unable to decrypt"));
3676
4414
d->client->sendMessage(m);
3680
4418
pt->deleteLater();
3683
4421
processEncryptedMessageNext();
3690
void PsiAccount::processEncryptedMessage(const Message &m)
3693
PGPTransaction *t = new PGPTransaction(d->psi->pgp());
3694
t->setMessage(m); // keep a copy
3695
connect(t, SIGNAL(needPassphrase()), SLOT(pgp_needPassphrase()));
3696
connect(t, SIGNAL(finished(bool)), SLOT(pgp_decryptFinished(bool)));
3697
QString str = OpenPGP::addHeaderFooter(m.xencrypted(), 0);
3701
4428
void PsiAccount::processMessageQueue()
3703
4430
while(!d->messageQueue.isEmpty()) {
3704
Message *mp = d->messageQueue.getFirst();
4431
Message *mp = d->messageQueue.first();
3707
if(d->psi->pgp() && !mp->xencrypted().isEmpty()) {
4434
if(PGPUtil::instance().pgpAvailable() && !mp->xencrypted().isEmpty()) {
3708
4435
processEncryptedMessageNext();
3712
4439
processIncomingMessage(*mp);
3713
d->messageQueue.removeRef(mp);
4440
d->messageQueue.remove(mp);
3717
4445
void PsiAccount::processEncryptedMessageNext()
3719
4447
// 'peek' and try to process it
3720
Message *mp = d->messageQueue.getFirst();
4448
Message *mp = d->messageQueue.first();
3721
4449
processEncryptedMessage(*mp);
3724
4452
void PsiAccount::processEncryptedMessageDone()
3726
4454
// 'pop' the message
3727
Message *mp = d->messageQueue.getFirst();
3728
d->messageQueue.removeRef(mp);
4455
if (!d->messageQueue.isEmpty())
4456
delete d->messageQueue.takeFirst();
3730
4458
// do the rest of the queue
3731
4459
processMessageQueue();
3734
4462
void PsiAccount::optionsUpdate()
3736
4464
d->cp->updateEntry(d->self);
3739
QString PsiAccount::resultToString(int result)
3743
case QCA::TLS::NoCert:
3744
s = tr("The server did not present a certificate.");
3746
case QCA::TLS::Valid:
3747
s = tr("Certificate is valid.");
3749
case QCA::TLS::HostMismatch:
3750
s = tr("The hostname does not match the one the certificate was issued to.");
3752
case QCA::TLS::Rejected:
3753
s = tr("Root CA is marked to reject the specified purpose.");
3755
case QCA::TLS::Untrusted:
3756
s = tr("Certificate not trusted for the required purpose.");
3758
case QCA::TLS::SignatureFailed:
3759
s = tr("Invalid signature.");
3761
case QCA::TLS::InvalidCA:
3762
s = tr("Invalid CA certificate.");
3764
case QCA::TLS::InvalidPurpose:
3765
s = tr("Invalid certificate purpose.");
3767
case QCA::TLS::SelfSigned:
3768
s = tr("Certificate is self-signed.");
3770
case QCA::TLS::Revoked:
3771
s = tr("Certificate has been revoked.");
3773
case QCA::TLS::PathLengthExceeded:
3774
s = tr("Maximum certificate chain length exceeded.");
3776
case QCA::TLS::Expired:
3777
s = tr("Certificate has expired.");
3779
case QCA::TLS::Unknown:
3781
s = tr("General certificate validation error.");
4468
bool publish = d->options->getOption("options.extended-presence.tune.publish").toBool();
4469
if (!d->lastTune.isNull() && !publish) {
4470
publishTune(Tune());
4472
else if (d->lastTune.isNull() && publish) {
4473
Tune current = d->psi->tuneController()->currentTune();
4474
if (!current.isNull())
4475
publishTune(current);
4480
setSendChatState(option.messageEvents);
4482
// Remote Controlling
4483
setRCEnabled(option.useRC);
4485
// Roster item exchange
4486
d->rosterItemExchangeTask->setIgnoreNonRoster(option.ignoreNonRoster);
4489
d->capsManager->setEnabled(option.useCaps);
4493
void PsiAccount::setRCEnabled(bool b)
4495
if (b && !d->rcSetStatusServer) {
4496
d->rcSetStatusServer = new RCSetStatusServer(d->ahcManager);
4497
d->rcForwardServer = new RCForwardServer(d->ahcManager);
4498
d->rcSetOptionsServer = new RCSetOptionsServer(d->ahcManager, d->psi);
4500
else if (!b && d->rcSetStatusServer) {
4501
delete d->rcSetStatusServer;
4502
d->rcSetStatusServer = 0;
4503
delete d->rcForwardServer;
4504
d->rcForwardServer = 0;
4505
delete d->rcSetOptionsServer;
4506
d->rcSetOptionsServer = 0;
4510
void PsiAccount::setSendChatState(bool b)
4512
if (b && !d->client->extensions().contains("cs")) {
4513
d->client->addExtension("cs",Features("http://jabber.org/protocol/chatstates"));
4515
setStatusActual(d->loginStatus);
4517
else if (!b && d->client->extensions().contains("cs")) {
4518
d->client->removeExtension("cs");
4520
setStatusActual(d->loginStatus);
3787
4525
void PsiAccount::invokeGCMessage(const Jid &j)
3917
bool inList = false;
3918
OpenPGP::KeyList list = d->psi->pgp()->publicKeys();
3919
for(OpenPGP::KeyList::ConstIterator lit = list.begin(); lit != list.end(); ++lit) {
3920
const OpenPGP::Key &k = *lit;
3921
if(k.keyID() == akey) {
3927
if(akey.isEmpty() || !inList) {
4650
if(akey.isEmpty() || PGPUtil::instance().getPublicKeyStoreEntry(akey).isNull()) {
3928
4651
int n = QMessageBox::information(0, CAP(tr("No key")), tr(
3929
4652
"<p>Psi was unable to locate the OpenPGP key to use for <b>%1</b>.<br>"
3931
4654
"This can happen if you do not have the key that the contact is advertising "
3932
4655
"via signed presence, or if the contact is not advertising any key at all.</p>"
3933
).arg(u->jid().full()), tr("&Choose key manually"), tr("Do ¬hing"));
4656
).arg(JIDUtil::toString(u->jid(),true)), tr("&Choose key manually"), tr("Do ¬hing"));
3938
PGPKeyDlg *w = new PGPKeyDlg(list, akey, 0);
3939
w->setCaption(tr("Public Key: %1").arg(j.full()));
4662
PGPKeyDlg *w = new PGPKeyDlg(PGPKeyDlg::Public, akey, 0);
4663
w->setWindowTitle(tr("Public Key: %1").arg(JIDUtil::toString(j,true)));
3940
4664
int r = w->exec();
4665
QCA::KeyStoreEntry entry;
3942
4666
if(r == QDialog::Accepted)
4667
entry = w->keyStoreEntry();
3947
u->setPublicKeyID(key);
4671
u->setPublicKeyID(entry.pgpPublicKey().keyId());
3955
//----------------------------------------------------------------------------
3957
//----------------------------------------------------------------------------
3958
class KeyViewItem : public QListViewItem
3961
KeyViewItem(const QString &_keyID, QListView *par)
3970
class PGPKeyDlg::Private
3979
PGPKeyDlg::PGPKeyDlg(const OpenPGP::KeyList &list, const QString &choose, QWidget *parent, const char *name)
3980
:PGPKeyUI(parent, name, true)
3984
connect(lv_keys, SIGNAL(doubleClicked(QListViewItem *)), SLOT(qlv_doubleClicked(QListViewItem *)));
3985
connect(pb_ok, SIGNAL(clicked()), SLOT(do_accept()));
3986
connect(pb_cancel, SIGNAL(clicked()), SLOT(reject()));
3988
QListViewItem *isel = 0;
3989
for(OpenPGP::KeyList::ConstIterator it = list.begin(); it != list.end(); ++it) {
3990
const OpenPGP::Key &k = *it;
3991
KeyViewItem *i = new KeyViewItem(k.keyID(), lv_keys);
3992
//i->setPixmap(0, IconsetFactory::icon("psi/gpg-yes"));
3993
i->setText(0, k.keyID().right(8));
3994
i->setText(1, k.userID());
3996
if(!choose.isEmpty() && k.keyID() == choose) {
3997
lv_keys->setSelected(i, true);
4001
if(lv_keys->childCount() > 0 && !isel)
4002
lv_keys->setSelected(lv_keys->firstChild(), true);
4004
lv_keys->ensureItemVisible(isel);
4007
PGPKeyDlg::~PGPKeyDlg()
4012
QString PGPKeyDlg::keyID() const
4017
QString PGPKeyDlg::userID() const
4022
void PGPKeyDlg::qlv_doubleClicked(QListViewItem *i)
4024
lv_keys->setSelected(i, true);
4028
void PGPKeyDlg::do_accept()
4030
KeyViewItem *i = (KeyViewItem *)lv_keys->selectedItem();
4032
QMessageBox::information(this, tr("Error"), tr("Please select a key."));
4035
d->keyID = i->keyID;
4036
d->userID = i->text(1);
4678
ServerInfoManager* PsiAccount::serverInfoManager()
4680
return d->serverInfoManager;
4683
PEPManager* PsiAccount::pepManager()
4685
return d->pepManager;
4688
BookmarkManager* PsiAccount::bookmarkManager()
4690
return d->bookmarkManager;
4040
4693
#include "psiaccount.moc"