1
/****************************************************************************
2
** jabtasks.cpp - basic tasks for use with the JabIO task system
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
****************************************************************************/
25
/****************************************************************************
27
****************************************************************************/
28
JT_Auth::JT_Auth(JabTask *parent, const QString &user, const QString &pass, const QString &sid, const QString &resource, bool plain)
31
iq = createIQ("set", "", id());
32
QDomElement query = doc()->createElement("query");
33
query.setAttribute("xmlns", "jabber:iq:auth");
34
iq.appendChild(query);
35
query.appendChild(textTag("username", user));
37
query.appendChild(textTag("password", pass));
39
QString hash = SHA1::digest(sid + pass);
40
query.appendChild(textTag("digest", hash));
42
query.appendChild(textTag("resource", resource));
50
bool JT_Auth::take(const QDomElement &x)
52
if(x.attribute("id") != id())
55
if(x.attribute("type") == "result") {
61
setError(getErrorString(x));
69
/****************************************************************************
71
****************************************************************************/
72
JT_Register::JT_Register(JabTask *parent)
77
void JT_Register::reg(const QString &user, const QString &pass)
79
iq = createIQ("set", "", id());
80
QDomElement query = doc()->createElement("query");
81
query.setAttribute("xmlns", "jabber:iq:register");
82
iq.appendChild(query);
83
query.appendChild(textTag("username", user));
84
query.appendChild(textTag("password", pass));
87
void JT_Register::go()
92
bool JT_Register::take(const QDomElement &x)
94
if(x.attribute("id") != id())
97
if(x.attribute("type") == "result") {
101
setError(getErrorString(x));
109
/****************************************************************************
111
****************************************************************************/
112
JT_Roster::JT_Roster(JabTask *parent)
118
void JT_Roster::get()
122
iq = createIQ("get", "", id());
123
QDomElement query = doc()->createElement("query");
124
query.setAttribute("xmlns", "jabber:iq:roster");
125
iq.appendChild(query);
128
void JT_Roster::set(const QString &_jid, const QString &_nick, const QStringList &_groups)
135
iq = createIQ("set", "", id());
136
QDomElement query = doc()->createElement("query");
137
query.setAttribute("xmlns", "jabber:iq:roster");
138
iq.appendChild(query);
140
QDomElement item = doc()->createElement("item");
141
item.setAttribute("jid", jid);
143
item.setAttribute("name", nick);
144
for(QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
145
item.appendChild(textTag("group", *it));
146
query.appendChild(item);
149
void JT_Roster::remove(const QString &jid)
153
iq = createIQ("set", "", id());
154
QDomElement query = doc()->createElement("query");
155
query.setAttribute("xmlns", "jabber:iq:roster");
156
iq.appendChild(query);
158
QDomElement item = doc()->createElement("item");
159
item.setAttribute("jid", jid);
160
item.setAttribute("subscription", "remove");
161
query.appendChild(item);
169
QString JT_Roster::toString()
178
list += lineEncodeList(groups);
179
return lineEncodeList(list);
182
bool JT_Roster::fromString(const QString &str)
184
QStringList args = lineDecodeList(str);
186
if(args.count() != 4)
189
QStringList::Iterator i = args.begin();
193
if(arg0 == "JT_Roster") {
194
QString jid = *(i++);
195
QString nick = *(i++);
196
QStringList groups = lineDecodeList(*(i++));
197
set(jid, nick, groups);
204
bool JT_Roster::take(const QDomElement &x)
206
if(x.attribute("id") != id())
210
if(x.attribute("type") == "result") {
211
QDomElement q = queryTag(x);
212
roster = xmlReadRoster(q);
216
setError(getErrorString(x));
223
if(x.attribute("type") == "result")
226
setError(getErrorString(x));
233
pdb(DEBUG_JABBER, "[Remove successful]\n");
243
/****************************************************************************
245
****************************************************************************/
246
JT_Presence::JT_Presence(JabTask *parent)
251
void JT_Presence::pres(int _status, const QString &_statusString, int _priority)
256
statusString = _statusString;
257
priority = _priority;
259
tag = doc()->createElement("presence");
260
if(status == STATUS_OFFLINE) {
261
tag.setAttribute("type", "unavailable");
262
if(!statusString.isEmpty())
263
tag.appendChild(textTag("status", statusString));
266
if(status != STATUS_ONLINE)
267
tag.appendChild(textTag("show", status2jabprestxt(status)));
268
if(!statusString.isEmpty())
269
tag.appendChild(textTag("status", statusString));
270
tag.appendChild(textTag("priority", QString("%1").arg(priority)));
274
void JT_Presence::sub(const Jid &to, int subType)
278
tag = doc()->createElement("presence");
279
tag.setAttribute("to", to.full());
280
if(subType == JABSUB_SUBSCRIBE)
281
tag.setAttribute("type", "subscribe");
282
else if(subType == JABSUB_SUBSCRIBED)
283
tag.setAttribute("type", "subscribed");
284
else if(subType == JABSUB_UNSUBSCRIBE)
285
tag.setAttribute("type", "unsubscribe");
286
else if(subType == JABSUB_UNSUBSCRIBED)
287
tag.setAttribute("type", "unsubscribed");
290
void JT_Presence::go()
293
if(type == 0 && status != STATUS_OFFLINE)
294
receivePresence(status, statusString);
299
/****************************************************************************
301
****************************************************************************/
302
JT_Login::JT_Login(JabTask *parent)
312
void JT_Login::login(const QString &_user, const QString &_pass, const QString &_sid, const QString &_resource, int _status, const QString &_statusString, int _priority, bool plain)
317
resource = _resource;
319
statusString = _statusString;
320
priority = _priority;
325
void JT_Login::create(const QString &_user, const QString &_pass, const QString &_sid, const QString &_resource, int _status, const QString &_statusString, int _priority, bool plain)
330
resource = _resource;
332
statusString = _statusString;
333
priority = _priority;
341
auth = new JT_Auth(this, user, pass, sid, resource, usePlain);
346
reg = new JT_Register(this);
347
reg->reg(user, pass);
353
void JT_Login::done(JabTask *p)
355
if(reg && p->id() == reg->id()) {
357
//printf("JT_Login: Created.\n");
361
auth = new JT_Auth(this, user, pass, sid, resource, usePlain);
366
setError(reg->errorString());
371
else if(auth && p->id() == auth->id()) {
372
if(auth->success()) {
373
//printf("JT_Login: Authorized.\n");
378
rost = new JT_Roster(this);
384
setError(auth->errorString());
389
else if(rost && p->id() == rost->id()) {
390
//printf("JT_Login: Got roster.\n");
391
receiveRoster(rost->roster);
395
pres = new JT_Presence(this);
396
pres->pres(status, statusString, priority);
399
else if(pres && p->id() == pres->id()) {
400
//printf("JT_Login: Sent presence.\n");
401
receivePresence(pres->status, pres->statusString);
410
/****************************************************************************
412
****************************************************************************/
413
JT_PushPresence::JT_PushPresence(JabTask *parent)
418
bool JT_PushPresence::take(const QDomElement &e)
420
if(e.tagName() != "presence")
424
p.jid = e.attribute("from");
425
p.status = STATUS_ONLINE;
428
p.songTitle = ""; // Gabber music
429
p.timeStamp = QDateTime::currentDateTime();
431
if(e.hasAttribute("type")) {
432
QString type = e.attribute("type");
433
if(type == "unavailable") {
434
p.status = STATUS_OFFLINE;
438
if(type == "subscribe") {
439
subType = JABSUB_SUBSCRIBE;
441
else if(type == "subscribed") {
442
subType = JABSUB_SUBSCRIBED;
444
else if(type == "unsubscribe") {
445
subType = JABSUB_UNSUBSCRIBE;
447
else if(type == "unsubscribed") {
448
subType = JABSUB_UNSUBSCRIBED;
453
subscription(p.jid, subType);
461
tag = findSubTag(e, "status", &found);
463
p.statusString = tagContent(tag);
464
tag = findSubTag(e, "show", &found);
466
p.status = jabprestxt2status(tagContent(tag));
467
tag = findSubTag(e, "priority", &found);
469
p.priority = tagContent(tag).toInt();
471
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
472
QDomElement i = n.toElement();
476
if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:delay") {
477
if(i.hasAttribute("stamp")) {
478
if(stamp2TS(i.attribute("stamp"), &p.timeStamp))
479
p.timeStamp = p.timeStamp.addSecs(getTZOffset() * 3600);
483
if(i.tagName() == "x" && i.attribute("xmlns") == "gabber:x:music:info") {
486
QString title, state;
488
t = findSubTag(i, "title", &found);
490
title = tagContent(t);
491
t = findSubTag(i, "state", &found);
493
state = tagContent(t);
495
if(!title.isEmpty() && state == "playing")
496
p.songTitle = tagContent(t);
506
/****************************************************************************
508
****************************************************************************/
509
JT_PushRoster::JT_PushRoster(JabTask *parent)
514
bool JT_PushRoster::take(const QDomElement &e)
517
if(e.tagName() != "iq")
520
// let's not steal non-push responses
521
if(e.hasAttribute("id"))
524
if(queryNS(e) != "jabber:iq:roster")
527
QDomElement q = queryTag(e);
528
JabRoster r = xmlReadRoster(q, TRUE);
535
/****************************************************************************
537
****************************************************************************/
538
JT_Message::JT_Message(JabTask *parent, const JabMessage &_jmsg)
544
void JT_Message::go()
546
QDomElement message = doc()->createElement("message");
547
message.setAttribute("to", jmsg.to.full());
548
if(jmsg.type == JABMESSAGE_CHAT)
549
message.setAttribute("type", "chat");
550
if(!jmsg.subject.isEmpty())
551
message.appendChild(textTag("subject", jmsg.subject));
552
message.appendChild(textTag("body", jmsg.body));
553
if(!jmsg.url.isEmpty()) {
554
QDomElement x = doc()->createElement("x");
555
x.setAttribute("xmlns", "jabber:x:oob");
556
x.appendChild(textTag("url", jmsg.url));
557
x.appendChild(textTag("desc", jmsg.url_desc));
558
message.appendChild(x);
565
/****************************************************************************
567
****************************************************************************/
568
JT_PushMessage::JT_PushMessage(JabTask *parent)
573
bool JT_PushMessage::take(const QDomElement &e)
575
if(e.tagName() != "message")
582
msg.timeStamp = QDateTime::currentDateTime();
585
QString type = e.attribute("type");
586
QString from = e.attribute("from");
588
msg.type = JABMESSAGE_NORM;
591
msg.type = JABMESSAGE_CHAT;
592
else if(type == "error")
593
msg.type = JABMESSAGE_ERROR;
594
else if(type == "headline")
595
msg.type = JABMESSAGE_HEADLINE;
597
tag = findSubTag(e, "body", &found);
599
msg.body = tagContent(tag);
601
// no body tag? no message!
602
if(!found && msg.type != JABMESSAGE_ERROR)
605
tag = findSubTag(e, "subject", &found);
607
msg.subject = tagContent(tag);
608
tag = findSubTag(e, "error", &found);
610
errorString = tagContent(tag);
611
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
612
QDomElement i = n.toElement();
616
if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:delay") {
617
if(i.hasAttribute("stamp")) {
618
if(stamp2TS(i.attribute("stamp"), &msg.timeStamp)) {
619
msg.timeStamp = msg.timeStamp.addSecs(getTZOffset() * 3600);
625
if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:oob") {
629
tag = findSubTag(i, "url", &found);
631
msg.url = tagContent(tag);
632
tag = findSubTag(i, "desc", &found);
634
msg.url_desc = tagContent(tag);
638
msg.originLocal = FALSE;
639
if(msg.type == JABMESSAGE_ERROR)
640
msg.body = QString("%1\n------\n%2").arg(errorString).arg(msg.body);
648
/****************************************************************************
650
****************************************************************************/
651
JT_Queue::JT_Queue(JabTask *parent)
658
void JT_Queue::addTask(JabTask *j)
662
//printf("JT_Queue: count=%d\n", count());
669
void JT_Queue::done(JabTask *j)
672
QTimer::singleShot(0, this, SLOT(afterDone()));
682
void JT_Queue::stop()
688
if(active->isDone()) {
698
void JT_Queue::afterDone()
703
// should be safe to delete now
711
void JT_Queue::doNext()
714
//printf("JT_Queue: count=%d\n", count());
715
active = list.getFirst();
721
int JT_Queue::count()
726
QString JT_Queue::toString()
729
QPtrListIterator<JabTask> it(list);
730
for(JabTask *j; (j = it.current()); ++it) {
731
QString s = j->toString();
735
return lineEncodeList(all);
738
bool JT_Queue::fromString(const QString &str)
740
QStringList all = lineDecodeList(str);
742
for(QStringList::Iterator it = all.begin(); it != all.end(); ++it) {
743
// only type that is supported is roster
744
JT_Roster *r = new JT_Roster(this);
745
//printf("trying to add: [%s]\n", (*it).latin1());
746
if(!r->fromString(*it)) {
751
//printf("success\n");
753
//printf("JT_Queue: count=%d\n", count());
759
/****************************************************************************
761
****************************************************************************/
762
JT_GetServices::JT_GetServices(JabTask *parent, const QString &host)
765
iq = createIQ("get", host, id());
766
QDomElement query = doc()->createElement("query");
767
query.setAttribute("xmlns", "jabber:iq:agents");
768
iq.appendChild(query);
771
void JT_GetServices::go()
776
bool JT_GetServices::take(const QDomElement &x)
778
if(x.attribute("id") != id())
781
if(x.attribute("type") == "result") {
782
QDomElement q = queryTag(x);
785
for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
786
QDomElement i = n.toElement();
790
if(i.tagName() == "agent") {
791
JabRosterEntry entry;
793
entry.jid = i.attribute("jid");
798
tag = findSubTag(i, "name", &found);
800
entry.nick = tagContent(tag);
801
tag = findSubTag(i, "register", &found);
803
entry.isRegisterable = TRUE;
804
tag = findSubTag(i, "search", &found);
806
entry.isSearchable = TRUE;
807
tag = findSubTag(i, "groupchat", &found);
809
entry.isGCCapable = TRUE;
810
tag = findSubTag(i, "transport", &found);
812
entry.isTransport = TRUE;
814
JabRosterEntry *tmp = new JabRosterEntry(entry);
822
setError(getErrorString(x));
830
/****************************************************************************
832
****************************************************************************/
833
JT_VCard::JT_VCard(JabTask *parent)
839
void JT_VCard::get(const QString &_jid)
843
iq = createIQ("get", jid, id());
844
QDomElement v = doc()->createElement("vCard");
845
v.setAttribute("xmlns", "vcard-temp");
846
v.setAttribute("version", "3.0");
847
v.setAttribute("prodid", "-//HandGen//NONSGML vGen v1.0//EN");
851
void JT_VCard::set(VCard &card)
854
iq = createIQ("set", "", id());
855
iq.appendChild(card.toXml());
863
bool JT_VCard::take(const QDomElement &x)
865
if(x.attribute("id") != id())
868
if(x.attribute("type") == "result") {
870
QDomElement q = x.firstChild().toElement();
871
if(q.tagName() == "vcard") {
872
if(vcard.fromXml(q)) {
887
setError(getErrorString(x));
895
/****************************************************************************
897
****************************************************************************/
898
JT_RegForm::JT_RegForm(JabTask *parent)
904
void JT_RegForm::get(const QString &_jid)
908
iq = createIQ("get", jid, id());
909
QDomElement query = doc()->createElement("query");
910
query.setAttribute("xmlns", "jabber:iq:register");
911
iq.appendChild(query);
914
void JT_RegForm::set(const JabForm &form)
917
jid = form.jid.full();
918
iq = createIQ("set", form.jid.full(), id());
919
QDomElement query = doc()->createElement("query");
920
query.setAttribute("xmlns", "jabber:iq:register");
921
iq.appendChild(query);
924
if(!form.key.isEmpty())
925
query.appendChild(textTag("key", form.key));
927
QPtrListIterator<JabFormField> it(form);
928
for(JabFormField *f; (f = it.current()); ++it)
929
query.appendChild(textTag(f->realName(), f->value()));
932
void JT_RegForm::go()
937
bool JT_RegForm::take(const QDomElement &x)
939
if(x.attribute("id") != id())
942
if(x.attribute("type") == "result") {
944
form.jid = x.attribute("from");
945
QDomElement q = queryTag(x);
946
for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
947
QDomElement i = n.toElement();
951
if(i.tagName() == "instructions")
952
form.instructions = tagContent(i);
953
else if(i.tagName() == "key")
954
form.key = tagContent(i);
956
JabFormField *f = new JabFormField;
957
if(f->setType(i.tagName())) {
958
f->setValue(tagContent(i));
970
jid = x.attribute("from");
976
setError(getErrorString(x));
984
/****************************************************************************
986
****************************************************************************/
987
JT_Search::JT_Search(JabTask *parent)
993
void JT_Search::get(const QString &_jid)
997
iq = createIQ("get", jid, id());
998
QDomElement query = doc()->createElement("query");
999
query.setAttribute("xmlns", "jabber:iq:search");
1000
iq.appendChild(query);
1003
void JT_Search::set(const JabForm &form)
1006
jid = form.jid.full();
1007
iq = createIQ("set", form.jid.full(), id());
1008
QDomElement query = doc()->createElement("query");
1009
query.setAttribute("xmlns", "jabber:iq:search");
1010
iq.appendChild(query);
1013
if(!form.key.isEmpty())
1014
query.appendChild(textTag("key", form.key));
1016
QPtrListIterator<JabFormField> it(form);
1017
for(JabFormField *f; (f = it.current()); ++it) {
1018
if(f->value().isEmpty())
1021
query.appendChild(textTag(f->realName(), f->value()));
1025
void JT_Search::go()
1030
bool JT_Search::take(const QDomElement &x)
1032
if(x.attribute("id") != id())
1035
if(x.attribute("type") == "result") {
1037
form.jid = x.attribute("from");
1038
QDomElement q = queryTag(x);
1039
for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
1040
QDomElement i = n.toElement();
1044
if(i.tagName() == "instructions")
1045
form.instructions = tagContent(i);
1046
else if(i.tagName() == "key")
1047
form.key = tagContent(i);
1049
JabFormField *f = new JabFormField;
1050
if(f->setType(i.tagName())) {
1051
f->setValue(tagContent(i));
1063
jid = x.attribute("from");
1064
QDomElement q = queryTag(x);
1065
for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
1066
QDomElement i = n.toElement();
1070
if(i.tagName() == "item") {
1071
JabRosterEntry entry;
1073
entry.jid = i.attribute("jid");
1078
tag = findSubTag(i, "nick", &found);
1080
entry.nick = tagContent(tag);
1081
tag = findSubTag(i, "first", &found);
1083
entry.first = tagContent(tag);
1084
tag = findSubTag(i, "last", &found);
1086
entry.last = tagContent(tag);
1087
tag = findSubTag(i, "email", &found);
1089
entry.email = tagContent(tag);
1091
JabRosterEntry *tmp = new JabRosterEntry(entry);
1100
setError(getErrorString(x));
1108
/****************************************************************************
1110
****************************************************************************/
1111
JT_ClientVersion::JT_ClientVersion(JabTask *parent, const Jid &_j)
1115
iq = createIQ("get", j.full(), id());
1116
QDomElement query = doc()->createElement("query");
1117
query.setAttribute("xmlns", "jabber:iq:version");
1118
iq.appendChild(query);
1121
void JT_ClientVersion::go()
1126
bool JT_ClientVersion::take(const QDomElement &x)
1128
if(x.attribute("id") != id())
1131
if(x.attribute("type") == "result") {
1133
QDomElement q = queryTag(x);
1135
tag = findSubTag(x, "name", &found);
1137
name = tagContent(tag);
1138
tag = findSubTag(x, "version", &found);
1140
version = tagContent(tag);
1141
tag = findSubTag(x, "os", &found);
1143
os = tagContent(tag);
1148
setError(getErrorString(x));
1156
/****************************************************************************
1158
****************************************************************************/
1159
JT_ClientTime::JT_ClientTime(JabTask *parent, const Jid &_j)
1163
iq = createIQ("get", j.full(), id());
1164
QDomElement query = doc()->createElement("query");
1165
query.setAttribute("xmlns", "jabber:iq:time");
1166
iq.appendChild(query);
1169
void JT_ClientTime::go()
1174
bool JT_ClientTime::take(const QDomElement &x)
1176
if(x.attribute("id") != id())
1179
if(x.attribute("type") == "result") {
1181
QDomElement q = queryTag(x);
1183
tag = findSubTag(x, "utc", &found);
1185
stamp2TS(tagContent(tag), &utc);
1186
tag = findSubTag(x, "tz", &found);
1188
timezone = tagContent(tag);
1189
tag = findSubTag(x, "display", &found);
1191
display = tagContent(tag);
1196
setError(getErrorString(x));
1204
/****************************************************************************
1206
****************************************************************************/
1207
JT_ServInfo::JT_ServInfo(JabTask *parent)
1212
bool JT_ServInfo::take(const QDomElement &e)
1214
if(e.tagName() != "iq")
1217
if(e.attribute("type") != "get")
1220
QString ns = queryNS(e);
1221
if(ns == "jabber:iq:version") {
1222
QDomElement iq = createIQ("result", e.attribute("from"), e.attribute("id"));
1223
QDomElement query = doc()->createElement("query");
1224
query.setAttribute("xmlns", "jabber:iq:version");
1225
iq.appendChild(query);
1226
query.appendChild(textTag("name", PROG_NAME));
1227
query.appendChild(textTag("version", PROG_VERSION));
1228
query.appendChild(textTag("os", getOSName()));
1232
else if(ns == "jabber:iq:time") {
1233
QDomElement iq = createIQ("result", e.attribute("from"), e.attribute("id"));
1234
QDomElement query = doc()->createElement("query");
1235
query.setAttribute("xmlns", "jabber:iq:time");
1236
iq.appendChild(query);
1237
QDateTime local = QDateTime::currentDateTime();
1238
QDateTime utc = local.addSecs(-getTZOffset() * 3600);
1239
QString str = getTZString();
1240
query.appendChild(textTag("utc", TS2stamp(utc)));
1241
query.appendChild(textTag("tz", str));
1242
query.appendChild(textTag("display", QString("%1 %2").arg(local.toString()).arg(str)));
1251
/****************************************************************************
1253
****************************************************************************/
1254
JT_Gateway::JT_Gateway(JabTask *parent)
1260
void JT_Gateway::get(const QString &_jid)
1264
iq = createIQ("get", jid, id());
1265
QDomElement query = doc()->createElement("query");
1266
query.setAttribute("xmlns", "jabber:iq:gateway");
1267
iq.appendChild(query);
1270
void JT_Gateway::set(const QString &_jid, const QString &prompt)
1274
iq = createIQ("set", jid, id());
1275
QDomElement query = doc()->createElement("query");
1276
query.setAttribute("xmlns", "jabber:iq:gateway");
1277
iq.appendChild(query);
1278
query.appendChild(textTag("prompt", prompt));
1281
void JT_Gateway::go()
1286
bool JT_Gateway::take(const QDomElement &x)
1288
if(x.attribute("id") != id())
1291
if(x.attribute("type") == "result") {
1293
QDomElement query = queryTag(x);
1296
tag = findSubTag(query, "desc", &found);
1298
desc = tagContent(tag);
1299
tag = findSubTag(query, "prompt", &found);
1301
prompt = tagContent(tag);
1304
QDomElement query = queryTag(x);
1307
tag = findSubTag(query, "prompt", &found);
1309
prompt = tagContent(tag);
1315
setError(getErrorString(x));