~ubuntu-branches/ubuntu/jaunty/psi/jaunty

« back to all changes in this revision

Viewing changes to src/eventdb.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
 * eventdb.cpp - asynchronous I/O event database
 
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"eventdb.h"
 
22
 
 
23
#define FAKEDELAY 0
 
24
 
 
25
#include<qfile.h>
 
26
#include<qptrlist.h>
 
27
#include<qtimer.h>
 
28
#include<qtextstream.h>
 
29
#include<qvaluevector.h>
 
30
#include"common.h"
 
31
#include"profiles.h"
 
32
 
 
33
 
 
34
//----------------------------------------------------------------------------
 
35
// EDBItem
 
36
//----------------------------------------------------------------------------
 
37
EDBItem::EDBItem(PsiEvent *event, const QString &id, const QString &prevId, const QString &nextId)
 
38
{
 
39
        e = event;
 
40
        v_id = id;
 
41
        v_prevId = prevId;
 
42
        v_nextId = nextId;
 
43
}
 
44
 
 
45
EDBItem::~EDBItem()
 
46
{
 
47
        delete e;
 
48
}
 
49
 
 
50
PsiEvent *EDBItem::event() const
 
51
{
 
52
        return e;
 
53
}
 
54
 
 
55
const QString & EDBItem::id() const
 
56
{
 
57
        return v_id;
 
58
}
 
59
 
 
60
const QString & EDBItem::nextId() const
 
61
{
 
62
        return v_nextId;
 
63
}
 
64
 
 
65
const QString & EDBItem::prevId() const
 
66
{
 
67
        return v_prevId;
 
68
}
 
69
 
 
70
 
 
71
//----------------------------------------------------------------------------
 
72
// EDBHandle
 
73
//----------------------------------------------------------------------------
 
74
class EDBHandle::Private
 
75
{
 
76
public:
 
77
        Private() {}
 
78
 
 
79
        EDB *edb;
 
80
        EDBResult *r;
 
81
        bool busy;
 
82
        bool writeSuccess;
 
83
        int listeningFor;
 
84
        int lastRequestType;
 
85
};
 
86
 
 
87
EDBHandle::EDBHandle(EDB *edb)
 
88
:QObject(0)
 
89
{
 
90
        d = new Private;
 
91
        d->edb = edb;
 
92
        d->r = 0;
 
93
        d->busy = false;
 
94
        d->writeSuccess = false;
 
95
        d->listeningFor = -1;
 
96
        d->lastRequestType = Read;
 
97
 
 
98
        d->edb->reg(this);
 
99
}
 
100
 
 
101
EDBHandle::~EDBHandle()
 
102
{
 
103
        d->edb->unreg(this);
 
104
 
 
105
        delete d->r;
 
106
        delete d;
 
107
}
 
108
 
 
109
void EDBHandle::getLatest(const Jid &j, int len)
 
110
{
 
111
        d->busy = true;
 
112
        d->lastRequestType = Read;
 
113
        d->listeningFor = d->edb->op_getLatest(j, len);
 
114
}
 
115
 
 
116
void EDBHandle::getOldest(const Jid &j, int len)
 
117
{
 
118
        d->busy = true;
 
119
        d->lastRequestType = Read;
 
120
        d->listeningFor = d->edb->op_getOldest(j, len);
 
121
}
 
122
 
 
123
void EDBHandle::get(const Jid &j, const QString &id, int direction, int len)
 
124
{
 
125
        d->busy = true;
 
126
        d->lastRequestType = Read;
 
127
        d->listeningFor = d->edb->op_get(j, id, direction, len);
 
128
}
 
129
 
 
130
void EDBHandle::find(const QString &str, const Jid &j, const QString &id, int direction)
 
131
{
 
132
        d->busy = true;
 
133
        d->lastRequestType = Read;
 
134
        d->listeningFor = d->edb->op_find(str, j, id, direction);
 
135
}
 
136
 
 
137
void EDBHandle::append(const Jid &j, PsiEvent *e)
 
138
{
 
139
        d->busy = true;
 
140
        d->lastRequestType = Write;
 
141
        d->listeningFor = d->edb->op_append(j, e);
 
142
}
 
143
 
 
144
bool EDBHandle::busy() const
 
145
{
 
146
        return d->busy;
 
147
}
 
148
 
 
149
const EDBResult *EDBHandle::result() const
 
150
{
 
151
        return d->r;
 
152
}
 
153
 
 
154
bool EDBHandle::writeSuccess() const
 
155
{
 
156
        return d->writeSuccess;
 
157
}
 
158
 
 
159
void EDBHandle::edb_resultReady(EDBResult *r)
 
160
{
 
161
        d->busy = false;
 
162
        if(r == 0) {
 
163
                delete d->r;
 
164
                d->r = 0;
 
165
        }
 
166
        else {
 
167
                d->r = r;
 
168
        }
 
169
        d->listeningFor = -1;
 
170
        finished();
 
171
}
 
172
 
 
173
void EDBHandle::edb_writeFinished(bool b)
 
174
{
 
175
        d->busy = false;
 
176
        d->writeSuccess = b;
 
177
        d->listeningFor = -1;
 
178
        finished();
 
179
}
 
180
 
 
181
int EDBHandle::listeningFor() const
 
182
{
 
183
        return d->listeningFor;
 
184
}
 
185
 
 
186
int EDBHandle::lastRequestType() const
 
187
{
 
188
        return d->lastRequestType;
 
189
}
 
190
 
 
191
 
 
192
//----------------------------------------------------------------------------
 
193
// EDB
 
194
//----------------------------------------------------------------------------
 
195
class EDB::Private
 
196
{
 
197
public:
 
198
        Private() {}
 
199
 
 
200
        QPtrList<EDBHandle> list;
 
201
        int reqid_base;
 
202
};
 
203
 
 
204
EDB::EDB()
 
205
{
 
206
        d = new Private;
 
207
        d->reqid_base = 0;
 
208
}
 
209
 
 
210
EDB::~EDB()
 
211
{
 
212
        d->list.setAutoDelete(true);
 
213
        d->list.clear();
 
214
        delete d;
 
215
}
 
216
 
 
217
int EDB::genUniqueId() const
 
218
{
 
219
        return d->reqid_base++;
 
220
}
 
221
 
 
222
void EDB::reg(EDBHandle *h)
 
223
{
 
224
        d->list.append(h);
 
225
}
 
226
 
 
227
void EDB::unreg(EDBHandle *h)
 
228
{
 
229
        d->list.removeRef(h);
 
230
}
 
231
 
 
232
int EDB::op_getLatest(const Jid &j, int len)
 
233
{
 
234
        return getLatest(j, len);
 
235
}
 
236
 
 
237
int EDB::op_getOldest(const Jid &j, int len)
 
238
{
 
239
        return getOldest(j, len);
 
240
}
 
241
 
 
242
int EDB::op_get(const Jid &jid, const QString &id, int direction, int len)
 
243
{
 
244
        return get(jid, id, direction, len);
 
245
}
 
246
 
 
247
int EDB::op_find(const QString &str, const Jid &j, const QString &id, int direction)
 
248
{
 
249
        return find(str, j, id, direction);
 
250
}
 
251
 
 
252
int EDB::op_append(const Jid &j, PsiEvent *e)
 
253
{
 
254
        return append(j, e);
 
255
}
 
256
 
 
257
void EDB::resultReady(int req, EDBResult *r)
 
258
{
 
259
        // deliver
 
260
        QPtrListIterator<EDBHandle> it(d->list);
 
261
        for(EDBHandle *h; (h = it.current()); ++it) {
 
262
                if(h->listeningFor() == req) {
 
263
                        h->edb_resultReady(r);
 
264
                        return;
 
265
                }
 
266
        }
 
267
        delete r;
 
268
}
 
269
 
 
270
void EDB::writeFinished(int req, bool b)
 
271
{
 
272
        // deliver
 
273
        QPtrListIterator<EDBHandle> it(d->list);
 
274
        for(EDBHandle *h; (h = it.current()); ++it) {
 
275
                if(h->listeningFor() == req) {
 
276
                        h->edb_writeFinished(b);
 
277
                        return;
 
278
                }
 
279
        }
 
280
}
 
281
 
 
282
 
 
283
//----------------------------------------------------------------------------
 
284
// EDBFlatFile
 
285
//----------------------------------------------------------------------------
 
286
struct item_file_req
 
287
{
 
288
        Jid j;
 
289
        int type; // 0 = latest, 1 = oldest, 2 = random, 3 = write
 
290
        int len;
 
291
        int dir;
 
292
        int id;
 
293
        int eventId;
 
294
        QString findStr;
 
295
        PsiEvent *event;
 
296
};
 
297
 
 
298
class EDBFlatFile::Private
 
299
{
 
300
public:
 
301
        Private() {}
 
302
 
 
303
        QPtrList<File> flist;
 
304
        QPtrList<item_file_req> rlist;
 
305
};
 
306
 
 
307
EDBFlatFile::EDBFlatFile()
 
308
:EDB()
 
309
{
 
310
        d = new Private;
 
311
}
 
312
 
 
313
EDBFlatFile::~EDBFlatFile()
 
314
{
 
315
        d->rlist.setAutoDelete(true);
 
316
        d->flist.setAutoDelete(true);
 
317
        d->flist.clear();
 
318
 
 
319
        delete d;
 
320
}
 
321
 
 
322
int EDBFlatFile::getLatest(const Jid &j, int len)
 
323
{
 
324
        item_file_req *r = new item_file_req;
 
325
        r->j = j;
 
326
        r->type = 0;
 
327
        r->len = len < 1 ? 1: len;
 
328
        r->id = genUniqueId();
 
329
        d->rlist.append(r);
 
330
 
 
331
        QTimer::singleShot(FAKEDELAY, this, SLOT(performRequests()));
 
332
        return r->id;
 
333
}
 
334
 
 
335
int EDBFlatFile::getOldest(const Jid &j, int len)
 
336
{
 
337
        item_file_req *r = new item_file_req;
 
338
        r->j = j;
 
339
        r->type = 1;
 
340
        r->len = len < 1 ? 1: len;
 
341
        r->id = genUniqueId();
 
342
        d->rlist.append(r);
 
343
 
 
344
        QTimer::singleShot(FAKEDELAY, this, SLOT(performRequests()));
 
345
        return r->id;
 
346
}
 
347
 
 
348
int EDBFlatFile::get(const Jid &j, const QString &id, int direction, int len)
 
349
{
 
350
        item_file_req *r = new item_file_req;
 
351
        r->j = j;
 
352
        r->type = 2;
 
353
        r->len = len < 1 ? 1: len;
 
354
        r->dir = direction;
 
355
        r->eventId = id.toInt();
 
356
        r->id = genUniqueId();
 
357
        d->rlist.append(r);
 
358
 
 
359
        QTimer::singleShot(FAKEDELAY, this, SLOT(performRequests()));
 
360
        return r->id;
 
361
}
 
362
 
 
363
int EDBFlatFile::find(const QString &str, const Jid &j, const QString &id, int direction)
 
364
{
 
365
        item_file_req *r = new item_file_req;
 
366
        r->j = j;
 
367
        r->type = 4;
 
368
        r->len = 1;
 
369
        r->dir = direction;
 
370
        r->findStr = str;
 
371
        r->eventId = id.toInt();
 
372
        r->id = genUniqueId();
 
373
        d->rlist.append(r);
 
374
 
 
375
        QTimer::singleShot(FAKEDELAY, this, SLOT(performRequests()));
 
376
        return r->id;
 
377
}
 
378
 
 
379
int EDBFlatFile::append(const Jid &j, PsiEvent *e)
 
380
{
 
381
        item_file_req *r = new item_file_req;
 
382
        r->j = j;
 
383
        r->type = 3;
 
384
        if(e->type() == PsiEvent::Message)
 
385
                r->event = new MessageEvent(*(MessageEvent *)e);
 
386
        else if(e->type() == PsiEvent::Auth)
 
387
                r->event = new AuthEvent(*(AuthEvent *)e);
 
388
        r->id = genUniqueId();
 
389
        d->rlist.append(r);
 
390
 
 
391
        QTimer::singleShot(FAKEDELAY, this, SLOT(performRequests()));
 
392
        return r->id;
 
393
}
 
394
 
 
395
EDBFlatFile::File *EDBFlatFile::findFile(const Jid &j) const
 
396
{
 
397
        QPtrListIterator<File> it(d->flist);
 
398
        for(File *i; (i = it.current()); ++it) {
 
399
                if(i->j.compare(j, false))
 
400
                        return i;
 
401
        }
 
402
        return 0;
 
403
}
 
404
 
 
405
EDBFlatFile::File *EDBFlatFile::ensureFile(const Jid &j)
 
406
{
 
407
        File *i = findFile(j);
 
408
        if(!i) {
 
409
                i = new File(Jid(j.userHost()));
 
410
                connect(i, SIGNAL(timeout()), SLOT(file_timeout()));
 
411
                d->flist.append(i);
 
412
        }
 
413
        return i;
 
414
}
 
415
 
 
416
void EDBFlatFile::performRequests()
 
417
{
 
418
        if(d->rlist.isEmpty())
 
419
                return;
 
420
 
 
421
        item_file_req *r = d->rlist.first();
 
422
        d->rlist.removeRef(r);
 
423
 
 
424
        File *f = ensureFile(r->j);
 
425
        int type = r->type;
 
426
        if(type >= 0 && type <= 2) {
 
427
                int id, direction;
 
428
 
 
429
                if(type == 0) {
 
430
                        direction = Backward;
 
431
                        id = f->total()-1;
 
432
                }
 
433
                else if(type == 1) {
 
434
                        direction = Forward;
 
435
                        id = 0;
 
436
                }
 
437
                else {
 
438
                        direction = r->dir;
 
439
                        id = r->eventId;
 
440
                }
 
441
 
 
442
                int len;
 
443
                if(direction == Forward) {
 
444
                        if(id + r->len > f->total())
 
445
                                len = f->total() - id;
 
446
                        else
 
447
                                len = r->len;
 
448
                }
 
449
                else {
 
450
                        if((id+1) - r->len < 0)
 
451
                                len = id+1;
 
452
                        else
 
453
                                len = r->len;
 
454
                }
 
455
 
 
456
                EDBResult *result = new EDBResult;
 
457
                result->setAutoDelete(true);
 
458
                for(int n = 0; n < len; ++n) {
 
459
                        PsiEvent *e = f->get(id);
 
460
                        if(e) {
 
461
                                QString prevId, nextId;
 
462
                                if(id > 0)
 
463
                                        prevId = QString::number(id-1);
 
464
                                if(id < f->total()-1)
 
465
                                        nextId = QString::number(id+1);
 
466
                                EDBItem *ei = new EDBItem(e, QString::number(id), prevId, nextId);
 
467
                                result->append(ei);
 
468
                        }
 
469
 
 
470
                        if(direction == Forward)
 
471
                                ++id;
 
472
                        else
 
473
                                --id;
 
474
                }
 
475
                resultReady(r->id, result);
 
476
        }
 
477
        else if(type == 3) {
 
478
                writeFinished(r->id, f->append(r->event));
 
479
                delete r->event;
 
480
        }
 
481
        else if(type == 4) {
 
482
                int id = r->eventId;
 
483
                EDBResult *result = new EDBResult;
 
484
                result->setAutoDelete(true);
 
485
                while(1) {
 
486
                        PsiEvent *e = f->get(id);
 
487
                        if(!e)
 
488
                                break;
 
489
 
 
490
                        QString prevId, nextId;
 
491
                        if(id > 0)
 
492
                                prevId = QString::number(id-1);
 
493
                        if(id < f->total()-1)
 
494
                                nextId = QString::number(id+1);
 
495
 
 
496
                        if(e->type() == PsiEvent::Message) {
 
497
                                MessageEvent *me = (MessageEvent *)e;
 
498
                                const Message &m = me->message();
 
499
                                if(m.body().find(r->findStr, 0, false) != -1) {
 
500
                                        EDBItem *ei = new EDBItem(e, QString::number(id), prevId, nextId);
 
501
                                        result->append(ei);
 
502
                                        break;
 
503
                                }
 
504
                        }
 
505
 
 
506
                        if(r->dir == Forward)
 
507
                                ++id;
 
508
                        else
 
509
                                --id;
 
510
                }
 
511
                resultReady(r->id, result);
 
512
        }
 
513
 
 
514
        delete r;
 
515
}
 
516
 
 
517
void EDBFlatFile::file_timeout()
 
518
{
 
519
        File *i = (File *)sender();
 
520
        d->flist.remove(i);
 
521
        delete i;
 
522
}
 
523
 
 
524
 
 
525
//----------------------------------------------------------------------------
 
526
// EDBFlatFile::File
 
527
//----------------------------------------------------------------------------
 
528
class EDBFlatFile::File::Private
 
529
{
 
530
public:
 
531
        Private() {}
 
532
 
 
533
        QValueVector<int> index;
 
534
};
 
535
 
 
536
EDBFlatFile::File::File(const Jid &_j)
 
537
{
 
538
        d = new Private;
 
539
 
 
540
        j = _j;
 
541
        valid = false;
 
542
        t = new QTimer(this);
 
543
        connect(t, SIGNAL(timeout()), SLOT(timer_timeout()));
 
544
 
 
545
        //printf("[EDB opening -- %s]\n", j.full().latin1());
 
546
        QString s = j.userHost();
 
547
        fname = getHistoryDir() + "/" + qstrlower(jidEncode(s)) + ".history";
 
548
        f.setName(fname);
 
549
        valid = f.open(IO_ReadWrite);
 
550
        if(valid) {
 
551
                //printf(" file: %s\n", fname.latin1());
 
552
                // build index
 
553
                while(1) {
 
554
                        int at = f.at();
 
555
 
 
556
                        // locate a newline
 
557
                        bool found = false;
 
558
                        do {
 
559
                                int c = f.getch();
 
560
                                if(c == '\n') {
 
561
                                        found = true;
 
562
                                        break;
 
563
                                }
 
564
                        } while(!f.atEnd());
 
565
 
 
566
                        if(!found)
 
567
                                break;
 
568
 
 
569
                        int oldsize = d->index.size();
 
570
                        d->index.resize(oldsize+1);
 
571
                        d->index[oldsize] = at;
 
572
                }
 
573
        }
 
574
        else {
 
575
                //printf(" file: can't open\n");
 
576
        }
 
577
 
 
578
        //printf(" messages: %d\n\n", d->index.size());
 
579
        touch();
 
580
}
 
581
 
 
582
EDBFlatFile::File::~File()
 
583
{
 
584
        if(valid)
 
585
                f.close();
 
586
        //printf("[EDB closing -- %s]\n", j.full().latin1());
 
587
 
 
588
        delete d;
 
589
}
 
590
 
 
591
int EDBFlatFile::File::total() const
 
592
{
 
593
        return d->index.size();
 
594
}
 
595
 
 
596
void EDBFlatFile::File::touch()
 
597
{
 
598
        t->start(30000);
 
599
}
 
600
 
 
601
void EDBFlatFile::File::timer_timeout()
 
602
{
 
603
        timeout();
 
604
}
 
605
 
 
606
PsiEvent *EDBFlatFile::File::get(int id)
 
607
{
 
608
        touch();
 
609
 
 
610
        if(!valid)
 
611
                return 0;
 
612
 
 
613
        if(id < 0 || id > (int)d->index.size())
 
614
                return 0;
 
615
 
 
616
        f.at(d->index[id]);
 
617
 
 
618
        QTextStream t;
 
619
        t.setDevice(&f);
 
620
        t.setEncoding(QTextStream::UnicodeUTF8);
 
621
        QString line = t.readLine();
 
622
        t.unsetDevice();
 
623
 
 
624
        return lineToEvent(line);
 
625
}
 
626
 
 
627
bool EDBFlatFile::File::append(PsiEvent *e)
 
628
{
 
629
        touch();
 
630
 
 
631
        if(!valid)
 
632
                return false;
 
633
 
 
634
        QString line = eventToLine(e);
 
635
        if(line.isEmpty())
 
636
                return false;
 
637
 
 
638
        f.at(f.size());
 
639
        int at = f.at();
 
640
 
 
641
        QTextStream t;
 
642
        t.setDevice(&f);
 
643
        t.setEncoding(QTextStream::UnicodeUTF8);
 
644
        t << line << endl;
 
645
        t.unsetDevice();
 
646
        f.flush();
 
647
 
 
648
        int oldsize = d->index.size();
 
649
        d->index.resize(oldsize+1);
 
650
        d->index[oldsize] = at;
 
651
 
 
652
        return true;
 
653
}
 
654
 
 
655
PsiEvent *EDBFlatFile::File::lineToEvent(const QString &line)
 
656
{
 
657
        // -- read the line --
 
658
        QString sTime, sType, sOrigin, sFlags, sText, sSubj, sUrl, sUrlDesc;
 
659
        int x1, x2;
 
660
        x1 = line.find('|') + 1;
 
661
 
 
662
        x2 = line.find('|', x1);
 
663
        sTime = line.mid(x1, x2-x1);
 
664
        x1 = x2 + 1;
 
665
 
 
666
        x2 = line.find('|', x1);
 
667
        sType = line.mid(x1, x2-x1);
 
668
        x1 = x2 + 1;
 
669
 
 
670
        x2 = line.find('|', x1);
 
671
        sOrigin = line.mid(x1, x2-x1);
 
672
        x1 = x2 + 1;
 
673
 
 
674
        x2 = line.find('|', x1);
 
675
        sFlags = line.mid(x1, x2-x1);
 
676
        x1 = x2 + 1;
 
677
 
 
678
        // check for extra fields
 
679
        if(sFlags[1] != '-') {
 
680
                int subflags = hexChar2int(sFlags[1].latin1());
 
681
 
 
682
                // have subject?
 
683
                if(subflags & 1) {
 
684
                        x2 = line.find('|', x1);
 
685
                        sSubj = line.mid(x1, x2-x1);
 
686
                        x1 = x2 + 1;
 
687
                }
 
688
                // have url?
 
689
                if(subflags & 2) {
 
690
                        x2 = line.find('|', x1);
 
691
                        sUrl = line.mid(x1, x2-x1);
 
692
                        x1 = x2 + 1;
 
693
                        x2 = line.find('|', x1);
 
694
                        sUrlDesc = line.mid(x1, x2-x1);
 
695
                        x1 = x2 + 1;
 
696
                }
 
697
        }
 
698
 
 
699
        // body text is last
 
700
        sText = line.mid(x1);
 
701
 
 
702
        // -- read end --
 
703
 
 
704
        int type = sType.toInt();
 
705
        if(type == 0 || type == 1 || type == 4 || type == 5) {
 
706
                Message m;
 
707
                m.setTimeStamp(QDateTime::fromString(sTime, Qt::ISODate));
 
708
                if(type == 1)
 
709
                        m.setType("chat");
 
710
                else if(type == 4)
 
711
                        m.setType("error");
 
712
                else if(type == 5)
 
713
                        m.setType("headline");
 
714
                else
 
715
                        m.setType("");
 
716
 
 
717
                bool originLocal = (sOrigin == "to") ? true: false;
 
718
                m.setFrom(j);
 
719
                if(sFlags[0] == 'N')
 
720
                        m.setBody(logdecode(sText));
 
721
                else
 
722
                        m.setBody(logdecode(QString::fromUtf8(sText)));
 
723
                m.setSubject(logdecode(sSubj));
 
724
 
 
725
                QString url = logdecode(sUrl);
 
726
                if(!url.isEmpty())
 
727
                        m.urlAdd(Url(url, logdecode(sUrlDesc)));
 
728
                m.setSpooled(true);
 
729
 
 
730
                MessageEvent *me = new MessageEvent(m, 0);
 
731
                me->setOriginLocal(originLocal);
 
732
 
 
733
                return me;
 
734
        }
 
735
        else if(type == 2 || type == 3 || type == 6 || type == 7 || type == 8) {
 
736
                QString subType = "subscribe";
 
737
                if(type == 2) {
 
738
                        // stupid "system message" from Psi <= 0.8.6
 
739
                        // try to figure out what kind it REALLY is based on the text
 
740
                        if(sText == tr("<big>[System Message]</big><br>You are now authorized."))
 
741
                                subType = "subscribed";
 
742
                        else if(sText == tr("<big>[System Message]</big><br>Your authorization has been removed!"))
 
743
                                subType = "unsubscribed";
 
744
                }
 
745
                else if(type == 3)
 
746
                        subType = "subscribe";
 
747
                else if(type == 6)
 
748
                        subType = "subscribed";
 
749
                else if(type == 7)
 
750
                        subType = "unsubscribe";
 
751
                else if(type == 8)
 
752
                        subType = "unsubscribed";
 
753
 
 
754
                AuthEvent *ae = new AuthEvent(j, subType, 0);
 
755
                ae->setTimeStamp(QDateTime::fromString(sTime, Qt::ISODate));
 
756
                return ae;
 
757
        }
 
758
        else
 
759
                return 0;
 
760
}
 
761
 
 
762
QString EDBFlatFile::File::eventToLine(PsiEvent *e)
 
763
{
 
764
        int subflags = 0;
 
765
        QString sTime, sType, sOrigin, sFlags;
 
766
 
 
767
        if(e->type() == PsiEvent::Message) {
 
768
                MessageEvent *me = (MessageEvent *)e;
 
769
                const Message &m = me->message();
 
770
                const UrlList urls = m.urlList();
 
771
 
 
772
                if(!m.subject().isEmpty())
 
773
                        subflags |= 1;
 
774
                if(!urls.isEmpty())
 
775
                        subflags |= 2;
 
776
 
 
777
                sTime = m.timeStamp().toString(Qt::ISODate);
 
778
                int n = 0;
 
779
                if(m.type() == "chat")
 
780
                        n = 1;
 
781
                else if(m.type() == "error")
 
782
                        n = 4;
 
783
                else if(m.type() == "headline")
 
784
                        n = 5;
 
785
                sType.setNum(n);
 
786
                sOrigin = e->originLocal() ? "to": "from";
 
787
                sFlags = "N---";
 
788
 
 
789
                if(subflags != 0)
 
790
                        sFlags[1] = int2hexChar(subflags);
 
791
 
 
792
                //  | date | type | To/from | flags | text
 
793
                QString line = "|" + sTime + "|" + sType + "|" + sOrigin + "|" + sFlags + "|";
 
794
 
 
795
                if(subflags & 1) {
 
796
                        line += logencode(m.subject()) + "|";
 
797
                }
 
798
                if(subflags & 2) {
 
799
                        const Url &url = urls.first();
 
800
                        line += logencode(url.url()) + "|";
 
801
                        line += logencode(url.desc()) + "|";
 
802
                }
 
803
                line += logencode(m.body());
 
804
 
 
805
                return line;
 
806
        }
 
807
        else if(e->type() == PsiEvent::Auth) {
 
808
                AuthEvent *ae = (AuthEvent *)e;
 
809
                sTime = ae->timeStamp().toString(Qt::ISODate);
 
810
                QString subType = ae->authType();
 
811
                int n = 0;
 
812
                if(subType == "subscribe")
 
813
                        n = 3;
 
814
                else if(subType == "subscribed")
 
815
                        n = 6;
 
816
                else if(subType == "unsubscribe")
 
817
                        n = 7;
 
818
                else if(subType == "unsubscribed")
 
819
                        n = 8;
 
820
                sType.setNum(n);
 
821
                sOrigin = e->originLocal() ? "to": "from";
 
822
                sFlags = "N---";
 
823
 
 
824
                //  | date | type | To/from | flags | text
 
825
                QString line = "|" + sTime + "|" + sType + "|" + sOrigin + "|" + sFlags + "|";
 
826
                line += logencode(subType);
 
827
 
 
828
                return line;
 
829
        }
 
830
        else
 
831
                return "";
 
832
}