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 +
"']";
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 );
904 void MUCRoom::handlePresence(
const Presence& presence )
906 if( ( presence.
from().
bare() != m_nick.
bare() ) || !m_roomHandler )
911 if( m_newNick.empty() )
931 MUCRoomParticipant party;
932 party.nick =
new JID( presence.
from() );
933 party.status = presence.
status();
934 party.affiliation = mu->affiliation();
935 party.role = mu->role();
936 party.jid = mu->jid() ?
new JID( *(mu->jid()) ) : 0;
937 party.actor = mu->actor() ?
new JID( *(mu->actor()) ) : 0;
938 party.reason = mu->reason() ? *(mu->reason()) :
EmptyString;
939 party.newNick = mu->newNick() ? *(mu->newNick()) :
EmptyString;
940 party.alternate = mu->alternate() ?
new JID( *(mu->alternate()) ) : 0;
941 party.flags = mu->flags();
949 m_affiliation = party.affiliation;
953 m_creationInProgress =
true;
962 && party.newNick == m_newNick )
974 delete party.alternate;
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()
1035 void MUCRoom::handleMessage(
const Message& msg, MessageSession* )
1037 if( !m_roomHandler )
1046 const MUCUser* mu = msg.findExtension<MUCUser>(
ExtMUCUser );
1049 const int flags = mu->flags();
1059 m_flags &= ~FlagPublicLogging;
1065 setFullyAnonymous();
1072 const DataForm* df = msg.findExtension<DataForm>(
ExtDataForm );
1073 if( m_roomConfigHandler && df )
1079 if( !msg.subject().empty() )
1081 m_roomHandler->
handleMUCSubject(
this, msg.from().resource(), msg.subject() );
1083 else if( !msg.body().empty() )
1086 bool privMsg =
false;
1087 bool history =
false;
1090 when = msg.when()->stamp();
1101 void MUCRoom::handleIqID(
const IQ& iq,
int context )
1103 if( !m_roomConfigHandler )
1106 switch( iq.subtype() )
1109 handleIqResult( iq, context );
1112 handleIqError( iq, context );
1119 void MUCRoom::handleIqResult(
const IQ& iq,
int context )
1144 const MUCOwner* mo = iq.findExtension<MUCOwner>(
ExtMUCOwner );
1159 const MUCAdmin* ma = iq.findExtension<MUCAdmin>(
ExtMUCAdmin );
1171 void MUCRoom::handleIqError(
const IQ& ,
int context )
1205 void MUCRoom::handleDiscoInfo(
const JID& ,
const Disco::Info& info,
int context )
1211 int oldflags = m_flags;
1213 if( oldflags & FlagPublicLogging )
1218 StringList::const_iterator it = l.begin();
1219 for( ; it != l.end(); ++it )
1221 if( (*it) ==
"muc_hidden" )
1223 else if( (*it) ==
"muc_membersonly" )
1225 else if( (*it) ==
"muc_moderated" )
1227 else if( (*it) ==
"muc_nonanonymous" )
1229 else if( (*it) ==
"muc_open" )
1231 else if( (*it) ==
"muc_passwordprotected" )
1233 else if( (*it) ==
"muc_persistent" )
1235 else if( (*it) ==
"muc_public" )
1237 else if( (*it) ==
"muc_semianonymous" )
1239 else if( (*it) ==
"muc_temporary" )
1241 else if( (*it) ==
"muc_fullyanonymous" )
1242 setFullyAnonymous();
1243 else if( (*it) ==
"muc_unmoderated" )
1245 else if( (*it) ==
"muc_unsecured" )
1251 name = il.front()->name();
1254 m_roomHandler->
handleMUCInfo(
this, m_flags, name, info.form() );
1262 void MUCRoom::handleDiscoItems(
const JID& ,
const Disco::Items& items,
int context )
1264 if( !m_roomHandler )
1279 void MUCRoom::handleDiscoError(
const JID& ,
const Error* ,
int context )
1281 if( !m_roomHandler )
1297 StringList MUCRoom::handleDiscoNodeFeatures(
const JID& ,
const std::string& )
1303 const std::string& )
1308 Disco::ItemList MUCRoom::handleDiscoNodeItems(
const JID& ,
const JID& ,
1309 const std::string& node )