16 #include "clientbase.h"
20 #include "mucmessagesession.h"
31 static const char* affiliationValues [] = {
40 static const char* roleValues [] = {
50 "maxchars",
"maxstanzas",
"seconds",
"since"
58 static inline MUCRoomRole roleType(
const std::string& type )
60 return (
MUCRoomRole)util::lookup( type, roleValues );
63 MUCRoom::MUCAdmin::MUCAdmin(
MUCRoomRole role,
const std::string& nick,
64 const std::string& reason )
67 m_list.push_back( MUCListItem( nick, role, reason ) );
70 MUCRoom::MUCAdmin::MUCAdmin( MUCRoomAffiliation affiliation,
const std::string& nick,
71 const std::string& reason )
74 m_list.push_back( MUCListItem( nick, affiliation, reason ) );
77 MUCRoom::MUCAdmin::MUCAdmin( MUCOperation operation,
const MUCListItemList& jids )
113 m_list.push_back( MUCListItem( JID() ) );
116 MUCRoom::MUCAdmin::MUCAdmin(
const Tag* tag )
119 if( !tag || tag->name() !=
"query" || tag->xmlns() !=
XMLNS_MUC_ADMIN )
122 const TagList& items = tag->findChildren(
"item" );
123 TagList::const_iterator it = items.begin();
124 for( ; it != items.end(); ++it )
126 m_list.push_back( MUCListItem( JID( (*it)->findAttribute(
"jid" ) ),
127 roleType( (*it)->findAttribute(
"role" ) ),
128 affiliationType( (*it)->findAttribute(
"affiliation" ) ),
129 (*it)->findAttribute(
"nick" ) ) );
131 m_role = roleType( (*it)->findAttribute(
"role" ) );
133 m_affiliation = affiliationType( (*it)->findAttribute(
"affiliation" ) );
137 MUCRoom::MUCAdmin::~MUCAdmin()
141 const std::string& MUCRoom::MUCAdmin::filterString()
const
143 static const std::string filter =
"/iq/query[@xmlns='" +
XMLNS_MUC_ADMIN +
"']";
147 Tag* MUCRoom::MUCAdmin::tag()
const
149 Tag* t =
new Tag(
"query" );
150 t->setXmlns( XMLNS_MUC_ADMIN );
155 MUCListItemList::const_iterator it = m_list.begin();
156 for( ; it != m_list.end(); ++it )
158 Tag* i =
new Tag( t,
"item" );
160 i->addAttribute(
"jid", (*it).jid().bare() );
161 if( !(*it).nick().empty() )
162 i->addAttribute(
"nick", (*it).nick() );
167 else if( m_role != RoleInvalid )
169 if( rol != RoleInvalid )
170 i->addAttribute(
"role", util::lookup( rol, roleValues ) );
174 aff = (*it).affiliation();
175 else if( m_affiliation != AffiliationInvalid )
177 if( aff != AffiliationInvalid )
178 i->addAttribute(
"affiliation", util::lookup( aff, affiliationValues ) );
179 if( !(*it).reason().empty() )
180 new Tag( i,
"reason", (*it).reason() );
188 MUCRoom::MUCOwner::MUCOwner( QueryType type, DataForm* form )
189 : StanzaExtension(
ExtMUCOwner ), m_type( type ), m_form( form )
198 case TypeCancelConfig:
201 case TypeInstantRoom:
209 MUCRoom::MUCOwner::MUCOwner(
const JID& alternate,
const std::string& reason,
210 const std::string& password )
211 : StanzaExtension(
ExtMUCOwner ), m_type( TypeDestroy ), m_jid( alternate ),
212 m_reason( reason ), m_pwd( password ), m_form( 0 )
217 MUCRoom::MUCOwner::MUCOwner(
const Tag* tag )
218 : StanzaExtension(
ExtMUCOwner ), m_type( TypeIncomingTag ), m_form( 0 )
220 if( !tag || tag->name() !=
"query" || tag->xmlns() !=
XMLNS_MUC_OWNER )
223 const TagList& l = tag->children();
224 TagList::const_iterator it = l.begin();
225 for( ; it != l.end(); ++it )
227 const std::string& name = (*it)->name();
230 m_form =
new DataForm( (*it) );
233 else if( name ==
"destroy" )
235 m_type = TypeDestroy;
236 m_jid = (*it)->findAttribute(
"jid" );
237 m_pwd = (*it)->findCData(
"/query/destroy/password" );
238 m_reason = (*it)->findCData(
"/query/destroy/reason" );
245 MUCRoom::MUCOwner::~MUCOwner()
250 const std::string& MUCRoom::MUCOwner::filterString()
const
252 static const std::string filter =
"/iq/query[@xmlns='" +
XMLNS_MUC_OWNER +
"']";
256 Tag* MUCRoom::MUCOwner::tag()
const
261 Tag* t =
new Tag(
"query" );
262 t->setXmlns( XMLNS_MUC_OWNER );
266 case TypeInstantRoom:
268 case TypeCancelConfig:
269 case TypeIncomingTag:
271 t->addChild( m_form->tag() );
275 Tag* d =
new Tag( t,
"destroy" );
277 d->addAttribute(
"jid", m_jid.bare() );
279 if( !m_reason.empty() )
280 new Tag( d,
"reason", m_reason );
283 new Tag( d,
"password", m_pwd );
287 case TypeRequestConfig:
299 const std::string& reason,
const std::string& thread )
301 m_jid( new
std::string( to ) ), m_actor( 0 ),
302 m_thread( thread.empty() ? 0 : new
std::string( thread ) ),
303 m_reason( new
std::string( reason ) ), m_newNick( 0 ), m_password( 0 ), m_alternate( 0 ),
304 m_operation( operation ),
305 m_flags( 0 ), m_del( false ), m_continue( !thread.empty() )
311 m_jid( 0 ), m_actor( 0 ), m_thread( 0 ), m_reason( 0 ), m_newNick( 0 ),
312 m_password( 0 ), m_alternate( 0 ), m_operation(
OpNone ),
313 m_flags( 0 ), m_del( false ), m_continue( false )
320 TagList::const_iterator it = l.begin();
321 for( ; it != l.end(); ++it )
323 if( (*it)->name() ==
"item" )
325 m_affiliation = getEnumAffiliation( (*it)->findAttribute(
"affiliation" ) );
326 m_role = getEnumRole( (*it)->findAttribute(
"role" ) );
328 if( (*it)->hasAttribute(
"jid" ) )
329 m_jid =
new std::string( (*it)->findAttribute(
"jid" ) );
331 if( ( t = (*it)->
findChild(
"actor" ) ) )
334 if( ( t = (*it)->
findChild(
"reason" ) ) )
335 m_reason =
new std::string( t->
cdata() );
337 if( (*it)->hasAttribute(
"nick" ) )
338 m_newNick =
new std::string( (*it)->findAttribute(
"nick" ) );
340 else if( (*it)->name() ==
"status" )
342 const std::string& code = (*it)->findAttribute(
"code" );
345 else if( code ==
"101" )
347 else if( code ==
"110" )
349 else if( code ==
"170" )
351 else if( code ==
"201" )
353 else if( code ==
"210" )
355 else if( code ==
"301" )
357 else if( code ==
"303" )
359 else if( code ==
"307" )
361 else if( code ==
"321" )
363 else if( code ==
"322" )
365 else if( code ==
"332" )
368 else if( (*it)->name() ==
"destroy" )
371 if( (*it)->hasAttribute(
"jid" ) )
372 m_alternate =
new std::string( (*it)->findAttribute(
"jid" ) );
374 if( ( t = (*it)->
findChild(
"reason" ) ) )
375 m_reason =
new std::string( t->
cdata() );
379 else if( (*it)->name() ==
"invite" )
382 m_jid =
new std::string( (*it)->findAttribute(
"from" ) );
386 m_jid->assign( (*it)->findAttribute(
"to" ) );
388 if( (*it)->hasChild(
"reason" ) )
389 m_reason =
new std::string( (*it)->findChild(
"reason" )->cdata() );
390 if( (*it)->hasChild(
"continue" ) )
393 m_thread =
new std::string( (*it)->findChild(
"continue" )->findAttribute(
"thread" ) );
396 else if( (*it)->name() ==
"decline" )
399 m_jid =
new std::string( (*it)->findAttribute(
"from" ) );
403 m_jid->assign( (*it)->findAttribute(
"from" ) );
405 if( (*it)->hasChild(
"reason" ) )
406 m_reason =
new std::string( (*it)->findChild(
"reason" )->cdata() );
408 else if( (*it)->name() ==
"password" )
410 m_password =
new std::string( (*it)->cdata() );
426 MUCRoomRole MUCRoom::MUCUser::getEnumRole(
const std::string& role )
428 if( role ==
"moderator" )
430 if( role ==
"participant" )
432 if( role ==
"visitor" )
437 MUCRoomAffiliation MUCRoom::MUCUser::getEnumAffiliation(
const std::string& affiliation )
439 if( affiliation ==
"owner" )
441 if( affiliation ==
"admin" )
443 if( affiliation ==
"member" )
445 if( affiliation ==
"outcast" )
452 static const std::string filter =
"/presence/x[@xmlns='" +
XMLNS_MUC_USER +
"']"
464 Tag* i =
new Tag( t,
"item" );
468 i->
addAttribute(
"role", util::lookup( m_role, roleValues ) );
470 i->
addAttribute(
"affiliation", util::lookup( m_affiliation, affiliationValues ) );
473 new Tag( i,
"actor",
"jid", *m_actor );
476 new Tag( t,
"status",
"code",
"100" );
478 new Tag( t,
"status",
"code",
"101" );
480 new Tag( t,
"status",
"code",
"110" );
482 new Tag( t,
"status",
"code",
"170" );
484 new Tag( t,
"status",
"code",
"201" );
486 new Tag( t,
"status",
"code",
"210" );
488 new Tag( t,
"status",
"code",
"301" );
490 new Tag( t,
"status",
"code",
"303" );
492 new Tag( t,
"status",
"code",
"307" );
494 new Tag( t,
"status",
"code",
"321" );
496 new Tag( t,
"status",
"code",
"322" );
498 new Tag( t,
"status",
"code",
"332" );
502 Tag* d =
new Tag( t,
"destroy" );
506 new Tag( d,
"reason", *m_reason );
508 else if( m_operation !=
OpNone && m_jid )
512 d =
new Tag( t,
"invite",
"to", *m_jid );
514 d =
new Tag( t,
"invite",
"from", *m_jid );
516 d =
new Tag( t,
"decline",
"to", *m_jid );
518 d =
new Tag( t,
"decline",
"from", *m_jid );
521 new Tag( d,
"reason", *m_reason );
525 Tag* c =
new Tag( d,
"continue" );
531 new Tag( t,
"password", *m_password );
542 const std::string& historySince,
545 m_password( password.empty() ? 0 : new
std::string( password ) ),
546 m_historySince( new
std::string( historySince ) ),
547 m_historyType( historyType ), m_historyValue( historyValue )
553 m_password( 0 ), m_historySince( 0 ),
560 TagList::const_iterator it = l.begin();
561 for( ; it != l.end(); ++it )
563 if( (*it)->name() ==
"history" )
565 if( (*it)->hasAttribute(
"seconds" ) )
566 m_historyValue = atoi( (*it)->findAttribute(
"seconds" ).c_str() );
567 else if( (*it)->hasAttribute(
"maxstanzas" ) )
568 m_historyValue = atoi( (*it)->findAttribute(
"maxstanzas" ).c_str() );
569 else if( (*it)->hasAttribute(
"maxchars" ) )
570 m_historyValue = atoi( (*it)->findAttribute(
"maxchars" ).c_str() );
571 else if( (*it)->hasAttribute(
"since" ) )
572 m_historySince =
new std::string( (*it)->findAttribute(
"since" ) );
574 else if( (*it)->name() ==
"password" )
576 m_password =
new std::string( (*it)->cdata() );
584 delete m_historySince;
589 static const std::string filter =
"/presence/x[@xmlns='" +
XMLNS_MUC +
"']";
600 const std::string& histStr = util::lookup( m_historyType, historyTypeValues );
601 Tag* h =
new Tag( t,
"history" );
609 new Tag( t,
"password", *m_password );
618 : m_parent( parent ), m_nick( nick ), m_joined( false ), m_roomHandler( mrh ),
620 m_historyType(
HistoryUnknown ), m_historyValue( 0 ), m_flags( 0 ),
621 m_creationInProgress( false ), m_configChanged( false ),
622 m_publishNick( false ), m_publish( false ), m_unique( false )
654 if( m_joined || !m_parent )
663 pres.
addExtension(
new MUC( m_password, m_historyType, m_historySince, m_historyValue ) );
665 m_parent->
send( pres );
676 m_parent->
send( pres );
690 const std::string&
id = m_parent->
getID();
692 iq.
addExtension(
new MUCOwner( alternate, reason, password ) );
698 if( m_session && m_joined )
699 m_session->
send( message );
704 if( m_session && m_joined )
710 if( m_parent && m_joined )
744 if( !m_parent || !m_joined )
749 m_parent->
send( msg );
762 m_publishNick = publishNick;
775 if( !m_joined || !m_parent )
785 m_historyType = type;
787 m_historyValue = value;
793 m_historySince = since;
806 if( !m_parent || !m_joined )
820 const std::string& reason )
822 if( !m_parent || !m_joined || nick.empty() || role ==
RoleInvalid )
847 m_parent->
send( iq,
this, action );
851 const std::string& reason )
857 switch( affiliation )
879 iq.
addExtension(
new MUCAdmin( affiliation, nick, reason ) );
881 m_parent->
send( iq,
this, action );
886 if( !m_parent || !m_joined || !m_roomConfigHandler )
891 m_parent->
send( iq,
this, operation );
896 if( !m_parent || !m_joined )
901 m_parent->
send( iq,
this, operation );
906 if( ( presence.
from().
bare() != m_nick.
bare() ) || !m_roomHandler )
911 if( m_newNick.empty() )
936 party.
jid = mu->jid() ?
new JID( *(mu->jid()) ) : 0;
937 party.
actor = mu->actor() ?
new JID( *(mu->actor()) ) : 0;
953 m_creationInProgress =
true;
962 && party.
newNick == m_newNick )
978 void MUCRoom::instantRoom(
int context )
980 if( !m_creationInProgress || !m_parent || !m_joined )
985 ? MUCOwner::TypeInstantRoom : MUCOwner::TypeCancelConfig ) );
987 m_parent->
send( iq,
this, context );
989 m_creationInProgress =
false;
994 if( !m_parent || !m_joined )
998 iq.
addExtension(
new MUCOwner( MUCOwner::TypeRequestConfig ) );
1002 if( m_creationInProgress )
1003 m_creationInProgress =
false;
1008 if( !m_parent || !m_joined )
1012 iq.
addExtension(
new MUCOwner( MUCOwner::TypeSendConfig, form ) );
1017 void MUCRoom::setNonAnonymous()
1023 void MUCRoom::setSemiAnonymous()
1029 void MUCRoom::setFullyAnonymous()
1037 if( !m_roomHandler )
1059 m_flags &= ~FlagPublicLogging;
1065 setFullyAnonymous();
1073 if( m_roomConfigHandler && df )
1083 else if( !msg.
body().empty() )
1086 bool privMsg =
false;
1100 if( !m_roomConfigHandler )
1106 handleIqResult( iq, context );
1109 handleIqError( iq, context );
1116 void MUCRoom::handleIqResult(
const IQ& iq,
int context )
1169 void MUCRoom::handleIqError(
const IQ& ,
int context )
1210 int oldflags = m_flags;
1217 StringList::const_iterator it = l.begin();
1218 for( ; it != l.end(); ++it )
1220 if( (*it) ==
"muc_hidden" )
1222 else if( (*it) ==
"muc_membersonly" )
1224 else if( (*it) ==
"muc_moderated" )
1226 else if( (*it) ==
"muc_nonanonymous" )
1228 else if( (*it) ==
"muc_open" )
1230 else if( (*it) ==
"muc_passwordprotected" )
1232 else if( (*it) ==
"muc_persistent" )
1234 else if( (*it) ==
"muc_public" )
1236 else if( (*it) ==
"muc_semianonymous" )
1238 else if( (*it) ==
"muc_temporary" )
1240 else if( (*it) ==
"muc_fullyanonymous" )
1241 setFullyAnonymous();
1242 else if( (*it) ==
"muc_unmoderated" )
1244 else if( (*it) ==
"muc_unsecured" )
1250 name = il.front()->name();
1263 if( !m_roomHandler )
1280 if( !m_roomHandler )
1302 const std::string& )
1308 const std::string& node )
virtual void handleMUCRequest(MUCRoom *room, const DataForm &form)=0
MUCUserOperation operation() const
const TagList & children() const
An abstraction of a MUC user query.
void setNick(const std::string &nick)
void addHistory(const std::string &message, const JID &from, const std::string &stamp)
An abstraction of a Disco query element (from Service Discovery, XEP-0030) in the disco::items namesp...
StanzaError error() const
bool setXmlns(const std::string &xmlns, const std::string &prefix=EmptyString)
const std::string subject(const std::string &lang="default") const
bool setResource(const std::string &resource)
const std::string XMLNS_MUC_REQUEST
void setRole(const std::string &nick, MUCRoomRole role, const std::string &reason=EmptyString)
std::list< Item * > ItemList
virtual Tag * tag() const
const ItemList & items() const
void removeIDHandler(IqHandler *ih)
An abstraction of a message session between any two entities.
This interface enables inheriting classes to be notified about certain events in a MUC room...
virtual void handleMUCInviteDecline(MUCRoom *room, const JID &invitee, const std::string &reason)=0
An abstraction of a MUC query.
std::list< std::string > StringList
void setSubject(const std::string &subject)
void invite(const JID &invitee, const std::string &reason, const std::string &thread=EmptyString)
const IdentityList & identities() const
An abstraction of an IQ stanza.
void getDiscoItems(const JID &to, const std::string &node, DiscoHandler *dh, int context, const std::string &tid=EmptyString)
void addExtension(const StanzaExtension *se)
void removeDiscoHandler(DiscoHandler *dh)
This is an implementation of XEP-0203 (Delayed Delivery).
std::list< Identity * > IdentityList
static Message * declineInvitation(const JID &room, const JID &invitor, const std::string &reason=EmptyString)
virtual void handleMUCSubject(MUCRoom *room, const std::string &nick, const std::string &subject)=0
virtual void handleMUCMessage(MUCRoom *room, const Message &msg, bool priv)=0
virtual bool handleMUCRoomCreation(MUCRoom *room)=0
void registerStanzaExtension(StanzaExtension *ext)
virtual Tag * tag() const
virtual void handleMUCConfigResult(MUCRoom *room, bool success, MUCOperation operation)=0
MessageType subtype() const
std::list< Tag * > TagList
void removeNodeHandler(DiscoNodeHandler *nh, const std::string &node)
void registerMessageHandler(MessageHandler *mh)
void storeList(const MUCListItemList items, MUCOperation operation)
MUCRoomAffiliation affiliation() const
void send(const std::string &message)
virtual void handleDiscoError(const JID &from, const Error *error, int context)
A stanza error abstraction implemented as a StanzaExtension.
An abstraction of a presence stanza.
This is a MessageSession, adapted to be used in a MUC context.
const std::string nick() const
const std::string * alternate() const
virtual void handleMUCError(MUCRoom *room, StanzaError error)=0
virtual void handleMUCItems(MUCRoom *room, const Disco::ItemList &items)=0
virtual void handleDiscoItems(const JID &from, const Disco::Items &items, int context)
virtual Disco::ItemList handleDiscoNodeItems(const JID &from, const JID &to, const std::string &node=EmptyString)
const std::string XMLNS_X_DATA
virtual void handleMessage(const Message &msg, MessageSession *session=0)
An abstraction of a message stanza.
const std::string status(const std::string &lang="default") const
void registerNodeHandler(DiscoNodeHandler *nh, const std::string &node)
virtual void setSubject(const std::string &subject)
void setPublish(bool publish, bool publishNick)
void setRoomConfig(DataForm *form)
void setRequestHistory(int value, HistoryRequestType type)
virtual const std::string & filterString() const
const std::string & bare() const
const std::string XMLNS_MUC_ADMIN
std::list< MUCListItem > MUCListItemList
static Message * createDataForm(const JID &room, const DataForm *df)
const std::string XMLNS_MUC_USER
The namespace for the gloox library.
This class abstracts a stanza extension, which is usually an element in a specific namespace...
const std::string & stamp() const
const std::string & xmlns() const
const StringList & features() const
virtual void join(Presence::PresenceType type=Presence::Available, const std::string &status=EmptyString, int priority=0)
virtual Disco * disco() const
const std::string & findAttribute(const std::string &name) const
MUC(const std::string &password, HistoryRequestType historyType=HistoryUnknown, const std::string &historySince=EmptyString, int historyValue=0)
virtual void send(const std::string &message)
virtual Disco::IdentityList handleDiscoNodeIdentities(const JID &from, const std::string &node)
virtual const std::string & filterString() const
virtual void handleMUCConfigForm(MUCRoom *room, const DataForm &form)=0
const std::string cdata() const
void disposeMessageSession(MessageSession *session)
MUCUser(MUCUserOperation operation, const std::string &to, const std::string &reason, const std::string &thread=EmptyString)
void setAffiliation(const std::string &nick, MUCRoomAffiliation affiliation, const std::string &reason)
void removePresenceHandler(PresenceHandler *ph)
MUCRoom(ClientBase *parent, const JID &nick, MUCRoomHandler *mrh, MUCRoomConfigHandler *mrch=0)
bool addAttribute(Attribute *attr)
PresenceType subtype() const
An abstraction of a Disco Info element (from Service Discovery, XEP-0030) as a StanzaExtension.
void requestList(MUCOperation operation)
const std::string & resource() const
const DataForm * form() const
const std::string & name() const
void registerPresenceHandler(PresenceHandler *ph)
virtual void handleMUCParticipantPresence(MUCRoom *room, const MUCRoomParticipant participant, const Presence &presence)=0
An abstraction of a Disco item (Service Discovery, XEP-0030).
virtual void handlePresence(const Presence &presence)
void getDiscoInfo(const JID &to, const std::string &node, DiscoHandler *dh, int context, const std::string &tid=EmptyString)
const std::string getID()
const Error * error() const
void acknowledgeInstantRoom()
const std::string XMLNS_MUC_ROOMS
const std::string name() const
const std::string & full() const
const std::string XMLNS_MUC_OWNER
virtual void handleIqID(const IQ &iq, int context)
const DelayedDelivery * when() const
void destroy(const std::string &reason=EmptyString, const JID &alternate=JID(), const std::string &password=EmptyString)
virtual bool instantRoomHook() const
virtual void handleDiscoInfo(const JID &from, const Disco::Info &info, int context)
const char * historyTypeValues[]
void leave(const std::string &msg=EmptyString)
Tag * findChild(const std::string &name) const
virtual void handleMUCConfigList(MUCRoom *room, const MUCListItemList &items, MUCOperation operation)=0
virtual void handleMUCInfo(MUCRoom *room, int features, const std::string &name, const DataForm *infoForm)=0
const std::string EmptyString
MUCRoomAffiliation affiliation
const std::string body(const std::string &lang="default") const
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
const StanzaExtension * findExtension(int type) const
This is an abstraction of an XML element.
void setPresence(Presence::PresenceType presence, const std::string &msg=EmptyString)
virtual StringList handleDiscoNodeFeatures(const JID &from, const std::string &node)
const std::string XMLNS_MUC
An abstract interface that can be implemented for MUC room configuration.