This repository has been archived on 2025-12-24. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
yachat/iris-legacy/iris/xmpp-im/xmpp_tasks.cpp

2321 lines
50 KiB
C++
Raw Permalink Normal View History

2025-12-25 01:37:49 +05:00
/*
* 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 <QtCrypto>
//#include "sha1.h"
#include "xmpp_xmlcommon.h"
//#include "xmpp_stream.h"
//#include "xmpp_types.h"
#include "xmpp_vcard.h"
#include <qregexp.h>
#include <QList>
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(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_Session
//----------------------------------------------------------------------------
//
#include "protocol.h"
JT_Session::JT_Session(Task *parent) : Task(parent)
{
}
void JT_Session::onGo()
{
QDomElement iq = createIQ(doc(), "set", "", id());
QDomElement session = doc()->createElement("session");
session.setAttribute("xmlns",NS_SESSION);
iq.appendChild(session);
send(iq);
}
bool JT_Session::take(const QDomElement& x)
{
if(!iqVerify(x, "", id()))
return false;
if(x.attribute("type") == "result") {
setSuccess();
}
else {
setError(x);
}
return true;
}
//----------------------------------------------------------------------------
// JT_Register
//----------------------------------------------------------------------------
class JT_Register::Private
{
public:
Private() {}
Form form;
XData xdata;
bool hasXData;
Jid jid;
int type;
};
JT_Register::JT_Register(Task *parent)
:Task(parent)
{
d = new Private;
d->type = -1;
d->hasXData = false;
}
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()));
}
}
void JT_Register::setForm(const Jid& to, const XData& xdata)
{
d->type = 4;
iq = createIQ(doc(), "set", to.full(), id());
QDomElement query = doc()->createElement("query");
query.setAttribute("xmlns", "jabber:iq:register");
iq.appendChild(query);
query.appendChild(xdata.toXml(doc(), true));
}
const Form & JT_Register::form() const
{
return d->form;
}
bool JT_Register::hasXData() const
{
return d->hasXData;
}
const XData& JT_Register::xdata() const
{
return d->xdata;
}
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 if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:data") {
d->xdata.fromXml(i);
d->hasXData = true;
}
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;
QList<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(QList<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(QList<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));
send(createIQ(doc(), "result", e.attribute("from"), e.attribute("id")));
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);
}
if(s.isMUC()) {
QDomElement m = doc()->createElement("x");
m.setAttribute("xmlns","http://jabber.org/protocol/muc");
if (!s.mucPassword().isEmpty()) {
m.appendChild(textTag(doc(),"password",s.mucPassword()));
}
if (s.hasMUCHistory()) {
QDomElement h = doc()->createElement("history");
if (s.mucHistoryMaxChars() >= 0)
h.setAttribute("maxchars",s.mucHistoryMaxChars());
if (s.mucHistoryMaxStanzas() >= 0)
h.setAttribute("maxstanzas",s.mucHistoryMaxStanzas());
if (s.mucHistorySeconds() >= 0)
h.setAttribute("seconds",s.mucHistorySeconds());
m.appendChild(h);
}
tag.appendChild(m);
}
if(s.hasPhotoHash()) {
QDomElement m = doc()->createElement("x");
m.setAttribute("xmlns", "vcard-temp:x:update");
m.appendChild(textTag(doc(), "photo", s.photoHash()));
tag.appendChild(m);
}
}
}
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, const QString& nick)
{
type = 1;
tag = doc()->createElement("presence");
tag.setAttribute("to", to.full());
tag.setAttribute("type", subType);
if (!nick.isEmpty()) {
QDomElement nick_tag = textTag(doc(),"nick",nick);
nick_tag.setAttribute("xmlns","http://jabber.org/protocol/nick");
tag.appendChild(nick_tag);
}
}
void JT_Presence::probe(const Jid &to)
{
type = 2;
tag = doc()->createElement("presence");
tag.setAttribute("to", to.full());
tag.setAttribute("type", "probe");
}
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, client()->stream().baseNS(), &code, &str);
p.setError(code, str);
}
else if(type == "subscribe" || type == "subscribed" || type == "unsubscribe" || type == "unsubscribed") {
QString nick;
bool found;
QDomElement tag = findSubTag(e, "nick", &found);
if (found && tag.attribute("xmlns") == "http://jabber.org/protocol/nick") {
nick = tagContent(tag);
}
emit subscription(j, type, nick);
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"));
}
else if(i.tagName() == "x" && i.attribute("xmlns") == "vcard-temp:x:update") {
QDomElement t;
bool found;
t = findSubTag(i, "photo", &found);
if (found)
p.setPhotoHash(tagContent(t));
else
p.setPhotoHash("");
}
else if(i.tagName() == "x" && i.attribute("xmlns") == "http://jabber.org/protocol/muc#user") {
for(QDomNode muc_n = i.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) {
QDomElement muc_e = muc_n.toElement();
if(muc_e.isNull())
continue;
if (muc_e.tagName() == "item")
p.setMUCItem(MUCItem(muc_e));
else if (muc_e.tagName() == "status")
p.setMUCStatus(muc_e.attribute("code").toInt());
else if (muc_e.tagName() == "destroy")
p.setMUCDestroy(MUCDestroy(muc_e));
}
}
#ifdef YAPSI
else if(i.tagName() == "x-notify" && i.attribute("xmlns") == "yandex:informer") {
QDomElement t;
bool found;
t = findSubTag(i, "value", &found);
if (found)
p.setNotifyValue(tagContent(t));
else
p.setNotifyValue(QString());
}
#endif
}
emit 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;
int 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;
if (m.id().isEmpty())
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
//----------------------------------------------------------------------------
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_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", type == 1 ? Jid().full() : 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 Jid &j, const VCard &card)
{
type = 1;
d->vcard = card;
d->jid = j;
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;
QList<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 QList<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
bool invalid_node = false;
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
#ifdef FILETRANSFER
// FIXME: isn't it supposed to take info from caps?
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);
#endif
feature = doc()->createElement("feature");
feature.setAttribute("var", "http://jabber.org/protocol/disco#info");
query.appendChild(feature);
// Client-specific features
QStringList clientFeatures = client()->features().list();
for (QStringList::ConstIterator i = clientFeatures.begin(); i != clientFeatures.end(); ++i) {
feature = doc()->createElement("feature");
feature.setAttribute("var", *i);
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 {
invalid_node = true;
}
}
else {
invalid_node = true;
}
if (!invalid_node) {
send(iq);
}
else {
// Create error reply
QDomElement error_reply = createIQ(doc(), "result", e.attribute("from"), e.attribute("id"));
// Copy children
for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
error_reply.appendChild(n.cloneNode());
}
// Add error
QDomElement error = doc()->createElement("error");
error.setAttribute("type","cancel");
error_reply.appendChild(error);
QDomElement error_type = doc()->createElement("item-not-found");
error_type.setAttribute("xmlns","urn:ietf:params:xml:ns:xmpp-stanzas");
error.appendChild(error_type);
send(error_reply);
}
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 Jid & JT_DiscoItems::jid() const
{
return d->jid;
}
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_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;
}
#ifdef YAPSI
//----------------------------------------------------------------------------
// JT_YaLogMessage
//----------------------------------------------------------------------------
JT_YaLogMessage::JT_YaLogMessage(Task *parent)
:Task(parent)
{
}
JT_YaLogMessage::~JT_YaLogMessage()
{
}
void JT_YaLogMessage::log(bool originLocal, const YaDateTime& timeStamp, const XMPP::Jid& accountJid, const Message &message)
{
originLocal_ = originLocal;
timeStamp_ = timeStamp;
selfJid_ = accountJid;
m_ = message;
if (m_.id().isEmpty()) {
m_.setId(id());
}
}
void JT_YaLogMessage::onGo()
{
if (originLocal_ && m_.from().isNull()) {
m_.setFrom(selfJid_);
}
Stanza s = m_.toStanza(&(client()->stream()));
QDomElement e = oldStyleNS(s.element());
QDomElement iq = createIQ(doc(), "set", "history.ya.ru", id());
QDomElement query = doc()->createElement("query");
query.setAttribute("xmlns", "yandex:history:foreign");
query.setAttribute("action", originLocal_ ? "send" : "recv");
query.setAttribute("twin", selfJid_.bare());
query.setAttribute("timestamp", timeStamp_.toYaTime_t());
query.appendChild(e);
iq.appendChild(query);
send(iq);
}
bool JT_YaLogMessage::take(const QDomElement &x)
{
if (!iqVerify(x, "history.ya.ru", id()) && !iqVerify(x, "ya.ru", id()))
return false;
if (x.attribute("type") == "result") {
setSuccess(true);
}
else {
setError(x);
}
return true;
}
//----------------------------------------------------------------------------
// JT_YaRemoveHistory
//----------------------------------------------------------------------------
JT_YaRemoveHistory::JT_YaRemoveHistory(Task *parent)
: Task(parent)
{
}
JT_YaRemoveHistory::~JT_YaRemoveHistory()
{
}
void JT_YaRemoveHistory::remove(const XMPP::Jid& owner)
{
selfJid_ = owner;
}
void JT_YaRemoveHistory::remove(const XMPP::Jid& owner, const XMPP::Jid& twin)
{
selfJid_ = owner;
twin_ = twin;
}
void JT_YaRemoveHistory::remove(const XMPP::Jid& owner, const XMPP::Jid& twin, const XMPP::Jid& contact)
{
selfJid_ = owner;
twin_ = twin;
contact_ = contact;
}
void JT_YaRemoveHistory::onGo()
{
Q_ASSERT(!selfJid_.isNull() && selfJid_.isValid());
QDomElement iq = createIQ(doc(), "set", "history.ya.ru", id());
QDomElement query = doc()->createElement("query");
query.setAttribute("xmlns", "yandex:history:delete");
query.setAttribute("owner", selfJid_.bare());
if (!twin_.isNull() && !twin_.compare(selfJid_))
query.setAttribute("twin", twin_.bare());
if (!contact_.isNull())
query.setAttribute("opp", contact_.bare());
iq.appendChild(query);
send(iq);
}
bool JT_YaRemoveHistory::take(const QDomElement &x)
{
if (!iqVerify(x, "history.ya.ru", id()))
return false;
if (x.attribute("type") == "result") {
setSuccess(true);
}
else {
setError(x);
}
return true;
}
//----------------------------------------------------------------------------
// JT_YaRemoveHistory
//----------------------------------------------------------------------------
JT_YaRetrieveHistory::JT_YaRetrieveHistory(Task *parent)
: Task(parent)
, messageCount_(-1)
, checkUnread_(false)
{
}
JT_YaRetrieveHistory::~JT_YaRetrieveHistory()
{
}
void JT_YaRetrieveHistory::retrieve(const XMPP::Jid& contact, int messageCount, YaDateTime startTime)
{
contact_ = contact;
messageCount_ = messageCount;
startTime_ = startTime;
}
void JT_YaRetrieveHistory::checkUnread(YaDateTime startTime)
{
checkUnread_ = true;
startTime_ = startTime;
}
void JT_YaRetrieveHistory::onGo()
{
if (!checkUnread_) {
Q_ASSERT(!contact_.isNull() && contact_.isValid());
}
int paginatorMax = messageCount_;
QDomElement iq = createIQ(doc(), "get", "history.ya.ru", id());
QDomElement query = doc()->createElement("retrieve");
query.setAttribute("xmlns", "yandex:history:retrieve");
if (!startTime_.isNull()) {
query.setAttribute("start", startTime_.toYaIsoTime());
}
if (!checkUnread_) {
query.setAttribute("with", contact_.bare());
// query.setAttribute("order_by", "asc");
}
else {
query.setAttribute("unread", "1");
paginatorMax = 100;
}
QDomElement set = doc()->createElement("set");
set.setAttribute("xmlns", "yandex:history:paginator");
set.appendChild(textTag(doc(), "max", QString::number(paginatorMax)));
query.appendChild(set);
iq.appendChild(query);
send(iq);
}
bool JT_YaRetrieveHistory::take(const QDomElement &x)
{
if (!iqVerify(x, "history.ya.ru", id()))
return false;
if (x.attribute("type") == "result") {
bool found;
QDomElement q = findSubTag(x, "chat", &found);
Q_ASSERT(q.attribute("xmlns") == "yandex:history:retrieve");
for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
QDomElement e = n.toElement();
if( e.isNull() )
continue;
if ( e.tagName() == "to" || e.tagName() == "from" ) {
JT_YaRetrieveHistory::Chat chat;
chat.timeStamp = YaDateTime::fromYaIsoTime(e.attribute("time"));
chat.body = XMLHelper::subTagText(e, "body");
chat.originLocal = e.tagName() == "to";
chat.jid = e.attribute("user");
if (chat.timeStamp.isNull()) {
qWarning("JT_YaRetrieveHistory::take(%s) '%s' '%s'", qPrintable(q.attribute("with")), qPrintable(e.attribute("time")), qPrintable(chat.timeStamp.toString()));
}
messages_ << chat;
}
}
setSuccess(true);
}
else {
setError(x);
}
return true;
}
const XMPP::Jid& JT_YaRetrieveHistory::contact() const
{
return contact_;
}
const QList<JT_YaRetrieveHistory::Chat>& JT_YaRetrieveHistory::messages() const
{
return messages_;
}
//----------------------------------------------------------------------------
// JT_YaMessageRead
//----------------------------------------------------------------------------
JT_YaMessageRead::JT_YaMessageRead(Task* parent)
: Task(parent)
{
}
JT_YaMessageRead::~JT_YaMessageRead()
{
}
void JT_YaMessageRead::messageRead(const XMPP::Jid& contact, const YaDateTime& timeStamp)
{
contact_ = contact;
timeStamp_ = timeStamp;
}
void JT_YaMessageRead::setTo(const XMPP::Jid& to)
{
to_ = to;
}
void JT_YaMessageRead::onGo()
{
QDomElement iq = createIQ(doc(),
"set",
to_.isNull() ? "history.ya.ru" : to_.full(),
id());
QDomElement query = doc()->createElement("read");
query.setAttribute("xmlns", "yandex:history:read");
query.setAttribute("with", contact_.full());
query.setAttribute("timestamp", timeStamp_.toYaTime_t());
iq.appendChild(query);
send(iq);
// we won't be getting a reply, so self-destruct is the only option
setSuccess(true);
}
bool JT_YaMessageRead::take(const QDomElement& x)
{
if (!iqVerify(x, "history.ya.ru", id()))
return false;
if (x.attribute("type") == "result") {
setSuccess(true);
}
else {
setError(x);
}
return true;
}
//----------------------------------------------------------------------------
// JT_YaMoodSwitch
//----------------------------------------------------------------------------
JT_YaMoodSwitch::JT_YaMoodSwitch(Task* parent)
: Task(parent)
, isGet_(false)
, enabled_(false)
{
}
JT_YaMoodSwitch::~JT_YaMoodSwitch()
{
}
void JT_YaMoodSwitch::get()
{
isGet_ = true;
enabled_ = false;
}
void JT_YaMoodSwitch::set(bool enabled)
{
isGet_ = false;
enabled_ = enabled;
}
bool JT_YaMoodSwitch::enabled() const
{
Q_ASSERT(isGet_);
return enabled_;
}
void JT_YaMoodSwitch::onGo()
{
QDomElement iq = createIQ(doc(), isGet_ ? "get" : "set", "", id());
QDomElement query = doc()->createElement("query");
query.setAttribute("xmlns", "yandex:mood-switch");
if (!isGet_) {
QDomElement moodSettings = doc()->createElement("mood-settings");
moodSettings.setAttribute("enabled", enabled_ ? "1" : "0");
query.appendChild(moodSettings);
}
iq.appendChild(query);
send(iq);
}
bool JT_YaMoodSwitch::take(const QDomElement& x)
{
if (!iqVerify(x, client()->host(), id()))
return false;
if (x.attribute("type") == "result") {
if (isGet_) {
bool found;
QDomElement q = findSubTag(x, "query", &found);
Q_ASSERT(found);
Q_ASSERT(q.attribute("xmlns") == "yandex:mood-switch");
QDomElement tag = findSubTag(q, "mood-settings", &found);
Q_ASSERT(found);
if (found) {
enabled_ = tag.attribute("enabled") == "1";
}
}
setSuccess(true);
}
else {
setError(x);
}
return true;
}
//----------------------------------------------------------------------------
// JT_YaMaxLast
//----------------------------------------------------------------------------
JT_YaMaxLast::JT_YaMaxLast(Task* parent)
: Task(parent)
, isGet_(false)
, maxLast_(-1)
{
}
JT_YaMaxLast::~JT_YaMaxLast()
{
}
void JT_YaMaxLast::get()
{
isGet_ = true;
maxLast_ = -1;
}
void JT_YaMaxLast::set(int maxLast)
{
isGet_ = false;
maxLast_ = maxLast;
}
int JT_YaMaxLast::maxLast() const
{
Q_ASSERT(isGet_);
return maxLast_;
}
void JT_YaMaxLast::onGo()
{
QDomElement iq = createIQ(doc(), isGet_ ? "get" : "set", "", id());
QDomElement query = doc()->createElement("query");
query.setAttribute("xmlns", "yandex:max-last");
if (!isGet_) {
if (maxLast_ > -1) {
query.appendChild(textTag(doc(), "max-last", QString::number(maxLast_)));
}
else {
query.appendChild(doc()->createElement("max-last"));
}
}
iq.appendChild(query);
send(iq);
}
bool JT_YaMaxLast::take(const QDomElement& x)
{
if (!iqVerify(x, client()->host(), id()))
return false;
if (x.attribute("type") == "result") {
if (isGet_) {
bool found;
QDomElement q = findSubTag(x, "query", &found);
Q_ASSERT(found);
Q_ASSERT(q.attribute("xmlns") == "yandex:max-last");
QString maxLast = XMLHelper::subTagText(q, "max-last");
if (maxLast.isEmpty()) {
maxLast_ = -1;
}
else {
maxLast_ = maxLast.toInt();
}
}
setSuccess(true);
}
else {
setError(x);
}
return true;
}
#endif