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.
tdenetwork/kopete/protocols/jabber/libiris/iris/xmpp-im/types.cpp

1878 lines
36 KiB

/*
* types.cpp - IM data types
* Copyright (C) 2003 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"im.h"
#include "protocol.h"
#include<tqmap.h>
#include<tqapplication.h>
#define NS_XML "http://www.w3.org/XML/1998/namespace"
static TQDomElement textTag(TQDomDocument *doc, const TQString &name, const TQString &content)
{
TQDomElement tag = doc->createElement(name);
TQDomText text = doc->createTextNode(content);
tag.appendChild(text);
return tag;
}
static TQString tagContent(const TQDomElement &e)
{
// look for some tag content
for(TQDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
TQDomText i = n.toText();
if(i.isNull())
continue;
return i.data();
}
return "";
}
static TQDateTime stamp2TS(const TQString &ts)
{
if(ts.length() != 17)
return TQDateTime();
int year = ts.mid(0,4).toInt();
int month = ts.mid(4,2).toInt();
int day = ts.mid(6,2).toInt();
int hour = ts.mid(9,2).toInt();
int min = ts.mid(12,2).toInt();
int sec = ts.mid(15,2).toInt();
TQDate xd;
xd.setYMD(year, month, day);
if(!xd.isValid())
return TQDateTime();
TQTime xt;
xt.setHMS(hour, min, sec);
if(!xt.isValid())
return TQDateTime();
return TQDateTime(xd, xt);
}
/*static TQString TS2stamp(const TQDateTime &d)
{
TQString str;
str.sprintf("%04d%02d%02dT%02d:%02d:%02d",
d.date().year(),
d.date().month(),
d.date().day(),
d.time().hour(),
d.time().minute(),
d.time().second());
return str;
}*/
namespace XMPP
{
//----------------------------------------------------------------------------
// Url
//----------------------------------------------------------------------------
class Url::Private
{
public:
TQString url;
TQString desc;
};
//! \brief Construct Url object with a given URL and Description.
//!
//! This function will construct a Url object.
//! \param TQString - url (default: empty string)
//! \param TQString - description of url (default: empty string)
//! \sa setUrl() setDesc()
Url::Url(const TQString &url, const TQString &desc)
{
d = new Private;
d->url = url;
d->desc = desc;
}
//! \brief Construct Url object.
//!
//! Overloaded constructor which will constructs a exact copy of the Url object that was passed to the constructor.
//! \param Url - Url Object
Url::Url(const Url &from)
{
d = new Private;
*this = from;
}
//! \brief operator overloader needed for d pointer (Internel).
Url & Url::operator=(const Url &from)
{
*d = *from.d;
return *this;
}
//! \brief destroy Url object.
Url::~Url()
{
delete d;
}
//! \brief Get url information.
//!
//! Returns url information.
TQString Url::url() const
{
return d->url;
}
//! \brief Get Description information.
//!
//! Returns desction of the URL.
TQString Url::desc() const
{
return d->desc;
}
//! \brief Set Url information.
//!
//! Set url information.
//! \param url - url string (eg: http://psi.affinix.com/)
void Url::setUrl(const TQString &url)
{
d->url = url;
}
//! \brief Set Description information.
//!
//! Set description of the url.
//! \param desc - description of url
void Url::setDesc(const TQString &desc)
{
d->desc = desc;
}
//----------------------------------------------------------------------------
// Message
//----------------------------------------------------------------------------
class Message::Private
{
public:
Jid to, from;
TQString id, type, lang;
StringMap subject, body, xHTMLBody;
TQString thread;
Stanza::Error error;
// extensions
TQDateTime timeStamp;
UrlList urlList;
TQValueList<MsgEvent> eventList;
TQString eventId;
TQString xencrypted, invite;
bool spooled, wasEncrypted;
};
//! \brief Constructs Message with given Jid information.
//!
//! This function will construct a Message container.
//! \param to - specify reciver (default: empty string)
Message::Message(const Jid &to)
{
d = new Private;
d->to = to;
d->spooled = false;
d->wasEncrypted = false;
/*d->flag = false;
d->spooled = false;
d->wasEncrypted = false;
d->errorCode = -1;*/
}
//! \brief Constructs a copy of Message object
//!
//! Overloaded constructor which will constructs a exact copy of the Message
//! object that was passed to the constructor.
//! \param from - Message object you want to copy
Message::Message(const Message &from)
{
d = new Private;
*this = from;
}
//! \brief Required for internel use.
Message & Message::operator=(const Message &from)
{
*d = *from.d;
return *this;
}
//! \brief Destroy Message object.
Message::~Message()
{
delete d;
}
//! \brief Return receiver's Jid information.
Jid Message::to() const
{
return d->to;
}
//! \brief Return sender's Jid information.
Jid Message::from() const
{
return d->from;
}
TQString Message::id() const
{
return d->id;
}
//! \brief Return type information
TQString Message::type() const
{
return d->type;
}
TQString Message::lang() const
{
return d->lang;
}
//! \brief Return subject information.
TQString Message::subject(const TQString &lang) const
{
return d->subject[lang];
}
//! \brief Return body information.
//!
//! This function will return a plain text or the Richtext version if it
//! it exists.
//! \param rich - Returns richtext if true and plain text if false. (default: false)
//! \note Richtext is in TQt's richtext format and not in xhtml.
TQString Message::body(const TQString &lang) const
{
return d->body[lang];
}
TQString Message::xHTMLBody(const TQString &lang) const
{
return d->xHTMLBody[lang];
}
TQString Message::thread() const
{
return d->thread;
}
Stanza::Error Message::error() const
{
return d->error;
}
//! \brief Set receivers information
//!
//! \param to - Receivers Jabber id
void Message::setTo(const Jid &j)
{
d->to = j;
//d->flag = false;
}
void Message::setFrom(const Jid &j)
{
d->from = j;
//d->flag = false;
}
void Message::setId(const TQString &s)
{
d->id = s;
}
//! \brief Set Type of message
//!
//! \param type - type of message your going to send
void Message::setType(const TQString &s)
{
d->type = s;
//d->flag = false;
}
void Message::setLang(const TQString &s)
{
d->lang = s;
}
//! \brief Set subject
//!
//! \param subject - Subject information
void Message::setSubject(const TQString &s, const TQString &lang)
{
d->subject[lang] = s;
//d->flag = false;
}
//! \brief Set body
//!
//! \param body - body information
//! \param rich - set richtext if true and set plaintext if false.
//! \note Richtext support will be implemented in the future... Sorry.
void Message::setBody(const TQString &s, const TQString &lang)
{
d->body[lang] = s;
}
void Message::setXHTMLBody(const TQString &s, const TQString &lang, const TQString &attr)
{
//ugly but needed if s is not a node but a list of leaf
TQString content = "<body xmlns='" + TQString(NS_XHTML) + "' "+attr+" >\n" + s +"\n</body>";
d->xHTMLBody[lang] = content;
}
void Message::setThread(const TQString &s)
{
d->thread = s;
}
void Message::setError(const Stanza::Error &err)
{
d->error = err;
}
TQDateTime Message::timeStamp() const
{
return d->timeStamp;
}
void Message::setTimeStamp(const TQDateTime &ts)
{
d->timeStamp = ts;
}
//! \brief Return list of urls attached to message.
UrlList Message::urlList() const
{
return d->urlList;
}
//! \brief Add Url to the url list.
//!
//! \param url - url to append
void Message::urlAdd(const Url &u)
{
d->urlList += u;
}
//! \brief clear out the url list.
void Message::urlsClear()
{
d->urlList.clear();
}
//! \brief Set urls to send
//!
//! \param urlList - list of urls to send
void Message::setUrlList(const UrlList &list)
{
d->urlList = list;
}
TQString Message::eventId() const
{
return d->eventId;
}
void Message::setEventId(const TQString& id)
{
d->eventId = id;
}
bool Message::containsEvents() const
{
return !d->eventList.isEmpty();
}
bool Message::containsEvent(MsgEvent e) const
{
return d->eventList.contains(e);
}
void Message::addEvent(MsgEvent e)
{
if (!d->eventList.contains(e)) {
if (e == CancelEvent || containsEvent(CancelEvent))
d->eventList.clear(); // Reset list
d->eventList += e;
}
}
TQString Message::xencrypted() const
{
return d->xencrypted;
}
void Message::setXEncrypted(const TQString &s)
{
d->xencrypted = s;
}
TQString Message::invite() const
{
return d->invite;
}
void Message::setInvite(const TQString &s)
{
d->invite = s;
}
bool Message::spooled() const
{
return d->spooled;
}
void Message::setSpooled(bool b)
{
d->spooled = b;
}
bool Message::wasEncrypted() const
{
return d->wasEncrypted;
}
void Message::setWasEncrypted(bool b)
{
d->wasEncrypted = b;
}
Stanza Message::toStanza(Stream *stream) const
{
Stanza s = stream->createStanza(Stanza::Message, d->to, d->type);
if(!d->from.isEmpty())
s.setFrom(d->from);
if(!d->id.isEmpty())
s.setId(d->id);
if(!d->lang.isEmpty())
s.setLang(d->lang);
StringMap::ConstIterator it;
for(it = d->subject.begin(); it != d->subject.end(); ++it) {
const TQString &str = it.data();
if(!str.isEmpty()) {
TQDomElement e = s.createTextElement(s.baseNS(), "subject", str);
if(!it.key().isEmpty())
e.setAttributeNS(NS_XML, "xml:lang", it.key());
s.appendChild(e);
}
}
for(it = d->body.begin(); it != d->body.end(); ++it) {
const TQString &str = it.data();
if(!str.isEmpty()) {
TQDomElement e = s.createTextElement(s.baseNS(), "body", str);
if(!it.key().isEmpty())
e.setAttributeNS(NS_XML, "xml:lang", it.key());
s.appendChild(e);
}
}
if ( !d->xHTMLBody.isEmpty()) {
TQDomElement parent = s.createElement(s.xhtmlImNS(), "html");
for(it = d->xHTMLBody.begin(); it != d->xHTMLBody.end(); ++it) {
const TQString &str = it.data();
if(!str.isEmpty()) {
TQDomElement child = s.createXHTMLElement(str);
if(!it.key().isEmpty())
child.setAttributeNS(NS_XML, "xml:lang", it.key());
parent.appendChild(child);
}
}
s.appendChild(parent);
}
if(d->type == "error")
s.setError(d->error);
// timestamp
/*if(!d->timeStamp.isNull()) {
TQDomElement e = s.createElement("jabber:x:delay", "x");
e.setAttribute("stamp", TS2stamp(d->timeStamp));
s.appendChild(e);
}*/
// urls
for(TQValueList<Url>::ConstIterator uit = d->urlList.begin(); uit != d->urlList.end(); ++uit) {
TQDomElement x = s.createElement("jabber:x:oob", "x");
x.appendChild(s.createTextElement("jabber:x:oob", "url", (*uit).url()));
if(!(*uit).desc().isEmpty())
x.appendChild(s.createTextElement("jabber:x:oob", "desc", (*uit).desc()));
s.appendChild(x);
}
// events
if (!d->eventList.isEmpty()) {
TQDomElement x = s.createElement("jabber:x:event", "x");
if (d->body.isEmpty()) {
if (d->eventId.isEmpty())
x.appendChild(s.createElement("jabber:x:event","id"));
else
x.appendChild(s.createTextElement("jabber:x:event","id",d->eventId));
}
else if (d->type=="chat" || d->type=="groupchat")
s.appendChild( s.createElement(NS_CHATSTATES , "active" ) );
bool need_x_event=false;
for(TQValueList<MsgEvent>::ConstIterator ev = d->eventList.begin(); ev != d->eventList.end(); ++ev) {
switch (*ev) {
case OfflineEvent:
x.appendChild(s.createElement("jabber:x:event", "offline"));
need_x_event=true;
break;
case DeliveredEvent:
x.appendChild(s.createElement("jabber:x:event", "delivered"));
need_x_event=true;
break;
case DisplayedEvent:
x.appendChild(s.createElement("jabber:x:event", "displayed"));
need_x_event=true;
break;
case ComposingEvent:
x.appendChild(s.createElement("jabber:x:event", "composing"));
need_x_event=true;
if (d->body.isEmpty() && (d->type=="chat" || d->type=="groupchat") )
s.appendChild( s.createElement(NS_CHATSTATES , "composing" ) );
break;
case CancelEvent:
need_x_event=true;
if (d->body.isEmpty() && (d->type=="chat" || d->type=="groupchat") )
s.appendChild( s.createElement(NS_CHATSTATES , "paused" ) );
break;
case InactiveEvent:
if (d->body.isEmpty() && (d->type=="chat" || d->type=="groupchat") )
s.appendChild( s.createElement(NS_CHATSTATES , "inactive" ) );
break;
case GoneEvent:
if (d->body.isEmpty() && (d->type=="chat" || d->type=="groupchat") )
s.appendChild( s.createElement(NS_CHATSTATES , "gone" ) );
break;
}
}
if(need_x_event) //we don't need to have the (empty) x:event element if this is only <gone> or <inactive>
s.appendChild(x);
}
// xencrypted
if(!d->xencrypted.isEmpty())
s.appendChild(s.createTextElement("jabber:x:encrypted", "x", d->xencrypted));
// invite
if(!d->invite.isEmpty()) {
TQDomElement e = s.createElement("jabber:x:conference", "x");
e.setAttribute("jid", d->invite);
s.appendChild(e);
}
return s;
}
bool Message::fromStanza(const Stanza &s, int timeZoneOffset)
{
if(s.kind() != Stanza::Message)
return false;
setTo(s.to());
setFrom(s.from());
setId(s.id());
setType(s.type());
setLang(s.lang());
d->subject.clear();
d->body.clear();
d->thread = TQString();
d->eventList.clear();
TQDomElement root = s.element();
TQDomNodeList nl = root.childNodes();
uint n;
for(n = 0; n < nl.count(); ++n) {
TQDomNode i = nl.item(n);
if(i.isElement()) {
TQDomElement e = i.toElement();
if(e.namespaceURI() == s.baseNS()) {
if(e.tagName() == "subject") {
TQString lang = e.attributeNS(NS_XML, "lang", "");
d->subject[lang] = e.text();
}
else if(e.tagName() == "body") {
TQString lang = e.attributeNS(NS_XML, "lang", "");
d->body[lang] = e.text();
}
else if(e.tagName() == "thread")
d->thread = e.text();
}
else if (e.namespaceURI() == s.xhtmlImNS()) {
if (e.tagName() == "html") {
TQDomNodeList htmlNL= e.childNodes();
for (unsigned int x = 0; x < htmlNL.count(); x++) {
TQDomElement i = htmlNL.item(x).toElement();
if (i.tagName() == "body") {
TQDomDocument RichText;
TQString lang = i.attributeNS(NS_XML, "lang", "");
RichText.appendChild(i);
d-> xHTMLBody[lang] = RichText.toString();
}
}
}
}
else if (e.namespaceURI() == NS_CHATSTATES)
{
if(e.tagName() == "active")
{
//like in JEP-0022 we let the client know that we can receive ComposingEvent
// (we can do that according to <20>4.6 of the JEP-0085)
d->eventList += ComposingEvent;
d->eventList += InactiveEvent;
d->eventList += GoneEvent;
}
else if (e.tagName() == "composing")
{
d->eventList += ComposingEvent;
}
else if (e.tagName() == "paused")
{
d->eventList += CancelEvent;
}
else if (e.tagName() == "inactive")
{
d->eventList += InactiveEvent;
}
else if (e.tagName() == "gone")
{
d->eventList += GoneEvent;
}
}
else {
//printf("extension element: [%s]\n", e.tagName().latin1());
}
}
}
if(s.type() == "error")
d->error = s.error();
// timestamp
TQDomElement t = root.elementsByTagNameNS("jabber:x:delay", "x").item(0).toElement();
if(!t.isNull()) {
d->timeStamp = stamp2TS(t.attribute("stamp"));
d->timeStamp = d->timeStamp.addSecs(timeZoneOffset * 3600);
d->spooled = true;
}
else {
d->timeStamp = TQDateTime::currentDateTime();
d->spooled = false;
}
// urls
d->urlList.clear();
nl = root.elementsByTagNameNS("jabber:x:oob", "x");
for(n = 0; n < nl.count(); ++n) {
TQDomElement t = nl.item(n).toElement();
Url u;
u.setUrl(t.elementsByTagName("url").item(0).toElement().text());
u.setDesc(t.elementsByTagName("desc").item(0).toElement().text());
d->urlList += u;
}
// events
nl = root.elementsByTagNameNS("jabber:x:event", "x");
if (nl.count()) {
nl = nl.item(0).childNodes();
for(n = 0; n < nl.count(); ++n) {
TQString evtag = nl.item(n).toElement().tagName();
if (evtag == "id") {
d->eventId = nl.item(n).toElement().text();
}
else if (evtag == "displayed")
d->eventList += DisplayedEvent;
else if (evtag == "composing")
d->eventList += ComposingEvent;
else if (evtag == "delivered")
d->eventList += DeliveredEvent;
else if (evtag == "offline")
d->eventList += OfflineEvent;
}
if (d->eventList.isEmpty())
d->eventList += CancelEvent;
}
// xencrypted
t = root.elementsByTagNameNS("jabber:x:encrypted", "x").item(0).toElement();
if(!t.isNull())
d->xencrypted = t.text();
else
d->xencrypted = TQString();
// invite
t = root.elementsByTagNameNS("jabber:x:conference", "x").item(0).toElement();
if(!t.isNull())
d->invite = t.attribute("jid");
else
d->invite = TQString();
return true;
}
//---------------------------------------------------------------------------
// Subscription
//---------------------------------------------------------------------------
Subscription::Subscription(SubType type)
{
value = type;
}
int Subscription::type() const
{
return value;
}
TQString Subscription::toString() const
{
switch(value) {
case Remove:
return "remove";
case Both:
return "both";
case From:
return "from";
case To:
return "to";
case None:
default:
return "none";
}
}
bool Subscription::fromString(const TQString &s)
{
if(s == "remove")
value = Remove;
else if(s == "both")
value = Both;
else if(s == "from")
value = From;
else if(s == "to")
value = To;
else if(s == "none")
value = None;
else
return false;
return true;
}
//---------------------------------------------------------------------------
// Status
//---------------------------------------------------------------------------
Status::Status(const TQString &show, const TQString &status, int priority, bool available)
{
v_isAvailable = available;
v_show = show;
v_status = status;
v_priority = priority;
v_timeStamp = TQDateTime::currentDateTime();
v_isInvisible = false;
ecode = -1;
}
Status::~Status()
{
}
bool Status::hasError() const
{
return (ecode != -1);
}
void Status::setError(int code, const TQString &str)
{
ecode = code;
estr = str;
}
void Status::setIsAvailable(bool available)
{
v_isAvailable = available;
}
void Status::setIsInvisible(bool invisible)
{
v_isInvisible = invisible;
}
void Status::setPriority(int x)
{
v_priority = x;
}
void Status::setShow(const TQString & _show)
{
v_show = _show;
}
void Status::setStatus(const TQString & _status)
{
v_status = _status;
}
void Status::setTimeStamp(const TQDateTime & _timestamp)
{
v_timeStamp = _timestamp;
}
void Status::setKeyID(const TQString &key)
{
v_key = key;
}
void Status::setXSigned(const TQString &s)
{
v_xsigned = s;
}
void Status::setSongTitle(const TQString & _songtitle)
{
v_songTitle = _songtitle;
}
void Status::setCapsNode(const TQString & _capsNode)
{
v_capsNode = _capsNode;
}
void Status::setCapsVersion(const TQString & _capsVersion)
{
v_capsVersion = _capsVersion;
}
void Status::setCapsExt(const TQString & _capsExt)
{
v_capsExt = _capsExt;
}
bool Status::isAvailable() const
{
return v_isAvailable;
}
bool Status::isAway() const
{
if(v_show == "away" || v_show == "xa" || v_show == "dnd")
return true;
return false;
}
bool Status::isInvisible() const
{
return v_isInvisible;
}
int Status::priority() const
{
return v_priority;
}
const TQString & Status::show() const
{
return v_show;
}
const TQString & Status::status() const
{
return v_status;
}
TQDateTime Status::timeStamp() const
{
return v_timeStamp;
}
const TQString & Status::keyID() const
{
return v_key;
}
const TQString & Status::xsigned() const
{
return v_xsigned;
}
const TQString & Status::songTitle() const
{
return v_songTitle;
}
const TQString & Status::capsNode() const
{
return v_capsNode;
}
const TQString & Status::capsVersion() const
{
return v_capsVersion;
}
const TQString & Status::capsExt() const
{
return v_capsExt;
}
int Status::errorCode() const
{
return ecode;
}
const TQString & Status::errorString() const
{
return estr;
}
//---------------------------------------------------------------------------
// Resource
//---------------------------------------------------------------------------
Resource::Resource(const TQString &name, const Status &stat)
{
v_name = name;
v_status = stat;
}
Resource::~Resource()
{
}
const TQString & Resource::name() const
{
return v_name;
}
int Resource::priority() const
{
return v_status.priority();
}
const Status & Resource::status() const
{
return v_status;
}
void Resource::setName(const TQString & _name)
{
v_name = _name;
}
void Resource::setStatus(const Status & _status)
{
v_status = _status;
}
//---------------------------------------------------------------------------
// ResourceList
//---------------------------------------------------------------------------
ResourceList::ResourceList()
:TQValueList<Resource>()
{
}
ResourceList::~ResourceList()
{
}
ResourceList::Iterator ResourceList::find(const TQString & _find)
{
for(ResourceList::Iterator it = begin(); it != end(); ++it) {
if((*it).name() == _find)
return it;
}
return end();
}
ResourceList::Iterator ResourceList::priority()
{
ResourceList::Iterator highest = end();
for(ResourceList::Iterator it = begin(); it != end(); ++it) {
if(highest == end() || (*it).priority() > (*highest).priority())
highest = it;
}
return highest;
}
ResourceList::ConstIterator ResourceList::find(const TQString & _find) const
{
for(ResourceList::ConstIterator it = begin(); it != end(); ++it) {
if((*it).name() == _find)
return it;
}
return end();
}
ResourceList::ConstIterator ResourceList::priority() const
{
ResourceList::ConstIterator highest = end();
for(ResourceList::ConstIterator it = begin(); it != end(); ++it) {
if(highest == end() || (*it).priority() > (*highest).priority())
highest = it;
}
return highest;
}
//---------------------------------------------------------------------------
// RosterItem
//---------------------------------------------------------------------------
RosterItem::RosterItem(const Jid &_jid)
{
v_jid = _jid;
}
RosterItem::~RosterItem()
{
}
const Jid & RosterItem::jid() const
{
return v_jid;
}
const TQString & RosterItem::name() const
{
return v_name;
}
const TQStringList & RosterItem::groups() const
{
return v_groups;
}
const Subscription & RosterItem::subscription() const
{
return v_subscription;
}
const TQString & RosterItem::ask() const
{
return v_ask;
}
bool RosterItem::isPush() const
{
return v_push;
}
bool RosterItem::inGroup(const TQString &g) const
{
for(TQStringList::ConstIterator it = v_groups.begin(); it != v_groups.end(); ++it) {
if(*it == g)
return true;
}
return false;
}
void RosterItem::setJid(const Jid &_jid)
{
v_jid = _jid;
}
void RosterItem::setName(const TQString &_name)
{
v_name = _name;
}
void RosterItem::setGroups(const TQStringList &_groups)
{
v_groups = _groups;
}
void RosterItem::setSubscription(const Subscription &type)
{
v_subscription = type;
}
void RosterItem::setAsk(const TQString &_ask)
{
v_ask = _ask;
}
void RosterItem::setIsPush(bool b)
{
v_push = b;
}
bool RosterItem::addGroup(const TQString &g)
{
if(inGroup(g))
return false;
v_groups += g;
return true;
}
bool RosterItem::removeGroup(const TQString &g)
{
for(TQStringList::Iterator it = v_groups.begin(); it != v_groups.end(); ++it) {
if(*it == g) {
v_groups.remove(it);
return true;
}
}
return false;
}
TQDomElement RosterItem::toXml(TQDomDocument *doc) const
{
TQDomElement item = doc->createElement("item");
item.setAttribute("jid", v_jid.full());
item.setAttribute("name", v_name);
item.setAttribute("subscription", v_subscription.toString());
if(!v_ask.isEmpty())
item.setAttribute("ask", v_ask);
for(TQStringList::ConstIterator it = v_groups.begin(); it != v_groups.end(); ++it)
item.appendChild(textTag(doc, "group", *it));
return item;
}
bool RosterItem::fromXml(const TQDomElement &item)
{
if(item.tagName() != "item")
return false;
Jid j(item.attribute("jid"));
if(!j.isValid())
return false;
TQString na = item.attribute("name");
Subscription s;
if(!s.fromString(item.attribute("subscription")) )
return false;
TQStringList g;
for(TQDomNode n = item.firstChild(); !n.isNull(); n = n.nextSibling()) {
TQDomElement i = n.toElement();
if(i.isNull())
continue;
if(i.tagName() == "group")
g += tagContent(i);
}
TQString a = item.attribute("ask");
v_jid = j;
v_name = na;
v_subscription = s;
v_groups = g;
v_ask = a;
return true;
}
//---------------------------------------------------------------------------
// Roster
//---------------------------------------------------------------------------
Roster::Roster()
:TQValueList<RosterItem>()
{
}
Roster::~Roster()
{
}
Roster::Iterator Roster::find(const Jid &j)
{
for(Roster::Iterator it = begin(); it != end(); ++it) {
if((*it).jid().compare(j))
return it;
}
return end();
}
Roster::ConstIterator Roster::find(const Jid &j) const
{
for(Roster::ConstIterator it = begin(); it != end(); ++it) {
if((*it).jid().compare(j))
return it;
}
return end();
}
//---------------------------------------------------------------------------
// FormField
//---------------------------------------------------------------------------
FormField::FormField(const TQString &type, const TQString &value)
{
v_type = misc;
if(!type.isEmpty()) {
int x = tagNameToType(type);
if(x != -1)
v_type = x;
}
v_value = value;
}
FormField::~FormField()
{
}
int FormField::type() const
{
return v_type;
}
TQString FormField::realName() const
{
return typeToTagName(v_type);
}
TQString FormField::fieldName() const
{
switch(v_type) {
case username: return TQObject::tr("Username");
case nick: return TQObject::tr("Nickname");
case password: return TQObject::tr("Password");
case name: return TQObject::tr("Name");
case first: return TQObject::tr("First Name");
case last: return TQObject::tr("Last Name");
case email: return TQObject::tr("E-mail");
case address: return TQObject::tr("Address");
case city: return TQObject::tr("City");
case state: return TQObject::tr("State");
case zip: return TQObject::tr("Zipcode");
case phone: return TQObject::tr("Phone");
case url: return TQObject::tr("URL");
case date: return TQObject::tr("Date");
case misc: return TQObject::tr("Misc");
default: return "";
};
}
bool FormField::isSecret() const
{
return (type() == password);
}
const TQString & FormField::value() const
{
return v_value;
}
void FormField::setType(int x)
{
v_type = x;
}
bool FormField::setType(const TQString &in)
{
int x = tagNameToType(in);
if(x == -1)
return false;
v_type = x;
return true;
}
void FormField::setValue(const TQString &in)
{
v_value = in;
}
int FormField::tagNameToType(const TQString &in) const
{
if(!in.compare("username")) return username;
if(!in.compare("nick")) return nick;
if(!in.compare("password")) return password;
if(!in.compare("name")) return name;
if(!in.compare("first")) return first;
if(!in.compare("last")) return last;
if(!in.compare("email")) return email;
if(!in.compare("address")) return address;
if(!in.compare("city")) return city;
if(!in.compare("state")) return state;
if(!in.compare("zip")) return zip;
if(!in.compare("phone")) return phone;
if(!in.compare("url")) return url;
if(!in.compare("date")) return date;
if(!in.compare("misc")) return misc;
return -1;
}
TQString FormField::typeToTagName(int type) const
{
switch(type) {
case username: return "username";
case nick: return "nick";
case password: return "password";
case name: return "name";
case first: return "first";
case last: return "last";
case email: return "email";
case address: return "address";
case city: return "city";
case state: return "state";
case zip: return "zipcode";
case phone: return "phone";
case url: return "url";
case date: return "date";
case misc: return "misc";
default: return "";
};
}
//---------------------------------------------------------------------------
// Form
//---------------------------------------------------------------------------
Form::Form(const Jid &j)
:TQValueList<FormField>()
{
setJid(j);
}
Form::~Form()
{
}
Jid Form::jid() const
{
return v_jid;
}
TQString Form::instructions() const
{
return v_instructions;
}
TQString Form::key() const
{
return v_key;
}
void Form::setJid(const Jid &j)
{
v_jid = j;
}
void Form::setInstructions(const TQString &s)
{
v_instructions = s;
}
void Form::setKey(const TQString &s)
{
v_key = s;
}
//---------------------------------------------------------------------------
// SearchResult
//---------------------------------------------------------------------------
SearchResult::SearchResult(const Jid &jid)
{
setJid(jid);
}
SearchResult::~SearchResult()
{
}
const Jid & SearchResult::jid() const
{
return v_jid;
}
const TQString & SearchResult::nick() const
{
return v_nick;
}
const TQString & SearchResult::first() const
{
return v_first;
}
const TQString & SearchResult::last() const
{
return v_last;
}
const TQString & SearchResult::email() const
{
return v_email;
}
void SearchResult::setJid(const Jid &jid)
{
v_jid = jid;
}
void SearchResult::setNick(const TQString &nick)
{
v_nick = nick;
}
void SearchResult::setFirst(const TQString &first)
{
v_first = first;
}
void SearchResult::setLast(const TQString &last)
{
v_last = last;
}
void SearchResult::setEmail(const TQString &email)
{
v_email = email;
}
//---------------------------------------------------------------------------
// Features
//---------------------------------------------------------------------------
Features::Features()
{
}
Features::Features(const TQStringList &l)
{
setList(l);
}
Features::Features(const TQString &str)
{
TQStringList l;
l << str;
setList(l);
}
Features::~Features()
{
}
TQStringList Features::list() const
{
return _list;
}
void Features::setList(const TQStringList &l)
{
_list = l;
}
bool Features::test(const TQStringList &ns) const
{
TQStringList::ConstIterator it = ns.begin();
for ( ; it != ns.end(); ++it)
if ( _list.find( *it ) != _list.end() )
return true;
return false;
}
#define FID_REGISTER "jabber:iq:register"
bool Features::canRegister() const
{
TQStringList ns;
ns << FID_REGISTER;
return test(ns);
}
#define FID_SEARCH "jabber:iq:search"
bool Features::canSearch() const
{
TQStringList ns;
ns << FID_SEARCH;
return test(ns);
}
#define FID_XHTML "http://jabber.org/protocol/xhtml-im"
bool Features::canXHTML() const
{
TQStringList ns;
ns << FID_XHTML;
return test(ns);
}
#define FID_GROUPCHAT "jabber:iq:conference"
bool Features::canGroupchat() const
{
TQStringList ns;
ns << "http://jabber.org/protocol/muc";
ns << FID_GROUPCHAT;
return test(ns);
}
#define FID_VOICE "http://www.google.com/xmpp/protocol/voice/v1"
bool Features::canVoice() const
{
TQStringList ns;
ns << FID_VOICE;
return test(ns);
}
#define FID_GATEWAY "jabber:iq:gateway"
bool Features::isGateway() const
{
TQStringList ns;
ns << FID_GATEWAY;
return test(ns);
}
#define FID_DISCO "http://jabber.org/protocol/disco"
bool Features::canDisco() const
{
TQStringList ns;
ns << FID_DISCO;
ns << "http://jabber.org/protocol/disco#info";
ns << "http://jabber.org/protocol/disco#items";
return test(ns);
}
#define FID_VCARD "vcard-temp"
bool Features::haveVCard() const
{
TQStringList ns;
ns << FID_VCARD;
return test(ns);
}
// custom Psi acitons
#define FID_ADD "psi:add"
class Features::FeatureName : public TQObject
{
Q_OBJECT
public:
FeatureName()
: TQObject(tqApp)
{
id2s[FID_Invalid] = tr("ERROR: Incorrect usage of Features class");
id2s[FID_None] = tr("None");
id2s[FID_Register] = tr("Register");
id2s[FID_Search] = tr("Search");
id2s[FID_Groupchat] = tr("Groupchat");
id2s[FID_Gateway] = tr("Gateway");
id2s[FID_Disco] = tr("Service Discovery");
id2s[FID_VCard] = tr("VCard");
// custom Psi actions
id2s[FID_Add] = tr("Add to roster");
// compute reverse map
//TQMap<TQString, long>::Iterator it = id2s.begin();
//for ( ; it != id2s.end(); ++it)
// s2id[it.data()] = it.key();
id2f[FID_Register] = FID_REGISTER;
id2f[FID_Search] = FID_SEARCH;
id2f[FID_Groupchat] = FID_GROUPCHAT;
id2f[FID_Gateway] = FID_GATEWAY;
id2f[FID_Disco] = FID_DISCO;
id2f[FID_VCard] = FID_VCARD;
// custom Psi actions
id2f[FID_Add] = FID_ADD;
}
//TQMap<TQString, long> s2id;
TQMap<long, TQString> id2s;
TQMap<long, TQString> id2f;
};
static Features::FeatureName *featureName = 0;
long Features::id() const
{
if ( _list.count() > 1 )
return FID_Invalid;
else if ( canRegister() )
return FID_Register;
else if ( canSearch() )
return FID_Search;
else if ( canGroupchat() )
return FID_Groupchat;
else if ( isGateway() )
return FID_Gateway;
else if ( canDisco() )
return FID_Disco;
else if ( haveVCard() )
return FID_VCard;
else if ( test(FID_ADD) )
return FID_Add;
return FID_None;
}
long Features::id(const TQString &feature)
{
Features f(feature);
return f.id();
}
TQString Features::feature(long id)
{
if ( !featureName )
featureName = new FeatureName();
return featureName->id2f[id];
}
TQString Features::name(long id)
{
if ( !featureName )
featureName = new FeatureName();
return featureName->id2s[id];
}
TQString Features::name() const
{
return name(id());
}
TQString Features::name(const TQString &feature)
{
Features f(feature);
return f.name(f.id());
}
//---------------------------------------------------------------------------
// DiscoItem
//---------------------------------------------------------------------------
class DiscoItem::Private
{
public:
Private()
{
action = None;
}
Jid jid;
TQString name;
TQString node;
Action action;
Features features;
Identities identities;
};
DiscoItem::DiscoItem()
{
d = new Private;
}
DiscoItem::DiscoItem(const DiscoItem &from)
{
d = new Private;
*this = from;
}
DiscoItem & DiscoItem::operator= (const DiscoItem &from)
{
d->jid = from.d->jid;
d->name = from.d->name;
d->node = from.d->node;
d->action = from.d->action;
d->features = from.d->features;
d->identities = from.d->identities;
return *this;
}
DiscoItem::~DiscoItem()
{
delete d;
}
AgentItem DiscoItem::toAgentItem() const
{
AgentItem ai;
ai.setJid( jid() );
ai.setName( name() );
Identity id;
if ( !identities().isEmpty() )
id = identities().first();
ai.setCategory( id.category );
ai.setType( id.type );
ai.setFeatures( d->features );
return ai;
}
void DiscoItem::fromAgentItem(const AgentItem &ai)
{
setJid( ai.jid() );
setName( ai.name() );
Identity id;
id.category = ai.category();
id.type = ai.type();
id.name = ai.name();
Identities idList;
idList << id;
setIdentities( idList );
setFeatures( ai.features() );
}
const Jid &DiscoItem::jid() const
{
return d->jid;
}
void DiscoItem::setJid(const Jid &j)
{
d->jid = j;
}
const TQString &DiscoItem::name() const
{
return d->name;
}
void DiscoItem::setName(const TQString &n)
{
d->name = n;
}
const TQString &DiscoItem::node() const
{
return d->node;
}
void DiscoItem::setNode(const TQString &n)
{
d->node = n;
}
DiscoItem::Action DiscoItem::action() const
{
return d->action;
}
void DiscoItem::setAction(Action a)
{
d->action = a;
}
const Features &DiscoItem::features() const
{
return d->features;
}
void DiscoItem::setFeatures(const Features &f)
{
d->features = f;
}
const DiscoItem::Identities &DiscoItem::identities() const
{
return d->identities;
}
void DiscoItem::setIdentities(const Identities &i)
{
d->identities = i;
if ( name().isEmpty() && i.count() )
setName( i.first().name );
}
DiscoItem::Action DiscoItem::string2action(TQString s)
{
Action a;
if ( s == "update" )
a = Update;
else if ( s == "remove" )
a = Remove;
else
a = None;
return a;
}
TQString DiscoItem::action2string(Action a)
{
TQString s;
if ( a == Update )
s = "update";
else if ( a == Remove )
s = "remove";
else
s = TQString();
return s;
}
}
#include"types.moc"