1 /*
2   Copyright (c) 2006-2019 by Jakob Schröter <js@camaya.net>
3   This file is part of the gloox library. http://camaya.net/gloox
4 
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.
9 
10   This software is distributed without any warranty.
11 */
12 
13 
14 
15 #ifndef MUCROOM_H__
16 #define MUCROOM_H__
17 
18 #include "discohandler.h"
19 #include "disconodehandler.h"
20 #include "dataform.h"
21 #include "presencehandler.h"
22 #include "iqhandler.h"
23 #include "messagehandler.h"
24 #include "mucroomhandler.h"
25 #include "mucroomconfighandler.h"
26 #include "jid.h"
27 #include "stanzaextension.h"
28 
29 #include <string>
30 
31 namespace gloox
32 {
33 
34   class ClientBase;
35   class MUCMessageSession;
36   class Message;
37 
38   /**
39    * @brief This is an implementation of @xep{0045} (Multi-User Chat).
40    *
41    * Usage is pretty simple:
42    *
43    * Derrive an object from MUCRoomHandler and implement its virtuals:
44    * @code
45    * class MyClass : public MUCRoomHandler
46    * {
47    *   ...
48    * };
49    * @endcode
50    *
51    * Then create a new MUCRoom object and pass it a valid ClientBase, the desired full room JID,
52    * your MUCRoomHandler-derived object, and an optional MUCRoomConfigHandler-derived object.
53    * @code
54    * void MyOtherClass::joinRoom( const std::string& room, const std::string& service,
55    *                              const std::string& nick )
56    * {
57    *   MyClass* myHandler = new MyClass(...);
58    *   JID roomJID( room + "@" + service + "/" + nick );
59    *   m_room = new MUCRoom( m_clientbase, roomJID, myHandler, 0 );
60    *   m_room->join();
61    * }
62    * @endcode
63    *
64    * When joining the room was successful, the various MUCRoomHandler functions will start to
65    * be called. If joining was not successful, MUCRoomHandler::handleMUCError() will be called,
66    * giving a hint at the reason for the failure.
67    *
68    * To set up your own room, or to configure an existing room, you should also derive a
69    * class from MUCRoomConfigHandler and register it with the MUCRoom (either by using it
70    * with MUCRoom's constructor, or by calling registerMUCRoomConfigHandler()).
71    *
72    * To quickly create an instant room, see InstantMUCRoom.
73    *
74    * To quickly create an instant room to turn a one-to-one chat into a multi-user chat,
75    * see UniqueMUCRoom.
76    *
77    * To send a private message to a room participant, use
78    * @link MessageSession gloox::MessageSession @endlink with the participant's full room JID
79    * (room\@service/nick).
80    *
81    * XEP version: 1.21
82    * @author Jakob Schröter <js@camaya.net>
83    * @since 0.9
84    */
85   class GLOOX_API MUCRoom : private DiscoHandler, private PresenceHandler,
86                             public IqHandler, private MessageHandler, private DiscoNodeHandler
87   {
88     public:
89       /**
90        * Allowable history request types. To disable sending of history, use any value except
91        * HistoryUnknown and specify a zero-length time span (using setRequestHistory()).
92        */
93       enum HistoryRequestType
94       {
95         HistoryMaxChars,            /**< Limit the total number of characters in the history to "X"
96                                      * (where the character count is the characters of the complete
97                                      * XML stanzas, not only their XML character data). */
98         HistoryMaxStanzas,          /**< Limit the total number of messages in the history to "X". */
99         HistorySeconds,             /**< Send only the messages received in the last "X" seconds. */
100         HistorySince,               /**< Send only the messages received since the datetime specified
101                                      * (which MUST conform to the DateTime profile specified in Jabber
102                                      * Date and Time Profiles (@xep{0082})). */
103         HistoryUnknown              /**< It is up to the service to decide how much history to send.
104                                      * This is the default. */
105       };
106 
107       /**
108        * Available operations.
109        */
110       enum MUCUserOperation
111       {
112         OpNone,                 /**< No operation. */
113         OpInviteTo,             /**< Invitation being sent to soemone. */
114         OpInviteFrom,           /**< Invitation received from someone. */
115         OpDeclineTo,            /**< Someone's invitation declined. */
116         OpDeclineFrom           /**< Someone declined an invitation. */
117       };
118 
119       /**
120        * @brief An abstraction of a MUC query.
121        *
122        * You should not need to use this class directly.
123        *
124        * @author Jakob Schröter <js@camaya.net>
125        * @since 1.0
126        */
127       class MUC : public StanzaExtension
128       {
129         public:
130           /**
131            * Creates a new MUC object.
132            * @param password An optional room password.
133            * @param historyType The type of room history to request.
134            * @param historySince A string describing the amount of room history.
135            * @param historyValue The amount of requested room history.
136            */
137           MUC( const std::string& password, HistoryRequestType historyType = HistoryUnknown,
138                const std::string& historySince = EmptyString, int historyValue = 0 );
139 
140           /**
141            * Constructs a new MUCUser object from the given Tag.
142            * @param tag The Tag to parse.
143            */
144           MUC( const Tag* tag = 0 );
145 
146           /**
147            * Virtual destructor.
148            */
149           virtual ~MUC();
150 
151           /**
152            * Returns a pointer to the current password, or 0.
153            * @return A pointer to the current password, or 0.
154            */
password()155           const std::string* password() const { return m_password; }
156 
157           /**
158            * Returns a pointer to the description of the amount of room history requested.
159            * @return A pointer to the description of the amount of room history requested.
160            */
historySince()161           const std::string* historySince() const { return m_historySince; }
162 
163           // reimplemented from StanzaExtension
164           virtual const std::string& filterString() const;
165 
166           // reimplemented from StanzaExtension
newInstance(const Tag * tag)167           virtual StanzaExtension* newInstance( const Tag* tag ) const
168           {
169             return new MUC( tag );
170           }
171 
172           // reimplemented from StanzaExtension
173           virtual Tag* tag() const;
174 
175           // reimplemented from StanzaExtension
clone()176           virtual StanzaExtension* clone() const
177           {
178             MUC* m = new MUC();
179             m->m_password = m_password ? new std::string( *m_password ) : 0;
180             m->m_historySince = m_historySince ? new std::string( *m_historySince ) : 0;
181             m->m_historyType = m_historyType;
182             m->m_historyValue = m_historyValue;
183             return m;
184           }
185 
186         private:
187           std::string* m_password;
188           std::string* m_historySince;
189           HistoryRequestType m_historyType;
190           int m_historyValue;
191       };
192 
193       /**
194        * @brief An abstraction of a MUC user query.
195        *
196        * You should not need to use this class directly.
197        *
198        * @author Jakob Schröter <js@camaya.net>
199        * @since 1.0
200        */
201       class MUCUser : public StanzaExtension
202       {
203         public:
204           /**
205            * Constructor.
206            * @param operation An operation to perform.
207            * @param to The recipient.
208            * @param reason The reason for the operation.
209            * @param thread If this is an invitation, and if the invitation is part of
210            * a transformation of a one-to-one chat to a MUC, include the one-to-one chat's
211            * thread ID here. Defaults to the empty string (i.e. not a continuation).
212            */
213           MUCUser( MUCUserOperation operation, const std::string& to, const std::string& reason,
214                    const std::string& thread = EmptyString );
215 
216           /**
217            * Constructs a new MUCUser object from the given Tag.
218            * @param tag The Tag to parse.
219            */
220           MUCUser( const Tag* tag = 0 );
221 
222           /**
223            * Virtual destructor.
224            */
225           virtual ~MUCUser();
226 
227           /**
228            * Returns the current room flags.
229            * @return The current room flags.
230            */
flags()231           int flags() const { return m_flags; }
232 
233           /**
234            * Returns the user's current room affiliation.
235            * @return The user's current room affiliation.
236            */
affiliation()237           MUCRoomAffiliation affiliation() const { return m_affiliation; }
238 
239           /**
240            * Returns the user's current room role.
241            * @return The user's current room role.
242            */
role()243           MUCRoomRole role() const { return m_role; }
244 
245           /**
246            *
247            */
jid()248           const std::string* jid() const { return m_jid; }
249 
250           /**
251            *
252            */
actor()253           const std::string* actor() const { return m_actor; }
254 
255           /**
256            *
257            */
password()258           const std::string* password() const { return m_password; }
259 
260           /**
261            *
262            */
thread()263           const std::string* thread() const { return m_thread; }
264 
265           /**
266            *
267            */
reason()268           const std::string* reason() const { return m_reason; }
269 
270           /**
271            *
272            */
newNick()273           const std::string* newNick() const { return m_newNick; }
274 
275           /**
276            * Returns an alternate venue, if set.
277            * @return An alternate venue, if set.
278            */
alternate()279           const std::string* alternate() const { return m_alternate; }
280 
281           /**
282            * Whether or not the 'continue' flag is set.
283            * @return Whether or not the 'continue' flag is set.
284            */
continued()285           bool continued() const { return m_continue; }
286 
287           /**
288            * Returns the current operation.
289            * @return The current operation.
290            */
operation()291           MUCUserOperation operation() const { return m_operation; }
292 
293           // reimplemented from StanzaExtension
294           virtual const std::string& filterString() const;
295 
296           // reimplemented from StanzaExtension
newInstance(const Tag * tag)297           virtual StanzaExtension* newInstance( const Tag* tag ) const
298           {
299             return new MUCUser( tag );
300           }
301 
302           // reimplemented from StanzaExtension
303           virtual Tag* tag() const;
304 
305           // reimplemented from StanzaExtension
clone()306           virtual StanzaExtension* clone() const
307           {
308             MUCUser* m = new MUCUser();
309             m->m_affiliation = m_affiliation;
310             m->m_role = m_role;
311             m->m_jid = m_jid ? new std::string( *m_jid ) : 0;
312             m->m_actor = m_actor ? new std::string( *m_actor ) : 0;
313             m->m_thread = m_thread ? new std::string( *m_thread ) : 0;
314             m->m_reason = m_reason ? new std::string( *m_reason ) : 0;
315             m->m_newNick = m_newNick ? new std::string( *m_newNick ) : 0;
316             m->m_password = m_password ? new std::string( *m_password ) : 0;
317             m->m_alternate = m_alternate ? new std::string( *m_alternate ) : 0;
318             m->m_operation = m_operation;
319             m->m_flags = m_flags;
320             m->m_del = m_del;
321             m->m_continue = m_continue;
322             return m;
323           }
324 
325         private:
326           static MUCRoomAffiliation getEnumAffiliation( const std::string& affiliation );
327           static MUCRoomRole getEnumRole( const std::string& role );
328 
329 
330           MUCRoomAffiliation m_affiliation;
331           MUCRoomRole m_role;
332           std::string* m_jid;
333           std::string* m_actor;
334           std::string* m_thread;
335           std::string* m_reason;
336           std::string* m_newNick;
337           std::string* m_password;
338           std::string* m_alternate;
339           MUCUserOperation m_operation;
340           int m_flags;
341           bool m_del;
342           bool m_continue;
343       };
344 
345       /**
346        * Creates a new abstraction of a Multi-User Chat room. The room is not joined automatically.
347        * Use join() to join the room, use leave() to leave it.
348        * @param parent The ClientBase object to use for the communication.
349        * @param nick The room's name and service plus the desired nickname in the form
350        * room\@service/nick.
351        * @param mrh The MUCRoomHandler that will listen to room events. May be 0 and may be specified
352        * later using registerMUCRoomHandler(). However, without one, MUC is no joy.
353        * @param mrch The MUCRoomConfigHandler that will listen to room config result. Defaults to 0
354        * initially. However, at the latest you need one when you create a new room which is not an
355        * instant room. You can set a MUCRoomConfigHandler using registerMUCRoomConfigHandler().
356        */
357       MUCRoom( ClientBase* parent, const JID& nick, MUCRoomHandler* mrh, MUCRoomConfigHandler* mrch = 0 );
358 
359       /**
360        * Virtual Destructor.
361        */
362       virtual ~MUCRoom();
363 
364       /**
365        * Use this function to set a password to use when joining a (password protected)
366        * room.
367        * @param password The password to use for this room.
368        * @note This function does not password-protect a room.
369        */
setPassword(const std::string & password)370       void setPassword( const std::string& password ) { m_password = password; }
371 
372       /**
373        * A convenience function that returns the room's name.
374        * @return The room's name.
375        */
name()376       const std::string name() const { return m_nick.username(); }
377 
378       /**
379        * A convenience function that returns the name/address of the MUC service the room is running on
380        * (e.g., conference.jabber.org).
381        * @return The MUC service's name/address.
382        */
service()383       const std::string service() const { return m_nick.server(); }
384 
385       /**
386        * A convenience function that returns the user's nickname in the room.
387        * @return The user's nickname.
388        */
nick()389       const std::string nick() const { return m_nick.resource(); }
390 
391       /**
392        * Join this room.
393        * @param type The presence to join with, defaults to Available.
394        * @param status The presence's optional status text.
395        * @param priority The presence's optional priority, defaults to 0.
396        * ClientBase will automatically include the default Presence extensions added using
397        * @link gloox::ClientBase::addPresenceExtension() ClientBase::addPresenceExtension() @endlink.
398        */
399       virtual void join( Presence::PresenceType type = Presence::Available,
400                          const std::string& status = EmptyString,
401                          int priority = 0 );
402 
403       /**
404        * Leave this room.
405        * @param msg An optional msg indicating the reason for leaving the room. Default: empty.
406        */
407       void leave( const std::string& msg = EmptyString );
408 
409       /**
410        * Sends a chat message to the room.
411        * @param message The message to send.
412        */
413       void send( const std::string& message );
414 
415       /**
416        * Sets the subject of the room to the given string.
417        * The MUC service may decline the request to set a new subject. You should
418        * not assume the subject was set successfully util it is acknowledged via the MUCRoomHandler.
419        * @param subject The new subject.
420        */
421       void setSubject( const std::string& subject );
422 
423       /**
424        * Returns the user's current affiliation with this room.
425        * @return The user's current affiliation.
426        */
affiliation()427       MUCRoomAffiliation affiliation() const { return m_affiliation; }
428 
429       /**
430        * Returns the user's current role in this room.
431        * @return The user's current role.
432        */
role()433       MUCRoomRole role() const { return m_role; }
434 
435       /**
436        * Use this function to change the user's nickname in the room.
437        * The MUC service may decline the request to set a new nickname. You should not assume
438        * the nick change was successful until it is acknowledged via the MUCRoomHandler.
439        * @param nick The user's new nickname.
440        */
441       void setNick( const std::string& nick );
442 
443       /**
444        * Use this function to set the user's presence in this room. It is not possible to
445        * use Unavailable with this function.
446        * @param presence The user's new presence.
447        * @param msg An optional status message. Default: empty.
448        */
449       void setPresence( Presence::PresenceType presence, const std::string& msg = EmptyString );
450 
451       /**
452        * Use this function to invite another user to this room.
453        * @param invitee The (bare) JID of the user to invite.
454        * @param reason The user-supplied reason for the invitation.
455        * @param thread If this invitation is part of a transformation of a
456        * one-to-one chat to a MUC, include the one-to-one chat's thread ID here. Defaults
457        * to the empty string (i.e. not a continuation).
458        */
459       void invite( const JID& invitee, const std::string& reason, const std::string& thread = EmptyString );
460 
461       /**
462        * Use this function to request basic room info, possibly prior to joining it.
463        * Results are announced using the MUCRoomHandler.
464        */
465       void getRoomInfo();
466 
467       /**
468        * Use this function to request information about the current room occupants,
469        * possibly prior to joining it. The room ay be configured not to disclose such
470        * information.
471        * Results are announced using the MUCRoomHandler.
472        */
473       void getRoomItems();
474 
475       /**
476        * The MUC spec enables other entities to discover via Service Discovery which rooms
477        * an entity is in. By default, gloox does not publish such info for privacy reasons.
478        * This function can be used to enable publishing the info for @b this room.
479        * @param publish Whether to enable other entities to discover the user's presence in
480        * @b this room.
481        * @param publishNick Whether to publish the nickname used in the room. This parameter
482        * is ignored if @c publish is @b false.
483        */
484       void setPublish( bool publish, bool publishNick );
485 
486       /**
487        * Use this function to register a (new) MUCRoomHandler with this room. There can be only one
488        * MUCRoomHandler per room at any one time.
489        * @param mrl The MUCRoomHandler to register.
490        */
registerMUCRoomHandler(MUCRoomHandler * mrl)491       void registerMUCRoomHandler( MUCRoomHandler* mrl ) { m_roomHandler = mrl; }
492 
493       /**
494        * Use this function to remove the registered MUCRoomHandler.
495        */
removeMUCRoomHandler()496       void removeMUCRoomHandler() { m_roomHandler = 0; }
497 
498       /**
499        * Use this function to register a (new) MUCRoomConfigHandler with this room. There can
500        * be only one MUCRoomConfigHandler per room at any one time.
501        * @param mrch The MUCRoomConfigHandler to register.
502        */
registerMUCRoomConfigHandler(MUCRoomConfigHandler * mrch)503       void registerMUCRoomConfigHandler( MUCRoomConfigHandler* mrch ) { m_roomConfigHandler = mrch; }
504 
505       /**
506        * Use this function to remove the registered MUCRoomConfigHandler.
507        */
removeMUCRoomConfigHandler()508       void removeMUCRoomConfigHandler() { m_roomConfigHandler = 0; }
509 
510       /**
511        * Use this function to add history to a (newly created) room. The use case from the MUC spec
512        * is to add history to a room that was created in the process of a transformation of a
513        * one-to-one chat to a multi-user chat.
514        * @param message A reason for declining the invitation.
515        * @param from The JID of the original author of this part of the history.
516        * @param stamp The datetime of the original message in the format: 20061224T12:15:23Z
517        * @note You should not attempt to use this function before
518        * MUCRoomHandler::handleMUCParticipantPresence() was called for the first time.
519        */
520       void addHistory( const std::string& message, const JID& from, const std::string& stamp );
521 
522       /**
523        * Use this function to request room history. Set @c value to zero to disable the room
524        * history request. You should not use HistorySince type with this function.
525        * History is sent only once after entering a room. You should use this function before joining.
526        * @param value Represents either the number of requested characters, the number of requested
527        * message stanzas, or the number seconds, depending on the value of @c type.
528        * @param type
529        * @note If this function is not used to request a specific amount of room history, it is up
530        * to the MUC service to decide how much history to send.
531        */
532       void setRequestHistory( int value, HistoryRequestType type );
533 
534       /**
535        * Use this function to request room history since specific datetime.
536        * History is sent only once after entering a room. You should use this function before joining.
537        * @param since A string representing a datetime conforming to the DateTime profile specified
538        * in Jabber Date and Time Profiles (@xep{0082}).
539        * @note If this function is not used to request a specific amount of room history, it is up
540        * to the MUC service to decide how much history to send.
541        */
542       void setRequestHistory( const std::string& since );
543 
544       /**
545        * This static function allows to formally decline a MUC
546        * invitation received via the MUCInvitationListener.
547        * @param room The JID of the room the invitation came from.
548        * @param invitor The JID of the invitor.
549        * @param reason An optional reason for the decline.
550        * @return A pointer to a Message. You will have to send (and
551        * possibly delete) this Message manually.
552        */
553       static Message* declineInvitation( const JID& room, const JID& invitor,
554                                      const std::string& reason = EmptyString);
555 
556       /**
557        * It is not possible for a visitor to speak in a moderated room. Use this function to request
558        * voice from the moderator.
559        */
560       void requestVoice();
561 
562       /**
563        * Use this function to kick a user from the room.
564        * Depending on service and/or room configuration and role/affiliation
565        * this may not always succeed. Usually, a role of 'moderator' is necessary.
566        * @note This is a convenience function. It directly uses setRole() with a MUCRoomRole of RoleNone.
567        * @param nick The nick of the user to be kicked.
568        * @param reason An optional reason for the kick.
569        */
570       void kick( const std::string& nick, const std::string& reason = EmptyString )
571         { setRole( nick, RoleNone, reason ); }
572 
573       /**
574        * Use this function to ban a user from the room.
575        * Depending on service and/or room configuration and role/affiliation
576        * this may not always succeed. Usually, an affiliation of admin is necessary.
577        * @note This is a convenience function. It directly uses setAffiliation() with a MUCRoomAffiliation
578        * of RoleOutcast.
579        * @param nick The nick of the user to be banned.
580        * @param reason An optional reason for the ban.
581        */
ban(const std::string & nick,const std::string & reason)582       void ban( const std::string& nick, const std::string& reason )
583         { setAffiliation( nick, AffiliationOutcast, reason ); }
584 
585       /**
586        * Use this function to grant voice to a user in a moderated room.
587        * Depending on service and/or room configuration and role/affiliation
588        * this may not always succeed. Usually, a role of 'moderator' is necessary.
589        * @note This is a convenience function. It directly uses setRole() with a MUCRoomRole
590        * of RoleParticipant.
591        * @param nick The nick of the user to be granted voice.
592        * @param reason An optional reason for the grant.
593        */
grantVoice(const std::string & nick,const std::string & reason)594       void grantVoice( const std::string& nick, const std::string& reason )
595         { setRole( nick, RoleParticipant, reason ); }
596 
597       /**
598        * Use this function to create a Tag that approves a voice request or registration request
599        * delivered via MUCRoomConfigHandler::handleMUCVoiceRequest(). You will need to send this
600        * Tag off manually using Client/ClientBase.
601        * @param room The room's JID. This is needed because you can use this function outside of
602        * room context (e.g, if the admin is not in the room).
603        * @param df The filled-in DataForm from the voice/registration request. The form object
604        * will be owned by the returned Message.
605        */
606       static Message* createDataForm( const JID& room, const DataForm* df );
607 
608       /**
609        * Use this function to revoke voice from a user in a moderated room.
610        * Depending on service and/or room configuration and role/affiliation
611        * this may not always succeed. Usually, a role of 'moderator' is necessary.
612        * @note This is a convenience function. It directly uses setRole() with a MUCRoomRole
613        * of RoleVisitor.
614        * @param nick The nick of the user.
615        * @param reason An optional reason for the revoke.
616        */
revokeVoice(const std::string & nick,const std::string & reason)617       void revokeVoice( const std::string& nick, const std::string& reason )
618         { setRole( nick, RoleVisitor, reason ); }
619 
620       /**
621        * Use this function to change the role of a user in the room.
622        * Usually, at least moderator privileges are required to succeed.
623        * @param nick The nick of the user who's role shall be modfified.
624        * @param role The user's new role in the room.
625        * @param reason An optional reason for the role change.
626        */
627       void setRole( const std::string& nick, MUCRoomRole role, const std::string& reason = EmptyString );
628 
629       /**
630        * Use this function to change the affiliation of a user in the room.
631        * Usually, at least admin privileges are required to succeed.
632        * @param nick The nick of the user who's affiliation shall be modfified.
633        * @param affiliation The user's new affiliation in the room.
634        * @param reason An optional reason for the affiliation change.
635        */
636       void setAffiliation( const std::string& nick, MUCRoomAffiliation affiliation,
637                            const std::string& reason );
638 
639       /**
640        * Use this function to request the room's configuration form.
641        * It can be used either after MUCRoomHandler::handleMUCRoomCreation() was called,
642        * or at any later time.
643        *
644        * Usually owner privileges are required for this action to
645        * succeed.
646        *
647        * Use setRoomConfig() to send the modified room config back.
648        */
649       void requestRoomConfig();
650 
651       /**
652        * After requesting (using requestRoomConfig()) and
653        * editing/filling in the room's configuration,
654        * use this function to send it back to the server.
655        * @param form The form to send. The function will delete the
656        * object pointed to.
657        */
658       void setRoomConfig( DataForm* form );
659 
660       /**
661        * Use this function to accept the room's default configuration. This function is useful
662        * only after MUCRoomHandler::handleMUCRoomCreation() was called. This is a NOOP at
663        * any other time.
664        */
acknowledgeInstantRoom()665       void acknowledgeInstantRoom()
666         { instantRoom( CreateInstantRoom ); }
667 
668       /**
669        * Use this function to cancel the creation of a room. This function is useful only after
670        * MUCRoomHandler::handleMUCRoomCreation() was called. This is a NOOP at any other time.
671        */
cancelRoomCreation()672       void cancelRoomCreation()
673         { instantRoom( CancelRoomCreation ); }
674 
675       /**
676        * Use this function to destroy the room. All the occupants will be removed from the room.
677        * @param reason An optional reason for the destruction.
678        * @param alternate A pointer to a JID of an alternate venue (e.g., another MUC room).
679        * May be 0.
680        * @param password An optional password for the alternate venue.
681        *
682        * Usually owner privileges are required for this action to succeed.
683        */
684       void destroy( const std::string& reason = EmptyString,
685                     const JID& alternate = JID(), const std::string& password = EmptyString );
686 
687       /**
688        * Use this function to request a particluar list of room occupants.
689        * @note There must be a MUCRoomConfigHandler registered with this room for this
690        * function to be executed.
691        * @param operation The following types of lists are available:
692        * @li Voice List: List of people having voice in a moderated room. Use RequestVoiceList.
693        * @li Members List: List of members of a room. Use RequestMemberList.
694        * @li Ban List: List of people banned from the room. Use RequestBanList.
695        * @li Moderator List: List of room moderators. Use RequestModeratorList.
696        * @li Admin List: List of room admins. Use RequestAdminList.
697        * @li Owner List: List of room owners. Use RequestOwnerList.
698        * Any other value of @c operation will be ignored.
699        */
700       void requestList( MUCOperation operation );
701 
702       /**
703        * Use this function to store a (modified) list for the room.
704        * @param items The list of items. Example:<br>
705        * You want to set the Voice List. The privilege of Voice refers to the role of Participant.
706        * Furthermore, you only store the delta of the original (Voice)List. (Optionally, you could
707        * probably store the whole list, however, remeber to include those items that were modified,
708        * too.)
709        * You want to, say, add one occupant to the Voice List, and remove another one.
710        * Therefore you store:
711        * @li GuyOne, role participant -- this guy gets voice granted, he/she is now a participant.
712        * @li GuyTwo, role visitor -- this guy gets voice revoked, he/she is now a mere visitor
713        * (Visitor is the Role "below" Participant in the privileges hierarchy).
714        *
715        * For operations modifying Roles, you should specifiy only the new Role in the MUCListItem
716        * structure, for those modifying Affiliations, you should only specify the new Affiliation,
717        * respectively. The nickname is mandatory in the MUCListItem structure. Items without nickname
718        * will be ignored.
719        *
720        * You may specify a reason for the role/affiliation change in the MUCListItem structure.
721        * You should not specify a JID in the MUCListItem structure, it will be ignored.
722        *
723        * @param operation See requestList() for a list of available list types. Any other value will
724        * be ignored.
725        */
726       void storeList( const MUCListItemList items, MUCOperation operation );
727 
728       /**
729        * Returns the currently known room flags.
730        * @return ORed MUCRoomFlag's describing the current room configuration.
731        */
flags()732       int flags() const { return m_flags; }
733 
734       // reimplemented from DiscoHandler
735       virtual void handleDiscoInfo( const JID& from, const Disco::Info& info, int context );
736 
737       // reimplemented from DiscoHandler
738       // reimplemented from DiscoHandler
739       virtual void handleDiscoItems( const JID& from, const Disco::Items& items, int context );
740 
741       // reimplemented from DiscoHandler
742       virtual void handleDiscoError( const JID& from, const Error* error, int context );
743 
744       // reimplemented from PresenceHandler
745       virtual void handlePresence( const Presence& presence );
746 
747       // reimplemented from MessageHandler
748       virtual void handleMessage( const Message& msg, MessageSession* session = 0 );
749 
750       // reimplemented from IqHandler
handleIq(const IQ & iq)751       virtual bool handleIq( const IQ& iq ) { (void)iq; return false; }
752 
753       // reimplemented from IqHandler
754       virtual void handleIqID( const IQ& iq, int context );
755 
756       // reimplemented from DiscoNodeHandler
757       virtual StringList handleDiscoNodeFeatures( const JID& from, const std::string& node );
758 
759       // reimplemented from DiscoNodeHandler
760       virtual Disco::IdentityList handleDiscoNodeIdentities( const JID& from,
761                                                              const std::string& node );
762 
763       // reimplemented from DiscoNodeHandler
764       virtual Disco::ItemList handleDiscoNodeItems( const JID& from, const JID& to,
765                                                     const std::string& node = EmptyString );
766 
767     protected:
768       /**
769        * Sets the room's name.
770        * @param name The room's name.
771        */
setName(const std::string & name)772       void setName( const std::string& name ) { m_nick.setUsername( name ); }
773 
774       /**
775        * Acknowledges instant room creation w/o a call to the MUCRoomConfigHandler.
776        * @return Whether an instant room is being created.
777        */
instantRoomHook()778       virtual bool instantRoomHook() const { return false; }
779 
780       ClientBase* m_parent;
781       JID m_nick;
782 
783       bool m_joined;
784 
785     private:
786 #ifdef MUCROOM_TEST
787     public:
788 #endif
789       /**
790        * @brief An abstraction of a MUC owner query.
791        *
792        * @author Jakob Schröter <js@camaya.net>
793        * @since 1.0
794        */
795       class MUCOwner : public StanzaExtension
796       {
797         public:
798 
799           /**
800            * Describes available query types for the muc#owner namespace.
801            */
802           enum QueryType
803           {
804             TypeCreate,             /**< Create a room. */
805             TypeRequestConfig,      /**< Request room config. */
806             TypeSendConfig,         /**< Submit configuration form to MUC service. */
807             TypeCancelConfig,       /**< Cancel room configuration. */
808             TypeInstantRoom,        /**< Request an instant room */
809             TypeDestroy,            /**< Destroy the room. */
810             TypeIncomingTag         /**< The Query has been created from an incoming Tag. */
811           };
812 
813           /**
814            * Creates a new MUCOwner object for the given query, possibly including
815            * the given DataForm.
816            * @param type The intended query type.
817            * @param form An optional pointer to a DataForm. Necessity depends on the query type.
818            */
819           MUCOwner( QueryType type, DataForm* form = 0 );
820 
821           /**
822            * Creates a new query that destroys the current room.
823            * @param alternate An optional alternate discussion venue.
824            * @param reason An optional reason for the room destruction.
825            * @param password An optional password for the new room.
826            */
827           MUCOwner( const JID& alternate = JID(), const std::string& reason = EmptyString,
828                     const std::string& password = EmptyString);
829 
830           /**
831            * Creates a new MUCOwner object from the given Tag.
832            * @param tag A Tag to parse.
833            */
834           MUCOwner( const Tag* tag );
835 
836           /**
837            * Virtual destructor.
838            */
839           virtual ~MUCOwner();
840 
841           /**
842            * Returns a pointer to a DataForm, included in the MUCOwner object. May be 0.
843            * @return A pointer to a configuration form.
844            */
form()845           const DataForm* form() const { return m_form; }
846 
847           // reimplemented from StanzaExtension
848           const std::string& filterString() const;
849 
850           // reimplemented from StanzaExtension
newInstance(const Tag * tag)851           StanzaExtension* newInstance( const Tag* tag ) const
852           {
853             return new MUCOwner( tag );
854           }
855 
856           // reimplemented from StanzaExtension
857           Tag* tag() const;
858 
859           // reimplemented from StanzaExtension
clone()860           virtual StanzaExtension* clone() const
861           {
862             MUCOwner* m = new MUCOwner();
863             m->m_type = m_type;
864             m->m_jid = m_jid;
865             m->m_reason = m_reason;
866             m->m_pwd = m_pwd;
867             m->m_form = m_form ? new DataForm( *m_form ) : 0;
868             return m;
869           }
870 
871         private:
872           QueryType m_type;
873           JID m_jid;
874           std::string m_reason;
875           std::string m_pwd;
876           DataForm* m_form;
877       };
878 
879       /**
880        * @brief An abstraction of a MUC admin query.
881        *
882        * @author Jakob Schröter <js@camaya.net>
883        * @since 1.0
884        */
885       class MUCAdmin : public StanzaExtension
886       {
887         public:
888           /**
889            * Creates a new object that can be used to change the role of a room participant.
890            * @param role The participant's new role.
891            * @param nick The participant's nick.
892            * @param reason An optional reason for the role change.
893            */
894           MUCAdmin( MUCRoomRole role, const std::string& nick,
895                     const std::string& reason = EmptyString );
896 
897           /**
898            * Creates a new object that can be used to change the affiliation of a room participant.
899            * @param affiliation The participant's new affiliation.
900            * @param nick The participant's nick.
901            * @param reason An optional reason for the role change.
902            */
903           MUCAdmin( MUCRoomAffiliation affiliation, const std::string& nick,
904                     const std::string& reason = EmptyString );
905 
906           /**
907            * Creates a new object that can be used to request or store a role/affiliation
908            * list.
909            * @param operation The MUCOperation to carry out. Only the Request* and Store*
910            * operations are valid. Any other value will be ignored.
911            * @param jids A list of bare JIDs. Only the JID member of the MUCListItem
912            * structure should be set. The type of the list will be determined from the
913            * @c operation parameter.
914            */
915           MUCAdmin( MUCOperation operation, const MUCListItemList& jids = MUCListItemList() );
916 
917           /**
918            * Constructs a new MUCAdmin object from the given Tag.
919            * @param tag The Tag to parse.
920            */
921           MUCAdmin( const Tag* tag = 0 );
922 
923           /**
924            * Virtual destructor.
925            */
926           virtual ~MUCAdmin();
927 
928           /**
929            * Returns the contained list of MUC items.
930            * @return The contained list of MUC items.
931            */
list()932           const MUCListItemList& list() const { return m_list; }
933 
934           // reimplemented from StanzaExtension
935           const std::string& filterString() const;
936 
937           // reimplemented from StanzaExtension
newInstance(const Tag * tag)938           StanzaExtension* newInstance( const Tag* tag ) const
939           {
940             return new MUCAdmin( tag );
941           }
942 
943           // reimplemented from StanzaExtension
944           Tag* tag() const;
945 
946           // reimplemented from StanzaExtension
clone()947           virtual StanzaExtension* clone() const
948           {
949             return new MUCAdmin( *this );
950           }
951 
952         private:
953           MUCListItemList m_list;
954           MUCRoomAffiliation m_affiliation;
955           MUCRoomRole m_role;
956       };
957 
958       void handleIqResult( const IQ& iq, int context );
959       void handleIqError( const IQ& iq, int context );
960       void setNonAnonymous();
961       void setSemiAnonymous();
962       void setFullyAnonymous();
963       void acknowledgeRoomCreation();
964       void instantRoom( int context );
965 
966       MUCRoomHandler* m_roomHandler;
967       MUCRoomConfigHandler* m_roomConfigHandler;
968       MUCMessageSession* m_session;
969 
970       typedef std::list<MUCRoomParticipant> ParticipantList;
971       ParticipantList m_participants;
972 
973       std::string m_password;
974       std::string m_newNick;
975 
976       MUCRoomAffiliation m_affiliation;
977       MUCRoomRole m_role;
978 
979       HistoryRequestType m_historyType;
980 
981       std::string m_historySince;
982       int m_historyValue;
983       int m_flags;
984       bool m_creationInProgress;
985       bool m_configChanged;
986       bool m_publishNick;
987       bool m_publish;
988       bool m_unique;
989 
990   };
991 
992 }
993 
994 #endif // MUCROOM_H__
995