source: psi/trunk/src/psievent.cpp@ 16

Last change on this file since 16 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 15.0 KB
Line 
1/*
2 * psievent.h - events
3 * Copyright (C) 2001, 2002 Justin Karneges
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * 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 "psievent.h"
22
23#include <qdom.h>
24
25#include "psicon.h"
26#include "psiaccount.h"
27#include "xmpp_xmlcommon.h"
28#include "filetransfer.h"
29
30using namespace XMLHelper;
31
32static PsiEvent *copyPsiEvent(PsiEvent *fe)
33{
34 PsiEvent *e = 0;
35 if ( fe->inherits("MessageEvent") )
36 e = new MessageEvent( *((MessageEvent *)fe) );
37 else if ( fe->inherits("AuthEvent") )
38 e = new AuthEvent( *((AuthEvent *)fe) );
39 else if ( fe->inherits("PGPEvent") )
40 e = new PGPEvent( *((PGPEvent *)fe) );
41 else
42 qWarning("copyPsiEvent(): Failed: unknown event type: %s", fe->className());
43
44 return 0;
45}
46
47//----------------------------------------------------------------------------
48// DummyStream
49//----------------------------------------------------------------------------
50class DummyStream : public Stream
51{
52public:
53 QDomDocument & doc() const { return v_doc; }
54 QString baseNS() const { return QString::null; }
55 bool old() const { return false; }
56
57 void close() { }
58 bool stanzaAvailable() const { return false; }
59 Stanza read() { return Stanza(); }
60 void write(const Stanza &) { }
61
62 int errorCondition() const { return 0; }
63 QString errorText() const { return QString::null; }
64 QDomElement errorAppSpec() const { return v_doc.documentElement(); }
65
66private:
67 static QDomDocument v_doc;
68};
69
70QDomDocument DummyStream::v_doc;
71
72//----------------------------------------------------------------------------
73// PsiEvent
74//----------------------------------------------------------------------------
75PsiEvent::PsiEvent(PsiAccount *acc)
76{
77 v_originLocal = false;
78 v_late = false;
79 v_account = acc;
80}
81
82PsiEvent::PsiEvent(const PsiEvent &from)
83: QObject()
84{
85 v_originLocal = from.v_originLocal;
86 v_late = from.v_late;
87 v_ts = from.v_ts;
88 v_jid = from.v_jid;
89 v_account = from.v_account;
90}
91
92PsiEvent::~PsiEvent()
93{
94}
95
96XMPP::Jid PsiEvent::jid() const
97{
98 return v_jid;
99}
100
101void PsiEvent::setJid(const XMPP::Jid &j)
102{
103 v_jid = j;
104}
105
106PsiAccount *PsiEvent::account() const
107{
108 return v_account;
109}
110
111bool PsiEvent::originLocal() const
112{
113 return v_originLocal;
114}
115
116bool PsiEvent::late() const
117{
118 return v_late;
119}
120
121QDateTime PsiEvent::timeStamp() const
122{
123 return v_ts;
124}
125
126void PsiEvent::setOriginLocal(bool b)
127{
128 v_originLocal = b;
129}
130
131void PsiEvent::setLate(bool b)
132{
133 v_late = b;
134}
135
136void PsiEvent::setTimeStamp(const QDateTime &t)
137{
138 v_ts = t;
139}
140
141QDomElement PsiEvent::toXml(QDomDocument *doc) const
142{
143 QDomElement e = doc->createElement("event");
144 e.setAttribute("type", className());
145
146 e.appendChild( textTag(*doc, "originLocal", v_originLocal) );
147 e.appendChild( textTag(*doc, "late", v_late) );
148 e.appendChild( textTag(*doc, "ts", v_ts.toString( ISODate )) );
149 if ( !v_jid.full().isEmpty() )
150 e.appendChild( textTag(*doc, "jid", v_jid.full()) );
151
152 if ( v_account )
153 e.appendChild( textTag(*doc, "account", v_account->name()) );
154
155 return e;
156}
157
158bool PsiEvent::fromXml(PsiCon *psi, PsiAccount *account, const QDomElement *e)
159{
160 if ( e->tagName() != "event" )
161 return false;
162 if ( e->attribute("type") != className() )
163 return false;
164
165 readBoolEntry(*e, "originLocal", &v_originLocal);
166 readBoolEntry(*e, "late", &v_late);
167 v_ts = QDateTime::fromString(subTagText(*e, "ts"), ISODate);
168 v_jid = Jid( subTagText(*e, "jid") );
169
170 if ( account ) {
171 v_account = account;
172 }
173 else if ( hasSubTag(*e, "account") ) {
174 PsiAccountList list = psi->accountList();
175 PsiAccountListIt it(list);
176 QString accName = subTagText(*e, "account");
177 for ( ; it.current(); ++it) {
178 if ( it.current()->name() == accName ) {
179 v_account = it.current();
180 break;
181 }
182 }
183 }
184
185 return true;
186}
187
188int PsiEvent::priority() const
189{
190 return Options::EventPriorityDontCare;
191}
192
193PsiEvent *PsiEvent::copy() const
194{
195 return 0;
196}
197
198//----------------------------------------------------------------------------
199// MessageEvent
200//----------------------------------------------------------------------------
201
202MessageEvent::MessageEvent(PsiAccount *acc)
203: PsiEvent(acc)
204{
205 v_sentToChatWindow = false;
206}
207
208MessageEvent::MessageEvent(const XMPP::Message &m, PsiAccount *acc)
209: PsiEvent(acc)
210{
211 v_sentToChatWindow = false;
212 setMessage(m);
213}
214
215MessageEvent::MessageEvent(const MessageEvent &from)
216: PsiEvent(from), v_m(from.v_m), v_sentToChatWindow(from.v_sentToChatWindow)
217{
218}
219
220MessageEvent::~MessageEvent()
221{
222}
223
224int MessageEvent::type() const
225{
226 return Message;
227}
228
229Jid MessageEvent::from() const
230{
231 return v_m.from();
232}
233
234void MessageEvent::setFrom(const Jid &j)
235{
236 v_m.setFrom(j);
237}
238
239bool MessageEvent::sentToChatWindow() const
240{
241 return v_sentToChatWindow;
242}
243
244const XMPP::Message & MessageEvent::message() const
245{
246 return v_m;
247}
248
249void MessageEvent::setSentToChatWindow(bool b)
250{
251 v_sentToChatWindow = b;
252}
253
254void MessageEvent::setMessage(const XMPP::Message &m)
255{
256 v_m = m;
257 setTimeStamp ( v_m.timeStamp() );
258 setLate ( v_m.spooled() );
259}
260
261QDomElement MessageEvent::toXml(QDomDocument *doc) const
262{
263 QDomElement e = PsiEvent::toXml(doc);
264
265 DummyStream stream;
266 Stanza s = v_m.toStanza(&stream);
267 e.appendChild( s.element() );
268
269 return e;
270}
271
272bool MessageEvent::fromXml(PsiCon *psi, PsiAccount *account, const QDomElement *e)
273{
274 if ( !PsiEvent::fromXml(psi, account, e) )
275 return false;
276
277 bool found = false;
278 QDomElement msg = findSubTag(*e, "message", &found);
279 if ( found ) {
280 DummyStream stream;
281 Stanza s = stream.createStanza(msg);
282 v_m.fromStanza(s, 0); // FIXME: fix tzoffset?
283 return true;
284 }
285
286 return false;
287}
288
289int MessageEvent::priority() const
290{
291 if ( v_m.type() == "headline" )
292 return option.eventPriorityHeadline;
293 else if ( v_m.type() == "chat" )
294 return option.eventPriorityChat;
295
296 return option.eventPriorityMessage;
297}
298
299PsiEvent *MessageEvent::copy() const
300{
301 return new MessageEvent( *this );
302}
303
304//----------------------------------------------------------------------------
305// AuthEvent
306//----------------------------------------------------------------------------
307
308AuthEvent::AuthEvent(const Jid &j, const QString &authType, PsiAccount *acc)
309: PsiEvent(acc)
310{
311 v_from = j;
312 v_at = authType;
313}
314
315AuthEvent::AuthEvent(const AuthEvent &from)
316: PsiEvent(from), v_from(from.v_from), v_at(from.v_at)
317{
318}
319
320AuthEvent::~AuthEvent()
321{
322}
323
324int AuthEvent::type() const
325{
326 return Auth;
327}
328
329Jid AuthEvent::from() const
330{
331 return v_from;
332}
333
334void AuthEvent::setFrom(const Jid &j)
335{
336 v_from = j;
337}
338
339QString AuthEvent::authType() const
340{
341 return v_at;
342}
343
344QDomElement AuthEvent::toXml(QDomDocument *doc) const
345{
346 QDomElement e = PsiEvent::toXml(doc);
347
348 e.appendChild( textTag(*doc, "from", v_from.full()) );
349 e.appendChild( textTag(*doc, "authType", v_at) );
350
351 return e;
352}
353
354bool AuthEvent::fromXml(PsiCon *psi, PsiAccount *account, const QDomElement *e)
355{
356 if ( !PsiEvent::fromXml(psi, account, e) )
357 return false;
358
359 v_from = Jid( subTagText(*e, "from") );
360 v_at = subTagText(*e, "authType");
361
362 return false;
363}
364
365int AuthEvent::priority() const
366{
367 return option.eventPriorityAuth;
368}
369
370PsiEvent *AuthEvent::copy() const
371{
372 return new AuthEvent( *this );
373}
374
375//----------------------------------------------------------------------------
376// FileEvent
377//----------------------------------------------------------------------------
378FileEvent::FileEvent(const Jid &j, FileTransfer *_ft, PsiAccount *acc)
379:PsiEvent(acc)
380{
381 v_from = j;
382 ft = _ft;
383}
384
385FileEvent::~FileEvent()
386{
387 delete ft;
388}
389
390int FileEvent::priority() const
391{
392 return option.eventPriorityFile;
393}
394
395Jid FileEvent::from() const
396{
397 return v_from;
398}
399
400void FileEvent::setFrom(const Jid &j)
401{
402 v_from = j;
403}
404
405FileTransfer *FileEvent::takeFileTransfer()
406{
407 FileTransfer *_ft = ft;
408 ft = 0;
409 return _ft;
410}
411
412//----------------------------------------------------------------------------
413// EventQueue
414//----------------------------------------------------------------------------
415
416class EventItem
417{
418public:
419 EventItem(PsiEvent *_e, int i)
420 {
421 e = _e;
422 v_id = i;
423 }
424
425 EventItem(const EventItem &from)
426 {
427 e = copyPsiEvent(from.e);
428 v_id = from.v_id;
429 }
430
431 ~EventItem()
432 {
433 }
434
435 int id() const
436 {
437 return v_id;
438 }
439
440 PsiEvent *event() const
441 {
442 return e;
443 }
444
445private:
446 PsiEvent *e;
447 int v_id;
448};
449
450class EventQueue::Private
451{
452public:
453 Private() {
454 list.setAutoDelete(true);
455 }
456
457 QPtrList<EventItem> list;
458 PsiCon *psi;
459 PsiAccount *account;
460};
461
462EventQueue::EventQueue(PsiAccount *account)
463{
464 d = new Private();
465
466 d->account = account;
467 d->psi = account->psi();
468}
469
470EventQueue::EventQueue(const EventQueue &from)
471 : QObject()
472{
473 d = new Private();
474
475 *this = from;
476}
477
478EventQueue::~EventQueue()
479{
480 delete d;
481}
482
483int EventQueue::nextId() const
484{
485 QPtrListIterator<EventItem> it(d->list);
486 EventItem *i = it.current();
487 if(!i)
488 return -1;
489 return i->id();
490}
491
492int EventQueue::count() const
493{
494 return d->list.count();
495}
496
497int EventQueue::count(const Jid &j, bool compareRes) const
498{
499 int total = 0;
500
501 QPtrListIterator<EventItem> it(d->list);
502 for(EventItem *i; (i = it.current()); ++it) {
503 Jid j2(i->event()->jid());
504 if(j.compare(j2, compareRes))
505 ++total;
506 }
507
508 return total;
509}
510
511void EventQueue::enqueue(PsiEvent *e)
512{
513 EventItem *i = new EventItem(e, d->psi->getId());
514
515 int prior = e->priority();
516 bool found = false;
517
518 // skip all with higher or equal priority
519 for ( EventItem *ei = d->list.first(); ei; ei = d->list.next() ) {
520 if ( ei && ei->event()->priority() < prior ) {
521 d->list.insert(d->list.find(ei), i);
522 found = true;
523 break;
524 }
525 }
526
527 // everything else
528 if ( !found )
529 d->list.append(i);
530
531 emit queueChanged();
532}
533
534void EventQueue::dequeue(PsiEvent *e)
535{
536 if ( !e )
537 return;
538
539 QPtrListIterator<EventItem> it(d->list);
540 for(EventItem *i; (i = it.current()); ++it) {
541 if ( e == i->event() ) {
542 d->list.remove(i);
543 return;
544 }
545 }
546
547 emit queueChanged();
548}
549
550PsiEvent *EventQueue::dequeue(const Jid &j, bool compareRes)
551{
552 QPtrListIterator<EventItem> it(d->list);
553 for(EventItem *i; (i = it.current()); ++it) {
554 PsiEvent *e = i->event();
555 Jid j2(e->jid());
556 if(j.compare(j2, compareRes)) {
557 d->list.removeRef(i);
558 emit queueChanged();
559 return e;
560 }
561 }
562
563 return 0;
564}
565
566PsiEvent *EventQueue::peek(const Jid &j, bool compareRes) const
567{
568 QPtrListIterator<EventItem> it(d->list);
569 for(EventItem *i; (i = it.current()); ++it) {
570 PsiEvent *e = i->event();
571 Jid j2(e->jid());
572 if(j.compare(j2, compareRes)) {
573 return e;
574 }
575 }
576
577 return 0;
578}
579
580PsiEvent *EventQueue::dequeueNext()
581{
582 QPtrListIterator<EventItem> it(d->list);
583 EventItem *i = it.current();
584 if(!i)
585 return 0;
586 PsiEvent *e = i->event();
587 d->list.remove(it);
588 emit queueChanged();
589 return e;
590}
591
592PsiEvent *EventQueue::peekNext() const
593{
594 QPtrListIterator<EventItem> it(d->list);
595 EventItem *i = it.current();
596 if(!i)
597 return 0;
598 return i->event();
599}
600
601PsiEvent *EventQueue::peekFirstChat(const Jid &j, bool compareRes) const
602{
603 QPtrListIterator<EventItem> it(d->list);
604 for(EventItem *i; (i = it.current()); ++it) {
605 PsiEvent *e = i->event();
606 if(e->type() == PsiEvent::Message) {
607 MessageEvent *me = (MessageEvent *)e;
608 if(j.compare(me->from(), compareRes) && me->message().type() == "chat")
609 return e;
610 }
611 }
612
613 return 0;
614}
615
616bool EventQueue::hasChats(const Jid &j, bool compareRes) const
617{
618 return (peekFirstChat(j, compareRes) ? true: false);
619}
620
621// this function extracts all chats from the queue, and returns a list of queue positions
622void EventQueue::extractChats(QPtrList<PsiEvent> *el, const Jid &j, bool compareRes)
623{
624 bool changed = false;
625
626 QPtrListIterator<EventItem> it(d->list);
627 for(EventItem *i; (i = it.current());) {
628 PsiEvent *e = i->event();
629 if(e->type() == PsiEvent::Message) {
630 MessageEvent *me = (MessageEvent *)e;
631 if(j.compare(me->from(), compareRes) && me->message().type() == "chat") {
632 el->append(me);
633 d->list.remove(it);
634 changed = true;
635 continue;
636 }
637 }
638 ++it;
639 }
640
641 if ( changed )
642 emit queueChanged();
643}
644
645void EventQueue::printContent() const
646{
647 QPtrListIterator<EventItem> it(d->list);
648 for(EventItem *i; (i = it.current()); ++it) {
649 PsiEvent *e = i->event();
650 printf(" %d: (%d) from=[%s] jid=[%s]\n", i->id(), e->type(), e->from().full().latin1(), e->jid().full().latin1());
651 }
652}
653
654void EventQueue::clear()
655{
656 d->list.clear();
657
658 emit queueChanged();
659}
660
661// this function removes all events associated with the input jid
662void EventQueue::clear(const Jid &j, bool compareRes)
663{
664 bool changed = false;
665
666 QPtrListIterator<EventItem> it(d->list);
667 for(EventItem *i; (i = it.current());) {
668 PsiEvent *e = i->event();
669 Jid j2(e->jid());
670 if(j.compare(j2, compareRes)) {
671 d->list.removeRef(i);
672 changed = true;
673 }
674 else
675 ++it;
676 }
677
678 if ( changed )
679 emit queueChanged();
680}
681
682EventQueue &EventQueue::operator= (const EventQueue &from)
683{
684 d->list.clear();
685 d->psi = from.d->psi;
686
687 QPtrListIterator<EventItem> it(d->list);
688 for(EventItem *i; (i = it.current()); ++i) {
689 PsiEvent *e = i->event();
690
691 enqueue( copyPsiEvent(e) );
692 }
693
694 return *this;
695}
696
697QDomElement EventQueue::toXml(QDomDocument *doc) const
698{
699 QDomElement e = doc->createElement("eventQueue");
700 e.setAttribute("version", "1.0");
701 e.appendChild(textTag(doc, "progver", PROG_VERSION));
702
703 QPtrListIterator<EventItem> it(d->list);
704 for(EventItem *i; (i = it.current()); ++it) {
705 QDomElement event = (*it)->event()->toXml(doc);
706 e.appendChild( event );
707 }
708
709 return e;
710}
711
712bool EventQueue::fromXml(const QDomElement *q)
713{
714 if ( !q )
715 return false;
716
717 if ( q->tagName() != "eventQueue" )
718 return false;
719
720 if ( q->attribute("version") != "1.0" )
721 return false;
722
723 QString progver = subTagText(*q, "progver");
724
725 for(QDomNode n = q->firstChild(); !n.isNull(); n = n.nextSibling()) {
726 QDomElement e = n.toElement();
727 if( e.isNull() )
728 continue;
729
730 if ( e.tagName() != "event" )
731 continue;
732
733 PsiEvent *event = 0;
734 QString eventType = e.attribute("type");
735 if ( eventType == "MessageEvent" ) {
736 event = new MessageEvent(0);
737 if ( !event->fromXml(d->psi, d->account, &e) ) {
738 delete event;
739 event = 0;
740 }
741 }
742 else if ( eventType == "AuthEvent" ) {
743 event = new AuthEvent("", "", 0);
744 if ( !event->fromXml(d->psi, d->account, &e) ) {
745 delete event;
746 event = 0;
747 }
748 }
749
750 if ( event )
751 emit handleEvent( event );
752 }
753
754 return true;
755}
756
757bool EventQueue::toFile(const QString &fname)
758{
759 QDomDocument doc;
760
761 QDomElement element = toXml(&doc);
762 doc.appendChild(element);
763
764 QFile f( fname );
765 if( !f.open(IO_WriteOnly) )
766 return FALSE;
767 QTextStream t;
768 t.setDevice( &f );
769 t.setEncoding( QTextStream::UnicodeUTF8 );
770 t << doc.toString(4);
771 t.unsetDevice();
772 f.close();
773
774 return TRUE;
775}
776
777bool EventQueue::fromFile(const QString &fname)
778{
779 QString confver;
780 QDomDocument doc;
781
782 QFile f(fname);
783 if(!f.open(IO_ReadOnly))
784 return FALSE;
785 if(!doc.setContent(&f, true))
786 return FALSE;
787 f.close();
788
789 QDomElement base = doc.documentElement();
790 return fromXml(&base);
791}
Note: See TracBrowser for help on using the repository browser.