2
* client.cpp - IM Client
3
* Copyright (C) 2003 Justin Karneges
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
#include"safedelete.h"
24
//! \class Client client.h
25
//! \brief Communicates with the Jabber network. Start here.
27
//! Client controls an active Jabber connection. It allows you to connect,
28
//! authenticate, manipulate the roster, and send / receive messages and
29
//! presence. It is the centerpiece of this library, and all Tasks must pass
32
//! For convenience, many Tasks are handled internally to Client (such as
33
//! JT_Auth). However, for accessing features beyond the basics provided by
34
//! Client, you will need to manually invoke Tasks. Fortunately, the
35
//! process is very simple.
37
//! The entire Task system is heavily founded on Qt. All Tasks have a parent,
38
//! except for the root Task, and are considered QObjects. By using Qt's RTTI
39
//! facilities (QObject::sender(), QObject::isA(), etc), you can use a
40
//! "fire and forget" approach with Tasks.
43
//! #include "client.h"
44
//! using namespace Jabber;
50
//! Session::Session()
52
//! client = new Client;
53
//! connect(client, SIGNAL(handshaken()), SLOT(clientHandshaken()));
54
//! connect(client, SIGNAL(authFinished(bool, int, const QString &)), SLOT(authFinished(bool, int, const QString &)));
55
//! client->connectToHost("jabber.org");
58
//! void Session::clientHandshaken()
60
//! client->authDigest("jabtest", "12345", "Psi");
63
//! void Session::authFinished(bool success, int, const QString &err)
66
//! printf("Login success!");
68
//! printf("Login failed. Here's why: %s\n", err.latin1());
73
#include<qobjectlist.h>
75
#include<qguardedptr.h>
76
#include"xmpp_tasks.h"
77
#include"xmpp_xmlcommon.h"
80
#include"xmpp_jidlink.h"
81
#include"filetransfer.h"
87
#include<qobjectlist.h>
89
#include"xmpp_stream.h"
90
#include"xmpp_tasks.h"
91
#include"xmpp_xmlcommon.h"
94
#include"xmpp_jidlink.h"
96
using namespace Jabber;*/
99
#define vsnprintf _vsnprintf
105
//----------------------------------------------------------------------------
107
//----------------------------------------------------------------------------
108
class Client::GroupChat
111
enum { Connecting, Connected, Closing };
118
class Client::ClientPrivate
123
ClientStream *stream;
127
QString host, user, pass, resource;
128
QString osname, tzname, clientName, clientVersion;
133
ResourceList resourceList;
136
JidLinkManager *jlman;
137
FileTransferManager *ftman;
139
QValueList<GroupChat> groupChatList;
143
Client::Client(QObject *par)
146
d = new ClientPrivate;
150
d->clientName = "N/A";
151
d->clientVersion = "0.0";
154
d->root = new Task(this, true);
158
d->s5bman = new S5BManager(this);
159
connect(d->s5bman, SIGNAL(incomingReady()), SLOT(s5b_incomingReady()));
161
d->ibbman = new IBBManager(this);
162
connect(d->ibbman, SIGNAL(incomingReady()), SLOT(ibb_incomingReady()));
164
d->jlman = new JidLinkManager(this);
182
void Client::connectToServer(ClientStream *s, const Jid &j, bool auth)
185
//connect(d->stream, SIGNAL(connected()), SLOT(streamConnected()));
186
//connect(d->stream, SIGNAL(handshaken()), SLOT(streamHandshaken()));
187
connect(d->stream, SIGNAL(error(int)), SLOT(streamError(int)));
188
//connect(d->stream, SIGNAL(sslCertificateReady(const QSSLCert &)), SLOT(streamSSLCertificateReady(const QSSLCert &)));
189
connect(d->stream, SIGNAL(readyRead()), SLOT(streamReadyRead()));
190
//connect(d->stream, SIGNAL(closeFinished()), SLOT(streamCloseFinished()));
191
connect(d->stream, SIGNAL(incomingXml(const QString &)), SLOT(streamIncomingXml(const QString &)));
192
connect(d->stream, SIGNAL(outgoingXml(const QString &)), SLOT(streamOutgoingXml(const QString &)));
194
d->stream->connectToServer(j, auth);
197
void Client::start(const QString &host, const QString &user, const QString &pass, const QString &_resource)
203
d->resource = _resource;
206
stat.setIsAvailable(false);
207
d->resourceList += Resource(resource(), stat);
209
JT_PushPresence *pp = new JT_PushPresence(rootTask());
210
connect(pp, SIGNAL(subscription(const Jid &, const QString &)), SLOT(ppSubscription(const Jid &, const QString &)));
211
connect(pp, SIGNAL(presence(const Jid &, const Status &)), SLOT(ppPresence(const Jid &, const Status &)));
213
JT_PushMessage *pm = new JT_PushMessage(rootTask());
214
connect(pm, SIGNAL(message(const Message &)), SLOT(pmMessage(const Message &)));
216
JT_PushRoster *pr = new JT_PushRoster(rootTask());
217
connect(pr, SIGNAL(roster(const Roster &)), SLOT(prRoster(const Roster &)));
219
new JT_ServInfo(rootTask());
224
void Client::setFileTransferEnabled(bool b)
228
d->ftman = new FileTransferManager(this);
238
FileTransferManager *Client::fileTransferManager() const
243
JidLinkManager *Client::jidLinkManager() const
248
S5BManager *Client::s5bManager() const
253
IBBManager *Client::ibbManager() const
258
bool Client::isActive() const
263
void Client::groupChatChangeNick(const QString &host, const QString &room, const QString &nick, const Status &_s)
265
Jid jid(room + "@" + host + "/" + nick);
266
for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
268
if(i.j.compare(jid, false)) {
272
s.setIsAvailable(true);
274
JT_Presence *j = new JT_Presence(rootTask());
283
bool Client::groupChatJoin(const QString &host, const QString &room, const QString &nick)
285
Jid jid(room + "@" + host + "/" + nick);
286
for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end();) {
288
if(i.j.compare(jid, false)) {
289
// if this room is shutting down, then free it up
290
if(i.status == GroupChat::Closing)
291
it = d->groupChatList.remove(it);
299
debug(QString("Client: Joined: [%1]\n").arg(jid.full()));
302
i.status = GroupChat::Connecting;
303
d->groupChatList += i;
305
JT_Presence *j = new JT_Presence(rootTask());
306
j->pres(jid, Status());
312
void Client::groupChatSetStatus(const QString &host, const QString &room, const Status &_s)
314
Jid jid(room + "@" + host);
316
for(QValueList<GroupChat>::ConstIterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
317
const GroupChat &i = *it;
318
if(i.j.compare(jid, false)) {
328
s.setIsAvailable(true);
330
JT_Presence *j = new JT_Presence(rootTask());
335
void Client::groupChatLeave(const QString &host, const QString &room)
337
Jid jid(room + "@" + host);
338
for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
341
if(!i.j.compare(jid, false))
344
i.status = GroupChat::Closing;
345
debug(QString("Client: Leaving: [%1]\n").arg(i.j.full()));
347
JT_Presence *j = new JT_Presence(rootTask());
349
s.setIsAvailable(false);
355
/*void Client::start()
357
if(d->stream->old()) {
358
// old has no activation step
368
void Client::close(bool)
372
for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
374
i.status = GroupChat::Closing;
376
JT_Presence *j = new JT_Presence(rootTask());
378
s.setIsAvailable(false);
384
d->stream->disconnect(this);
392
void Client::cleanup()
396
d->groupChatList.clear();
399
/*void Client::continueAfterCert()
401
d->stream->continueAfterCert();
404
void Client::streamConnected()
409
void Client::streamHandshaken()
414
void Client::streamError(int)
416
//StreamError e = err;
419
//if(!e.isWarning()) {
425
/*void Client::streamSSLCertificateReady(const QSSLCert &cert)
430
void Client::streamCloseFinished()
435
static QDomElement oldStyleNS(const QDomElement &e)
437
// find closest parent with a namespace
438
QDomNode par = e.parentNode();
439
while(!par.isNull() && par.namespaceURI().isNull())
440
par = par.parentNode();
441
bool noShowNS = false;
442
if(!par.isNull() && par.namespaceURI() == e.namespaceURI())
448
i = e.ownerDocument().createElement(e.tagName());
450
// i = e.ownerDocument().createElementNS(e.namespaceURI(), e.tagName());
453
QDomNamedNodeMap al = e.attributes();
454
for(x = 0; x < al.count(); ++x)
455
i.setAttributeNode(al.item(x).cloneNode().toAttr());
458
i.setAttribute("xmlns", e.namespaceURI());
461
QDomNodeList nl = e.childNodes();
462
for(x = 0; x < nl.count(); ++x) {
463
QDomNode n = nl.item(x);
465
i.appendChild(oldStyleNS(n.toElement()));
467
i.appendChild(n.cloneNode());
472
void Client::streamReadyRead()
475
QGuardedPtr<ClientStream> pstream = d->stream;
477
while(pstream && d->stream->stanzaAvailable()) {
478
Stanza s = d->stream->read();
480
QString out = s.toString();
481
debug(QString("Client: incoming: [\n%1]\n").arg(out));
484
QDomElement x = oldStyleNS(s.element());
489
void Client::streamIncomingXml(const QString &s)
492
if(str.at(str.length()-1) != '\n')
497
void Client::streamOutgoingXml(const QString &s)
500
if(str.at(str.length()-1) != '\n')
505
void Client::debug(const QString &str)
510
QString Client::genUniqueId()
513
s.sprintf("a%x", d->id_seed);
518
Task *Client::rootTask()
523
QDomDocument *Client::doc() const
528
void Client::distribute(const QDomElement &x)
530
if(x.hasAttribute("from")) {
531
Jid j(x.attribute("from"));
533
debug("Client: bad 'from' JID\n");
538
if(!rootTask()->take(x)) {
539
debug("Client: packet was ignored.\n");
543
static QDomElement addCorrectNS(const QDomElement &e)
548
/*QDomDocumentFragment frag = e.ownerDocument().createDocumentFragment();
549
QDomNodeList nl = e.childNodes();
550
for(x = 0; x < nl.count(); ++x)
551
frag.appendChild(nl.item(x).cloneNode());*/
553
// find closest xmlns
555
while(!n.isNull() && !n.toElement().hasAttribute("xmlns"))
558
if(n.isNull() || !n.toElement().hasAttribute("xmlns"))
559
ns = "jabber:client";
561
ns = n.toElement().attribute("xmlns");
564
QDomElement i = e.ownerDocument().createElementNS(ns, e.tagName());
567
QDomNamedNodeMap al = e.attributes();
568
for(x = 0; x < al.count(); ++x) {
569
QDomAttr a = al.item(x).toAttr();
570
if(a.name() != "xmlns")
571
i.setAttributeNodeNS(a.cloneNode().toAttr());
575
QDomNodeList nl = e.childNodes();
576
for(x = 0; x < nl.count(); ++x) {
577
QDomNode n = nl.item(x);
579
i.appendChild(addCorrectNS(n.toElement()));
581
i.appendChild(n.cloneNode());
584
//i.appendChild(frag);
588
void Client::send(const QDomElement &x)
594
//QTextStream ts(&out, IO_WriteOnly);
597
//QString out = Stream::xmlToString(x);
598
//debug(QString("Client: outgoing: [\n%1]\n").arg(out));
601
QDomElement e = addCorrectNS(x);
602
Stanza s = d->stream->createStanza(e);
604
//printf("bad stanza??\n");
608
QString out = s.toString();
609
debug(QString("Client: outgoing: [\n%1]\n").arg(out));
612
//printf("x[%s] x2[%s] s[%s]\n", Stream::xmlToString(x).latin1(), Stream::xmlToString(e).latin1(), s.toString().latin1());
616
void Client::send(const QString &str)
621
debug(QString("Client: outgoing: [\n%1]\n").arg(str));
623
static_cast<ClientStream*>(d->stream)->writeDirect(str);
626
Stream & Client::stream()
631
const LiveRoster & Client::roster() const
636
const ResourceList & Client::resourceList() const
638
return d->resourceList;
641
QString Client::host() const
646
QString Client::user() const
651
QString Client::pass() const
656
QString Client::resource() const
661
Jid Client::jid() const
664
if(!d->user.isEmpty())
667
if(!d->resource.isEmpty()) {
675
void Client::ppSubscription(const Jid &j, const QString &s)
680
void Client::ppPresence(const Jid &j, const Status &s)
683
debug(QString("Client: %1 is available.\n").arg(j.full()));
685
debug(QString("Client: %1 is unavailable.\n").arg(j.full()));
687
for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
690
if(i.j.compare(j, false)) {
691
bool us = (i.j.resource() == j.resource() || j.resource().isEmpty()) ? true: false;
693
debug(QString("for groupchat i=[%1] pres=[%2], [us=%3].\n").arg(i.j.full()).arg(j.full()).arg(us));
695
case GroupChat::Connecting:
696
if(us && s.hasError()) {
698
d->groupChatList.remove(it);
699
groupChatError(j, s.errorCode(), s.errorString());
702
// don't signal success unless it is a non-error presence
704
i.status = GroupChat::Connected;
705
groupChatJoined(i.j);
707
groupChatPresence(j, s);
710
case GroupChat::Connected:
711
groupChatPresence(j, s);
713
case GroupChat::Closing:
714
if(us && !s.isAvailable()) {
716
d->groupChatList.remove(it);
729
presenceError(j, s.errorCode(), s.errorString());
734
if(j.compare(jid(), false)) {
735
updateSelfPresence(j, s);
738
// update all relavent roster entries
739
for(LiveRoster::Iterator it = d->roster.begin(); it != d->roster.end(); ++it) {
740
LiveRosterItem &i = *it;
742
if(!i.jid().compare(j, false))
745
// roster item has its own resource?
746
if(!i.jid().resource().isEmpty()) {
747
if(i.jid().resource() != j.resource())
751
updatePresence(&i, j, s);
756
void Client::updateSelfPresence(const Jid &j, const Status &s)
758
ResourceList::Iterator rit = d->resourceList.find(j.resource());
759
bool found = (rit == d->resourceList.end()) ? false: true;
761
// unavailable? remove the resource
762
if(!s.isAvailable()) {
764
debug(QString("Client: Removing self resource: name=[%1]\n").arg(j.resource()));
766
resourceUnavailable(j, *rit);
767
d->resourceList.remove(rit);
770
// available? add/update the resource
774
r = Resource(j.resource(), s);
775
d->resourceList += r;
776
debug(QString("Client: Adding self resource: name=[%1]\n").arg(j.resource()));
781
debug(QString("Client: Updating self resource: name=[%1]\n").arg(j.resource()));
784
resourceAvailable(j, r);
788
void Client::updatePresence(LiveRosterItem *i, const Jid &j, const Status &s)
790
ResourceList::Iterator rit = i->resourceList().find(j.resource());
791
bool found = (rit == i->resourceList().end()) ? false: true;
793
// unavailable? remove the resource
794
if(!s.isAvailable()) {
797
debug(QString("Client: Removing resource from [%1]: name=[%2]\n").arg(i->jid().full()).arg(j.resource()));
798
resourceUnavailable(j, *rit);
799
i->resourceList().remove(rit);
800
i->setLastUnavailableStatus(s);
803
// available? add/update the resource
807
r = Resource(j.resource(), s);
808
i->resourceList() += r;
809
debug(QString("Client: Adding resource to [%1]: name=[%2]\n").arg(i->jid().full()).arg(j.resource()));
814
debug(QString("Client: Updating resource to [%1]: name=[%2]\n").arg(i->jid().full()).arg(j.resource()));
817
resourceAvailable(j, r);
821
void Client::pmMessage(const Message &m)
823
debug(QString("Client: Message from %1\n").arg(m.from().full()));
825
if(m.type() == "groupchat") {
826
for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
827
const GroupChat &i = *it;
829
if(!i.j.compare(m.from(), false))
832
if(i.status == GroupChat::Connected)
840
void Client::prRoster(const Roster &r)
845
void Client::rosterRequest()
850
JT_Roster *r = new JT_Roster(rootTask());
851
connect(r, SIGNAL(finished()), SLOT(slotRosterRequestFinished()));
853
d->roster.flagAllForDelete(); // mod_groups patch
857
void Client::slotRosterRequestFinished()
859
JT_Roster *r = (JT_Roster *)sender();
860
// on success, let's take it
862
//d->roster.flagAllForDelete(); // mod_groups patch
864
importRoster(r->roster());
866
for(LiveRoster::Iterator it = d->roster.begin(); it != d->roster.end();) {
867
LiveRosterItem &i = *it;
868
if(i.flagForDelete()) {
869
rosterItemRemoved(i);
870
it = d->roster.remove(it);
877
// don't report a disconnect. Client::error() will do that.
878
if(r->statusCode() == Task::ErrDisc)
882
// report success / fail
883
rosterRequestFinished(r->success(), r->statusCode(), r->statusString());
886
void Client::importRoster(const Roster &r)
888
for(Roster::ConstIterator it = r.begin(); it != r.end(); ++it) {
889
importRosterItem(*it);
893
void Client::importRosterItem(const RosterItem &item)
896
switch(item.subscription().type()) {
897
case Subscription::Both:
898
substr = "<-->"; break;
899
case Subscription::From:
900
substr = " ->"; break;
901
case Subscription::To:
902
substr = "<- "; break;
903
case Subscription::Remove:
904
substr = "xxxx"; break;
905
case Subscription::None:
907
substr = "----"; break;
911
str.sprintf(" %s %-32s", substr.latin1(), item.jid().full().latin1());
912
if(!item.name().isEmpty())
913
str += QString(" [") + item.name() + "]";
917
if(item.subscription().type() == Subscription::Remove) {
918
LiveRoster::Iterator it = d->roster.find(item.jid());
919
if(it != d->roster.end()) {
920
rosterItemRemoved(*it);
921
d->roster.remove(it);
923
dstr = "Client: (Removed) ";
927
LiveRoster::Iterator it = d->roster.find(item.jid());
928
if(it != d->roster.end()) {
929
LiveRosterItem &i = *it;
930
i.setFlagForDelete(false);
931
i.setRosterItem(item);
932
rosterItemUpdated(i);
933
dstr = "Client: (Updated) ";
936
LiveRosterItem i(item);
941
dstr = "Client: (Added) ";
948
void Client::sendMessage(const Message &m)
950
JT_Message *j = new JT_Message(rootTask(), m);
954
void Client::sendSubscription(const Jid &jid, const QString &type)
956
JT_Presence *j = new JT_Presence(rootTask());
961
void Client::setPresence(const Status &s)
963
JT_Presence *j = new JT_Presence(rootTask());
967
// update our resourceList
968
ppPresence(jid(), s);
969
//ResourceList::Iterator rit = d->resourceList.find(resource());
970
//Resource &r = *rit;
974
QString Client::OSName() const
979
QString Client::timeZone() const
984
int Client::timeZoneOffset() const
989
QString Client::clientName() const
991
return d->clientName;
994
QString Client::clientVersion() const
996
return d->clientVersion;
999
void Client::setOSName(const QString &name)
1004
void Client::setTimeZone(const QString &name, int offset)
1007
d->tzoffset = offset;
1010
void Client::setClientName(const QString &s)
1015
void Client::setClientVersion(const QString &s)
1017
d->clientVersion = s;
1020
void Client::s5b_incomingReady()
1022
S5BConnection *c = d->s5bman->takeIncoming();
1030
d->ftman->s5b_incomingReady(c);
1031
//d->jlman->insertStream(c);
1032
//incomingJidLink();
1035
void Client::ibb_incomingReady()
1037
IBBConnection *c = d->ibbman->takeIncoming();
1041
//d->jlman->insertStream(c);
1042
//incomingJidLink();
1045
//----------------------------------------------------------------------------
1047
//----------------------------------------------------------------------------
1048
class Task::TaskPrivate
1056
QString statusString;
1058
bool insig, deleteme, autoDelete;
1062
Task::Task(Task *parent)
1067
d->client = parent->client();
1068
d->id = client()->genUniqueId();
1069
connect(d->client, SIGNAL(disconnected()), SLOT(clientDisconnected()));
1072
Task::Task(Client *parent, bool)
1078
connect(d->client, SIGNAL(disconnected()), SLOT(clientDisconnected()));
1088
d = new TaskPrivate;
1091
d->deleteme = false;
1092
d->autoDelete = false;
1096
Task *Task::parent() const
1098
return (Task *)QObject::parent();
1101
Client *Task::client() const
1106
QDomDocument *Task::doc() const
1108
return client()->doc();
1111
QString Task::id() const
1116
bool Task::success() const
1121
int Task::statusCode() const
1123
return d->statusCode;
1126
const QString & Task::statusString() const
1128
return d->statusString;
1131
void Task::go(bool autoDelete)
1133
d->autoDelete = autoDelete;
1138
bool Task::take(const QDomElement &x)
1140
const QObjectList *p = children();
1144
// pass along the xml
1145
QObjectListIt it(*p);
1147
for(; it.current(); ++it) {
1148
QObject *obj = it.current();
1149
if(!obj->inherits("XMPP::Task"))
1152
t = static_cast<Task*>(obj);
1160
void Task::safeDelete()
1167
SafeDelete::deleteSingle(this);
1174
void Task::onDisconnect()
1178
d->statusCode = ErrDisc;
1179
d->statusString = tr("Disconnected");
1181
// delay this so that tasks that react don't block the shutdown
1182
QTimer::singleShot(0, this, SLOT(done()));
1186
void Task::send(const QDomElement &x)
1191
void Task::setSuccess(int code, const QString &str)
1195
d->statusCode = code;
1196
d->statusString = str;
1201
void Task::setError(const QDomElement &e)
1205
getErrorFromElement(e, &d->statusCode, &d->statusString);
1210
void Task::setError(int code, const QString &str)
1214
d->statusCode = code;
1215
d->statusString = str;
1222
if(d->done || d->insig)
1226
if(d->deleteme || d->autoDelete)
1234
SafeDelete::deleteSingle(this);
1237
void Task::clientDisconnected()
1242
void Task::debug(const char *fmt, ...)
1250
buf = new char[size];
1253
r = vsnprintf(buf, size, fmt, ap);
1267
void Task::debug(const QString &str)
1269
client()->debug(QString("%1: ").arg(className()) + str);
1272
bool Task::iqVerify(const QDomElement &x, const Jid &to, const QString &id, const QString &xmlns)
1274
if(x.tagName() != "iq")
1277
Jid from(x.attribute("from"));
1278
Jid local = client()->jid();
1279
Jid server = client()->host();
1282
if(from.isEmpty()) {
1283
// allowed if we are querying the server
1284
if(!to.isEmpty() && !to.compare(server))
1288
else if(from.compare(local, false)) {
1289
// allowed if we are querying ourself or the server
1290
if(!to.isEmpty() && !to.compare(local, false) && !to.compare(server))
1293
// from anywhere else?
1295
if(!from.compare(to))
1300
if(x.attribute("id") != id)
1304
if(!xmlns.isEmpty()) {
1305
if(queryNS(x) != xmlns)
1312
//---------------------------------------------------------------------------
1314
//---------------------------------------------------------------------------
1315
LiveRosterItem::LiveRosterItem(const Jid &jid)
1318
setFlagForDelete(false);
1321
LiveRosterItem::LiveRosterItem(const RosterItem &i)
1324
setFlagForDelete(false);
1327
LiveRosterItem::~LiveRosterItem()
1331
void LiveRosterItem::setRosterItem(const RosterItem &i)
1335
setGroups(i.groups());
1336
setSubscription(i.subscription());
1338
setIsPush(i.isPush());
1341
ResourceList & LiveRosterItem::resourceList()
1343
return v_resourceList;
1346
ResourceList::Iterator LiveRosterItem::priority()
1348
return v_resourceList.priority();
1351
const ResourceList & LiveRosterItem::resourceList() const
1353
return v_resourceList;
1356
ResourceList::ConstIterator LiveRosterItem::priority() const
1358
return v_resourceList.priority();
1361
bool LiveRosterItem::isAvailable() const
1363
if(v_resourceList.count() > 0)
1368
const Status & LiveRosterItem::lastUnavailableStatus() const
1370
return v_lastUnavailableStatus;
1373
bool LiveRosterItem::flagForDelete() const
1375
return v_flagForDelete;
1378
void LiveRosterItem::setLastUnavailableStatus(const Status &s)
1380
v_lastUnavailableStatus = s;
1383
void LiveRosterItem::setFlagForDelete(bool b)
1385
v_flagForDelete = b;
1388
//---------------------------------------------------------------------------
1390
//---------------------------------------------------------------------------
1391
LiveRoster::LiveRoster()
1392
:QValueList<LiveRosterItem>()
1396
LiveRoster::~LiveRoster()
1400
void LiveRoster::flagAllForDelete()
1402
for(Iterator it = begin(); it != end(); ++it)
1403
(*it).setFlagForDelete(true);
1406
LiveRoster::Iterator LiveRoster::find(const Jid &j, bool compareRes)
1409
for(it = begin(); it != end(); ++it) {
1410
if((*it).jid().compare(j, compareRes))
1416
LiveRoster::ConstIterator LiveRoster::find(const Jid &j, bool compareRes) const
1419
for(it = begin(); it != end(); ++it) {
1420
if((*it).jid().compare(j, compareRes))