diff options
Diffstat (limited to 'kopete/protocols/jabber/libiris/iris/xmpp-im/xmpp_tasks.cpp')
-rw-r--r-- | kopete/protocols/jabber/libiris/iris/xmpp-im/xmpp_tasks.cpp | 2120 |
1 files changed, 2120 insertions, 0 deletions
diff --git a/kopete/protocols/jabber/libiris/iris/xmpp-im/xmpp_tasks.cpp b/kopete/protocols/jabber/libiris/iris/xmpp-im/xmpp_tasks.cpp new file mode 100644 index 00000000..ffd7e6ae --- /dev/null +++ b/kopete/protocols/jabber/libiris/iris/xmpp-im/xmpp_tasks.cpp @@ -0,0 +1,2120 @@ +/* + * tasks.cpp - basic tasks + * Copyright (C) 2001, 2002 Justin Karneges + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include"xmpp_tasks.h" + +#include"base64.h" +//#include"sha1.h" +#include"xmpp_xmlcommon.h" +//#include"xmpp_stream.h" +//#include"xmpp_types.h" +#include"xmpp_vcard.h" + +#include<qregexp.h> +#include<qvaluelist.h> + +using namespace XMPP; + + +static QString lineEncode(QString str) +{ + str.replace(QRegExp("\\\\"), "\\\\"); // backslash to double-backslash + str.replace(QRegExp("\\|"), "\\p"); // pipe to \p + str.replace(QRegExp("\n"), "\\n"); // newline to \n + return str; +} + +static QString lineDecode(const QString &str) +{ + QString ret; + + for(unsigned int n = 0; n < str.length(); ++n) { + if(str.at(n) == '\\') { + ++n; + if(n >= str.length()) + break; + + if(str.at(n) == 'n') + ret.append('\n'); + if(str.at(n) == 'p') + ret.append('|'); + if(str.at(n) == '\\') + ret.append('\\'); + } + else { + ret.append(str.at(n)); + } + } + + return ret; +} + +static Roster xmlReadRoster(const QDomElement &q, bool push) +{ + Roster r; + + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + if(i.tagName() == "item") { + RosterItem item; + item.fromXml(i); + + if(push) + item.setIsPush(true); + + r += item; + } + } + + return r; +} + + +//---------------------------------------------------------------------------- +// JT_Register +//---------------------------------------------------------------------------- +class JT_Register::Private +{ +public: + Private() {} + + Form form; + Jid jid; + int type; +}; + +JT_Register::JT_Register(Task *parent) +:Task(parent) +{ + d = new Private; + d->type = -1; +} + +JT_Register::~JT_Register() +{ + delete d; +} + +void JT_Register::reg(const QString &user, const QString &pass) +{ + d->type = 0; + to = client()->host(); + iq = createIQ(doc(), "set", to.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:register"); + iq.appendChild(query); + query.appendChild(textTag(doc(), "username", user)); + query.appendChild(textTag(doc(), "password", pass)); +} + +void JT_Register::changepw(const QString &pass) +{ + d->type = 1; + to = client()->host(); + iq = createIQ(doc(), "set", to.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:register"); + iq.appendChild(query); + query.appendChild(textTag(doc(), "username", client()->user())); + query.appendChild(textTag(doc(), "password", pass)); +} + +void JT_Register::unreg(const Jid &j) +{ + d->type = 2; + to = j.isEmpty() ? client()->host() : j.full(); + iq = createIQ(doc(), "set", to.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:register"); + iq.appendChild(query); + + // this may be useful + if(!d->form.key().isEmpty()) + query.appendChild(textTag(doc(), "key", d->form.key())); + + query.appendChild(doc()->createElement("remove")); +} + +void JT_Register::getForm(const Jid &j) +{ + d->type = 3; + to = j; + iq = createIQ(doc(), "get", to.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:register"); + iq.appendChild(query); +} + +void JT_Register::setForm(const Form &form) +{ + d->type = 4; + to = form.jid(); + iq = createIQ(doc(), "set", to.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:register"); + iq.appendChild(query); + + // key? + if(!form.key().isEmpty()) + query.appendChild(textTag(doc(), "key", form.key())); + + // fields + for(Form::ConstIterator it = form.begin(); it != form.end(); ++it) { + const FormField &f = *it; + query.appendChild(textTag(doc(), f.realName(), f.value())); + } +} + +const Form & JT_Register::form() const +{ + return d->form; +} + +void JT_Register::onGo() +{ + send(iq); +} + +bool JT_Register::take(const QDomElement &x) +{ + if(!iqVerify(x, to, id())) + return false; + + Jid from(x.attribute("from")); + if(x.attribute("type") == "result") { + if(d->type == 3) { + d->form.clear(); + d->form.setJid(from); + + QDomElement q = queryTag(x); + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + if(i.tagName() == "instructions") + d->form.setInstructions(tagContent(i)); + else if(i.tagName() == "key") + d->form.setKey(tagContent(i)); + else { + FormField f; + if(f.setType(i.tagName())) { + f.setValue(tagContent(i)); + d->form += f; + } + } + } + } + + setSuccess(); + } + else + setError(x); + + return true; +} + +//---------------------------------------------------------------------------- +// JT_UnRegister +//---------------------------------------------------------------------------- +class JT_UnRegister::Private +{ +public: + Private() { } + + Jid j; + JT_Register *jt_reg; +}; + +JT_UnRegister::JT_UnRegister(Task *parent) +: Task(parent) +{ + d = new Private; + d->jt_reg = 0; +} + +JT_UnRegister::~JT_UnRegister() +{ + delete d->jt_reg; + delete d; +} + +void JT_UnRegister::unreg(const Jid &j) +{ + d->j = j; +} + +void JT_UnRegister::onGo() +{ + delete d->jt_reg; + + d->jt_reg = new JT_Register(this); + d->jt_reg->getForm(d->j); + connect(d->jt_reg, SIGNAL(finished()), SLOT(getFormFinished())); + d->jt_reg->go(false); +} + +void JT_UnRegister::getFormFinished() +{ + disconnect(d->jt_reg, 0, this, 0); + + d->jt_reg->unreg(d->j); + connect(d->jt_reg, SIGNAL(finished()), SLOT(unregFinished())); + d->jt_reg->go(false); +} + +void JT_UnRegister::unregFinished() +{ + if ( d->jt_reg->success() ) + setSuccess(); + else + setError(d->jt_reg->statusCode(), d->jt_reg->statusString()); + + delete d->jt_reg; + d->jt_reg = 0; +} + +//---------------------------------------------------------------------------- +// JT_Roster +//---------------------------------------------------------------------------- +class JT_Roster::Private +{ +public: + Private() {} + + Roster roster; + QValueList<QDomElement> itemList; +}; + +JT_Roster::JT_Roster(Task *parent) +:Task(parent) +{ + type = -1; + d = new Private; +} + +JT_Roster::~JT_Roster() +{ + delete d; +} + +void JT_Roster::get() +{ + type = 0; + //to = client()->host(); + iq = createIQ(doc(), "get", to.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:roster"); + iq.appendChild(query); +} + +void JT_Roster::set(const Jid &jid, const QString &name, const QStringList &groups) +{ + type = 1; + //to = client()->host(); + QDomElement item = doc()->createElement("item"); + item.setAttribute("jid", jid.full()); + if(!name.isEmpty()) + item.setAttribute("name", name); + for(QStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it) + item.appendChild(textTag(doc(), "group", *it)); + d->itemList += item; +} + +void JT_Roster::remove(const Jid &jid) +{ + type = 1; + //to = client()->host(); + QDomElement item = doc()->createElement("item"); + item.setAttribute("jid", jid.full()); + item.setAttribute("subscription", "remove"); + d->itemList += item; +} + +void JT_Roster::onGo() +{ + if(type == 0) + send(iq); + else if(type == 1) { + //to = client()->host(); + iq = createIQ(doc(), "set", to.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:roster"); + iq.appendChild(query); + for(QValueList<QDomElement>::ConstIterator it = d->itemList.begin(); it != d->itemList.end(); ++it) + query.appendChild(*it); + send(iq); + } +} + +const Roster & JT_Roster::roster() const +{ + return d->roster; +} + +QString JT_Roster::toString() const +{ + if(type != 1) + return ""; + + QDomElement i = doc()->createElement("request"); + i.setAttribute("type", "JT_Roster"); + for(QValueList<QDomElement>::ConstIterator it = d->itemList.begin(); it != d->itemList.end(); ++it) + i.appendChild(*it); + return lineEncode(Stream::xmlToString(i)); + return ""; +} + +bool JT_Roster::fromString(const QString &str) +{ + QDomDocument *dd = new QDomDocument; + if(!dd->setContent(lineDecode(str).utf8())) + return false; + QDomElement e = doc()->importNode(dd->documentElement(), true).toElement(); + delete dd; + + if(e.tagName() != "request" || e.attribute("type") != "JT_Roster") + return false; + + type = 1; + d->itemList.clear(); + for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + d->itemList += i; + } + + return true; +} + +bool JT_Roster::take(const QDomElement &x) +{ + if(!iqVerify(x, client()->host(), id())) + return false; + + // get + if(type == 0) { + if(x.attribute("type") == "result") { + QDomElement q = queryTag(x); + d->roster = xmlReadRoster(q, false); + setSuccess(); + } + else { + setError(x); + } + + return true; + } + // set + else if(type == 1) { + if(x.attribute("type") == "result") + setSuccess(); + else + setError(x); + + return true; + } + // remove + else if(type == 2) { + setSuccess(); + return true; + } + + return false; +} + + +//---------------------------------------------------------------------------- +// JT_PushRoster +//---------------------------------------------------------------------------- +JT_PushRoster::JT_PushRoster(Task *parent) +:Task(parent) +{ +} + +JT_PushRoster::~JT_PushRoster() +{ +} + +bool JT_PushRoster::take(const QDomElement &e) +{ + // must be an iq-set tag + if(e.tagName() != "iq" || e.attribute("type") != "set") + return false; + + if(!iqVerify(e, client()->host(), "", "jabber:iq:roster")) + return false; + + roster(xmlReadRoster(queryTag(e), true)); + + return true; +} + + +//---------------------------------------------------------------------------- +// JT_Presence +//---------------------------------------------------------------------------- +JT_Presence::JT_Presence(Task *parent) +:Task(parent) +{ + type = -1; +} + +JT_Presence::~JT_Presence() +{ +} + +void JT_Presence::pres(const Status &s) +{ + type = 0; + + tag = doc()->createElement("presence"); + if(!s.isAvailable()) { + tag.setAttribute("type", "unavailable"); + if(!s.status().isEmpty()) + tag.appendChild(textTag(doc(), "status", s.status())); + } + else { + if(s.isInvisible()) + tag.setAttribute("type", "invisible"); + + if(!s.show().isEmpty()) + tag.appendChild(textTag(doc(), "show", s.show())); + if(!s.status().isEmpty()) + tag.appendChild(textTag(doc(), "status", s.status())); + + tag.appendChild( textTag(doc(), "priority", QString("%1").arg(s.priority()) ) ); + + if(!s.keyID().isEmpty()) { + QDomElement x = textTag(doc(), "x", s.keyID()); + x.setAttribute("xmlns", "http://jabber.org/protocol/e2e"); + tag.appendChild(x); + } + if(!s.xsigned().isEmpty()) { + QDomElement x = textTag(doc(), "x", s.xsigned()); + x.setAttribute("xmlns", "jabber:x:signed"); + tag.appendChild(x); + } + + if(!s.capsNode().isEmpty() && !s.capsVersion().isEmpty()) { + QDomElement c = doc()->createElement("c"); + c.setAttribute("xmlns","http://jabber.org/protocol/caps"); + c.setAttribute("node",s.capsNode()); + c.setAttribute("ver",s.capsVersion()); + if (!s.capsExt().isEmpty()) + c.setAttribute("ext",s.capsExt()); + tag.appendChild(c); + } + } +} + +void JT_Presence::pres(const Jid &to, const Status &s) +{ + pres(s); + tag.setAttribute("to", to.full()); +} + +void JT_Presence::sub(const Jid &to, const QString &subType) +{ + type = 1; + + tag = doc()->createElement("presence"); + tag.setAttribute("to", to.full()); + tag.setAttribute("type", subType); +} + +void JT_Presence::onGo() +{ + send(tag); + setSuccess(); +} + + +//---------------------------------------------------------------------------- +// JT_PushPresence +//---------------------------------------------------------------------------- +JT_PushPresence::JT_PushPresence(Task *parent) +:Task(parent) +{ +} + +JT_PushPresence::~JT_PushPresence() +{ +} + +bool JT_PushPresence::take(const QDomElement &e) +{ + if(e.tagName() != "presence") + return false; + + Jid j(e.attribute("from")); + Status p; + + if(e.hasAttribute("type")) { + QString type = e.attribute("type"); + if(type == "unavailable") { + p.setIsAvailable(false); + } + else if(type == "error") { + QString str = ""; + int code = 0; + getErrorFromElement(e, &code, &str); + p.setError(code, str); + } + else { + subscription(j, type); + return true; + } + } + + QDomElement tag; + bool found; + + tag = findSubTag(e, "status", &found); + if(found) + p.setStatus(tagContent(tag)); + tag = findSubTag(e, "show", &found); + if(found) + p.setShow(tagContent(tag)); + tag = findSubTag(e, "priority", &found); + if(found) + p.setPriority(tagContent(tag).toInt()); + + for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:delay") { + if(i.hasAttribute("stamp")) { + QDateTime dt; + if(stamp2TS(i.attribute("stamp"), &dt)) + dt = dt.addSecs(client()->timeZoneOffset() * 3600); + p.setTimeStamp(dt); + } + } + else if(i.tagName() == "x" && i.attribute("xmlns") == "gabber:x:music:info") { + QDomElement t; + bool found; + QString title, state; + + t = findSubTag(i, "title", &found); + if(found) + title = tagContent(t); + t = findSubTag(i, "state", &found); + if(found) + state = tagContent(t); + + if(!title.isEmpty() && state == "playing") + p.setSongTitle(title); + } + else if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:signed") { + p.setXSigned(tagContent(i)); + } + else if(i.tagName() == "x" && i.attribute("xmlns") == "http://jabber.org/protocol/e2e") { + p.setKeyID(tagContent(i)); + } + else if(i.tagName() == "c" && i.attribute("xmlns") == "http://jabber.org/protocol/caps") { + p.setCapsNode(i.attribute("node")); + p.setCapsVersion(i.attribute("ver")); + p.setCapsExt(i.attribute("ext")); + } + } + + presence(j, p); + + return true; +} + + +//---------------------------------------------------------------------------- +// JT_Message +//---------------------------------------------------------------------------- +static QDomElement oldStyleNS(const QDomElement &e) +{ + // find closest parent with a namespace + QDomNode par = e.parentNode(); + while(!par.isNull() && par.namespaceURI().isNull()) + par = par.parentNode(); + bool noShowNS = false; + if(!par.isNull() && par.namespaceURI() == e.namespaceURI()) + noShowNS = true; + + QDomElement i; + uint x; + //if(noShowNS) + i = e.ownerDocument().createElement(e.tagName()); + //else + // i = e.ownerDocument().createElementNS(e.namespaceURI(), e.tagName()); + + // copy attributes + QDomNamedNodeMap al = e.attributes(); + for(x = 0; x < al.count(); ++x) + i.setAttributeNode(al.item(x).cloneNode().toAttr()); + + if(!noShowNS) + i.setAttribute("xmlns", e.namespaceURI()); + + // copy children + QDomNodeList nl = e.childNodes(); + for(x = 0; x < nl.count(); ++x) { + QDomNode n = nl.item(x); + if(n.isElement()) + i.appendChild(oldStyleNS(n.toElement())); + else + i.appendChild(n.cloneNode()); + } + return i; +} + +JT_Message::JT_Message(Task *parent, const Message &msg) +:Task(parent) +{ + m = msg; + m.setId(id()); +} + +JT_Message::~JT_Message() +{ +} + +void JT_Message::onGo() +{ + Stanza s = m.toStanza(&(client()->stream())); + QDomElement e = oldStyleNS(s.element()); + send(e); + setSuccess(); +} + + +//---------------------------------------------------------------------------- +// JT_PushMessage +//---------------------------------------------------------------------------- +static QDomElement addCorrectNS(const QDomElement &e) +{ + uint x; + + // grab child nodes + /*QDomDocumentFragment frag = e.ownerDocument().createDocumentFragment(); + QDomNodeList nl = e.childNodes(); + for(x = 0; x < nl.count(); ++x) + frag.appendChild(nl.item(x).cloneNode());*/ + + // find closest xmlns + QDomNode n = e; + while(!n.isNull() && !n.toElement().hasAttribute("xmlns")) + n = n.parentNode(); + QString ns; + if(n.isNull() || !n.toElement().hasAttribute("xmlns")) + ns = "jabber:client"; + else + ns = n.toElement().attribute("xmlns"); + + // make a new node + QDomElement i = e.ownerDocument().createElementNS(ns, e.tagName()); + + // copy attributes + QDomNamedNodeMap al = e.attributes(); + for(x = 0; x < al.count(); ++x) { + QDomAttr a = al.item(x).toAttr(); + if(a.name() != "xmlns") + i.setAttributeNodeNS(al.item(x).cloneNode().toAttr()); + } + + // copy children + QDomNodeList nl = e.childNodes(); + for(x = 0; x < nl.count(); ++x) { + QDomNode n = nl.item(x); + if(n.isElement()) + i.appendChild(addCorrectNS(n.toElement())); + else + i.appendChild(n.cloneNode()); + } + + //i.appendChild(frag); + return i; +} + +JT_PushMessage::JT_PushMessage(Task *parent) +:Task(parent) +{ +} + +JT_PushMessage::~JT_PushMessage() +{ +} + +bool JT_PushMessage::take(const QDomElement &e) +{ + if(e.tagName() != "message") + return false; + + Stanza s = client()->stream().createStanza(addCorrectNS(e)); + if(s.isNull()) { + //printf("take: bad stanza??\n"); + return false; + } + + Message m; + if(!m.fromStanza(s, client()->timeZoneOffset())) { + //printf("bad message\n"); + return false; + } + + message(m); + return true; +} + + +//---------------------------------------------------------------------------- +// JT_GetLastActivity +//---------------------------------------------------------------------------- +class JT_GetLastActivity::Private +{ +public: + Private() {} + + int seconds; + QString message; +}; + +JT_GetLastActivity::JT_GetLastActivity(Task *parent) +:Task(parent) +{ + d = new Private; +} + +JT_GetLastActivity::~JT_GetLastActivity() +{ + delete d; +} + +void JT_GetLastActivity::get(const Jid &j) +{ + jid = j; + iq = createIQ(doc(), "get", jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:last"); + iq.appendChild(query); +} + +int JT_GetLastActivity::seconds() const +{ + return d->seconds; +} + +const QString &JT_GetLastActivity::message() const +{ + return d->message; +} + +void JT_GetLastActivity::onGo() +{ + send(iq); +} + +bool JT_GetLastActivity::take(const QDomElement &x) +{ + if(!iqVerify(x, jid, id())) + return false; + + if(x.attribute("type") == "result") { + QDomElement q = queryTag(x); + + d->message = q.text(); + bool ok; + d->seconds = q.attribute("seconds").toInt(&ok); + + setSuccess(ok); + } + else { + setError(x); + } + + return true; +} + +//---------------------------------------------------------------------------- +// JT_GetServices +//---------------------------------------------------------------------------- +JT_GetServices::JT_GetServices(Task *parent) +:Task(parent) +{ +} + +void JT_GetServices::get(const Jid &j) +{ + agentList.clear(); + + jid = j; + iq = createIQ(doc(), "get", jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:agents"); + iq.appendChild(query); +} + +const AgentList & JT_GetServices::agents() const +{ + return agentList; +} + +void JT_GetServices::onGo() +{ + send(iq); +} + +bool JT_GetServices::take(const QDomElement &x) +{ + if(!iqVerify(x, jid, id())) + return false; + + if(x.attribute("type") == "result") { + QDomElement q = queryTag(x); + + // agents + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + if(i.tagName() == "agent") { + AgentItem a; + + a.setJid(Jid(i.attribute("jid"))); + + QDomElement tag; + bool found; + + tag = findSubTag(i, "name", &found); + if(found) + a.setName(tagContent(tag)); + + // determine which namespaces does item support + QStringList ns; + + tag = findSubTag(i, "register", &found); + if(found) + ns << "jabber:iq:register"; + tag = findSubTag(i, "search", &found); + if(found) + ns << "jabber:iq:search"; + tag = findSubTag(i, "groupchat", &found); + if(found) + ns << "jabber:iq:conference"; + tag = findSubTag(i, "transport", &found); + if(found) + ns << "jabber:iq:gateway"; + + a.setFeatures(ns); + + agentList += a; + } + } + + setSuccess(true); + } + else { + setError(x); + } + + return true; +} + + +//---------------------------------------------------------------------------- +// JT_VCard +//---------------------------------------------------------------------------- +class JT_VCard::Private +{ +public: + Private() {} + + QDomElement iq; + Jid jid; + VCard vcard; +}; + +JT_VCard::JT_VCard(Task *parent) +:Task(parent) +{ + type = -1; + d = new Private; +} + +JT_VCard::~JT_VCard() +{ + delete d; +} + +void JT_VCard::get(const Jid &_jid) +{ + type = 0; + d->jid = _jid; + d->iq = createIQ(doc(), "get", d->jid.full(), id()); + QDomElement v = doc()->createElement("vCard"); + v.setAttribute("xmlns", "vcard-temp"); + v.setAttribute("version", "2.0"); + v.setAttribute("prodid", "-//HandGen//NONSGML vGen v1.0//EN"); + d->iq.appendChild(v); +} + +const Jid & JT_VCard::jid() const +{ + return d->jid; +} + +const VCard & JT_VCard::vcard() const +{ + return d->vcard; +} + +void JT_VCard::set(const VCard &card) +{ + type = 1; + d->vcard = card; + d->jid = ""; + d->iq = createIQ(doc(), "set", d->jid.full(), id()); + d->iq.appendChild(card.toXml(doc()) ); +} + +void JT_VCard::onGo() +{ + send(d->iq); +} + +bool JT_VCard::take(const QDomElement &x) +{ + Jid to = d->jid; + if (to.userHost() == client()->jid().userHost()) + to = client()->host(); + if(!iqVerify(x, to, id())) + return false; + + if(x.attribute("type") == "result") { + if(type == 0) { + for(QDomNode n = x.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement q = n.toElement(); + if(q.isNull()) + continue; + + if(q.tagName().upper() == "VCARD") { + if(d->vcard.fromXml(q)) { + setSuccess(); + return true; + } + } + } + + setError(ErrDisc + 1, tr("No VCard available")); + return true; + } + else { + setSuccess(); + return true; + } + } + else { + setError(x); + } + + return true; +} + + +//---------------------------------------------------------------------------- +// JT_Search +//---------------------------------------------------------------------------- +class JT_Search::Private +{ +public: + Private() {} + + Jid jid; + Form form; + QValueList<SearchResult> resultList; +}; + +JT_Search::JT_Search(Task *parent) +:Task(parent) +{ + d = new Private; + type = -1; +} + +JT_Search::~JT_Search() +{ + delete d; +} + +void JT_Search::get(const Jid &jid) +{ + type = 0; + d->jid = jid; + iq = createIQ(doc(), "get", d->jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:search"); + iq.appendChild(query); +} + +void JT_Search::set(const Form &form) +{ + type = 1; + d->jid = form.jid(); + iq = createIQ(doc(), "set", d->jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:search"); + iq.appendChild(query); + + // key? + if(!form.key().isEmpty()) + query.appendChild(textTag(doc(), "key", form.key())); + + // fields + for(Form::ConstIterator it = form.begin(); it != form.end(); ++it) { + const FormField &f = *it; + query.appendChild(textTag(doc(), f.realName(), f.value())); + } +} + +const Form & JT_Search::form() const +{ + return d->form; +} + +const QValueList<SearchResult> & JT_Search::results() const +{ + return d->resultList; +} + +void JT_Search::onGo() +{ + send(iq); +} + +bool JT_Search::take(const QDomElement &x) +{ + if(!iqVerify(x, d->jid, id())) + return false; + + Jid from(x.attribute("from")); + if(x.attribute("type") == "result") { + if(type == 0) { + d->form.clear(); + d->form.setJid(from); + + QDomElement q = queryTag(x); + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + if(i.tagName() == "instructions") + d->form.setInstructions(tagContent(i)); + else if(i.tagName() == "key") + d->form.setKey(tagContent(i)); + else { + FormField f; + if(f.setType(i.tagName())) { + f.setValue(tagContent(i)); + d->form += f; + } + } + } + } + else { + d->resultList.clear(); + + QDomElement q = queryTag(x); + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + if(i.tagName() == "item") { + SearchResult r(Jid(i.attribute("jid"))); + + QDomElement tag; + bool found; + + tag = findSubTag(i, "nick", &found); + if(found) + r.setNick(tagContent(tag)); + tag = findSubTag(i, "first", &found); + if(found) + r.setFirst(tagContent(tag)); + tag = findSubTag(i, "last", &found); + if(found) + r.setLast(tagContent(tag)); + tag = findSubTag(i, "email", &found); + if(found) + r.setEmail(tagContent(tag)); + + d->resultList += r; + } + } + } + setSuccess(); + } + else { + setError(x); + } + + return true; +} + + +//---------------------------------------------------------------------------- +// JT_ClientVersion +//---------------------------------------------------------------------------- +JT_ClientVersion::JT_ClientVersion(Task *parent) +:Task(parent) +{ +} + +void JT_ClientVersion::get(const Jid &jid) +{ + j = jid; + iq = createIQ(doc(), "get", j.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:version"); + iq.appendChild(query); +} + +void JT_ClientVersion::onGo() +{ + send(iq); +} + +bool JT_ClientVersion::take(const QDomElement &x) +{ + if(!iqVerify(x, j, id())) + return false; + + if(x.attribute("type") == "result") { + bool found; + QDomElement q = queryTag(x); + QDomElement tag; + tag = findSubTag(q, "name", &found); + if(found) + v_name = tagContent(tag); + tag = findSubTag(q, "version", &found); + if(found) + v_ver = tagContent(tag); + tag = findSubTag(q, "os", &found); + if(found) + v_os = tagContent(tag); + + setSuccess(); + } + else { + setError(x); + } + + return true; +} + +const Jid & JT_ClientVersion::jid() const +{ + return j; +} + +const QString & JT_ClientVersion::name() const +{ + return v_name; +} + +const QString & JT_ClientVersion::version() const +{ + return v_ver; +} + +const QString & JT_ClientVersion::os() const +{ + return v_os; +} + + +//---------------------------------------------------------------------------- +// JT_ClientTime +//---------------------------------------------------------------------------- +/*JT_ClientTime::JT_ClientTime(Task *parent, const Jid &_j) +:Task(parent) +{ + j = _j; + iq = createIQ("get", j.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:time"); + iq.appendChild(query); +} + +void JT_ClientTime::go() +{ + send(iq); +} + +bool JT_ClientTime::take(const QDomElement &x) +{ + if(x.attribute("id") != id()) + return FALSE; + + if(x.attribute("type") == "result") { + bool found; + QDomElement q = queryTag(x); + QDomElement tag; + tag = findSubTag(q, "utc", &found); + if(found) + stamp2TS(tagContent(tag), &utc); + tag = findSubTag(q, "tz", &found); + if(found) + timezone = tagContent(tag); + tag = findSubTag(q, "display", &found); + if(found) + display = tagContent(tag); + + setSuccess(TRUE); + } + else { + setError(getErrorString(x)); + setSuccess(FALSE); + } + + return TRUE; +} +*/ + + +//---------------------------------------------------------------------------- +// JT_ServInfo +//---------------------------------------------------------------------------- +JT_ServInfo::JT_ServInfo(Task *parent) +:Task(parent) +{ +} + +JT_ServInfo::~JT_ServInfo() +{ +} + +bool JT_ServInfo::take(const QDomElement &e) +{ + if(e.tagName() != "iq" || e.attribute("type") != "get") + return false; + + QString ns = queryNS(e); + if(ns == "jabber:iq:version") { + QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:version"); + iq.appendChild(query); + query.appendChild(textTag(doc(), "name", client()->clientName())); + query.appendChild(textTag(doc(), "version", client()->clientVersion())); + query.appendChild(textTag(doc(), "os", client()->OSName())); + send(iq); + return true; + } + //else if(ns == "jabber:iq:time") { + // QDomElement iq = createIQ("result", e.attribute("from"), e.attribute("id")); + // QDomElement query = doc()->createElement("query"); + // query.setAttribute("xmlns", "jabber:iq:time"); + // iq.appendChild(query); + // QDateTime local = QDateTime::currentDateTime(); + // QDateTime utc = local.addSecs(-getTZOffset() * 3600); + // QString str = getTZString(); + // query.appendChild(textTag("utc", TS2stamp(utc))); + // query.appendChild(textTag("tz", str)); + // query.appendChild(textTag("display", QString("%1 %2").arg(local.toString()).arg(str))); + // send(iq); + // return TRUE; + //} + else if(ns == "http://jabber.org/protocol/disco#info") { + // Find out the node + QString node; + bool found; + QDomElement q = findSubTag(e, "query", &found); + if(found) // NOTE: Should always be true, since a NS was found above + node = q.attribute("node"); + + QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "http://jabber.org/protocol/disco#info"); + if (!node.isEmpty()) + query.setAttribute("node", node); + iq.appendChild(query); + + // Identity + DiscoItem::Identity identity = client()->identity(); + QDomElement id = doc()->createElement("identity"); + if (!identity.category.isEmpty() && !identity.type.isEmpty()) { + id.setAttribute("category",identity.category); + id.setAttribute("type",identity.type); + if (!identity.name.isEmpty()) { + id.setAttribute("name",identity.name); + } + } + else { + // Default values + id.setAttribute("category","client"); + id.setAttribute("type","pc"); + } + query.appendChild(id); + + QDomElement feature; + if (node.isEmpty() || node == client()->capsNode() + "#" + client()->capsVersion()) { + // Standard features + feature = doc()->createElement("feature"); + feature.setAttribute("var", "http://jabber.org/protocol/bytestreams"); + query.appendChild(feature); + + feature = doc()->createElement("feature"); + feature.setAttribute("var", "http://jabber.org/protocol/si"); + query.appendChild(feature); + + feature = doc()->createElement("feature"); + feature.setAttribute("var", "http://jabber.org/protocol/si/profile/file-transfer"); + query.appendChild(feature); + + feature = doc()->createElement("feature"); + feature.setAttribute("var", "http://jabber.org/protocol/xhtml-im"); + query.appendChild(feature); + + feature = doc()->createElement("feature"); + feature.setAttribute("var", "http://jabber.org/protocol/disco#info"); + query.appendChild(feature); + + if (node.isEmpty()) { + // Extended features + QStringList exts = client()->extensions(); + for (QStringList::ConstIterator i = exts.begin(); i != exts.end(); ++i) { + const QStringList& l = client()->extension(*i).list(); + for ( QStringList::ConstIterator j = l.begin(); j != l.end(); ++j ) { + feature = doc()->createElement("feature"); + feature.setAttribute("var", *j); + query.appendChild(feature); + } + } + } + } + else if (node.startsWith(client()->capsNode() + "#")) { + QString ext = node.right(node.length()-client()->capsNode().length()-1); + if (client()->extensions().contains(ext)) { + const QStringList& l = client()->extension(ext).list(); + for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) { + feature = doc()->createElement("feature"); + feature.setAttribute("var", *it); + query.appendChild(feature); + } + } + else { + // TODO: ERROR + } + } + else { + // TODO: ERROR + } + + send(iq); + return true; + } + + return false; +} + + +//---------------------------------------------------------------------------- +// JT_Gateway +//---------------------------------------------------------------------------- +JT_Gateway::JT_Gateway(Task *parent) +:Task(parent) +{ + type = -1; +} + +void JT_Gateway::get(const Jid &jid) +{ + type = 0; + v_jid = jid; + iq = createIQ(doc(), "get", v_jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:gateway"); + iq.appendChild(query); +} + +void JT_Gateway::set(const Jid &jid, const QString &prompt) +{ + type = 1; + v_jid = jid; + v_prompt = prompt; + iq = createIQ(doc(), "set", v_jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:gateway"); + iq.appendChild(query); + query.appendChild(textTag(doc(), "prompt", v_prompt)); +} + +void JT_Gateway::onGo() +{ + send(iq); +} + +Jid JT_Gateway::jid() const +{ + return v_jid; +} + +QString JT_Gateway::desc() const +{ + return v_desc; +} + +QString JT_Gateway::prompt() const +{ + return v_prompt; +} + +bool JT_Gateway::take(const QDomElement &x) +{ + if(!iqVerify(x, v_jid, id())) + return false; + + if(x.attribute("type") == "result") { + if(type == 0) { + QDomElement query = queryTag(x); + bool found; + QDomElement tag; + tag = findSubTag(query, "desc", &found); + if(found) + v_desc = tagContent(tag); + tag = findSubTag(query, "prompt", &found); + if(found) + v_prompt = tagContent(tag); + } + else { + QDomElement query = queryTag(x); + bool found; + QDomElement tag; + tag = findSubTag(query, "prompt", &found); + if(found) + v_prompt = tagContent(tag); + } + + setSuccess(); + } + else { + setError(x); + } + + return true; +} + +//---------------------------------------------------------------------------- +// JT_Browse +//---------------------------------------------------------------------------- +class JT_Browse::Private +{ +public: + QDomElement iq; + Jid jid; + AgentList agentList; + AgentItem root; +}; + +JT_Browse::JT_Browse (Task *parent) +:Task (parent) +{ + d = new Private; +} + +JT_Browse::~JT_Browse () +{ + delete d; +} + +void JT_Browse::get (const Jid &j) +{ + d->agentList.clear(); + + d->jid = j; + d->iq = createIQ(doc(), "get", d->jid.full(), id()); + QDomElement query = doc()->createElement("item"); + query.setAttribute("xmlns", "jabber:iq:browse"); + d->iq.appendChild(query); +} + +const AgentList & JT_Browse::agents() const +{ + return d->agentList; +} + +const AgentItem & JT_Browse::root() const +{ + return d->root; +} + +void JT_Browse::onGo () +{ + send(d->iq); +} + +AgentItem JT_Browse::browseHelper (const QDomElement &i) +{ + AgentItem a; + + if ( i.tagName() == "ns" ) + return a; + + a.setName ( i.attribute("name") ); + a.setJid ( i.attribute("jid") ); + + // there are two types of category/type specification: + // + // 1. <item category="category_name" type="type_name" /> + // 2. <category_name type="type_name" /> + + if ( i.tagName() == "item" || i.tagName() == "query" ) + a.setCategory ( i.attribute("category") ); + else + a.setCategory ( i.tagName() ); + + a.setType ( i.attribute("type") ); + + QStringList ns; + for(QDomNode n = i.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + if ( i.tagName() == "ns" ) + ns << i.text(); + } + + // For now, conference.jabber.org returns proper namespace only + // when browsing individual rooms. So it's a quick client-side fix. + if ( !a.features().canGroupchat() && a.category() == "conference" ) + ns << "jabber:iq:conference"; + + a.setFeatures (ns); + + return a; +} + +bool JT_Browse::take(const QDomElement &x) +{ + if(!iqVerify(x, d->jid, id())) + return false; + + if(x.attribute("type") == "result") { + for(QDomNode n = x.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + + d->root = browseHelper (i); + + for(QDomNode nn = i.firstChild(); !nn.isNull(); nn = nn.nextSibling()) { + QDomElement e = nn.toElement(); + if ( e.isNull() ) + continue; + if ( e.tagName() == "ns" ) + continue; + + d->agentList += browseHelper (e); + } + } + + setSuccess(true); + } + else { + setError(x); + } + + return true; +} + +//---------------------------------------------------------------------------- +// JT_DiscoItems +//---------------------------------------------------------------------------- +class JT_DiscoItems::Private +{ +public: + Private() { } + + QDomElement iq; + Jid jid; + DiscoList items; +}; + +JT_DiscoItems::JT_DiscoItems(Task *parent) +: Task(parent) +{ + d = new Private; +} + +JT_DiscoItems::~JT_DiscoItems() +{ + delete d; +} + +void JT_DiscoItems::get(const DiscoItem &item) +{ + get(item.jid(), item.node()); +} + +void JT_DiscoItems::get (const Jid &j, const QString &node) +{ + d->items.clear(); + + d->jid = j; + d->iq = createIQ(doc(), "get", d->jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "http://jabber.org/protocol/disco#items"); + + if ( !node.isEmpty() ) + query.setAttribute("node", node); + + d->iq.appendChild(query); +} + +const DiscoList &JT_DiscoItems::items() const +{ + return d->items; +} + +void JT_DiscoItems::onGo () +{ + send(d->iq); +} + +bool JT_DiscoItems::take(const QDomElement &x) +{ + if(!iqVerify(x, d->jid, id())) + return false; + + if(x.attribute("type") == "result") { + QDomElement q = queryTag(x); + + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement e = n.toElement(); + if( e.isNull() ) + continue; + + if ( e.tagName() == "item" ) { + DiscoItem item; + + item.setJid ( e.attribute("jid") ); + item.setName( e.attribute("name") ); + item.setNode( e.attribute("node") ); + item.setAction( DiscoItem::string2action(e.attribute("action")) ); + + d->items.append( item ); + } + } + + setSuccess(true); + } + else { + setError(x); + } + + return true; +} + +//---------------------------------------------------------------------------- +// JT_DiscoInfo +//---------------------------------------------------------------------------- +class JT_DiscoInfo::Private +{ +public: + Private() { } + + QDomElement iq; + Jid jid; + QString node; + DiscoItem item; +}; + +JT_DiscoInfo::JT_DiscoInfo(Task *parent) +: Task(parent) +{ + d = new Private; +} + +JT_DiscoInfo::~JT_DiscoInfo() +{ + delete d; +} + +void JT_DiscoInfo::get(const DiscoItem &item) +{ + DiscoItem::Identity id; + if ( item.identities().count() == 1 ) + id = item.identities().first(); + get(item.jid(), item.node(), id); +} + +void JT_DiscoInfo::get (const Jid &j, const QString &node, DiscoItem::Identity ident) +{ + d->item = DiscoItem(); // clear item + + d->jid = j; + d->node = node; + d->iq = createIQ(doc(), "get", d->jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "http://jabber.org/protocol/disco#info"); + + if ( !node.isEmpty() ) + query.setAttribute("node", node); + + if ( !ident.category.isEmpty() && !ident.type.isEmpty() ) { + QDomElement i = doc()->createElement("item"); + + i.setAttribute("category", ident.category); + i.setAttribute("type", ident.type); + if ( !ident.name.isEmpty() ) + i.setAttribute("name", ident.name); + + query.appendChild( i ); + + } + + d->iq.appendChild(query); +} + + +/** + * Original requested jid. + * Is here because sometimes the responder does not include this information + * in the reply. + */ +const Jid& JT_DiscoInfo::jid() const +{ + return d->jid; +} + +/** + * Original requested node. + * Is here because sometimes the responder does not include this information + * in the reply. + */ +const QString& JT_DiscoInfo::node() const +{ + return d->node; +} + + + +const DiscoItem &JT_DiscoInfo::item() const +{ + return d->item; +} + +void JT_DiscoInfo::onGo () +{ + send(d->iq); +} + +bool JT_DiscoInfo::take(const QDomElement &x) +{ + if(!iqVerify(x, d->jid, id())) + return false; + + if(x.attribute("type") == "result") { + QDomElement q = queryTag(x); + + DiscoItem item; + + item.setJid( d->jid ); + item.setNode( q.attribute("node") ); + + QStringList features; + DiscoItem::Identities identities; + + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement e = n.toElement(); + if( e.isNull() ) + continue; + + if ( e.tagName() == "feature" ) { + features << e.attribute("var"); + } + else if ( e.tagName() == "identity" ) { + DiscoItem::Identity id; + + id.category = e.attribute("category"); + id.name = e.attribute("name"); + id.type = e.attribute("type"); + + identities.append( id ); + } + } + + item.setFeatures( features ); + item.setIdentities( identities ); + + d->item = item; + + setSuccess(true); + } + else { + setError(x); + } + + return true; +} + +//---------------------------------------------------------------------------- +// JT_DiscoPublish +//---------------------------------------------------------------------------- +class JT_DiscoPublish::Private +{ +public: + Private() { } + + QDomElement iq; + Jid jid; + DiscoList list; +}; + +JT_DiscoPublish::JT_DiscoPublish(Task *parent) +: Task(parent) +{ + d = new Private; +} + +JT_DiscoPublish::~JT_DiscoPublish() +{ + delete d; +} + +void JT_DiscoPublish::set(const Jid &j, const DiscoList &list) +{ + d->list = list; + d->jid = j; + + d->iq = createIQ(doc(), "set", d->jid.full(), id()); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "http://jabber.org/protocol/disco#items"); + + // FIXME: unsure about this + //if ( !node.isEmpty() ) + // query.setAttribute("node", node); + + DiscoList::ConstIterator it = list.begin(); + for ( ; it != list.end(); ++it) { + QDomElement w = doc()->createElement("item"); + + w.setAttribute("jid", (*it).jid().full()); + if ( !(*it).name().isEmpty() ) + w.setAttribute("name", (*it).name()); + if ( !(*it).node().isEmpty() ) + w.setAttribute("node", (*it).node()); + w.setAttribute("action", DiscoItem::action2string((*it).action())); + + query.appendChild( w ); + } + + d->iq.appendChild(query); +} + +void JT_DiscoPublish::onGo () +{ + send(d->iq); +} + +bool JT_DiscoPublish::take(const QDomElement &x) +{ + if(!iqVerify(x, d->jid, id())) + return false; + + if(x.attribute("type") == "result") { + setSuccess(true); + } + else { + setError(x); + } + + return true; +} + +//---------------------------------------------------------------------------- +// JT_MucPresence +//---------------------------------------------------------------------------- +JT_MucPresence::JT_MucPresence(Task *parent) +:Task(parent) +{ + type = -1; +} + +JT_MucPresence::~JT_MucPresence() +{ +} + +void JT_MucPresence::pres(const Status &s) +{ + type = 0; + + tag = doc()->createElement("presence"); + if(!s.isAvailable()) { + tag.setAttribute("type", "unavailable"); + if(!s.status().isEmpty()) + tag.appendChild(textTag(doc(), "status", s.status())); + } + else { + if(s.isInvisible()) + tag.setAttribute("type", "invisible"); + + if(!s.show().isEmpty()) + tag.appendChild(textTag(doc(), "show", s.show())); + if(!s.status().isEmpty()) + tag.appendChild(textTag(doc(), "status", s.status())); + + tag.appendChild( textTag(doc(), "priority", QString("%1").arg(s.priority()) ) ); + + if(!s.keyID().isEmpty()) { + QDomElement x = textTag(doc(), "x", s.keyID()); + x.setAttribute("xmlns", "http://jabber.org/protocol/e2e"); + tag.appendChild(x); + } + if(!s.xsigned().isEmpty()) { + QDomElement x = textTag(doc(), "x", s.xsigned()); + x.setAttribute("xmlns", "jabber:x:signed"); + tag.appendChild(x); + } + + if(!s.capsNode().isEmpty() && !s.capsVersion().isEmpty()) { + QDomElement c = doc()->createElement("c"); + c.setAttribute("xmlns","http://jabber.org/protocol/caps"); + c.setAttribute("node",s.capsNode()); + c.setAttribute("ver",s.capsVersion()); + if (!s.capsExt().isEmpty()) + c.setAttribute("ext",s.capsExt()); + tag.appendChild(c); + } + } +} + +void JT_MucPresence::pres(const Jid &to, const Status &s, const QString &password) +{ + pres(s); + tag.setAttribute("to", to.full()); + QDomElement x = textTag(doc(), "x", s.xsigned()); + x.setAttribute("xmlns", "http://jabber.org/protocol/muc"); + x.appendChild( textTag(doc(), "password", password.latin1()) ); + tag.appendChild(x); +} + +void JT_MucPresence::onGo() +{ + send(tag); + setSuccess(); +} + + +//---------------------------------------------------------------------------- +// JT_PrivateStorage +//---------------------------------------------------------------------------- +class JT_PrivateStorage::Private +{ + public: + Private() : type(-1) {} + + QDomElement iq; + QDomElement elem; + int type; +}; + +JT_PrivateStorage::JT_PrivateStorage(Task *parent) + :Task(parent) +{ + d = new Private; +} + +JT_PrivateStorage::~JT_PrivateStorage() +{ + delete d; +} + +void JT_PrivateStorage::get(const QString& tag, const QString& xmlns) +{ + d->type = 0; + d->iq = createIQ(doc(), "get" , QString() , id() ); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:private"); + d->iq.appendChild(query); + QDomElement s = doc()->createElement(tag); + if(!xmlns.isEmpty()) + s.setAttribute("xmlns", xmlns); + query.appendChild(s); +} + +void JT_PrivateStorage::set(const QDomElement& element) +{ + d->type = 1; + d->elem=element; + QDomNode n=doc()->importNode(element,true); + + d->iq = createIQ(doc(), "set" , QString() , id() ); + QDomElement query = doc()->createElement("query"); + query.setAttribute("xmlns", "jabber:iq:private"); + d->iq.appendChild(query); + query.appendChild(n); +} + +void JT_PrivateStorage::onGo() +{ + send(d->iq); +} + +bool JT_PrivateStorage::take(const QDomElement &x) +{ + QString to = client()->host(); + if(!iqVerify(x, to, id())) + return false; + + if(x.attribute("type") == "result") { + if(d->type == 0) { + QDomElement q = queryTag(x); + for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement i = n.toElement(); + if(i.isNull()) + continue; + d->elem=i; + break; + } + } + setSuccess(); + return true; + } + else { + setError(x); + } + + return true; +} + + +QDomElement JT_PrivateStorage::element( ) +{ + return d->elem; +} + |