1
/****************************************************************************
2
** jabcommon.cpp - common classes and functions for handling Jabber data
3
** Copyright (C) 2001, 2002 Justin Karneges
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.
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.
15
** You should have received a copy of the GNU General Public License
16
** along with this program; if not, write to the Free Software
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
19
****************************************************************************/
26
QString lineEncode(QString str)
28
str.replace(QRegExp("\\\\"), "\\\\"); // backslash to double-backslash
29
str.replace(QRegExp("\\|"), "\\p"); // pipe to \p
30
str.replace(QRegExp("\n"), "\\n"); // newline to \n
34
QString lineDecode(const QString &str)
38
for(unsigned int n = 0; n < str.length(); ++n) {
39
if(str.at(n) == '\\') {
52
ret.append(str.at(n));
59
QString lineEncodeList(QStringList list)
64
for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
67
str += lineEncode(*it);
71
return lineEncode(str);
74
QStringList lineDecodeList(const QString &in)
76
QString str = lineDecode(in);
82
p2 = str.find('|', p1);
89
chunk = str.mid(p1, p2-p1);
93
list.append(lineDecode(chunk));
100
QString status2jabprestxt(int status)
103
case STATUS_AWAY: return "away";
104
case STATUS_XA: return "xa";
105
case STATUS_DND: return "dnd";
111
int jabprestxt2status(const QString &str)
113
if(str == "away") return STATUS_AWAY;
114
else if(str == "xa") return STATUS_XA;
115
else if(str == "dnd") return STATUS_DND;
117
return STATUS_ONLINE;
120
QString cleanJid(QString jid)
122
int x = jid.find('/');
130
bool jidcmp(const QString &jid1, const QString &jid2)
132
QString jid1clean = cleanJid(jid1);
133
QString jid2clean = cleanJid(jid2);
135
if(jid1clean.length() != jid2clean.length())
138
for(unsigned int n = 0; n < jid1clean.length(); ++n) {
139
if(jid1clean.at(n).lower() != jid2clean.at(n).lower())
146
bool jidIsAgent(const QString &jid)
148
return (jid.find('@') == -1) ? TRUE : FALSE;
152
/****************************************************************************
154
****************************************************************************/
159
Jid::Jid(const QString &s)
164
void Jid::set(const QString &s)
174
n = realJid.find('@');
176
v_user = realJid.mid(0, n);
178
// host: locate the '@'
179
n = realJid.find('@');
184
// host: locate the '/'
185
n2 = realJid.find('/', n);
187
v_host = realJid.mid(n);
189
v_host = realJid.mid(n, n2-n);
193
n = realJid.find('/');
195
v_resource = realJid.mid(n+1);
198
n = realJid.find('/');
202
v_s = realJid.mid(0, n);
205
v_isAgent = realJid.find('@') == -1 ? TRUE: FALSE;
208
Jid & Jid::operator=(const QString &s)
214
bool operator==(const Jid &j1, const Jid &j2)
216
if(j1.s().length() != j2.s().length())
219
for(unsigned int n = 0; n < j1.s().length(); ++n) {
220
if(j1.s().at(n).lower() != j2.s().at(n).lower())
228
/****************************************************************************
230
****************************************************************************/
231
JabFormField::JabFormField()
236
QString JabFormField::realName()
239
case username: return "username";
240
case nick: return "nick";
241
case password: return "password";
242
case name: return "name";
243
case first: return "first";
244
case last: return "last";
245
case email: return "email";
246
case address: return "address";
247
case city: return "city";
248
case state: return "state";
249
case zip: return "zipcode";
250
case phone: return "phone";
251
case url: return "url";
252
case date: return "date";
253
case misc: return "misc";
258
QString JabFormField::fieldName()
261
case username: return QObject::tr("Username");
262
case nick: return QObject::tr("Nickname");
263
case password: return QObject::tr("Password");
264
case name: return QObject::tr("Name");
265
case first: return QObject::tr("First Name");
266
case last: return QObject::tr("Last Name");
267
case email: return QObject::tr("E-mail");
268
case address: return QObject::tr("Address");
269
case city: return QObject::tr("City");
270
case state: return QObject::tr("State");
271
case zip: return QObject::tr("Zipcode");
272
case phone: return QObject::tr("Phone");
273
case url: return QObject::tr("URL");
274
case date: return QObject::tr("Date");
275
case misc: return QObject::tr("Misc");
280
void JabFormField::setType(int x)
285
bool JabFormField::setType(const QString &in)
287
int x = str2type(in);
295
void JabFormField::setValue(const QString &in)
300
int JabFormField::str2type(const QString &in)
302
if(!in.compare("username")) return username;
303
if(!in.compare("nick")) return nick;
304
if(!in.compare("password")) return password;
305
if(!in.compare("name")) return name;
306
if(!in.compare("first")) return first;
307
if(!in.compare("last")) return last;
308
if(!in.compare("email")) return email;
309
if(!in.compare("address")) return address;
310
if(!in.compare("city")) return city;
311
if(!in.compare("state")) return state;
312
if(!in.compare("zip")) return zip;
313
if(!in.compare("phone")) return phone;
314
if(!in.compare("url")) return url;
315
if(!in.compare("date")) return date;
316
if(!in.compare("misc")) return misc;
322
/****************************************************************************
324
****************************************************************************/
330
JabForm::JabForm(const JabForm &from)
331
:QPtrList<JabFormField>()
337
JabForm & JabForm::operator=(const JabForm &from)
341
QPtrListIterator<JabFormField> it(from);
343
for(; (f = it.current()); ++it)
344
append(new JabFormField(*f));
347
instructions = from.instructions;
353
JabFormField *JabForm::find(int type) const
355
QPtrListIterator<JabFormField> it(*this);
357
for(; (f = it.current()); ++it) {
358
if(f->type() == type)
366
/****************************************************************************
367
JabRoster - holds a bunch of JabRosterEntries
368
****************************************************************************/
369
JabRoster::JabRoster()
371
list.setAutoDelete(TRUE);
374
JabRoster::~JabRoster()
376
//printf("JabRoster: destructing [%d]\n", list.count());
379
JabRoster::JabRoster(const JabRoster &from)
381
//printf("JabRoster: copy()\n");
385
QPtrList<JabRosterEntry> fromlist = from.list;
386
for(JabRosterEntry *entry = fromlist.first(); entry; entry = fromlist.next())
390
JabRoster & JabRoster::operator=(const JabRoster &from)
392
//printf("JabRoster: assignment\n");
394
//printf("JabRoster: deleting %d contacts.\n", list.count());
396
QPtrList<JabRosterEntry> fromlist = from.list;
397
for(JabRosterEntry *entry = fromlist.first(); entry; entry = fromlist.next())
398
add(new JabRosterEntry(*entry));
400
//printf("JabRoster: list now has %d contacts.\n", list.count());
405
int JabRoster::size()
410
JabRosterEntry *JabRoster::first()
415
JabRosterEntry *JabRoster::current()
417
return list.current();
420
JabRosterEntry *JabRoster::next()
425
JabRosterEntry *JabRoster::getFirst() const
427
return list.getFirst();
430
void JabRoster::add(JabRosterEntry *entry)
435
void JabRoster::remove(JabRosterEntry *entry)
440
void JabRoster::clear()
445
JabRosterEntry *JabRoster::findByJid(const QString &jid)
447
QPtrListIterator<JabRosterEntry> it(list);
448
JabRosterEntry *entry;
450
for( ; it.current(); ++it) {
451
entry = it.current();
452
if(jidcmp(entry->jid,jid))
458
JabRosterEntry *JabRoster::findByNick(const QString &nick)
460
QPtrListIterator<JabRosterEntry> it(list);
461
JabRosterEntry *entry;
463
for( ; it.current(); ++it) {
464
entry = it.current();
465
if(entry->nick == nick)
472
/****************************************************************************
473
JabRosterEntry - holds minimal contact info
474
****************************************************************************/
475
JabRosterEntry::JabRosterEntry()
480
isRegisterable = isSearchable = isGCCapable = hasSubAgents = isTransport = FALSE;
482
flagForDelete = FALSE;
485
JabRosterEntry::~JabRosterEntry()
489
bool JabRosterEntry::isAvailable() const
491
return res.isEmpty() ? FALSE: TRUE;
494
JabResource *JabRosterEntry::local() const
499
JabResource *JabRosterEntry::priority() const
501
return res.priority();
504
int JabRosterEntry::localStatus() const
507
return res.local()->status;
509
return STATUS_OFFLINE;
514
/****************************************************************************
516
****************************************************************************/
521
QString VCard::tagContent(const QDomElement &e)
523
// look for some tag content
524
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
525
QDomText i = n.toText();
534
QDomElement VCard::findSubTag(const QDomElement &e, const QString &name, bool *found)
539
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
540
QDomElement i = n.toElement();
543
if(i.tagName() == name) {
554
QDomElement VCard::textTag(const QString &name, const QString &content)
556
QDomElement tag = doc.createElement(name);
557
QDomText text = doc.createTextNode(content);
558
tag.appendChild(text);
563
QDomElement VCard::toXml()
565
QDomElement v = doc.createElement("vCard");
566
v.setAttribute("version", "3.0");
567
v.setAttribute("prodid", "-//HandGen//NONSGML vGen v1.0//EN");
568
v.setAttribute("xmlns", "vcard-temp"); // <-- FIXME: how to do namespace attributes?
570
if(!field[vFullname].isEmpty())
571
v.appendChild(textTag("FN", field[vFullname]));
572
if(!field[vNickname].isEmpty())
573
v.appendChild(textTag("NICKNAME", field[vNickname]));
574
if(!field[vDesc].isEmpty())
575
v.appendChild(textTag("DESC", field[vDesc]));
576
if(!field[vEmail].isEmpty())
577
v.appendChild(textTag("EMAIL", field[vEmail]));
578
if(!field[vBday].isEmpty())
579
v.appendChild(textTag("BDAY", field[vBday]));
580
if(!field[vHomepage].isEmpty())
581
v.appendChild(textTag("URL", field[vHomepage]));
584
QDomElement w = doc.createElement("ORG");
585
if(!field[vOrgName].isEmpty())
586
w.appendChild(textTag("ORGNAME", field[vOrgName]));
587
if(!field[vOrgUnit].isEmpty())
588
w.appendChild(textTag("ORGUNIT", field[vOrgUnit]));
592
if(!field[vTitle].isEmpty())
593
v.appendChild(textTag("TITLE", field[vTitle]));
594
if(!field[vRole].isEmpty())
595
v.appendChild(textTag("ROLE", field[vRole]));
596
if(!field[vPhone].isEmpty()) {
597
QDomElement w = doc.createElement("TEL");
599
QDomElement x = doc.createElement("HOME");
602
w.appendChild(textTag("VOICE", field[vPhone]));
608
QDomElement w = doc.createElement("ADR");
610
QDomElement x = doc.createElement("HOME");
613
if(!field[vStreet].isEmpty())
614
w.appendChild(textTag("STREET", field[vStreet]));
615
if(!field[vExt].isEmpty())
616
w.appendChild(textTag("EXTADD", field[vExt]));
617
if(!field[vCity].isEmpty())
618
w.appendChild(textTag("LOCALITY", field[vCity]));
619
if(!field[vState].isEmpty())
620
w.appendChild(textTag("REGION", field[vState]));
621
if(!field[vPcode].isEmpty())
622
w.appendChild(textTag("PCODE", field[vPcode]));
623
if(!field[vCountry].isEmpty())
624
w.appendChild(textTag("COUNTRY", field[vCountry]));
633
bool VCard::fromXml(const QDomElement &q)
635
if(q.tagName() != "vcard")
637
//if(q.attribute("version") != "3.0")
641
for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
642
QDomElement i = n.toElement();
646
if(i.tagName() == "fn")
647
field[vFullname] = tagContent(i);
648
else if(i.tagName() == "nickname")
649
field[vNickname] = tagContent(i);
650
else if(i.tagName() == "desc")
651
field[vDesc] = tagContent(i);
652
else if(i.tagName() == "email") {
653
// email tag is weird. check parent first
654
QString str = tagContent(i);
657
for(QDomNode n = i.firstChild(); !n.isNull(); n = n.nextSibling()) {
658
QDomElement e = n.toElement();
668
else if(i.tagName() == "bday")
669
field[vBday] = tagContent(i);
670
else if(i.tagName() == "url")
671
field[vHomepage] = tagContent(i);
672
else if(i.tagName() == "org") {
674
QDomElement tag = findSubTag(i, "orgname", &found);
676
field[vOrgName] = tagContent(tag);
677
tag = findSubTag(i, "orgunit", &found);
679
field[vOrgUnit] = tagContent(tag);
681
else if(i.tagName() == "title")
682
field[vTitle] = tagContent(i);
683
else if(i.tagName() == "role")
684
field[vRole] = tagContent(i);
685
else if(i.tagName() == "tel") {
690
findSubTag(i, "home", &found);
694
tag = findSubTag(i, "voice", &found);
697
field[vPhone] = tagContent(tag);
700
else if(i.tagName() == "adr") {
705
findSubTag(i, "home", &found);
708
findSubTag(i, "work", &found);
713
tag = findSubTag(i, "extadd", &found);
715
field[vExt] = tagContent(tag);
716
tag = findSubTag(i, "street", &found);
718
field[vStreet] = tagContent(tag);
719
tag = findSubTag(i, "locality", &found);
721
field[vCity] = tagContent(tag);
722
tag = findSubTag(i, "region", &found);
724
field[vState] = tagContent(tag);
725
tag = findSubTag(i, "pcode", &found);
727
field[vPcode] = tagContent(tag);
728
tag = findSubTag(i, "country", &found);
730
field[vCountry] = tagContent(tag);
738
bool VCard::isIncomplete()
740
for(int n = 0; n < NUM_VCARDFIELDS; ++n) {
741
if(!field[n].isEmpty())
748
/****************************************************************************
750
****************************************************************************/
751
JabResource::JabResource()
755
status = STATUS_OFFLINE;
760
/****************************************************************************
761
JabResourceList - holds a list of resources
762
****************************************************************************/
763
JabResourceList::JabResourceList()
768
JabResourceList::JabResourceList(const JabResourceList &from)
769
:QPtrList<JabResource>()
775
JabResourceList & JabResourceList::operator=(const JabResourceList &from)
779
QPtrListIterator<JabResource> it(from);
781
for(; (r = it.current()); ++it)
782
append(new JabResource(*r));
787
JabResource *JabResourceList::find(const QString &name) const
789
QPtrListIterator<JabResource> it(*this);
791
for(; (r = it.current()); ++it) {
799
JabResource *JabResourceList::local() const
804
JabResource *JabResourceList::priority() const
806
JabResource *highest = 0;
809
QPtrListIterator<JabResource> it(*this);
811
for(; (r = it.current()); ++it) {
812
if(!highest || (r->priority > highest->priority)) {
814
highest_val = r->priority;