~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to iris/xmpp-im/client.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2005-01-10 17:41:43 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050110174143-ltocv5zapl6blf5d
Tags: 0.9.3-1
* New upstream release
* Cleaned up debian/rules (some things are done by upstream Makefiles now)
* Fixed some lintian warnings:
  - removed executable bit from some .png files
  - moved psi.desktop to /usr/share/applications
* Updated menu files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * client.cpp - IM Client
 
3
 * Copyright (C) 2003  Justin Karneges
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 *
 
19
 */
 
20
 
 
21
#include"im.h"
 
22
#include"safedelete.h"
 
23
 
 
24
//! \class Client client.h
 
25
//! \brief Communicates with the Jabber network.  Start here.
 
26
//!
 
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
 
30
//!  through it.
 
31
//!
 
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.
 
36
//!
 
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.
 
41
//!
 
42
//!  \code
 
43
//!  #include "client.h"
 
44
//!  using namespace Jabber;
 
45
//!
 
46
//!  ...
 
47
//!
 
48
//!  Client *client;
 
49
//!
 
50
//!  Session::Session()
 
51
//!  {
 
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");
 
56
//!  }
 
57
//!
 
58
//!  void Session::clientHandshaken()
 
59
//!  {
 
60
//!    client->authDigest("jabtest", "12345", "Psi");
 
61
//!  }
 
62
//!
 
63
//!  void Session::authFinished(bool success, int, const QString &err)
 
64
//!  {
 
65
//!    if(success)
 
66
//!      printf("Login success!");
 
67
//!    else
 
68
//!      printf("Login failed.  Here's why: %s\n", err.latin1());
 
69
//!  }
 
70
//!  \endcode
 
71
 
 
72
#include<stdarg.h>
 
73
#include<qobjectlist.h>
 
74
#include<qtimer.h>
 
75
#include<qguardedptr.h>
 
76
#include"xmpp_tasks.h"
 
77
#include"xmpp_xmlcommon.h"
 
78
#include"s5b.h"
 
79
#include"xmpp_ibb.h"
 
80
#include"xmpp_jidlink.h"
 
81
#include"filetransfer.h"
 
82
 
 
83
/*#include<stdio.h>
 
84
#include<stdarg.h>
 
85
#include<qstring.h>
 
86
#include<qdom.h>
 
87
#include<qobjectlist.h>
 
88
#include<qtimer.h>
 
89
#include"xmpp_stream.h"
 
90
#include"xmpp_tasks.h"
 
91
#include"xmpp_xmlcommon.h"
 
92
#include"xmpp_dtcp.h"
 
93
#include"xmpp_ibb.h"
 
94
#include"xmpp_jidlink.h"
 
95
 
 
96
using namespace Jabber;*/
 
97
 
 
98
#ifdef Q_WS_WIN
 
99
#define vsnprintf _vsnprintf
 
100
#endif
 
101
 
 
102
namespace XMPP
 
103
{
 
104
 
 
105
//----------------------------------------------------------------------------
 
106
// Client
 
107
//----------------------------------------------------------------------------
 
108
class Client::GroupChat
 
109
{
 
110
public:
 
111
        enum { Connecting, Connected, Closing };
 
112
        GroupChat() {}
 
113
 
 
114
        Jid j;
 
115
        int status;
 
116
};
 
117
 
 
118
class Client::ClientPrivate
 
119
{
 
120
public:
 
121
        ClientPrivate() {}
 
122
 
 
123
        ClientStream *stream;
 
124
        QDomDocument doc;
 
125
        int id_seed;
 
126
        Task *root;
 
127
        QString host, user, pass, resource;
 
128
        QString osname, tzname, clientName, clientVersion;
 
129
        int tzoffset;
 
130
        bool active;
 
131
 
 
132
        LiveRoster roster;
 
133
        ResourceList resourceList;
 
134
        S5BManager *s5bman;
 
135
        IBBManager *ibbman;
 
136
        JidLinkManager *jlman;
 
137
        FileTransferManager *ftman;
 
138
        bool ftEnabled;
 
139
        QValueList<GroupChat> groupChatList;
 
140
};
 
141
 
 
142
 
 
143
Client::Client(QObject *par)
 
144
:QObject(par)
 
145
{
 
146
        d = new ClientPrivate;
 
147
        d->tzoffset = 0;
 
148
        d->active = false;
 
149
        d->osname = "N/A";
 
150
        d->clientName = "N/A";
 
151
        d->clientVersion = "0.0";
 
152
 
 
153
        d->id_seed = 0xaaaa;
 
154
        d->root = new Task(this, true);
 
155
 
 
156
        d->stream = 0;
 
157
 
 
158
        d->s5bman = new S5BManager(this);
 
159
        connect(d->s5bman, SIGNAL(incomingReady()), SLOT(s5b_incomingReady()));
 
160
 
 
161
        d->ibbman = new IBBManager(this);
 
162
        connect(d->ibbman, SIGNAL(incomingReady()), SLOT(ibb_incomingReady()));
 
163
 
 
164
        d->jlman = new JidLinkManager(this);
 
165
 
 
166
        d->ftman = 0;
 
167
}
 
168
 
 
169
Client::~Client()
 
170
{
 
171
        close(true);
 
172
 
 
173
        delete d->ftman;
 
174
        delete d->jlman;
 
175
        delete d->ibbman;
 
176
        delete d->s5bman;
 
177
        delete d->root;
 
178
        //delete d->stream;
 
179
        delete d;
 
180
}
 
181
 
 
182
void Client::connectToServer(ClientStream *s, const Jid &j, bool auth)
 
183
{
 
184
        d->stream = s;
 
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 &)));
 
193
 
 
194
        d->stream->connectToServer(j, auth);
 
195
}
 
196
 
 
197
void Client::start(const QString &host, const QString &user, const QString &pass, const QString &_resource)
 
198
{
 
199
        // TODO
 
200
        d->host = host;
 
201
        d->user = user;
 
202
        d->pass = pass;
 
203
        d->resource = _resource;
 
204
 
 
205
        Status stat;
 
206
        stat.setIsAvailable(false);
 
207
        d->resourceList += Resource(resource(), stat);
 
208
 
 
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 &)));
 
212
 
 
213
        JT_PushMessage *pm = new JT_PushMessage(rootTask());
 
214
        connect(pm, SIGNAL(message(const Message &)), SLOT(pmMessage(const Message &)));
 
215
 
 
216
        JT_PushRoster *pr = new JT_PushRoster(rootTask());
 
217
        connect(pr, SIGNAL(roster(const Roster &)), SLOT(prRoster(const Roster &)));
 
218
 
 
219
        new JT_ServInfo(rootTask());
 
220
 
 
221
        d->active = true;
 
222
}
 
223
 
 
224
void Client::setFileTransferEnabled(bool b)
 
225
{
 
226
        if(b) {
 
227
                if(!d->ftman)
 
228
                        d->ftman = new FileTransferManager(this);
 
229
        }
 
230
        else {
 
231
                if(d->ftman) {
 
232
                        delete d->ftman;
 
233
                        d->ftman = 0;
 
234
                }
 
235
        }
 
236
}
 
237
 
 
238
FileTransferManager *Client::fileTransferManager() const
 
239
{
 
240
        return d->ftman;
 
241
}
 
242
 
 
243
JidLinkManager *Client::jidLinkManager() const
 
244
{
 
245
        return d->jlman;
 
246
}
 
247
 
 
248
S5BManager *Client::s5bManager() const
 
249
{
 
250
        return d->s5bman;
 
251
}
 
252
 
 
253
IBBManager *Client::ibbManager() const
 
254
{
 
255
        return d->ibbman;
 
256
}
 
257
 
 
258
bool Client::isActive() const
 
259
{
 
260
        return d->active;
 
261
}
 
262
 
 
263
void Client::groupChatChangeNick(const QString &host, const QString &room, const QString &nick, const Status &_s)
 
264
{
 
265
        Jid jid(room + "@" + host + "/" + nick);
 
266
        for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
 
267
                GroupChat &i = *it;
 
268
                if(i.j.compare(jid, false)) {
 
269
                        i.j = jid;
 
270
 
 
271
                        Status s = _s;
 
272
                        s.setIsAvailable(true);
 
273
 
 
274
                        JT_Presence *j = new JT_Presence(rootTask());
 
275
                        j->pres(jid, s);
 
276
                        j->go(true);
 
277
 
 
278
                        break;
 
279
                }
 
280
        }
 
281
}
 
282
 
 
283
bool Client::groupChatJoin(const QString &host, const QString &room, const QString &nick)
 
284
{
 
285
        Jid jid(room + "@" + host + "/" + nick);
 
286
        for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end();) {
 
287
                GroupChat &i = *it;
 
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);
 
292
                        else
 
293
                                return false;
 
294
                }
 
295
                else
 
296
                        ++it;
 
297
        }
 
298
 
 
299
        debug(QString("Client: Joined: [%1]\n").arg(jid.full()));
 
300
        GroupChat i;
 
301
        i.j = jid;
 
302
        i.status = GroupChat::Connecting;
 
303
        d->groupChatList += i;
 
304
 
 
305
        JT_Presence *j = new JT_Presence(rootTask());
 
306
        j->pres(jid, Status());
 
307
        j->go(true);
 
308
 
 
309
        return true;
 
310
}
 
311
 
 
312
void Client::groupChatSetStatus(const QString &host, const QString &room, const Status &_s)
 
313
{
 
314
        Jid jid(room + "@" + host);
 
315
        bool found = false;
 
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)) {
 
319
                        found = true;
 
320
                        jid = i.j;
 
321
                        break;
 
322
                }
 
323
        }
 
324
        if(!found)
 
325
                return;
 
326
 
 
327
        Status s = _s;
 
328
        s.setIsAvailable(true);
 
329
 
 
330
        JT_Presence *j = new JT_Presence(rootTask());
 
331
        j->pres(jid, s);
 
332
        j->go(true);
 
333
}
 
334
 
 
335
void Client::groupChatLeave(const QString &host, const QString &room)
 
336
{
 
337
        Jid jid(room + "@" + host);
 
338
        for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
 
339
                GroupChat &i = *it;
 
340
 
 
341
                if(!i.j.compare(jid, false))
 
342
                        continue;
 
343
 
 
344
                i.status = GroupChat::Closing;
 
345
                debug(QString("Client: Leaving: [%1]\n").arg(i.j.full()));
 
346
 
 
347
                JT_Presence *j = new JT_Presence(rootTask());
 
348
                Status s;
 
349
                s.setIsAvailable(false);
 
350
                j->pres(i.j, s);
 
351
                j->go(true);
 
352
        }
 
353
}
 
354
 
 
355
/*void Client::start()
 
356
{
 
357
        if(d->stream->old()) {
 
358
                // old has no activation step
 
359
                d->active = true;
 
360
                activated();
 
361
        }
 
362
        else {
 
363
                // TODO: IM session
 
364
        }
 
365
}*/
 
366
 
 
367
// TODO: fast close
 
368
void Client::close(bool)
 
369
{
 
370
        if(d->stream) {
 
371
                if(d->active) {
 
372
                        for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
 
373
                                GroupChat &i = *it;
 
374
                                i.status = GroupChat::Closing;
 
375
 
 
376
                                JT_Presence *j = new JT_Presence(rootTask());
 
377
                                Status s;
 
378
                                s.setIsAvailable(false);
 
379
                                j->pres(i.j, s);
 
380
                                j->go(true);
 
381
                        }
 
382
                }
 
383
 
 
384
                d->stream->disconnect(this);
 
385
                d->stream->close();
 
386
                d->stream = 0;
 
387
        }
 
388
        disconnected();
 
389
        cleanup();
 
390
}
 
391
 
 
392
void Client::cleanup()
 
393
{
 
394
        d->active = false;
 
395
        //d->authed = false;
 
396
        d->groupChatList.clear();
 
397
}
 
398
 
 
399
/*void Client::continueAfterCert()
 
400
{
 
401
        d->stream->continueAfterCert();
 
402
}
 
403
 
 
404
void Client::streamConnected()
 
405
{
 
406
        connected();
 
407
}
 
408
 
 
409
void Client::streamHandshaken()
 
410
{
 
411
        handshaken();
 
412
}*/
 
413
 
 
414
void Client::streamError(int)
 
415
{
 
416
        //StreamError e = err;
 
417
        //error(e);
 
418
 
 
419
        //if(!e.isWarning()) {
 
420
                disconnected();
 
421
                cleanup();
 
422
        //}
 
423
}
 
424
 
 
425
/*void Client::streamSSLCertificateReady(const QSSLCert &cert)
 
426
{
 
427
        sslCertReady(cert);
 
428
}
 
429
 
 
430
void Client::streamCloseFinished()
 
431
{
 
432
        closeFinished();
 
433
}*/
 
434
 
 
435
static QDomElement oldStyleNS(const QDomElement &e)
 
436
{
 
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())
 
443
                noShowNS = true;
 
444
 
 
445
        QDomElement i;
 
446
        uint x;
 
447
        //if(noShowNS)
 
448
                i = e.ownerDocument().createElement(e.tagName());
 
449
        //else
 
450
        //      i = e.ownerDocument().createElementNS(e.namespaceURI(), e.tagName());
 
451
 
 
452
        // copy attributes
 
453
        QDomNamedNodeMap al = e.attributes();
 
454
        for(x = 0; x < al.count(); ++x)
 
455
                i.setAttributeNode(al.item(x).cloneNode().toAttr());
 
456
 
 
457
        if(!noShowNS)
 
458
                i.setAttribute("xmlns", e.namespaceURI());
 
459
 
 
460
        // copy children
 
461
        QDomNodeList nl = e.childNodes();
 
462
        for(x = 0; x < nl.count(); ++x) {
 
463
                QDomNode n = nl.item(x);
 
464
                if(n.isElement())
 
465
                        i.appendChild(oldStyleNS(n.toElement()));
 
466
                else
 
467
                        i.appendChild(n.cloneNode());
 
468
        }
 
469
        return i;
 
470
}
 
471
 
 
472
void Client::streamReadyRead()
 
473
{
 
474
        // HACK HACK HACK
 
475
        QGuardedPtr<ClientStream> pstream = d->stream;
 
476
 
 
477
        while(pstream && d->stream->stanzaAvailable()) {
 
478
                Stanza s = d->stream->read();
 
479
 
 
480
                QString out = s.toString();
 
481
                debug(QString("Client: incoming: [\n%1]\n").arg(out));
 
482
                xmlIncoming(out);
 
483
 
 
484
                QDomElement x = oldStyleNS(s.element());
 
485
                distribute(x);
 
486
        }
 
487
}
 
488
 
 
489
void Client::streamIncomingXml(const QString &s)
 
490
{
 
491
        QString str = s;
 
492
        if(str.at(str.length()-1) != '\n')
 
493
                str += '\n';
 
494
        xmlIncoming(str);
 
495
}
 
496
 
 
497
void Client::streamOutgoingXml(const QString &s)
 
498
{
 
499
        QString str = s;
 
500
        if(str.at(str.length()-1) != '\n')
 
501
                str += '\n';
 
502
        xmlOutgoing(str);
 
503
}
 
504
 
 
505
void Client::debug(const QString &str)
 
506
{
 
507
        debugText(str);
 
508
}
 
509
 
 
510
QString Client::genUniqueId()
 
511
{
 
512
        QString s;
 
513
        s.sprintf("a%x", d->id_seed);
 
514
        d->id_seed += 0x10;
 
515
        return s;
 
516
}
 
517
 
 
518
Task *Client::rootTask()
 
519
{
 
520
        return d->root;
 
521
}
 
522
 
 
523
QDomDocument *Client::doc() const
 
524
{
 
525
        return &d->doc;
 
526
}
 
527
 
 
528
void Client::distribute(const QDomElement &x)
 
529
{
 
530
        if(x.hasAttribute("from")) {
 
531
                Jid j(x.attribute("from"));
 
532
                if(!j.isValid()) {
 
533
                        debug("Client: bad 'from' JID\n");
 
534
                        return;
 
535
                }
 
536
        }
 
537
 
 
538
        if(!rootTask()->take(x)) {
 
539
                debug("Client: packet was ignored.\n");
 
540
        }
 
541
}
 
542
 
 
543
static QDomElement addCorrectNS(const QDomElement &e)
 
544
{
 
545
        uint x;
 
546
 
 
547
        // grab child nodes
 
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());*/
 
552
 
 
553
        // find closest xmlns
 
554
        QDomNode n = e;
 
555
        while(!n.isNull() && !n.toElement().hasAttribute("xmlns"))
 
556
                n = n.parentNode();
 
557
        QString ns;
 
558
        if(n.isNull() || !n.toElement().hasAttribute("xmlns"))
 
559
                ns = "jabber:client";
 
560
        else
 
561
                ns = n.toElement().attribute("xmlns");
 
562
 
 
563
        // make a new node
 
564
        QDomElement i = e.ownerDocument().createElementNS(ns, e.tagName());
 
565
 
 
566
        // copy attributes
 
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());
 
572
        }
 
573
 
 
574
        // copy children
 
575
        QDomNodeList nl = e.childNodes();
 
576
        for(x = 0; x < nl.count(); ++x) {
 
577
                QDomNode n = nl.item(x);
 
578
                if(n.isElement())
 
579
                        i.appendChild(addCorrectNS(n.toElement()));
 
580
                else
 
581
                        i.appendChild(n.cloneNode());
 
582
        }
 
583
 
 
584
        //i.appendChild(frag);
 
585
        return i;
 
586
}
 
587
 
 
588
void Client::send(const QDomElement &x)
 
589
{
 
590
        if(!d->stream)
 
591
                return;
 
592
 
 
593
        //QString out;
 
594
        //QTextStream ts(&out, IO_WriteOnly);
 
595
        //x.save(ts, 0);
 
596
 
 
597
        //QString out = Stream::xmlToString(x);
 
598
        //debug(QString("Client: outgoing: [\n%1]\n").arg(out));
 
599
        //xmlOutgoing(out);
 
600
 
 
601
        QDomElement e = addCorrectNS(x);
 
602
        Stanza s = d->stream->createStanza(e);
 
603
        if(s.isNull()) {
 
604
                //printf("bad stanza??\n");
 
605
                return;
 
606
        }
 
607
 
 
608
        QString out = s.toString();
 
609
        debug(QString("Client: outgoing: [\n%1]\n").arg(out));
 
610
        xmlOutgoing(out);
 
611
 
 
612
        //printf("x[%s] x2[%s] s[%s]\n", Stream::xmlToString(x).latin1(), Stream::xmlToString(e).latin1(), s.toString().latin1());
 
613
        d->stream->write(s);
 
614
}
 
615
 
 
616
void Client::send(const QString &str)
 
617
{
 
618
        if(!d->stream)
 
619
                return;
 
620
 
 
621
        debug(QString("Client: outgoing: [\n%1]\n").arg(str));
 
622
        xmlOutgoing(str);
 
623
        static_cast<ClientStream*>(d->stream)->writeDirect(str);
 
624
}
 
625
 
 
626
Stream & Client::stream()
 
627
{
 
628
        return *d->stream;
 
629
}
 
630
 
 
631
const LiveRoster & Client::roster() const
 
632
{
 
633
        return d->roster;
 
634
}
 
635
 
 
636
const ResourceList & Client::resourceList() const
 
637
{
 
638
        return d->resourceList;
 
639
}
 
640
 
 
641
QString Client::host() const
 
642
{
 
643
        return d->host;
 
644
}
 
645
 
 
646
QString Client::user() const
 
647
{
 
648
        return d->user;
 
649
}
 
650
 
 
651
QString Client::pass() const
 
652
{
 
653
        return d->pass;
 
654
}
 
655
 
 
656
QString Client::resource() const
 
657
{
 
658
        return d->resource;
 
659
}
 
660
 
 
661
Jid Client::jid() const
 
662
{
 
663
        QString s;
 
664
        if(!d->user.isEmpty())
 
665
                s += d->user + '@';
 
666
        s += d->host;
 
667
        if(!d->resource.isEmpty()) {
 
668
                s += '/';
 
669
                s += d->resource;
 
670
        }
 
671
 
 
672
        return Jid(s);
 
673
}
 
674
 
 
675
void Client::ppSubscription(const Jid &j, const QString &s)
 
676
{
 
677
        subscription(j, s);
 
678
}
 
679
 
 
680
void Client::ppPresence(const Jid &j, const Status &s)
 
681
{
 
682
        if(s.isAvailable())
 
683
                debug(QString("Client: %1 is available.\n").arg(j.full()));
 
684
        else
 
685
                debug(QString("Client: %1 is unavailable.\n").arg(j.full()));
 
686
 
 
687
        for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
 
688
                GroupChat &i = *it;
 
689
 
 
690
                if(i.j.compare(j, false)) {
 
691
                        bool us = (i.j.resource() == j.resource() || j.resource().isEmpty()) ? true: false;
 
692
 
 
693
                        debug(QString("for groupchat i=[%1] pres=[%2], [us=%3].\n").arg(i.j.full()).arg(j.full()).arg(us));
 
694
                        switch(i.status) {
 
695
                                case GroupChat::Connecting:
 
696
                                        if(us && s.hasError()) {
 
697
                                                Jid j = i.j;
 
698
                                                d->groupChatList.remove(it);
 
699
                                                groupChatError(j, s.errorCode(), s.errorString());
 
700
                                        }
 
701
                                        else {
 
702
                                                // don't signal success unless it is a non-error presence
 
703
                                                if(!s.hasError()) {
 
704
                                                        i.status = GroupChat::Connected;
 
705
                                                        groupChatJoined(i.j);
 
706
                                                }
 
707
                                                groupChatPresence(j, s);
 
708
                                        }
 
709
                                        break;
 
710
                                case GroupChat::Connected:
 
711
                                        groupChatPresence(j, s);
 
712
                                        break;
 
713
                                case GroupChat::Closing:
 
714
                                        if(us && !s.isAvailable()) {
 
715
                                                Jid j = i.j;
 
716
                                                d->groupChatList.remove(it);
 
717
                                                groupChatLeft(j);
 
718
                                        }
 
719
                                        break;
 
720
                                default:
 
721
                                        break;
 
722
                        }
 
723
 
 
724
                        return;
 
725
                }
 
726
        }
 
727
 
 
728
        if(s.hasError()) {
 
729
                presenceError(j, s.errorCode(), s.errorString());
 
730
                return;
 
731
        }
 
732
 
 
733
        // is it me?
 
734
        if(j.compare(jid(), false)) {
 
735
                updateSelfPresence(j, s);
 
736
        }
 
737
        else {
 
738
                // update all relavent roster entries
 
739
                for(LiveRoster::Iterator it = d->roster.begin(); it != d->roster.end(); ++it) {
 
740
                        LiveRosterItem &i = *it;
 
741
 
 
742
                        if(!i.jid().compare(j, false))
 
743
                                continue;
 
744
 
 
745
                        // roster item has its own resource?
 
746
                        if(!i.jid().resource().isEmpty()) {
 
747
                                if(i.jid().resource() != j.resource())
 
748
                                        continue;
 
749
                        }
 
750
 
 
751
                        updatePresence(&i, j, s);
 
752
                }
 
753
        }
 
754
}
 
755
 
 
756
void Client::updateSelfPresence(const Jid &j, const Status &s)
 
757
{
 
758
        ResourceList::Iterator rit = d->resourceList.find(j.resource());
 
759
        bool found = (rit == d->resourceList.end()) ? false: true;
 
760
 
 
761
        // unavailable?  remove the resource
 
762
        if(!s.isAvailable()) {
 
763
                if(found) {
 
764
                        debug(QString("Client: Removing self resource: name=[%1]\n").arg(j.resource()));
 
765
                        (*rit).setStatus(s);
 
766
                        resourceUnavailable(j, *rit);
 
767
                        d->resourceList.remove(rit);
 
768
                }
 
769
        }
 
770
        // available?  add/update the resource
 
771
        else {
 
772
                Resource r;
 
773
                if(!found) {
 
774
                        r = Resource(j.resource(), s);
 
775
                        d->resourceList += r;
 
776
                        debug(QString("Client: Adding self resource: name=[%1]\n").arg(j.resource()));
 
777
                }
 
778
                else {
 
779
                        (*rit).setStatus(s);
 
780
                        r = *rit;
 
781
                        debug(QString("Client: Updating self resource: name=[%1]\n").arg(j.resource()));
 
782
                }
 
783
 
 
784
                resourceAvailable(j, r);
 
785
        }
 
786
}
 
787
 
 
788
void Client::updatePresence(LiveRosterItem *i, const Jid &j, const Status &s)
 
789
{
 
790
        ResourceList::Iterator rit = i->resourceList().find(j.resource());
 
791
        bool found = (rit == i->resourceList().end()) ? false: true;
 
792
 
 
793
        // unavailable?  remove the resource
 
794
        if(!s.isAvailable()) {
 
795
                if(found) {
 
796
                        (*rit).setStatus(s);
 
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);
 
801
                }
 
802
        }
 
803
        // available?  add/update the resource
 
804
        else {
 
805
                Resource r;
 
806
                if(!found) {
 
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()));
 
810
                }
 
811
                else {
 
812
                        (*rit).setStatus(s);
 
813
                        r = *rit;
 
814
                        debug(QString("Client: Updating resource to [%1]: name=[%2]\n").arg(i->jid().full()).arg(j.resource()));
 
815
                }
 
816
 
 
817
                resourceAvailable(j, r);
 
818
        }
 
819
}
 
820
 
 
821
void Client::pmMessage(const Message &m)
 
822
{
 
823
        debug(QString("Client: Message from %1\n").arg(m.from().full()));
 
824
 
 
825
        if(m.type() == "groupchat") {
 
826
                for(QValueList<GroupChat>::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) {
 
827
                        const GroupChat &i = *it;
 
828
 
 
829
                        if(!i.j.compare(m.from(), false))
 
830
                                continue;
 
831
 
 
832
                        if(i.status == GroupChat::Connected)
 
833
                                messageReceived(m);
 
834
                }
 
835
        }
 
836
        else
 
837
                messageReceived(m);
 
838
}
 
839
 
 
840
void Client::prRoster(const Roster &r)
 
841
{
 
842
        importRoster(r);
 
843
}
 
844
 
 
845
void Client::rosterRequest()
 
846
{
 
847
        if(!d->active)
 
848
                return;
 
849
 
 
850
        JT_Roster *r = new JT_Roster(rootTask());
 
851
        connect(r, SIGNAL(finished()), SLOT(slotRosterRequestFinished()));
 
852
        r->get();
 
853
        d->roster.flagAllForDelete(); // mod_groups patch
 
854
        r->go(true);
 
855
}
 
856
 
 
857
void Client::slotRosterRequestFinished()
 
858
{
 
859
        JT_Roster *r = (JT_Roster *)sender();
 
860
        // on success, let's take it
 
861
        if(r->success()) {
 
862
                //d->roster.flagAllForDelete(); // mod_groups patch
 
863
 
 
864
                importRoster(r->roster());
 
865
 
 
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);
 
871
                        }
 
872
                        else
 
873
                                ++it;
 
874
                }
 
875
        }
 
876
        else {
 
877
                // don't report a disconnect.  Client::error() will do that.
 
878
                if(r->statusCode() == Task::ErrDisc)
 
879
                        return;
 
880
        }
 
881
 
 
882
        // report success / fail
 
883
        rosterRequestFinished(r->success(), r->statusCode(), r->statusString());
 
884
}
 
885
 
 
886
void Client::importRoster(const Roster &r)
 
887
{
 
888
        for(Roster::ConstIterator it = r.begin(); it != r.end(); ++it) {
 
889
                importRosterItem(*it);
 
890
        }
 
891
}
 
892
 
 
893
void Client::importRosterItem(const RosterItem &item)
 
894
{
 
895
        QString substr;
 
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:
 
906
                default:
 
907
                        substr = "----";  break;
 
908
        }
 
909
 
 
910
        QString dstr, str;
 
911
        str.sprintf("  %s %-32s", substr.latin1(), item.jid().full().latin1());
 
912
        if(!item.name().isEmpty())
 
913
                str += QString(" [") + item.name() + "]";
 
914
        str += '\n';
 
915
 
 
916
        // Remove
 
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);
 
922
                }
 
923
                dstr = "Client: (Removed) ";
 
924
        }
 
925
        // Add/Update
 
926
        else {
 
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) ";
 
934
                }
 
935
                else {
 
936
                        LiveRosterItem i(item);
 
937
                        d->roster += i;
 
938
 
 
939
                        // signal it
 
940
                        rosterItemAdded(i);
 
941
                        dstr = "Client: (Added)   ";
 
942
                }
 
943
        }
 
944
 
 
945
        debug(dstr + str);
 
946
}
 
947
 
 
948
void Client::sendMessage(const Message &m)
 
949
{
 
950
        JT_Message *j = new JT_Message(rootTask(), m);
 
951
        j->go(true);
 
952
}
 
953
 
 
954
void Client::sendSubscription(const Jid &jid, const QString &type)
 
955
{
 
956
        JT_Presence *j = new JT_Presence(rootTask());
 
957
        j->sub(jid, type);
 
958
        j->go(true);
 
959
}
 
960
 
 
961
void Client::setPresence(const Status &s)
 
962
{
 
963
        JT_Presence *j = new JT_Presence(rootTask());
 
964
        j->pres(s);
 
965
        j->go(true);
 
966
 
 
967
        // update our resourceList
 
968
        ppPresence(jid(), s);
 
969
        //ResourceList::Iterator rit = d->resourceList.find(resource());
 
970
        //Resource &r = *rit;
 
971
        //r.setStatus(s);
 
972
}
 
973
 
 
974
QString Client::OSName() const
 
975
{
 
976
        return d->osname;
 
977
}
 
978
 
 
979
QString Client::timeZone() const
 
980
{
 
981
        return d->tzname;
 
982
}
 
983
 
 
984
int Client::timeZoneOffset() const
 
985
{
 
986
        return d->tzoffset;
 
987
}
 
988
 
 
989
QString Client::clientName() const
 
990
{
 
991
        return d->clientName;
 
992
}
 
993
 
 
994
QString Client::clientVersion() const
 
995
{
 
996
        return d->clientVersion;
 
997
}
 
998
 
 
999
void Client::setOSName(const QString &name)
 
1000
{
 
1001
        d->osname = name;
 
1002
}
 
1003
 
 
1004
void Client::setTimeZone(const QString &name, int offset)
 
1005
{
 
1006
        d->tzname = name;
 
1007
        d->tzoffset = offset;
 
1008
}
 
1009
 
 
1010
void Client::setClientName(const QString &s)
 
1011
{
 
1012
        d->clientName = s;
 
1013
}
 
1014
 
 
1015
void Client::setClientVersion(const QString &s)
 
1016
{
 
1017
        d->clientVersion = s;
 
1018
}
 
1019
 
 
1020
void Client::s5b_incomingReady()
 
1021
{
 
1022
        S5BConnection *c = d->s5bman->takeIncoming();
 
1023
        if(!c)
 
1024
                return;
 
1025
        if(!d->ftman) {
 
1026
                c->close();
 
1027
                c->deleteLater();
 
1028
                return;
 
1029
        }
 
1030
        d->ftman->s5b_incomingReady(c);
 
1031
        //d->jlman->insertStream(c);
 
1032
        //incomingJidLink();
 
1033
}
 
1034
 
 
1035
void Client::ibb_incomingReady()
 
1036
{
 
1037
        IBBConnection *c = d->ibbman->takeIncoming();
 
1038
        if(!c)
 
1039
                return;
 
1040
        c->deleteLater();
 
1041
        //d->jlman->insertStream(c);
 
1042
        //incomingJidLink();
 
1043
}
 
1044
 
 
1045
//----------------------------------------------------------------------------
 
1046
// Task
 
1047
//----------------------------------------------------------------------------
 
1048
class Task::TaskPrivate
 
1049
{
 
1050
public:
 
1051
        TaskPrivate() {}
 
1052
 
 
1053
        QString id;
 
1054
        bool success;
 
1055
        int statusCode;
 
1056
        QString statusString;
 
1057
        Client *client;
 
1058
        bool insig, deleteme, autoDelete;
 
1059
        bool done;
 
1060
};
 
1061
 
 
1062
Task::Task(Task *parent)
 
1063
:QObject(parent)
 
1064
{
 
1065
        init();
 
1066
 
 
1067
        d->client = parent->client();
 
1068
        d->id = client()->genUniqueId();
 
1069
        connect(d->client, SIGNAL(disconnected()), SLOT(clientDisconnected()));
 
1070
}
 
1071
 
 
1072
Task::Task(Client *parent, bool)
 
1073
:QObject(0)
 
1074
{
 
1075
        init();
 
1076
 
 
1077
        d->client = parent;
 
1078
        connect(d->client, SIGNAL(disconnected()), SLOT(clientDisconnected()));
 
1079
}
 
1080
 
 
1081
Task::~Task()
 
1082
{
 
1083
        delete d;
 
1084
}
 
1085
 
 
1086
void Task::init()
 
1087
{
 
1088
        d = new TaskPrivate;
 
1089
        d->success = false;
 
1090
        d->insig = false;
 
1091
        d->deleteme = false;
 
1092
        d->autoDelete = false;
 
1093
        d->done = false;
 
1094
}
 
1095
 
 
1096
Task *Task::parent() const
 
1097
{
 
1098
        return (Task *)QObject::parent();
 
1099
}
 
1100
 
 
1101
Client *Task::client() const
 
1102
{
 
1103
        return d->client;
 
1104
}
 
1105
 
 
1106
QDomDocument *Task::doc() const
 
1107
{
 
1108
        return client()->doc();
 
1109
}
 
1110
 
 
1111
QString Task::id() const
 
1112
{
 
1113
        return d->id;
 
1114
}
 
1115
 
 
1116
bool Task::success() const
 
1117
{
 
1118
        return d->success;
 
1119
}
 
1120
 
 
1121
int Task::statusCode() const
 
1122
{
 
1123
        return d->statusCode;
 
1124
}
 
1125
 
 
1126
const QString & Task::statusString() const
 
1127
{
 
1128
        return d->statusString;
 
1129
}
 
1130
 
 
1131
void Task::go(bool autoDelete)
 
1132
{
 
1133
        d->autoDelete = autoDelete;
 
1134
 
 
1135
        onGo();
 
1136
}
 
1137
 
 
1138
bool Task::take(const QDomElement &x)
 
1139
{
 
1140
        const QObjectList *p = children();
 
1141
        if(!p)
 
1142
                return false;
 
1143
 
 
1144
        // pass along the xml
 
1145
        QObjectListIt it(*p);
 
1146
        Task *t;
 
1147
        for(; it.current(); ++it) {
 
1148
                QObject *obj = it.current();
 
1149
                if(!obj->inherits("XMPP::Task"))
 
1150
                        continue;
 
1151
 
 
1152
                t = static_cast<Task*>(obj);
 
1153
                if(t->take(x))
 
1154
                        return true;
 
1155
        }
 
1156
 
 
1157
        return false;
 
1158
}
 
1159
 
 
1160
void Task::safeDelete()
 
1161
{
 
1162
        if(d->deleteme)
 
1163
                return;
 
1164
 
 
1165
        d->deleteme = true;
 
1166
        if(!d->insig)
 
1167
                SafeDelete::deleteSingle(this);
 
1168
}
 
1169
 
 
1170
void Task::onGo()
 
1171
{
 
1172
}
 
1173
 
 
1174
void Task::onDisconnect()
 
1175
{
 
1176
        if(!d->done) {
 
1177
                d->success = false;
 
1178
                d->statusCode = ErrDisc;
 
1179
                d->statusString = tr("Disconnected");
 
1180
 
 
1181
                // delay this so that tasks that react don't block the shutdown
 
1182
                QTimer::singleShot(0, this, SLOT(done()));
 
1183
        }
 
1184
}
 
1185
 
 
1186
void Task::send(const QDomElement &x)
 
1187
{
 
1188
        client()->send(x);
 
1189
}
 
1190
 
 
1191
void Task::setSuccess(int code, const QString &str)
 
1192
{
 
1193
        if(!d->done) {
 
1194
                d->success = true;
 
1195
                d->statusCode = code;
 
1196
                d->statusString = str;
 
1197
                done();
 
1198
        }
 
1199
}
 
1200
 
 
1201
void Task::setError(const QDomElement &e)
 
1202
{
 
1203
        if(!d->done) {
 
1204
                d->success = false;
 
1205
                getErrorFromElement(e, &d->statusCode, &d->statusString);
 
1206
                done();
 
1207
        }
 
1208
}
 
1209
 
 
1210
void Task::setError(int code, const QString &str)
 
1211
{
 
1212
        if(!d->done) {
 
1213
                d->success = false;
 
1214
                d->statusCode = code;
 
1215
                d->statusString = str;
 
1216
                done();
 
1217
        }
 
1218
}
 
1219
 
 
1220
void Task::done()
 
1221
{
 
1222
        if(d->done || d->insig)
 
1223
                return;
 
1224
        d->done = true;
 
1225
 
 
1226
        if(d->deleteme || d->autoDelete)
 
1227
                d->deleteme = true;
 
1228
 
 
1229
        d->insig = true;
 
1230
        finished();
 
1231
        d->insig = false;
 
1232
 
 
1233
        if(d->deleteme)
 
1234
                SafeDelete::deleteSingle(this);
 
1235
}
 
1236
 
 
1237
void Task::clientDisconnected()
 
1238
{
 
1239
        onDisconnect();
 
1240
}
 
1241
 
 
1242
void Task::debug(const char *fmt, ...)
 
1243
{
 
1244
        char *buf;
 
1245
        QString str;
 
1246
        int size = 1024;
 
1247
        int r;
 
1248
 
 
1249
        do {
 
1250
                buf = new char[size];
 
1251
                va_list ap;
 
1252
                va_start(ap, fmt);
 
1253
                r = vsnprintf(buf, size, fmt, ap);
 
1254
                va_end(ap);
 
1255
 
 
1256
                if(r != -1)
 
1257
                        str = QString(buf);
 
1258
 
 
1259
                delete [] buf;
 
1260
 
 
1261
                size *= 2;
 
1262
        } while(r == -1);
 
1263
 
 
1264
        debug(str);
 
1265
}
 
1266
 
 
1267
void Task::debug(const QString &str)
 
1268
{
 
1269
        client()->debug(QString("%1: ").arg(className()) + str);
 
1270
}
 
1271
 
 
1272
bool Task::iqVerify(const QDomElement &x, const Jid &to, const QString &id, const QString &xmlns)
 
1273
{
 
1274
        if(x.tagName() != "iq")
 
1275
                return false;
 
1276
 
 
1277
        Jid from(x.attribute("from"));
 
1278
        Jid local = client()->jid();
 
1279
        Jid server = client()->host();
 
1280
 
 
1281
        // empty 'from' ?
 
1282
        if(from.isEmpty()) {
 
1283
                // allowed if we are querying the server
 
1284
                if(!to.isEmpty() && !to.compare(server))
 
1285
                        return false;
 
1286
        }
 
1287
        // from ourself?
 
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))
 
1291
                        return false;
 
1292
        }
 
1293
        // from anywhere else?
 
1294
        else {
 
1295
                if(!from.compare(to))
 
1296
                        return false;
 
1297
        }
 
1298
 
 
1299
        if(!id.isEmpty()) {
 
1300
                if(x.attribute("id") != id)
 
1301
                        return false;
 
1302
        }
 
1303
 
 
1304
        if(!xmlns.isEmpty()) {
 
1305
                if(queryNS(x) != xmlns)
 
1306
                        return false;
 
1307
        }
 
1308
 
 
1309
        return true;
 
1310
}
 
1311
 
 
1312
//---------------------------------------------------------------------------
 
1313
// LiveRosterItem
 
1314
//---------------------------------------------------------------------------
 
1315
LiveRosterItem::LiveRosterItem(const Jid &jid)
 
1316
:RosterItem(jid)
 
1317
{
 
1318
        setFlagForDelete(false);
 
1319
}
 
1320
 
 
1321
LiveRosterItem::LiveRosterItem(const RosterItem &i)
 
1322
{
 
1323
        setRosterItem(i);
 
1324
        setFlagForDelete(false);
 
1325
}
 
1326
 
 
1327
LiveRosterItem::~LiveRosterItem()
 
1328
{
 
1329
}
 
1330
 
 
1331
void LiveRosterItem::setRosterItem(const RosterItem &i)
 
1332
{
 
1333
        setJid(i.jid());
 
1334
        setName(i.name());
 
1335
        setGroups(i.groups());
 
1336
        setSubscription(i.subscription());
 
1337
        setAsk(i.ask());
 
1338
        setIsPush(i.isPush());
 
1339
}
 
1340
 
 
1341
ResourceList & LiveRosterItem::resourceList()
 
1342
{
 
1343
        return v_resourceList;
 
1344
}
 
1345
 
 
1346
ResourceList::Iterator LiveRosterItem::priority()
 
1347
{
 
1348
        return v_resourceList.priority();
 
1349
}
 
1350
 
 
1351
const ResourceList & LiveRosterItem::resourceList() const
 
1352
{
 
1353
        return v_resourceList;
 
1354
}
 
1355
 
 
1356
ResourceList::ConstIterator LiveRosterItem::priority() const
 
1357
{
 
1358
        return v_resourceList.priority();
 
1359
}
 
1360
 
 
1361
bool LiveRosterItem::isAvailable() const
 
1362
{
 
1363
        if(v_resourceList.count() > 0)
 
1364
                return true;
 
1365
        return false;
 
1366
}
 
1367
 
 
1368
const Status & LiveRosterItem::lastUnavailableStatus() const
 
1369
{
 
1370
        return v_lastUnavailableStatus;
 
1371
}
 
1372
 
 
1373
bool LiveRosterItem::flagForDelete() const
 
1374
{
 
1375
        return v_flagForDelete;
 
1376
}
 
1377
 
 
1378
void LiveRosterItem::setLastUnavailableStatus(const Status &s)
 
1379
{
 
1380
        v_lastUnavailableStatus = s;
 
1381
}
 
1382
 
 
1383
void LiveRosterItem::setFlagForDelete(bool b)
 
1384
{
 
1385
        v_flagForDelete = b;
 
1386
}
 
1387
 
 
1388
//---------------------------------------------------------------------------
 
1389
// LiveRoster
 
1390
//---------------------------------------------------------------------------
 
1391
LiveRoster::LiveRoster()
 
1392
:QValueList<LiveRosterItem>()
 
1393
{
 
1394
}
 
1395
 
 
1396
LiveRoster::~LiveRoster()
 
1397
{
 
1398
}
 
1399
 
 
1400
void LiveRoster::flagAllForDelete()
 
1401
{
 
1402
        for(Iterator it = begin(); it != end(); ++it)
 
1403
                (*it).setFlagForDelete(true);
 
1404
}
 
1405
 
 
1406
LiveRoster::Iterator LiveRoster::find(const Jid &j, bool compareRes)
 
1407
{
 
1408
        Iterator it;
 
1409
        for(it = begin(); it != end(); ++it) {
 
1410
                if((*it).jid().compare(j, compareRes))
 
1411
                        break;
 
1412
        }
 
1413
        return it;
 
1414
}
 
1415
 
 
1416
LiveRoster::ConstIterator LiveRoster::find(const Jid &j, bool compareRes) const
 
1417
{
 
1418
        ConstIterator it;
 
1419
        for(it = begin(); it != end(); ++it) {
 
1420
                if((*it).jid().compare(j, compareRes))
 
1421
                        break;
 
1422
        }
 
1423
        return it;
 
1424
}
 
1425
 
 
1426
}