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.
657 lines
19 KiB
657 lines
19 KiB
/*
|
|
jabbercapabilitiesmanager.cpp - Manage entity capabilities(JEP-0115).
|
|
|
|
Copyright (c) 2006 by Michaël Larouche <michael.larouche@kdemail.net>
|
|
|
|
Kopete (c) 2001-2006 by the Kopete developers <kopete-devel@kde.org>
|
|
|
|
Imported from caps.cpp from Psi:
|
|
Copyright (C) 2005 Remko Troncon
|
|
|
|
*************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
*************************************************************************
|
|
*/
|
|
#include "jabbercapabilitiesmanager.h"
|
|
|
|
#include <tqstring.h>
|
|
#include <tqstringlist.h>
|
|
#include <tqtimer.h>
|
|
#include <tqpair.h>
|
|
#include <tqdom.h>
|
|
#include <tqtextstream.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
#include <kdebug.h>
|
|
|
|
#include <xmpp_tasks.h>
|
|
|
|
#include "jabberaccount.h"
|
|
#include "jabberprotocol.h"
|
|
|
|
using namespace XMPP;
|
|
|
|
//BEGIN Capabilities
|
|
JabberCapabilitiesManager::Capabilities::Capabilities()
|
|
{}
|
|
|
|
JabberCapabilitiesManager::Capabilities::Capabilities(const TQString& node, const TQString& version, const TQString& extensions)
|
|
: m_node(node), m_version(version), m_extensions(extensions)
|
|
{}
|
|
|
|
const TQString& JabberCapabilitiesManager::Capabilities::node() const
|
|
{
|
|
return m_node;
|
|
}
|
|
|
|
const TQString& JabberCapabilitiesManager::Capabilities::version() const
|
|
{
|
|
return m_version;
|
|
}
|
|
|
|
const TQString& JabberCapabilitiesManager::Capabilities::extensions() const
|
|
{
|
|
return m_extensions;
|
|
}
|
|
|
|
JabberCapabilitiesManager::CapabilitiesList JabberCapabilitiesManager::Capabilities::flatten() const
|
|
{
|
|
CapabilitiesList capsList;
|
|
capsList.append( Capabilities(node(), version(), version()) );
|
|
|
|
TQStringList extensionList = TQStringList::split(" ",extensions());
|
|
TQStringList::ConstIterator it, itEnd = extensionList.constEnd();
|
|
for(it = extensionList.constBegin(); it != itEnd; ++it)
|
|
{
|
|
capsList.append( Capabilities(node(),version(),*it) );
|
|
}
|
|
|
|
return capsList;
|
|
}
|
|
|
|
bool JabberCapabilitiesManager::Capabilities::operator==(const Capabilities &other) const
|
|
{
|
|
return (node() == other.node() && version() == other.version() && extensions() == other.extensions());
|
|
}
|
|
|
|
bool JabberCapabilitiesManager::Capabilities::operator!=(const Capabilities &other) const
|
|
{
|
|
return !((*this) == other);
|
|
}
|
|
|
|
bool JabberCapabilitiesManager::Capabilities::operator<(const Capabilities &other) const
|
|
{
|
|
return (node() != other.node() ? node() < other.node() :
|
|
(version() != other.version() ? version() < other.version() :
|
|
extensions() < other.extensions()));
|
|
}
|
|
//END Capabilities
|
|
|
|
//BEGIN CapabilitiesInformation
|
|
JabberCapabilitiesManager::CapabilitiesInformation::CapabilitiesInformation()
|
|
: m_discovered(false), m_pendingRequests(0)
|
|
{
|
|
updateLastSeen();
|
|
}
|
|
|
|
const TQStringList& JabberCapabilitiesManager::CapabilitiesInformation::features() const
|
|
{
|
|
return m_features;
|
|
}
|
|
|
|
const DiscoItem::Identities& JabberCapabilitiesManager::CapabilitiesInformation::identities() const
|
|
{
|
|
return m_identities;
|
|
}
|
|
|
|
TQStringList JabberCapabilitiesManager::CapabilitiesInformation::jids() const
|
|
{
|
|
TQStringList jids;
|
|
|
|
TQValueList<TQPair<TQString,JabberAccount*> >::ConstIterator it = m_jids.constBegin(), itEnd = m_jids.constEnd();
|
|
for( ; it != itEnd; ++it)
|
|
{
|
|
TQString jid( (*it).first );
|
|
if( !jids.tqcontains(jid) )
|
|
jids.push_back(jid);
|
|
}
|
|
|
|
return jids;
|
|
}
|
|
|
|
bool JabberCapabilitiesManager::CapabilitiesInformation::discovered() const
|
|
{
|
|
return m_discovered;
|
|
}
|
|
|
|
int JabberCapabilitiesManager::CapabilitiesInformation::pendingRequests() const
|
|
{
|
|
return m_pendingRequests;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::reset()
|
|
{
|
|
m_features.clear();
|
|
m_identities.clear();
|
|
m_discovered = false;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::removeAccount(JabberAccount *account)
|
|
{
|
|
TQValueList<TQPair<TQString,JabberAccount*> >::Iterator it = m_jids.begin();
|
|
while( it != m_jids.end() )
|
|
{
|
|
if( (*it).second == account)
|
|
{
|
|
TQValueList<TQPair<TQString,JabberAccount*> >::Iterator otherIt = it;
|
|
it++;
|
|
m_jids.remove(otherIt);
|
|
}
|
|
else
|
|
{
|
|
it++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::addJid(const Jid& jid, JabberAccount* account)
|
|
{
|
|
TQPair<TQString,JabberAccount*> jidAccountPair(jid.full(),account);
|
|
|
|
if( !m_jids.tqcontains(jidAccountPair) )
|
|
{
|
|
m_jids.push_back(jidAccountPair);
|
|
updateLastSeen();
|
|
}
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::removeJid(const Jid& jid)
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Unregistering " << TQString(jid.full()).tqreplace('%',"%%") << endl;
|
|
|
|
TQValueList<TQPair<TQString,JabberAccount*> >::Iterator it = m_jids.begin();
|
|
while( it != m_jids.end() )
|
|
{
|
|
if( (*it).first == jid.full() )
|
|
{
|
|
TQValueList<TQPair<TQString,JabberAccount*> >::Iterator otherIt = it;
|
|
it++;
|
|
m_jids.remove(otherIt);
|
|
}
|
|
else
|
|
{
|
|
it++;
|
|
}
|
|
}
|
|
}
|
|
|
|
TQPair<Jid,JabberAccount*> JabberCapabilitiesManager::CapabilitiesInformation::nextJid(const Jid& jid, const Task* t)
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Looking for next JID" << endl;
|
|
|
|
TQValueList<TQPair<TQString,JabberAccount*> >::ConstIterator it = m_jids.constBegin(), itEnd = m_jids.constEnd();
|
|
for( ; it != itEnd; ++it)
|
|
{
|
|
if( (*it).first == jid.full() && (*it).second->client()->rootTask() == t)
|
|
{
|
|
it++;
|
|
if (it == itEnd)
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "No more JIDs" << endl;
|
|
|
|
return TQPair<Jid,JabberAccount*>(Jid(),0L);
|
|
}
|
|
else if( (*it).second->isConnected() )
|
|
{
|
|
//qDebug("caps.cpp: Account isn't active");
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Account isn't connected." << endl;
|
|
|
|
return TQPair<Jid,JabberAccount*>( (*it).first,(*it).second );
|
|
}
|
|
}
|
|
}
|
|
return TQPair<Jid,JabberAccount*>(Jid(),0L);
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::setDiscovered(bool value)
|
|
{
|
|
m_discovered = value;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::setPendingRequests(int pendingRequests)
|
|
{
|
|
m_pendingRequests = pendingRequests;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::setIdentities(const DiscoItem::Identities& identities)
|
|
{
|
|
m_identities = identities;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::setFeatures(const TQStringList& featureList)
|
|
{
|
|
m_features = featureList;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::updateLastSeen()
|
|
{
|
|
m_lastSeen = TQDate::tqcurrentDate();
|
|
}
|
|
|
|
TQDomElement JabberCapabilitiesManager::CapabilitiesInformation::toXml(TQDomDocument *doc) const
|
|
{
|
|
TQDomElement info = doc->createElement("info");
|
|
//info.setAttribute("last-seen",lastSeen_.toString(Qt::ISODate));
|
|
|
|
// Identities
|
|
DiscoItem::Identities::ConstIterator discoIt = m_identities.constBegin(), discoItEnd = m_identities.constEnd();
|
|
for( ; discoIt != discoItEnd; ++discoIt )
|
|
{
|
|
TQDomElement identity = doc->createElement("identity");
|
|
identity.setAttribute("category",(*discoIt).category);
|
|
identity.setAttribute("name",(*discoIt).name);
|
|
identity.setAttribute("type",(*discoIt).type);
|
|
info.appendChild(identity);
|
|
}
|
|
|
|
// Features
|
|
TQStringList::ConstIterator featuresIt = m_features.constBegin(), featuresItEnd = m_features.constEnd();
|
|
for( ; featuresIt != featuresItEnd; ++featuresIt )
|
|
{
|
|
TQDomElement feature = doc->createElement("feature");
|
|
feature.setAttribute("node",*featuresIt);
|
|
info.appendChild(feature);
|
|
}
|
|
|
|
return info;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::CapabilitiesInformation::fromXml(const TQDomElement &element)
|
|
{
|
|
if( element.tagName() != "info")
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Invalid info element" << endl;
|
|
return;
|
|
}
|
|
|
|
//if (!e.attribute("last-seen").isEmpty())
|
|
// lastSeen_ = TQDate::fromString(e.attribute("last-seen"),Qt::ISODate);
|
|
|
|
for(TQDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling())
|
|
{
|
|
TQDomElement infoElement = node.toElement();
|
|
if( infoElement.isNull() )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Null element" << endl;
|
|
continue;
|
|
}
|
|
|
|
if( infoElement.tagName() == "identity")
|
|
{
|
|
DiscoItem::Identity id;
|
|
id.category = infoElement.attribute("category");
|
|
id.name = infoElement.attribute("name");
|
|
id.type = infoElement.attribute("type");
|
|
m_identities += id;
|
|
}
|
|
else if( infoElement.tagName() == "feature" )
|
|
{
|
|
m_features += infoElement.attribute("node");
|
|
}
|
|
else
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Unknown element" << endl;
|
|
}
|
|
|
|
m_discovered = true;
|
|
}
|
|
}
|
|
//END CapabilitiesInformation
|
|
|
|
//BEGIN Private(d-ptr)
|
|
class JabberCapabilitiesManager::Private
|
|
{
|
|
public:
|
|
Private()
|
|
{}
|
|
|
|
// Map a full jid to a capabilities
|
|
TQMap<TQString,Capabilities> jidCapabilitiesMap;
|
|
// Map a capabilities to its detail information
|
|
TQMap<Capabilities,CapabilitiesInformation> capabilitiesInformationMap;
|
|
};
|
|
//END Private(d-ptr)
|
|
|
|
JabberCapabilitiesManager::JabberCapabilitiesManager()
|
|
: d(new Private)
|
|
{
|
|
}
|
|
|
|
JabberCapabilitiesManager::~JabberCapabilitiesManager()
|
|
{
|
|
saveInformation();
|
|
delete d;
|
|
}
|
|
|
|
void JabberCapabilitiesManager::removeAccount(JabberAccount *account)
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing account " << account->accountId() << endl;
|
|
|
|
TQValueList<CapabilitiesInformation> info = d->capabilitiesInformationMap.values();
|
|
|
|
TQValueList<CapabilitiesInformation>::Iterator it, itEnd = info.end();
|
|
for(it = info.begin(); it != info.end(); ++it)
|
|
{
|
|
(*it).removeAccount(account);
|
|
}
|
|
}
|
|
|
|
void JabberCapabilitiesManager::updateCapabilities(JabberAccount *account, const XMPP::Jid &jid, const XMPP::tqStatus &status )
|
|
{
|
|
if( !account->client() || !account->client()->rootTask() )
|
|
return;
|
|
|
|
|
|
// Do don't anything if the jid correspond to the account's JabberClient jid.
|
|
// false means that we don't check for resources.
|
|
if( jid.compare(account->client()->jid(), false) )
|
|
return;
|
|
|
|
TQString node = status.capsNode(), version = status.capsVersion(), extensions = status.capsExt();
|
|
Capabilities capabilities( node, version, extensions );
|
|
|
|
// Check if the capabilities was really updated(i.e the content is different)
|
|
if( d->jidCapabilitiesMap[jid.full()] != capabilities)
|
|
{
|
|
// Unregister from all old caps nodes
|
|
// FIXME: We should only unregister & register from changed nodes
|
|
CapabilitiesList oldCaps = d->jidCapabilitiesMap[jid.full()].flatten();
|
|
CapabilitiesList::Iterator oldCapsIt = oldCaps.begin(), oldCapsItEnd = oldCaps.end();
|
|
for( ; oldCapsIt != oldCapsItEnd; ++oldCapsIt)
|
|
{
|
|
if( (*oldCapsIt) != Capabilities() )
|
|
{
|
|
d->capabilitiesInformationMap[*oldCapsIt].removeJid(jid);
|
|
}
|
|
}
|
|
|
|
// Check if the jid has caps in his presence message.
|
|
if( !status.capsNode().isEmpty() && !status.capsVersion().isEmpty() )
|
|
{
|
|
// Register with all new caps nodes
|
|
d->jidCapabilitiesMap[jid.full()] = capabilities;
|
|
CapabilitiesList caps = capabilities.flatten();
|
|
CapabilitiesList::Iterator newCapsIt = caps.begin(), newCapsItEnd = caps.end();
|
|
for( ; newCapsIt != newCapsItEnd; ++newCapsIt )
|
|
{
|
|
d->capabilitiesInformationMap[*newCapsIt].addJid(jid,account);
|
|
}
|
|
|
|
emit capabilitiesChanged(jid);
|
|
|
|
// Register new caps and check if we need to discover features
|
|
newCapsIt = caps.begin();
|
|
for( ; newCapsIt != newCapsItEnd; ++newCapsIt )
|
|
{
|
|
if( !d->capabilitiesInformationMap[*newCapsIt].discovered() && d->capabilitiesInformationMap[*newCapsIt].pendingRequests() == 0 )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << TQString("Sending disco request to %1, node=%2").tqarg(TQString(jid.full()).tqreplace('%',"%%")).tqarg(node + "#" + (*newCapsIt).extensions()) << endl;
|
|
|
|
d->capabilitiesInformationMap[*newCapsIt].setPendingRequests(1);
|
|
requestDiscoInfo(account, jid, node + "#" + (*newCapsIt).extensions());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Remove all caps specifications
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << TQString("Illegal caps info from %1: node=%2, ver=%3").tqarg(TQString(jid.full()).tqreplace('%',"%%")).tqarg(node).tqarg(version) << endl;
|
|
|
|
d->jidCapabilitiesMap.remove( jid.full() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Add to the list of jids
|
|
CapabilitiesList caps = capabilities.flatten();
|
|
CapabilitiesList::Iterator capsIt = caps.begin(), capsItEnd = caps.end();
|
|
for( ; capsIt != capsItEnd; ++capsIt)
|
|
{
|
|
d->capabilitiesInformationMap[*capsIt].addJid(jid,account);
|
|
}
|
|
}
|
|
}
|
|
|
|
void JabberCapabilitiesManager::requestDiscoInfo(JabberAccount *account, const Jid& jid, const TQString& node)
|
|
{
|
|
if( !account->client()->rootTask() )
|
|
return;
|
|
|
|
JT_DiscoInfo *discoInfo = new JT_DiscoInfo(account->client()->rootTask());
|
|
connect(discoInfo, TQT_SIGNAL(finished()), TQT_SLOT(discoRequestFinished()));
|
|
discoInfo->get(jid, node);
|
|
//pending_++;
|
|
//timer_.start(REQUEST_TIMEOUT,true);
|
|
discoInfo->go(true);
|
|
}
|
|
|
|
void JabberCapabilitiesManager::discoRequestFinished()
|
|
{
|
|
JT_DiscoInfo *discoInfo = (JT_DiscoInfo*)sender();
|
|
if (!discoInfo)
|
|
return;
|
|
|
|
DiscoItem item = discoInfo->item();
|
|
Jid jid = discoInfo->jid();
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << TQString("Disco response from %1, node=%2, success=%3").tqarg(TQString(jid.full()).tqreplace('%',"%%")).tqarg(discoInfo->node()).tqarg(discoInfo->success()) << endl;
|
|
|
|
TQStringList tokens = TQStringList::split("#",discoInfo->node());
|
|
|
|
// Update features
|
|
Q_ASSERT(tokens.count() == 2);
|
|
TQString node = tokens[0];
|
|
TQString extensions = tokens[1];
|
|
|
|
Capabilities jidCapabilities = d->jidCapabilitiesMap[jid.full()];
|
|
if( jidCapabilities.node() == node )
|
|
{
|
|
Capabilities capabilities(node, jidCapabilities.version(), extensions);
|
|
|
|
if( discoInfo->success() )
|
|
{
|
|
// Save identities & features
|
|
d->capabilitiesInformationMap[capabilities].setIdentities(item.identities());
|
|
d->capabilitiesInformationMap[capabilities].setFeatures(item.features().list());
|
|
d->capabilitiesInformationMap[capabilities].setPendingRequests(0);
|
|
d->capabilitiesInformationMap[capabilities].setDiscovered(true);
|
|
|
|
// Save(Cache) information
|
|
saveInformation();
|
|
|
|
// Notify affected jids.
|
|
TQStringList jids = d->capabilitiesInformationMap[capabilities].jids();
|
|
TQStringList::ConstIterator jidsIt = jids.constBegin(), jidsItEnd = jids.constEnd();
|
|
for( ; jidsIt != jidsItEnd; ++jidsItEnd )
|
|
{
|
|
emit capabilitiesChanged(*jidsIt);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQPair<Jid,JabberAccount*> jidAccountPair = d->capabilitiesInformationMap[capabilities].nextJid(jid,discoInfo->tqparent());
|
|
if( jidAccountPair.second )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << TQString("Falling back on %1.").tqarg(TQString(jidAccountPair.first.full()).tqreplace('%',"%%")) << endl;
|
|
requestDiscoInfo( jidAccountPair.second, jidAccountPair.first, discoInfo->node() );
|
|
}
|
|
else
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << "No valid disco request avalable." << endl;
|
|
d->capabilitiesInformationMap[capabilities].setPendingRequests(0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << TQString("Current client node '%1' does not match response '%2'").tqarg(jidCapabilities.node()).tqarg(node) << endl;
|
|
|
|
//for (unsigned int i = 0; i < item.features().list().count(); i++)
|
|
// printf(" Feature: %s\n",item.features().list()[i].latin1());
|
|
|
|
// Check pending requests
|
|
// pending_ = (pending_ > 0 ? pending_-1 : 0);
|
|
// if (!pending_) {
|
|
// timer_.stop();
|
|
// updatePendingJIDs();
|
|
// }
|
|
}
|
|
|
|
void JabberCapabilitiesManager::loadCachedInformation()
|
|
{
|
|
TQString capsFileName;
|
|
capsFileName = locateLocal("appdata", TQString::fromUtf8("jabber-capabilities-cache.xml"));
|
|
|
|
// Load settings
|
|
TQDomDocument doc;
|
|
TQFile cacheFile(capsFileName);
|
|
if( !cacheFile.open(IO_ReadOnly) )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Could not open the Capabilities cache from disk." << endl;
|
|
return;
|
|
}
|
|
if( !doc.setContent(&cacheFile) )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Could not set the Capabilities cache from file." << endl;
|
|
return;
|
|
}
|
|
cacheFile.close();
|
|
|
|
TQDomElement caps = doc.documentElement();
|
|
if( caps.tagName() != "capabilities" )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Invalid capabilities element." << endl;
|
|
return;
|
|
}
|
|
|
|
TQDomNode node;
|
|
for(node = caps.firstChild(); !node.isNull(); node = node.nextSibling())
|
|
{
|
|
TQDomElement element = node.toElement();
|
|
if( element.isNull() )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Found a null element." << endl;
|
|
continue;
|
|
}
|
|
|
|
if( element.tagName() == "info" )
|
|
{
|
|
CapabilitiesInformation info;
|
|
info.fromXml(element);
|
|
Capabilities entityCaps( element.attribute("node"),element.attribute("ver"),element.attribute("ext") );
|
|
d->capabilitiesInformationMap[entityCaps] = info;
|
|
}
|
|
else
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Unknow element" << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool JabberCapabilitiesManager::capabilitiesEnabled(const Jid &jid) const
|
|
{
|
|
return d->jidCapabilitiesMap.tqcontains( jid.full() );
|
|
}
|
|
|
|
XMPP::Features JabberCapabilitiesManager::features(const Jid& jid) const
|
|
{
|
|
TQStringList featuresList;
|
|
|
|
if( capabilitiesEnabled(jid) )
|
|
{
|
|
CapabilitiesList capabilitiesList = d->jidCapabilitiesMap[jid.full()].flatten();
|
|
CapabilitiesList::ConstIterator capsIt = capabilitiesList.constBegin(), capsItEnd = capabilitiesList.constEnd();
|
|
for( ; capsIt != capsItEnd; ++capsIt)
|
|
{
|
|
featuresList += d->capabilitiesInformationMap[*capsIt].features();
|
|
}
|
|
}
|
|
|
|
return Features(featuresList);
|
|
}
|
|
|
|
TQString JabberCapabilitiesManager::clientName(const Jid& jid) const
|
|
{
|
|
if( capabilitiesEnabled(jid) )
|
|
{
|
|
Capabilities caps = d->jidCapabilitiesMap[jid.full()];
|
|
TQString name = d->capabilitiesInformationMap[Capabilities(caps.node(),caps.version(),caps.version())].identities().first().name;
|
|
|
|
// Try to be intelligent about the name
|
|
/*if (name.isEmpty()) {
|
|
name = cs.node();
|
|
if (name.startsWith("http://"))
|
|
name = name.right(name.length() - 7);
|
|
|
|
if (name.startsWith("www."))
|
|
name = name.right(name.length() - 4);
|
|
|
|
int cut_pos = name.tqfind(".");
|
|
if (cut_pos != -1) {
|
|
name = name.left(cut_pos);
|
|
}
|
|
}*/
|
|
|
|
return name;
|
|
}
|
|
else
|
|
{
|
|
return TQString();
|
|
}
|
|
}
|
|
|
|
TQString JabberCapabilitiesManager::clientVersion(const Jid& jid) const
|
|
{
|
|
return (capabilitiesEnabled(jid) ? d->jidCapabilitiesMap[jid.full()].version() : TQString());
|
|
}
|
|
|
|
void JabberCapabilitiesManager::saveInformation()
|
|
{
|
|
TQString capsFileName;
|
|
capsFileName = locateLocal("appdata", TQString::fromUtf8("jabber-capabilities-cache.xml"));
|
|
|
|
// Generate XML
|
|
TQDomDocument doc;
|
|
TQDomElement capabilities = doc.createElement("capabilities");
|
|
doc.appendChild(capabilities);
|
|
TQMap<Capabilities,CapabilitiesInformation>::ConstIterator it = d->capabilitiesInformationMap.constBegin(), itEnd = d->capabilitiesInformationMap.constEnd();
|
|
for( ; it != itEnd; ++it )
|
|
{
|
|
TQDomElement info = it.data().toXml(&doc);
|
|
info.setAttribute("node",it.key().node());
|
|
info.setAttribute("ver",it.key().version());
|
|
info.setAttribute("ext",it.key().extensions());
|
|
capabilities.appendChild(info);
|
|
}
|
|
|
|
// Save
|
|
TQFile capsFile(capsFileName);
|
|
if( !capsFile.open(IO_WriteOnly) )
|
|
{
|
|
kdDebug(JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Error while opening Capabilities cache file." << endl;
|
|
return;
|
|
}
|
|
|
|
TQTextStream textStream;
|
|
textStream.setDevice(TQT_TQIODEVICE(&capsFile));
|
|
textStream.setEncoding(TQTextStream::UnicodeUTF8);
|
|
textStream << doc.toString();
|
|
textStream.unsetDevice();
|
|
capsFile.close();
|
|
}
|
|
|
|
#include "jabbercapabilitiesmanager.moc"
|