/*
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 . contains ( 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 . contains ( jidAccountPair ) )
{
m_jids . push_back ( jidAccountPair ) ;
updateLastSeen ( ) ;
}
}
void JabberCapabilitiesManager : : CapabilitiesInformation : : removeJid ( const Jid & jid )
{
kdDebug ( JABBER_DEBUG_GLOBAL ) < < k_funcinfo < < " Unregistering " < < TQString ( jid . full ( ) ) . replace ( ' % ' , " %% " ) < < 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 ( ) )
{
//tqDebug("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 : : currentDate ( ) ;
}
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 : : Status & 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 " ) . arg ( TQString ( jid . full ( ) ) . replace ( ' % ' , " %% " ) ) . arg ( 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 " ) . arg ( TQString ( jid . full ( ) ) . replace ( ' % ' , " %% " ) ) . arg ( node ) . arg ( 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 " ) . arg ( TQString ( jid . full ( ) ) . replace ( ' % ' , " %% " ) ) . arg ( discoInfo - > node ( ) ) . arg ( 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 - > parent ( ) ) ;
if ( jidAccountPair . second )
{
kdDebug ( JABBER_DEBUG_GLOBAL ) < < TQString ( " Falling back on %1. " ) . arg ( TQString ( jidAccountPair . first . full ( ) ) . replace ( ' % ' , " %% " ) ) < < 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' " ) . arg ( jidCapabilities . node ( ) ) . arg ( 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 . contains ( 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 . find ( " . " ) ;
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"