2
Copyright (c) 2004-2009 by Jakob Schroeter <js@camaya.net>
3
This file is part of the gloox library. http://camaya.net/gloox
5
This software is distributed under a license. The full license
6
agreement can be found in the file LICENSE in this distribution.
7
This software may not be copied, modified, sold or distributed
8
other than expressed in the named license agreement.
10
This software is distributed without any warranty.
20
#include "disconodehandler.h"
21
#include "discohandler.h"
22
#include "iqhandler.h"
23
#include "stanzaextension.h"
35
class AdhocCommandProvider;
38
* @brief This class implements a provider for XEP-0050 (Ad-hoc Commands).
40
* The current, not complete, implementation is probably best suited for fire-and-forget
41
* type of commands. Any additional feature, like multiple stages, etc., would have to be
44
* To offer commands to remote entities, use this class as follows:<br>
45
* Create a class that will handle command execution requests and derive it from
46
* AdhocCommandProvider. Instantiate an Adhoc object and register your
47
* AdhocCommandProvider-derived object with the Adhoc object using
48
* registerAdhocCommandProvider(). The additional parameters to that method are the internal
49
* name of the command as used in the code, and the public name of the command as it
50
* will be shown to an end user:
54
* Adhoc* m_adhoc = new Adhoc( m_client );
56
* // this might be a bot monitoring a weather station, for example
57
* m_adhoc->registerAdhocCommandProvider( this, "getTemp", "Retrieve current temperature" );
58
* m_adhoc->registerAdhocCommandProvider( this, "getPressure", "Retrieve current air pressure" );
62
* In this example, MyClass is AdhocCommandProvider-derived so it is obviously the command handler, too.
64
* And that's about it you can do with the Adhoc class. Of course you can have a AdhocCommandProvider
65
* handle more than one command, just register it with the Adhoc object for every desired command,
68
* What the Adhoc object does when you install a new command is tell the supplied Disco object
69
* to advertise these commands to clients using the 'Service Discovery' protocol to learn about
70
* this implementation's features. These clients can then call and execute the command. Of course you
71
* are free to implement access restrictions to not let anyone mess with your bot, for example.
72
* However, the commands offered using Service Discovery are publically visible in any case.
74
* To execute commands offered by a remote entity:<br>
78
* @author Jakob Schroeter <js@camaya.net>
80
class GLOOX_API Adhoc : public DiscoNodeHandler, public DiscoHandler, public IqHandler
84
* @brief An abstraction of an Adhoc Command element (from Adhoc Commands, XEP-0050)
85
* as a StanzaExtension.
87
* @author Jakob Schroeter <js@camaya.net>
90
class GLOOX_API Command : public StanzaExtension
97
* Specifies the action to undertake with the given command.
101
Execute = 1, /**< The command should be executed or continue to be executed.
102
* This is the default value. */
103
Cancel = 2, /**< The command should be canceled. */
104
Previous = 4, /**< The command should be digress to the previous stage of
106
Next = 8, /**< The command should progress to the next stage of
108
Complete = 16, /**< The command should be completed (if possible). */
109
InvalidAction = 32 /**< The action is unknown or invalid. */
113
* Describes the current status of a command.
117
Executing, /**< The command is being executed. */
118
Completed, /**< The command has completed. The command session has ended. */
119
Canceled, /**< The command has been canceled. The command session has ended. */
120
InvalidStatus /**< The status is unknown or invalid. */
124
* An abstraction of a command note.
126
* @author Jakob Schroeter <js@camaya.net>
132
friend class Command;
136
* Specifies the severity of a note.
140
Info, /**< The note is informational only. This is not really an
141
* exceptional condition. */
142
Warning, /**< The note indicates a warning. Possibly due to illogical
143
* (yet valid) data. */
144
Error, /**< The note indicates an error. The text should indicate the
145
* reason for the error. */
146
InvalidSeverity /**< The note type is unknown or invalid. */
150
* A convenience constructor.
151
* @param sev The note's severity.
152
* @param note The note's content.
154
Note( Severity sev, const std::string& note )
155
: m_severity( sev ), m_note( note ) {}
163
* Returns the note's severity.
164
* @return The note's severity.
166
Severity severity() const { return m_severity; }
169
* Returns the note's content.
170
* @return The note's content.
172
const std::string& content() const { return m_note; }
175
* Returns a Tag representation of the Note.
176
* @return A Tag representation.
181
#ifdef ADHOC_COMMANDS_TEST
185
* Constructs a new Note from the given Tag.
186
* @param tag The Tag to parse.
188
Note( const Tag* tag );
190
Severity m_severity; /**< The note's severity. */
191
std::string m_note; /**< The note's content. */
195
* A list of command notes.
197
typedef std::list<const Note*> NoteList;
200
* Creates a Command object that can be used to perform the provided Action.
201
* This constructor is used best to continue execution of a multi stage command
202
* (for which the session ID must be known).
203
* @param node The node (command) to perform the action on.
204
* @param sessionid The session ID of an already running adhoc command session.
205
* @param action The action to perform.
206
* @param form An optional DataForm to include in the request. Will be deleted in Command's
209
Command( const std::string& node, const std::string& sessionid, Action action,
210
DataForm* form = 0 );
213
* Creates a Command object that can be used to perform the provided Action.
214
* This constructor is used best to reply to an execute request.
215
* @param node The node (command) to perform the action on.
216
* @param sessionid The (possibly newly created) session ID of the adhoc command session.
217
* @param status The execution status.
218
* @param form An optional DataForm to include in the reply. Will be deleted in Command's
221
Command( const std::string& node, const std::string& sessionid, Status status,
222
DataForm* form = 0 );
225
* Creates a Command object that can be used to perform the provided Action.
226
* This constructor is used best to reply to a multi stage command that is not yet completed
227
* (for which the session ID must be known).
228
* @param node The node (command) to perform the action on.
229
* @param sessionid The (possibly newly created) session ID of the adhoc command session.
230
* @param status The execution status.
231
* @param executeAction The action to execute.
232
* @param allowedActions Allowed reply actions.
233
* @param form An optional DataForm to include in the reply. Will be deleted in Command's
236
Command( const std::string& node, const std::string& sessionid, Status status,
237
Action executeAction, int allowedActions = Complete,
238
DataForm* form = 0 );
241
* Creates a Command object that can be used to perform the provided Action.
242
* This constructor is used best to execute the initial step of a command
243
* (single or multi stage).
244
* @param node The node (command) to perform the action on.
245
* @param action The action to perform.
246
* @param form An optional DataForm to include in the request. Will be deleted in Command's
249
Command( const std::string& node, Action action,
250
DataForm* form = 0 );
253
* Creates a Command object from the given Tag.
254
* @param tag A <command> tag in the adhoc commands' namespace.
256
Command( const Tag* tag = 0 );
259
* Virtual destructor.
264
* Returns the node identifier (the command).
265
* @return The node identifier.
267
const std::string& node() const { return m_node; }
270
* Returns the command's session ID, if any.
271
* @return The command's session ID.
273
const std::string& sessionID() const { return m_sessionid; }
276
* Returns the execution status for a command. Only valid for execution
278
* @return The execution status for a command.
280
Status status() const { return m_status; }
283
* Returns the command's action.
284
* @return The command's action.
286
Action action() const { return m_action; }
289
* Returns the ORed actions that are allowed to be executed on the
291
* @return An int containing the ORed actions.
293
int actions() const { return m_actions; }
296
* Returns the list of notes associated with the command.
297
* @return The list of notes.
299
const NoteList& notes() const { return m_notes; }
302
* Use this function to add a note to the command.
303
* @param note A pointer to a Note object. The Command will own
306
void addNote( const Note* note ) { m_notes.push_back( note ); }
309
* Returns the command's embedded DataForm.
310
* @return The command's embedded DataForm. May be 0.
312
const DataForm* form() const { return m_form; }
314
// reimplemented from StanzaExtension
315
virtual const std::string& filterString() const;
317
// reimplemented from StanzaExtension
318
virtual StanzaExtension* newInstance( const Tag* tag ) const
320
return new Command( tag );
323
// reimplemented from StanzaExtension
324
virtual Tag* tag() const;
326
// reimplemented from StanzaExtension
327
virtual StanzaExtension* clone() const
329
Command* c = new Command();
331
NoteList::const_iterator it = m_notes.begin();
332
for( ; it != m_notes.end(); ++it )
333
c->m_notes.push_back( new Note( *(*it) ) );
336
c->m_sessionid = m_sessionid;
337
c->m_form = m_form ? static_cast<DataForm*>( m_form->clone() ) : 0;
338
c->m_action = m_action;
339
c->m_status = m_status;
340
c->m_actions = m_actions;
346
#ifdef ADHOC_COMMANDS_TEST
352
std::string m_sessionid;
361
* Creates a new Adhoc client that registers as IqHandler with a ClientBase.
362
* @param parent The ClientBase used for XMPP communication.
364
Adhoc( ClientBase* parent );
367
* Virtual destructor.
372
* This function queries the given remote entity for Adhoc Commands support.
373
* @param remote The remote entity's JID.
374
* @param ah The object handling the result of this request.
376
void checkSupport( const JID& remote, AdhocHandler* ah );
379
* Retrieves a list of commands from the remote entity. You should check whether the remote
380
* entity actually supports Adhoc Commands by means of checkSupport().
381
* @param remote The remote entity's JID.
382
* @param ah The object handling the result of this request.
384
void getCommands( const JID& remote, AdhocHandler* ah );
387
* Executes or continues the given command on the given remote entity.
388
* To construct the @c command object, it is recommended to use either
389
* Command( const std::string&, Action ) to begin execution of a command, or
390
* Command( const std::string&, const std::string&, Action ) to continue execution
392
* @param remote The remote entity's JID.
393
* @param command The command to execute.
394
* @param ah The object handling the result of this request.
396
void execute( const JID& remote, const Adhoc::Command* command, AdhocHandler* ah );
399
* Use this function to respond to an execution request submitted by means
400
* of AdhocCommandProvider::handleAdhocCommand().
401
* It is recommended to use
402
* Command( const std::string&, const std::string&, Status, DataForm* )
403
* to construct the @c command object.
404
* Optionally, an Error object can be included. In that case the IQ sent is of type @c error.
405
* @param remote The requester's JID.
406
* @param command The response. The Adhoc object will own and delete the
407
* command object pointed to.
408
* @param error An optional Error obejct to include.
410
void respond( const JID& remote, const Adhoc::Command* command, const Error* error = 0 );
413
* Using this function, you can register a AdhocCommandProvider -derived object as
414
* handler for a specific Ad-hoc Command as defined in XEP-0050.
415
* @param acp The obejct to register as handler for the specified command.
416
* @param command The node name of the command. Will be announced in disco#items.
417
* @param name The natural-language name of the command. Will be announced in disco#items.
419
void registerAdhocCommandProvider( AdhocCommandProvider* acp, const std::string& command,
420
const std::string& name );
423
* Use this function to unregister an adhoc command previously registered using
424
* registerAdhocCommandProvider().
425
* @param command The command to unregister.
427
void removeAdhocCommandProvider( const std::string& command );
429
// reimplemented from DiscoNodeHandler
430
virtual StringList handleDiscoNodeFeatures( const JID& from, const std::string& node );
432
// reimplemented from DiscoNodeHandler
433
virtual Disco::IdentityList handleDiscoNodeIdentities( const JID& from,
434
const std::string& node );
436
// reimplemented from DiscoNodeHandler
437
virtual Disco::ItemList handleDiscoNodeItems( const JID& from, const JID& to, const std::string& node );
439
// reimplemented from IqHandler
440
virtual bool handleIq( const IQ& iq );
442
// reimplemented from IqHandler
443
virtual void handleIqID( const IQ& iq, int context );
445
// reimplemented from DiscoHandler
446
virtual void handleDiscoInfo( const JID& from, const Disco::Info& info, int context );
448
// reimplemented from DiscoHandler
449
virtual void handleDiscoItems( const JID& from, const Disco::Items& items, int context );
451
// reimplemented from DiscoHandler
452
virtual void handleDiscoError( const JID& from, const Error* error, int context );
458
typedef std::map<const std::string, AdhocCommandProvider*> AdhocCommandProviderMap;
459
AdhocCommandProviderMap m_adhocCommandProviders;
471
AdhocContext context;
475
typedef std::map<std::string, TrackStruct> AdhocTrackMap;
476
AdhocTrackMap m_adhocTrackMap;
478
ClientBase* m_parent;
481
StringMap m_activeSessions;