You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2121 lines
45 KiB
2121 lines
45 KiB
/*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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<tqregexp.h>
|
|
#include<tqvaluelist.h>
|
|
|
|
using namespace XMPP;
|
|
|
|
|
|
static TQString lineEncode(TQString str)
|
|
{
|
|
str.tqreplace(TQRegExp("\\\\"), "\\\\"); // backslash to double-backslash
|
|
str.tqreplace(TQRegExp("\\|"), "\\p"); // pipe to \p
|
|
str.tqreplace(TQRegExp("\n"), "\\n"); // newline to \n
|
|
return str;
|
|
}
|
|
|
|
static TQString lineDecode(const TQString &str)
|
|
{
|
|
TQString 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 TQDomElement &q, bool push)
|
|
{
|
|
Roster r;
|
|
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement 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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
d = new Private;
|
|
d->type = -1;
|
|
}
|
|
|
|
JT_Register::~JT_Register()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void JT_Register::reg(const TQString &user, const TQString &pass)
|
|
{
|
|
d->type = 0;
|
|
to = client()->host();
|
|
iq = createIQ(doc(), "set", to.full(), id());
|
|
TQDomElement 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 TQString &pass)
|
|
{
|
|
d->type = 1;
|
|
to = client()->host();
|
|
iq = createIQ(doc(), "set", to.full(), id());
|
|
TQDomElement 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());
|
|
TQDomElement 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());
|
|
TQDomElement 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());
|
|
TQDomElement 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 TQDomElement &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);
|
|
|
|
TQDomElement q = queryTag(x);
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement 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 *tqparent)
|
|
: Task(tqparent)
|
|
{
|
|
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, TQT_SIGNAL(finished()), TQT_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, TQT_SIGNAL(finished()), TQT_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;
|
|
TQValueList<TQDomElement> itemList;
|
|
};
|
|
|
|
JT_Roster::JT_Roster(Task *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
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());
|
|
TQDomElement query = doc()->createElement("query");
|
|
query.setAttribute("xmlns", "jabber:iq:roster");
|
|
iq.appendChild(query);
|
|
}
|
|
|
|
void JT_Roster::set(const Jid &jid, const TQString &name, const TQStringList &groups)
|
|
{
|
|
type = 1;
|
|
//to = client()->host();
|
|
TQDomElement item = doc()->createElement("item");
|
|
item.setAttribute("jid", jid.full());
|
|
if(!name.isEmpty())
|
|
item.setAttribute("name", name);
|
|
for(TQStringList::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();
|
|
TQDomElement 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());
|
|
TQDomElement query = doc()->createElement("query");
|
|
query.setAttribute("xmlns", "jabber:iq:roster");
|
|
iq.appendChild(query);
|
|
for(TQValueList<TQDomElement>::ConstIterator it = d->itemList.begin(); it != d->itemList.end(); ++it)
|
|
query.appendChild(*it);
|
|
send(iq);
|
|
}
|
|
}
|
|
|
|
const Roster & JT_Roster::roster() const
|
|
{
|
|
return d->roster;
|
|
}
|
|
|
|
TQString JT_Roster::toString() const
|
|
{
|
|
if(type != 1)
|
|
return "";
|
|
|
|
TQDomElement i = doc()->createElement("request");
|
|
i.setAttribute("type", "JT_Roster");
|
|
for(TQValueList<TQDomElement>::ConstIterator it = d->itemList.begin(); it != d->itemList.end(); ++it)
|
|
i.appendChild(*it);
|
|
return lineEncode(Stream::xmlToString(i));
|
|
return "";
|
|
}
|
|
|
|
bool JT_Roster::fromString(const TQString &str)
|
|
{
|
|
TQDomDocument *dd = new TQDomDocument;
|
|
if(!dd->setContent(lineDecode(str).utf8()))
|
|
return false;
|
|
TQDomElement 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(TQDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement i = n.toElement();
|
|
if(i.isNull())
|
|
continue;
|
|
d->itemList += i;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool JT_Roster::take(const TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, client()->host(), id()))
|
|
return false;
|
|
|
|
// get
|
|
if(type == 0) {
|
|
if(x.attribute("type") == "result") {
|
|
TQDomElement 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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
}
|
|
|
|
JT_PushRoster::~JT_PushRoster()
|
|
{
|
|
}
|
|
|
|
bool JT_PushRoster::take(const TQDomElement &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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
type = -1;
|
|
}
|
|
|
|
JT_Presence::~JT_Presence()
|
|
{
|
|
}
|
|
|
|
void JT_Presence::pres(const tqStatus &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", TQString("%1").tqarg(s.priority()) ) );
|
|
|
|
if(!s.keyID().isEmpty()) {
|
|
TQDomElement x = textTag(doc(), "x", s.keyID());
|
|
x.setAttribute("xmlns", "http://jabber.org/protocol/e2e");
|
|
tag.appendChild(x);
|
|
}
|
|
if(!s.xsigned().isEmpty()) {
|
|
TQDomElement x = textTag(doc(), "x", s.xsigned());
|
|
x.setAttribute("xmlns", "jabber:x:signed");
|
|
tag.appendChild(x);
|
|
}
|
|
|
|
if(!s.capsNode().isEmpty() && !s.capsVersion().isEmpty()) {
|
|
TQDomElement 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 tqStatus &s)
|
|
{
|
|
pres(s);
|
|
tag.setAttribute("to", to.full());
|
|
}
|
|
|
|
void JT_Presence::sub(const Jid &to, const TQString &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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
}
|
|
|
|
JT_PushPresence::~JT_PushPresence()
|
|
{
|
|
}
|
|
|
|
bool JT_PushPresence::take(const TQDomElement &e)
|
|
{
|
|
if(e.tagName() != "presence")
|
|
return false;
|
|
|
|
Jid j(e.attribute("from"));
|
|
tqStatus p;
|
|
|
|
if(e.hasAttribute("type")) {
|
|
TQString type = e.attribute("type");
|
|
if(type == "unavailable") {
|
|
p.setIsAvailable(false);
|
|
}
|
|
else if(type == "error") {
|
|
TQString str = "";
|
|
int code = 0;
|
|
getErrorFromElement(e, &code, &str);
|
|
p.setError(code, str);
|
|
}
|
|
else {
|
|
subscription(j, type);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
TQDomElement tag;
|
|
bool found;
|
|
|
|
tag = findSubTag(e, "status", &found);
|
|
if(found)
|
|
p.settqStatus(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(TQDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement i = n.toElement();
|
|
if(i.isNull())
|
|
continue;
|
|
|
|
if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:delay") {
|
|
if(i.hasAttribute("stamp")) {
|
|
TQDateTime 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") {
|
|
TQDomElement t;
|
|
bool found;
|
|
TQString 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 TQDomElement oldStyleNS(const TQDomElement &e)
|
|
{
|
|
// find closest tqparent with a namespace
|
|
TQDomNode par = e.parentNode();
|
|
while(!par.isNull() && par.namespaceURI().isNull())
|
|
par = par.parentNode();
|
|
bool noShowNS = false;
|
|
if(!par.isNull() && par.namespaceURI() == e.namespaceURI())
|
|
noShowNS = true;
|
|
|
|
TQDomElement i;
|
|
uint x;
|
|
//if(noShowNS)
|
|
i = e.ownerDocument().createElement(e.tagName());
|
|
//else
|
|
// i = e.ownerDocument().createElementNS(e.namespaceURI(), e.tagName());
|
|
|
|
// copy attributes
|
|
TQDomNamedNodeMap 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 tqchildren
|
|
TQDomNodeList nl = e.childNodes();
|
|
for(x = 0; x < nl.count(); ++x) {
|
|
TQDomNode n = nl.item(x);
|
|
if(n.isElement())
|
|
i.appendChild(oldStyleNS(n.toElement()));
|
|
else
|
|
i.appendChild(n.cloneNode());
|
|
}
|
|
return i;
|
|
}
|
|
|
|
JT_Message::JT_Message(Task *tqparent, const Message &msg)
|
|
:Task(tqparent)
|
|
{
|
|
m = msg;
|
|
m.setId(id());
|
|
}
|
|
|
|
JT_Message::~JT_Message()
|
|
{
|
|
}
|
|
|
|
void JT_Message::onGo()
|
|
{
|
|
Stanza s = m.toStanza(&(client()->stream()));
|
|
TQDomElement e = oldStyleNS(s.element());
|
|
send(e);
|
|
setSuccess();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// JT_PushMessage
|
|
//----------------------------------------------------------------------------
|
|
static TQDomElement addCorrectNS(const TQDomElement &e)
|
|
{
|
|
uint x;
|
|
|
|
// grab child nodes
|
|
/*TQDomDocumentFragment frag = e.ownerDocument().createDocumentFragment();
|
|
TQDomNodeList nl = e.childNodes();
|
|
for(x = 0; x < nl.count(); ++x)
|
|
frag.appendChild(nl.item(x).cloneNode());*/
|
|
|
|
// find closest xmlns
|
|
TQDomNode n = e;
|
|
while(!n.isNull() && !n.toElement().hasAttribute("xmlns"))
|
|
n = n.parentNode();
|
|
TQString ns;
|
|
if(n.isNull() || !n.toElement().hasAttribute("xmlns"))
|
|
ns = "jabber:client";
|
|
else
|
|
ns = n.toElement().attribute("xmlns");
|
|
|
|
// make a new node
|
|
TQDomElement i = e.ownerDocument().createElementNS(ns, e.tagName());
|
|
|
|
// copy attributes
|
|
TQDomNamedNodeMap al = e.attributes();
|
|
for(x = 0; x < al.count(); ++x) {
|
|
TQDomAttr a = al.item(x).toAttr();
|
|
if(a.name() != "xmlns")
|
|
i.setAttributeNodeNS(al.item(x).cloneNode().toAttr());
|
|
}
|
|
|
|
// copy tqchildren
|
|
TQDomNodeList nl = e.childNodes();
|
|
for(x = 0; x < nl.count(); ++x) {
|
|
TQDomNode 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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
}
|
|
|
|
JT_PushMessage::~JT_PushMessage()
|
|
{
|
|
}
|
|
|
|
bool JT_PushMessage::take(const TQDomElement &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;
|
|
TQString message;
|
|
};
|
|
|
|
JT_GetLastActivity::JT_GetLastActivity(Task *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
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());
|
|
TQDomElement query = doc()->createElement("query");
|
|
query.setAttribute("xmlns", "jabber:iq:last");
|
|
iq.appendChild(query);
|
|
}
|
|
|
|
int JT_GetLastActivity::seconds() const
|
|
{
|
|
return d->seconds;
|
|
}
|
|
|
|
const TQString &JT_GetLastActivity::message() const
|
|
{
|
|
return d->message;
|
|
}
|
|
|
|
void JT_GetLastActivity::onGo()
|
|
{
|
|
send(iq);
|
|
}
|
|
|
|
bool JT_GetLastActivity::take(const TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, jid, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
TQDomElement 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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
}
|
|
|
|
void JT_GetServices::get(const Jid &j)
|
|
{
|
|
agentList.clear();
|
|
|
|
jid = j;
|
|
iq = createIQ(doc(), "get", jid.full(), id());
|
|
TQDomElement 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 TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, jid, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
TQDomElement q = queryTag(x);
|
|
|
|
// agents
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement i = n.toElement();
|
|
if(i.isNull())
|
|
continue;
|
|
|
|
if(i.tagName() == "agent") {
|
|
AgentItem a;
|
|
|
|
a.setJid(Jid(i.attribute("jid")));
|
|
|
|
TQDomElement tag;
|
|
bool found;
|
|
|
|
tag = findSubTag(i, "name", &found);
|
|
if(found)
|
|
a.setName(tagContent(tag));
|
|
|
|
// determine which namespaces does item support
|
|
TQStringList 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() {}
|
|
|
|
TQDomElement iq;
|
|
Jid jid;
|
|
VCard vcard;
|
|
};
|
|
|
|
JT_VCard::JT_VCard(Task *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
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());
|
|
TQDomElement 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 TQDomElement &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(TQDomNode n = x.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement 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;
|
|
TQValueList<SearchResult> resultList;
|
|
};
|
|
|
|
JT_Search::JT_Search(Task *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
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());
|
|
TQDomElement 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());
|
|
TQDomElement 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 TQValueList<SearchResult> & JT_Search::results() const
|
|
{
|
|
return d->resultList;
|
|
}
|
|
|
|
void JT_Search::onGo()
|
|
{
|
|
send(iq);
|
|
}
|
|
|
|
bool JT_Search::take(const TQDomElement &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);
|
|
|
|
TQDomElement q = queryTag(x);
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement 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();
|
|
|
|
TQDomElement q = queryTag(x);
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement i = n.toElement();
|
|
if(i.isNull())
|
|
continue;
|
|
|
|
if(i.tagName() == "item") {
|
|
SearchResult r(Jid(i.attribute("jid")));
|
|
|
|
TQDomElement 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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
}
|
|
|
|
void JT_ClientVersion::get(const Jid &jid)
|
|
{
|
|
j = jid;
|
|
iq = createIQ(doc(), "get", j.full(), id());
|
|
TQDomElement query = doc()->createElement("query");
|
|
query.setAttribute("xmlns", "jabber:iq:version");
|
|
iq.appendChild(query);
|
|
}
|
|
|
|
void JT_ClientVersion::onGo()
|
|
{
|
|
send(iq);
|
|
}
|
|
|
|
bool JT_ClientVersion::take(const TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, j, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
bool found;
|
|
TQDomElement q = queryTag(x);
|
|
TQDomElement 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 TQString & JT_ClientVersion::name() const
|
|
{
|
|
return v_name;
|
|
}
|
|
|
|
const TQString & JT_ClientVersion::version() const
|
|
{
|
|
return v_ver;
|
|
}
|
|
|
|
const TQString & JT_ClientVersion::os() const
|
|
{
|
|
return v_os;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// JT_ClientTime
|
|
//----------------------------------------------------------------------------
|
|
/*JT_ClientTime::JT_ClientTime(Task *tqparent, const Jid &_j)
|
|
:Task(tqparent)
|
|
{
|
|
j = _j;
|
|
iq = createIQ("get", j.full(), id());
|
|
TQDomElement query = doc()->createElement("query");
|
|
query.setAttribute("xmlns", "jabber:iq:time");
|
|
iq.appendChild(query);
|
|
}
|
|
|
|
void JT_ClientTime::go()
|
|
{
|
|
send(iq);
|
|
}
|
|
|
|
bool JT_ClientTime::take(const TQDomElement &x)
|
|
{
|
|
if(x.attribute("id") != id())
|
|
return FALSE;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
bool found;
|
|
TQDomElement q = queryTag(x);
|
|
TQDomElement 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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
}
|
|
|
|
JT_ServInfo::~JT_ServInfo()
|
|
{
|
|
}
|
|
|
|
bool JT_ServInfo::take(const TQDomElement &e)
|
|
{
|
|
if(e.tagName() != "iq" || e.attribute("type") != "get")
|
|
return false;
|
|
|
|
TQString ns = queryNS(e);
|
|
if(ns == "jabber:iq:version") {
|
|
TQDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id"));
|
|
TQDomElement 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") {
|
|
// TQDomElement iq = createIQ("result", e.attribute("from"), e.attribute("id"));
|
|
// TQDomElement query = doc()->createElement("query");
|
|
// query.setAttribute("xmlns", "jabber:iq:time");
|
|
// iq.appendChild(query);
|
|
// TQDateTime local = TQDateTime::tqcurrentDateTime();
|
|
// TQDateTime utc = local.addSecs(-getTZOffset() * 3600);
|
|
// TQString str = getTZString();
|
|
// query.appendChild(textTag("utc", TS2stamp(utc)));
|
|
// query.appendChild(textTag("tz", str));
|
|
// query.appendChild(textTag("display", TQString("%1 %2").tqarg(local.toString()).tqarg(str)));
|
|
// send(iq);
|
|
// return TRUE;
|
|
//}
|
|
else if(ns == "http://jabber.org/protocol/disco#info") {
|
|
// Find out the node
|
|
TQString node;
|
|
bool found;
|
|
TQDomElement q = findSubTag(e, "query", &found);
|
|
if(found) // NOTE: Should always be true, since a NS was found above
|
|
node = q.attribute("node");
|
|
|
|
TQDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id"));
|
|
TQDomElement 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();
|
|
TQDomElement 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);
|
|
|
|
TQDomElement 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
|
|
TQStringList exts = client()->extensions();
|
|
for (TQStringList::ConstIterator i = exts.begin(); i != exts.end(); ++i) {
|
|
const TQStringList& l = client()->extension(*i).list();
|
|
for ( TQStringList::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() + "#")) {
|
|
TQString ext = node.right(node.length()-client()->capsNode().length()-1);
|
|
if (client()->extensions().tqcontains(ext)) {
|
|
const TQStringList& l = client()->extension(ext).list();
|
|
for ( TQStringList::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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
type = -1;
|
|
}
|
|
|
|
void JT_Gateway::get(const Jid &jid)
|
|
{
|
|
type = 0;
|
|
v_jid = jid;
|
|
iq = createIQ(doc(), "get", v_jid.full(), id());
|
|
TQDomElement query = doc()->createElement("query");
|
|
query.setAttribute("xmlns", "jabber:iq:gateway");
|
|
iq.appendChild(query);
|
|
}
|
|
|
|
void JT_Gateway::set(const Jid &jid, const TQString &prompt)
|
|
{
|
|
type = 1;
|
|
v_jid = jid;
|
|
v_prompt = prompt;
|
|
iq = createIQ(doc(), "set", v_jid.full(), id());
|
|
TQDomElement 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;
|
|
}
|
|
|
|
TQString JT_Gateway::desc() const
|
|
{
|
|
return v_desc;
|
|
}
|
|
|
|
TQString JT_Gateway::prompt() const
|
|
{
|
|
return v_prompt;
|
|
}
|
|
|
|
bool JT_Gateway::take(const TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, v_jid, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
if(type == 0) {
|
|
TQDomElement query = queryTag(x);
|
|
bool found;
|
|
TQDomElement tag;
|
|
tag = findSubTag(query, "desc", &found);
|
|
if(found)
|
|
v_desc = tagContent(tag);
|
|
tag = findSubTag(query, "prompt", &found);
|
|
if(found)
|
|
v_prompt = tagContent(tag);
|
|
}
|
|
else {
|
|
TQDomElement query = queryTag(x);
|
|
bool found;
|
|
TQDomElement 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:
|
|
TQDomElement iq;
|
|
Jid jid;
|
|
AgentList agentList;
|
|
AgentItem root;
|
|
};
|
|
|
|
JT_Browse::JT_Browse (Task *tqparent)
|
|
:Task (tqparent)
|
|
{
|
|
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());
|
|
TQDomElement 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 TQDomElement &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") );
|
|
|
|
TQStringList ns;
|
|
for(TQDomNode n = i.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement 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 TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, d->jid, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
for(TQDomNode n = x.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement i = n.toElement();
|
|
if(i.isNull())
|
|
continue;
|
|
|
|
d->root = browseHelper (i);
|
|
|
|
for(TQDomNode nn = i.firstChild(); !nn.isNull(); nn = nn.nextSibling()) {
|
|
TQDomElement 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() { }
|
|
|
|
TQDomElement iq;
|
|
Jid jid;
|
|
DiscoList items;
|
|
};
|
|
|
|
JT_DiscoItems::JT_DiscoItems(Task *tqparent)
|
|
: Task(tqparent)
|
|
{
|
|
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 TQString &node)
|
|
{
|
|
d->items.clear();
|
|
|
|
d->jid = j;
|
|
d->iq = createIQ(doc(), "get", d->jid.full(), id());
|
|
TQDomElement 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 TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, d->jid, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
TQDomElement q = queryTag(x);
|
|
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement 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() { }
|
|
|
|
TQDomElement iq;
|
|
Jid jid;
|
|
TQString node;
|
|
DiscoItem item;
|
|
};
|
|
|
|
JT_DiscoInfo::JT_DiscoInfo(Task *tqparent)
|
|
: Task(tqparent)
|
|
{
|
|
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 TQString &node, DiscoItem::Identity ident)
|
|
{
|
|
d->item = DiscoItem(); // clear item
|
|
|
|
d->jid = j;
|
|
d->node = node;
|
|
d->iq = createIQ(doc(), "get", d->jid.full(), id());
|
|
TQDomElement 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() ) {
|
|
TQDomElement 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 TQString& 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 TQDomElement &x)
|
|
{
|
|
if(!iqVerify(x, d->jid, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
TQDomElement q = queryTag(x);
|
|
|
|
DiscoItem item;
|
|
|
|
item.setJid( d->jid );
|
|
item.setNode( q.attribute("node") );
|
|
|
|
TQStringList features;
|
|
DiscoItem::Identities identities;
|
|
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement 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() { }
|
|
|
|
TQDomElement iq;
|
|
Jid jid;
|
|
DiscoList list;
|
|
};
|
|
|
|
JT_DiscoPublish::JT_DiscoPublish(Task *tqparent)
|
|
: Task(tqparent)
|
|
{
|
|
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());
|
|
TQDomElement 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) {
|
|
TQDomElement 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 TQDomElement &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 *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
type = -1;
|
|
}
|
|
|
|
JT_MucPresence::~JT_MucPresence()
|
|
{
|
|
}
|
|
|
|
void JT_MucPresence::pres(const tqStatus &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", TQString("%1").tqarg(s.priority()) ) );
|
|
|
|
if(!s.keyID().isEmpty()) {
|
|
TQDomElement x = textTag(doc(), "x", s.keyID());
|
|
x.setAttribute("xmlns", "http://jabber.org/protocol/e2e");
|
|
tag.appendChild(x);
|
|
}
|
|
if(!s.xsigned().isEmpty()) {
|
|
TQDomElement x = textTag(doc(), "x", s.xsigned());
|
|
x.setAttribute("xmlns", "jabber:x:signed");
|
|
tag.appendChild(x);
|
|
}
|
|
|
|
if(!s.capsNode().isEmpty() && !s.capsVersion().isEmpty()) {
|
|
TQDomElement 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 tqStatus &s, const TQString &password)
|
|
{
|
|
pres(s);
|
|
tag.setAttribute("to", to.full());
|
|
TQDomElement 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) {}
|
|
|
|
TQDomElement iq;
|
|
TQDomElement elem;
|
|
int type;
|
|
};
|
|
|
|
JT_PrivateStorage::JT_PrivateStorage(Task *tqparent)
|
|
:Task(tqparent)
|
|
{
|
|
d = new Private;
|
|
}
|
|
|
|
JT_PrivateStorage::~JT_PrivateStorage()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void JT_PrivateStorage::get(const TQString& tag, const TQString& xmlns)
|
|
{
|
|
d->type = 0;
|
|
d->iq = createIQ(doc(), "get" , TQString() , id() );
|
|
TQDomElement query = doc()->createElement("query");
|
|
query.setAttribute("xmlns", "jabber:iq:private");
|
|
d->iq.appendChild(query);
|
|
TQDomElement s = doc()->createElement(tag);
|
|
if(!xmlns.isEmpty())
|
|
s.setAttribute("xmlns", xmlns);
|
|
query.appendChild(s);
|
|
}
|
|
|
|
void JT_PrivateStorage::set(const TQDomElement& element)
|
|
{
|
|
d->type = 1;
|
|
d->elem=element;
|
|
TQDomNode n=doc()->importNode(element,true);
|
|
|
|
d->iq = createIQ(doc(), "set" , TQString() , id() );
|
|
TQDomElement 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 TQDomElement &x)
|
|
{
|
|
TQString to = client()->host();
|
|
if(!iqVerify(x, to, id()))
|
|
return false;
|
|
|
|
if(x.attribute("type") == "result") {
|
|
if(d->type == 0) {
|
|
TQDomElement q = queryTag(x);
|
|
for(TQDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
TQDomElement i = n.toElement();
|
|
if(i.isNull())
|
|
continue;
|
|
d->elem=i;
|
|
break;
|
|
}
|
|
}
|
|
setSuccess();
|
|
return true;
|
|
}
|
|
else {
|
|
setError(x);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
TQDomElement JT_PrivateStorage::element( )
|
|
{
|
|
return d->elem;
|
|
}
|
|
|