adhoc.cpp
/*
Copyright (c) 2004-2023 by Jakob Schröter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#include "adhoc.h"
#include "adhochandler.h"
#include "adhoccommandprovider.h"
#include "disco.h"
#include "dataform.h"
#include "error.h"
#include "iodata.h"
#include "discohandler.h"
#include "clientbase.h"
#include "adhocplugin.h"
#include "util.h"
#include "mutexguard.h"
namespace gloox
{
static const char* cmdActionStringValues[] =
{
"execute", "cancel", "prev", "next", "complete"
};
static inline const std::string actionString( Adhoc::Command::Action action )
{
return util::lookup2( action, cmdActionStringValues );
}
static const char* cmdStatusStringValues[] =
{
"executing", "completed", "canceled"
};
static inline const std::string statusString( Adhoc::Command::Status status )
{
return util::lookup( status, cmdStatusStringValues );
}
static const char* cmdNoteStringValues[] =
{
"info", "warn", "error"
};
static inline const std::string noteString( Adhoc::Command::Note::Severity sev )
{
return util::lookup( sev, cmdNoteStringValues );
}
// ---- Adhoc::Command::Note ----
Adhoc::Command::Note::Note( const Tag* tag )
: m_severity( InvalidSeverity )
{
if( !tag || tag->name() != "note" )
return;
m_severity = static_cast<Severity>( util::deflookup( tag->findAttribute( "type" ), cmdNoteStringValues, Info ) );
m_note = tag->cdata();
}
Tag* Adhoc::Command::Note::tag() const
{
if( m_note.empty() || m_severity == InvalidSeverity )
return 0;
Tag* n = new Tag( "note", m_note );
n->addAttribute( TYPE, noteString( m_severity ) );
return n;
}
// ---- ~Adhoc::Command::Note ----
// ---- Adhoc::Command ----
Adhoc::Command::Command( const std::string& node, Adhoc::Command::Action action,
AdhocPlugin* plugin )
: StanzaExtension( ExtAdhocCommand ), m_node( node ), m_plugin( plugin ), m_action( action ),
m_status( InvalidStatus ), m_actions( 0 )
{
}
Adhoc::Command::Command( const std::string& node, const std::string& sessionid, Status status,
AdhocPlugin* plugin )
: StanzaExtension( ExtAdhocCommand ), m_node( node ), m_sessionid( sessionid ),
m_plugin( plugin ), m_action( InvalidAction ), m_status( status ), m_actions( 0 )
{
}
Adhoc::Command::Command( const std::string& node, const std::string& sessionid,
Adhoc::Command::Action action,
AdhocPlugin* plugin )
: StanzaExtension( ExtAdhocCommand ), m_node( node ), m_sessionid( sessionid ),
m_plugin( plugin ), m_action( action ), m_actions( 0 )
{
}
Adhoc::Command::Command( const std::string& node, const std::string& sessionid, Status status,
Action executeAction, int allowedActions,
AdhocPlugin* plugin )
: StanzaExtension( ExtAdhocCommand ), m_node( node ), m_sessionid( sessionid ),
m_plugin( plugin ), m_action( executeAction ), m_status( status ), m_actions( allowedActions )
{
}
Adhoc::Command::Command( const Tag* tag )
: StanzaExtension( ExtAdhocCommand ), m_plugin( 0 ), m_actions( 0 )
{
if( !tag || tag->name() != "command" || tag->xmlns() != XMLNS_ADHOC_COMMANDS )
return;
m_node = tag->findAttribute( "node" );
m_sessionid = tag->findAttribute( "sessionid" );
m_status = static_cast<Status>( util::lookup( tag->findAttribute( "status" ), cmdStatusStringValues ) );
Tag* a = tag->findChild( "actions" );
if( a )
{
// Multi-stage response
m_action = static_cast<Action>( util::deflookup2( a->findAttribute( "action" ), cmdActionStringValues, Complete ) );
if( a->hasChild( "prev" ) )
m_actions |= Previous;
if( a->hasChild( "next" ) )
m_actions |= Next;
if( a->hasChild( "complete" ) )
m_actions |= Complete;
}
else
{
m_action = static_cast<Action>( util::deflookup2( tag->findAttribute( "action" ), cmdActionStringValues, Execute ) );
}
const ConstTagList& l = tag->findTagList( "/command/note" );
ConstTagList::const_iterator it = l.begin();
for( ; it != l.end(); ++it )
m_notes.push_back( new Note( (*it) ) );
Tag* x = tag->findChild( "x", "xmlns", XMLNS_X_DATA );
if( x )
m_plugin = new DataForm( x );
else
{
Tag* x = tag->findChild( "iodata", "xmlns", XMLNS_IODATA );
if( x )
m_plugin = new IOData( x );
}
}
Adhoc::Command::~Command()
{
util::clearList( m_notes );
delete m_plugin;
}
const std::string& Adhoc::Command::filterString() const
{
static const std::string filter = "/iq/command[@xmlns='" + XMLNS_ADHOC_COMMANDS + "']";
return filter;
}
Tag* Adhoc::Command::tag() const
{
if( m_node.empty() )
return 0;
Tag* c = new Tag( "command" );
c->setXmlns( XMLNS_ADHOC_COMMANDS );
c->addAttribute( "node", m_node );
if( m_actions != 0 )
{
// Multi-stage command response
if( m_status != InvalidStatus )
c->addAttribute( "status", statusString( m_status ) );
else
c->addAttribute( "status", statusString( Executing ) );
Tag* actions = new Tag( c, "actions" );
if( m_action != InvalidAction )
c->addAttribute( "execute", actionString( m_action ) );
else
c->addAttribute( "execute", actionString( Complete ) );
if( ( m_actions & Previous ) == Previous )
new Tag( actions, "prev" );
if( ( m_actions & Next ) == Next )
new Tag( actions, "next" );
if( ( m_actions & Complete ) == Complete )
new Tag( actions, "complete" );
}
else
{
// Single-stage command request/response or Multi-stage command request
if( m_action != InvalidAction )
c->addAttribute( "action", actionString( m_action ) );
if( m_status != InvalidStatus )
c->addAttribute( "status", statusString( m_status ) );
}
if ( !m_sessionid.empty() )
c->addAttribute( "sessionid", m_sessionid );
if( m_plugin && *m_plugin )
c->addChild( m_plugin->tag() );
NoteList::const_iterator it = m_notes.begin();
for( ; it != m_notes.end(); ++it )
c->addChild( (*it)->tag() );
return c;
}
// ---- ~Adhoc::Command ----
// ---- Adhoc ----
Adhoc::Adhoc( ClientBase* parent )
: m_parent( parent )
{
if( !m_parent || !m_parent->disco() )
return;
m_parent->disco()->addFeature( XMLNS_ADHOC_COMMANDS );
m_parent->disco()->registerNodeHandler( this, XMLNS_ADHOC_COMMANDS );
m_parent->disco()->registerNodeHandler( this, EmptyString );
m_parent->registerIqHandler( this, ExtAdhocCommand );
m_parent->registerStanzaExtension( new Adhoc::Command() );
}
Adhoc::~Adhoc()
{
m_adhocTrackMapMutex.lock();
m_adhocTrackMap.clear();
m_adhocTrackMapMutex.unlock();
if( !m_parent || !m_parent->disco() )
return;
m_parent->disco()->removeFeature( XMLNS_ADHOC_COMMANDS );
m_parent->disco()->removeNodeHandler( this, XMLNS_ADHOC_COMMANDS );
m_parent->disco()->removeNodeHandler( this, EmptyString );
m_parent->removeIqHandler( this, ExtAdhocCommand );
m_parent->removeIDHandler( this );
m_parent->removeStanzaExtension( ExtAdhocCommand );
}
StringList Adhoc::handleDiscoNodeFeatures( const JID& /*from*/, const std::string& /*node*/ )
{
StringList features;
features.push_back( XMLNS_ADHOC_COMMANDS );
return features;
// return StringList( 1, XMLNS_ADHOC_COMMANDS );
}
Disco::ItemList Adhoc::handleDiscoNodeItems( const JID& from, const JID& /*to*/, const std::string& node )
{
Disco::ItemList l;
if( node.empty() )
{
l.push_back( new Disco::Item( m_parent->jid(), XMLNS_ADHOC_COMMANDS, "Ad-Hoc Commands" ) );
}
else if( node == XMLNS_ADHOC_COMMANDS )
{
StringMap::const_iterator it = m_items.begin();
for( ; it != m_items.end(); ++it )
{
AdhocCommandProviderMap::const_iterator itp = m_adhocCommandProviders.find( (*it).first );
if( itp != m_adhocCommandProviders.end()
&& (*itp).second
&& (*itp).second->handleAdhocAccessRequest( from, (*it).first ) )
{
l.push_back( new Disco::Item( m_parent->jid(), (*it).first, (*it).second ) );
}
}
}
return l;
}
Disco::IdentityList Adhoc::handleDiscoNodeIdentities( const JID& /*from*/, const std::string& node )
{
Disco::IdentityList l;
StringMap::const_iterator it = m_items.find( node );
l.push_back( new Disco::Identity( "automation",
node == XMLNS_ADHOC_COMMANDS ? "command-list" : "command-node",
it == m_items.end() ? "Ad-Hoc Commands" : (*it).second ) );
return l;
}
bool Adhoc::handleIq( const IQ& iq )
{
if( iq.subtype() != IQ::Set )
return false;
const Adhoc::Command* ac = iq.findExtension<Adhoc::Command>( ExtAdhocCommand );
if( !ac || ac->node().empty())
return false;
AdhocCommandProviderMap::const_iterator it = m_adhocCommandProviders.find( ac->node() );
if( it != m_adhocCommandProviders.end() )
{
const std::string& sess = ac->sessionID().empty() ? m_parent->getID() : ac->sessionID();
m_activeSessions[sess] = iq.id();
(*it).second->handleAdhocCommand( iq.from(), *ac, sess );
return true;
}
return false;
}
void Adhoc::handleIqID( const IQ& iq, int context )
{
if( context != ExecuteAdhocCommand )
return;
m_adhocTrackMapMutex.lock();
AdhocTrackMap::iterator it = m_adhocTrackMap.find( iq.id() );
bool haveIdHandler = ( it != m_adhocTrackMap.end() );
m_adhocTrackMapMutex.unlock();
if( !haveIdHandler || (*it).second.context != context
|| (*it).second.remote != iq.from() )
return;
switch( iq.subtype() )
{
case IQ::Error:
(*it).second.ah->handleAdhocError( iq.from(), iq.error(), (*it).second.handlerContext );
break;
case IQ::Result:
{
const Adhoc::Command* ac = iq.findExtension<Adhoc::Command>( ExtAdhocCommand );
if( ac )
(*it).second.ah->handleAdhocExecutionResult( iq.from(), *ac, (*it).second.handlerContext );
break;
}
default:
break;
}
m_adhocTrackMapMutex.lock();
m_adhocTrackMap.erase( it );
m_adhocTrackMapMutex.unlock();
}
void Adhoc::registerAdhocCommandProvider( AdhocCommandProvider* acp, const std::string& command,
const std::string& name )
{
if( !m_parent || !m_parent->disco() )
return;
m_parent->disco()->registerNodeHandler( this, command );
m_adhocCommandProviders[command] = acp;
m_items[command] = name;
}
void Adhoc::handleDiscoInfo( const JID& from, const Disco::Info& info, int context )
{
if( context != CheckAdhocSupport )
return;
util::MutexGuard m( m_adhocTrackMapMutex );
AdhocTrackMap::iterator it = m_adhocTrackMap.begin();
for( ; it != m_adhocTrackMap.end() && (*it).second.context != context
&& (*it).second.remote != from; ++it )
;
if( it == m_adhocTrackMap.end() )
return;
(*it).second.ah->handleAdhocSupport( from, info.hasFeature( XMLNS_ADHOC_COMMANDS ), (*it).second.handlerContext );
m_adhocTrackMap.erase( it );
}
void Adhoc::handleDiscoItems( const JID& from, const Disco::Items& items, int context )
{
if( context != FetchAdhocCommands )
return;
util::MutexGuard m( m_adhocTrackMapMutex );
AdhocTrackMap::iterator it = m_adhocTrackMap.begin();
for( ; it != m_adhocTrackMap.end(); ++it )
{
if( (*it).second.context == context && (*it).second.remote == from )
{
StringMap commands;
const Disco::ItemList& l = items.items();
Disco::ItemList::const_iterator it2 = l.begin();
for( ; it2 != l.end(); ++it2 )
{
commands[(*it2)->node()] = (*it2)->name();
}
(*it).second.ah->handleAdhocCommands( from, commands, (*it).second.handlerContext );
m_adhocTrackMap.erase( it );
break;
}
}
}
void Adhoc::handleDiscoError( const JID& from, const Error* error, int context )
{
util::MutexGuard m( m_adhocTrackMapMutex );
for( AdhocTrackMap::iterator it = m_adhocTrackMap.begin(); it != m_adhocTrackMap.end(); )
{
if( (*it).second.context == context && (*it).second.remote == from )
{
(*it).second.ah->handleAdhocError( from, error, (*it).second.handlerContext );
// Normally we'd just assign it to the return value of the .erase() call,
// which is either the next element, or .end(). However,
// it's only since C++11 that this works; C++03 version returns void.
// So instead, we do a post-increment. this increments the iterator to point
// to the next element, then passes a copy of the old iterator (that is to the item to be deleted)
m_adhocTrackMap.erase( it++ );
}
else
{
++it;
}
}
}
void Adhoc::checkSupport( const JID& remote, AdhocHandler* ah, int context )
{
if( !remote || !ah || !m_parent || !m_parent->disco() )
return;
TrackStruct track;
track.remote = remote;
track.context = CheckAdhocSupport;
track.ah = ah;
track.handlerContext = context;
const std::string& id = m_parent->getID();
m_adhocTrackMapMutex.lock();
m_adhocTrackMap[id] = track;
m_adhocTrackMapMutex.unlock();
m_parent->disco()->getDiscoInfo( remote, EmptyString, this, CheckAdhocSupport, id );
}
void Adhoc::getCommands( const JID& remote, AdhocHandler* ah, int context )
{
if( !remote || !ah || !m_parent || !m_parent->disco() )
return;
TrackStruct track;
track.remote = remote;
track.context = FetchAdhocCommands;
track.ah = ah;
track.handlerContext = context;
const std::string& id = m_parent->getID();
m_adhocTrackMapMutex.lock();
m_adhocTrackMap[id] = track;
m_adhocTrackMapMutex.unlock();
m_parent->disco()->getDiscoItems( remote, XMLNS_ADHOC_COMMANDS, this, FetchAdhocCommands, id );
}
void Adhoc::execute( const JID& remote, const Adhoc::Command* command, AdhocHandler* ah, int context )
{
if( !remote || !command || !m_parent || !ah )
return;
const std::string& id = m_parent->getID();
IQ iq( IQ::Set, remote, id );
iq.addExtension( command );
TrackStruct track;
track.remote = remote;
track.context = ExecuteAdhocCommand;
track.session = command->sessionID();
track.ah = ah;
track.handlerContext = context;
m_adhocTrackMapMutex.lock();
m_adhocTrackMap[id] = track;
m_adhocTrackMapMutex.unlock();
m_parent->send( iq, this, ExecuteAdhocCommand );
}
void Adhoc::respond( const JID& remote, const Adhoc::Command* command, const Error* error )
{
if( !remote || !command || !m_parent )
return;
StringMap::iterator it = m_activeSessions.find( command->sessionID() );
if( it == m_activeSessions.end() )
return;
IQ re( error ? IQ::Error : IQ::Result, remote, (*it).second );
re.addExtension( command );
if( error )
re.addExtension( error );
m_parent->send( re );
m_activeSessions.erase( it );
}
void Adhoc::removeAdhocCommandProvider( const std::string& command )
{
if( !m_parent || !m_parent->disco() )
return;
m_parent->disco()->removeNodeHandler( this, command );
m_adhocCommandProviders.erase( command );
m_items.erase( command );
}
}
gloox::AdhocCommandProvider
A virtual interface for an Ad-hoc Command Provider according to XEP-0050.
Definition adhoccommandprovider.h:37
gloox::AdhocHandler
A virtual interface for an Ad-hoc Command users according to XEP-0050.
Definition adhochandler.h:33
gloox::AdhocPlugin
A base class for Adhoc Command plugins (DataForm, IO Data, ...).
Definition adhocplugin.h:39
gloox::Adhoc::Command::Note
Definition adhoc.h:131
gloox::Adhoc::Command::Note::Severity
Severity
Definition adhoc.h:140
gloox::Adhoc::Command::Note::InvalidSeverity
@ InvalidSeverity
Definition adhoc.h:147
gloox::Adhoc::Command::Note::Note
Note(Severity sev, const std::string &note)
Definition adhoc.h:155
gloox::Adhoc::Command::Note::tag
Tag * tag() const
Definition adhoc.cpp:71
gloox::Adhoc::Command
An abstraction of an Adhoc Command element (from Adhoc Commands, XEP-0050) as a StanzaExtension.
Definition adhoc.h:92
gloox::Adhoc::Command::node
const std::string & node() const
Definition adhoc.h:268
gloox::Adhoc::Command::~Command
virtual ~Command()
Definition adhoc.cpp:156
gloox::Adhoc::Command::Command
Command(const std::string &node, const std::string &sessionid, Action action, AdhocPlugin *plugin=0)
Definition adhoc.cpp:97
gloox::Adhoc::Command::Status
Status
Definition adhoc.h:117
gloox::Adhoc::Command::Executing
@ Executing
Definition adhoc.h:118
gloox::Adhoc::Command::InvalidStatus
@ InvalidStatus
Definition adhoc.h:121
gloox::Adhoc::Command::plugin
const AdhocPlugin * plugin() const
Definition adhoc.h:320
gloox::Adhoc::Command::Action
Action
Definition adhoc.h:101
gloox::Adhoc::Command::InvalidAction
@ InvalidAction
Definition adhoc.h:110
gloox::Adhoc::Command::Previous
@ Previous
Definition adhoc.h:105
gloox::Adhoc::Command::Complete
@ Complete
Definition adhoc.h:109
gloox::Adhoc::Command::Next
@ Next
Definition adhoc.h:107
gloox::Adhoc::Command::filterString
virtual const std::string & filterString() const
Definition adhoc.cpp:162
gloox::Adhoc::Command::actions
int actions() const
Definition adhoc.h:294
gloox::Adhoc::Command::status
Status status() const
Definition adhoc.h:281
gloox::Adhoc::Command::tag
virtual Tag * tag() const
Definition adhoc.cpp:168
gloox::Adhoc::Command::sessionID
const std::string & sessionID() const
Definition adhoc.h:274
gloox::Adhoc::Command::action
Action action() const
Definition adhoc.h:287
gloox::Adhoc::handleDiscoNodeItems
virtual Disco::ItemList handleDiscoNodeItems(const JID &from, const JID &to, const std::string &node)
Definition adhoc.cpp:262
gloox::Adhoc::handleIqID
virtual void handleIqID(const IQ &iq, int context)
Definition adhoc.cpp:317
gloox::Adhoc::handleIq
virtual bool handleIq(const IQ &iq)
Definition adhoc.cpp:296
gloox::Adhoc::handleDiscoInfo
virtual void handleDiscoInfo(const JID &from, const Disco::Info &info, int context)
Definition adhoc.cpp:361
gloox::Adhoc::registerAdhocCommandProvider
void registerAdhocCommandProvider(AdhocCommandProvider *acp, const std::string &command, const std::string &name)
Definition adhoc.cpp:350
gloox::Adhoc::~Adhoc
virtual ~Adhoc()
Definition adhoc.cpp:237
gloox::Adhoc::respond
void respond(const JID &remote, const Adhoc::Command *command, const Error *error=0)
Definition adhoc.cpp:485
gloox::Adhoc::handleDiscoError
virtual void handleDiscoError(const JID &from, const Error *error, int context)
Definition adhoc.cpp:406
gloox::Adhoc::getCommands
void getCommands(const JID &remote, AdhocHandler *ah, int context=0)
Definition adhoc.cpp:446
gloox::Adhoc::removeAdhocCommandProvider
void removeAdhocCommandProvider(const std::string &command)
Definition adhoc.cpp:502
gloox::Adhoc::handleDiscoItems
virtual void handleDiscoItems(const JID &from, const Disco::Items &items, int context)
Definition adhoc.cpp:379
gloox::Adhoc::checkSupport
void checkSupport(const JID &remote, AdhocHandler *ah, int context=0)
Definition adhoc.cpp:429
gloox::Adhoc::execute
void execute(const JID &remote, const Adhoc::Command *command, AdhocHandler *ah, int context=0)
Definition adhoc.cpp:463
gloox::Adhoc::handleDiscoNodeIdentities
virtual Disco::IdentityList handleDiscoNodeIdentities(const JID &from, const std::string &node)
Definition adhoc.cpp:286
gloox::Adhoc::handleDiscoNodeFeatures
virtual StringList handleDiscoNodeFeatures(const JID &from, const std::string &node)
Definition adhoc.cpp:254
gloox::Adhoc::Adhoc
Adhoc(ClientBase *parent)
Definition adhoc.cpp:224
gloox::ClientBase
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
Definition clientbase.h:79
gloox::DataForm
An abstraction of a XEP-0004 Data Form.
Definition dataform.h:57
gloox::Disco::Identity
An abstraction of a Disco identity (Service Discovery, XEP-0030).
Definition disco.h:197
gloox::Disco::Info
An abstraction of a Disco Info element (from Service Discovery, XEP-0030) as a StanzaExtension.
Definition disco.h:66
gloox::Disco::Info::hasFeature
bool hasFeature(const std::string &feature) const
Definition disco.cpp:121
gloox::Disco::Item
An abstraction of a Disco item (Service Discovery, XEP-0030).
Definition disco.h:353
gloox::Disco::Items
An abstraction of a Disco query element (from Service Discovery, XEP-0030) in the disco::items namesp...
Definition disco.h:276
gloox::Disco::Items::items
const ItemList & items() const
Definition disco.h:311
gloox::Disco::IdentityList
std::list< Identity * > IdentityList
Definition disco.h:56
gloox::Disco::ItemList
std::list< Item * > ItemList
Definition disco.h:266
gloox::Error
A stanza error abstraction implemented as a StanzaExtension.
Definition error.h:35
gloox::IOData
This is an abstraction of the IO Data specification XEP-0244.
Definition iodata.h:37
gloox::IQ
An abstraction of an IQ stanza.
Definition iq.h:34
gloox::IQ::subtype
IqType subtype() const
Definition iq.h:74
gloox::IQ::Set
@ Set
Definition iq.h:46
gloox::IQ::Error
@ Error
Definition iq.h:49
gloox::IQ::Result
@ Result
Definition iq.h:48
gloox::JID
An abstraction of a JID.
Definition jid.h:31
gloox::StanzaExtension::StanzaExtension
StanzaExtension(int type)
Definition stanzaextension.h:211
gloox::Stanza::addExtension
void addExtension(const StanzaExtension *se)
Definition stanza.cpp:52
gloox::Stanza::id
const std::string & id() const
Definition stanza.h:63
gloox::Stanza::error
const Error * error() const
Definition stanza.cpp:47
gloox::Stanza::from
const JID & from() const
Definition stanza.h:51
gloox::Stanza::findExtension
const StanzaExtension * findExtension(int type) const
Definition stanza.cpp:57
gloox::Tag
This is an abstraction of an XML element.
Definition tag.h:47
gloox::Tag::name
const std::string & name() const
Definition tag.h:394
gloox::Tag::addAttribute
bool addAttribute(Attribute *attr)
Definition tag.cpp:354
gloox::Tag::addChild
void addChild(Tag *child)
Definition tag.cpp:424
gloox::Tag::cdata
const std::string cdata() const
Definition tag.cpp:497
gloox::Tag::findAttribute
const std::string & findAttribute(const std::string &name) const
Definition tag.cpp:589
gloox::Tag::setXmlns
bool setXmlns(const std::string &xmlns, const std::string &prefix=EmptyString)
Definition tag.cpp:522
gloox::util::MutexGuard
A simple implementation of a mutex guard.
Definition mutexguard.h:32
gloox::util::clearList
void clearList(std::list< T * > &L)
Definition util.h:152
gloox
The namespace for the gloox library.
Definition adhoc.cpp:28
gloox::StringList
std::list< std::string > StringList
Definition gloox.h:1251
gloox::XMLNS_X_DATA
const std::string XMLNS_X_DATA
Definition gloox.cpp:49
gloox::EmptyString
const std::string EmptyString
Definition gloox.cpp:124
gloox::TYPE
const std::string TYPE
Definition gloox.cpp:123
gloox::ConstTagList
std::list< const Tag * > ConstTagList
Definition tag.h:36
gloox::XMLNS_IODATA
const std::string XMLNS_IODATA
Definition gloox.cpp:114
gloox::XMLNS_ADHOC_COMMANDS
const std::string XMLNS_ADHOC_COMMANDS
Definition gloox.cpp:26
gloox::ExtAdhocCommand
@ ExtAdhocCommand
Definition stanzaextension.h:62
gloox::StringMap
std::map< std::string, std::string > StringMap
Definition gloox.h:1261