00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "mucroom.h"
00016 #include "clientbase.h"
00017 #include "dataform.h"
00018 #include "stanza.h"
00019 #include "disco.h"
00020 #include "mucmessagesession.h"
00021
00022 namespace gloox
00023 {
00024
00025 MUCRoom::MUCRoom( ClientBase *parent, const JID& nick, MUCRoomHandler *mrh,
00026 MUCRoomConfigHandler *mrch )
00027 : m_parent( parent ), m_nick( nick ), m_joined( false ), m_roomHandler( mrh ),
00028 m_roomConfigHandler( mrch ), m_affiliation( AffiliationNone ), m_role( RoleNone ),
00029 m_historyType( HistoryUnknown ), m_historyValue( 0 ), m_flags( 0 ),
00030 m_creationInProgress( false ), m_configChanged( false ),
00031 m_publishNick( false ), m_publish( false ), m_unique( false )
00032 {
00033 }
00034
00035 MUCRoom::~MUCRoom()
00036 {
00037 if( m_joined )
00038 leave();
00039
00040 if( m_parent && m_publish )
00041 m_parent->disco()->removeNodeHandler( this, XMLNS_MUC_ROOMS );
00042 }
00043
00044 void MUCRoom::join()
00045 {
00046 if( m_joined || !m_parent )
00047 return;
00048
00049 m_parent->registerPresenceHandler( m_nick.bareJID(), this );
00050
00051 m_session = new MUCMessageSession( m_parent, m_nick.bareJID() );
00052 m_session->registerMessageHandler( this );
00053
00054 Stanza *s = Stanza::createPresenceStanza( m_nick );
00055 Tag *x = new Tag( s, "x" );
00056 x->addAttribute( "xmlns", XMLNS_MUC );
00057 if( !m_password.empty() )
00058 new Tag( x, "password", m_password );
00059 if( m_historyType != HistoryUnknown )
00060 {
00061 switch( m_historyType )
00062 {
00063 case HistoryMaxChars:
00064 {
00065 Tag *h = new Tag( x, "history" );
00066 h->addAttribute( "maxchars", m_historyValue );
00067 break;
00068 }
00069 case HistoryMaxStanzas:
00070 {
00071 Tag *h = new Tag( x, "history" );
00072 h->addAttribute( "maxstanzas", m_historyValue );
00073 break;
00074 }
00075 case HistorySeconds:
00076 {
00077 Tag *h = new Tag( x, "history" );
00078 h->addAttribute( "seconds", m_historyValue );
00079 break;
00080 }
00081 case HistorySince:
00082 {
00083 Tag *h = new Tag( x, "history" );
00084 h->addAttribute( "since", m_historySince );
00085 break;
00086 }
00087 default:
00088 break;
00089 }
00090 }
00091
00092 if( m_parent )
00093 m_parent->send( s );
00094
00095 m_joined = true;
00096 }
00097
00098 void MUCRoom::leave( const std::string& msg )
00099 {
00100 if( !m_joined )
00101 return;
00102
00103 Stanza *s = Stanza::createPresenceStanza( m_nick, msg, PresenceUnavailable );
00104 Tag *x = new Tag( s, "x" );
00105 x->addAttribute( "xmlns", XMLNS_MUC );
00106
00107 if( m_parent )
00108 m_parent->send( s );
00109
00110 m_parent->removePresenceHandler( m_nick.bareJID(), this );
00111 m_parent->disposeMessageSession( m_session );
00112 m_session = 0;
00113
00114 m_joined = false;
00115 }
00116
00117 void MUCRoom::destroy( const std::string& reason, const JID* alternate, const std::string& password )
00118 {
00119 if( !m_parent || !m_joined )
00120 return;
00121
00122 Tag *d = new Tag( "destroy" );
00123 if( alternate )
00124 d->addAttribute( "jid", alternate->bare() );
00125
00126 if( !reason.empty() )
00127 new Tag( d, "reason", reason );
00128
00129 if( !password.empty() )
00130 new Tag( d, "password", password );
00131
00132 const std::string& id = m_parent->getID();
00133
00134 JID j( m_nick.bare() );
00135 Stanza *iq = Stanza::createIqStanza( j, id, StanzaIqSet, XMLNS_MUC_OWNER, d );
00136
00137 m_parent->trackID( this, id, DestroyRoom );
00138 m_parent->send( iq );
00139 }
00140
00141 void MUCRoom::send( const std::string& message )
00142 {
00143 if( m_session && m_joined )
00144 m_session->send( message );
00145 }
00146
00147 void MUCRoom::setSubject( const std::string& subject )
00148 {
00149 if( m_session && m_joined )
00150 m_session->setSubject( subject );
00151 }
00152
00153 void MUCRoom::setNick( const std::string& nick )
00154 {
00155 if( m_parent && m_joined )
00156 {
00157 m_newNick = nick;
00158
00159 Tag *p = new Tag( "presence" );
00160 p->addAttribute( "to", m_nick.bare() + "/" + m_newNick );
00161 m_parent->send( p );
00162 }
00163 else
00164 m_nick.setResource( nick );
00165 }
00166
00167 void MUCRoom::getRoomInfo()
00168 {
00169 if( m_parent )
00170 {
00171 JID j( m_nick.bare() );
00172 m_parent->disco()->getDiscoInfo( j, "", this, GetRoomInfo );
00173 }
00174 }
00175
00176 void MUCRoom::getRoomItems()
00177 {
00178 if( m_parent )
00179 {
00180 JID j( m_nick.bare() );
00181 m_parent->disco()->getDiscoItems( j, "", this, GetRoomItems );
00182 }
00183 }
00184
00185 void MUCRoom::setPresence( Presence presence, const std::string& msg )
00186 {
00187 if( m_parent && presence != PresenceUnavailable && m_joined )
00188 {
00189 Stanza *p = Stanza::createPresenceStanza( m_nick, msg, presence );
00190 m_parent->send( p );
00191 }
00192 }
00193
00194 void MUCRoom::invite( const JID& invitee, const std::string& reason, bool cont )
00195 {
00196 if( !m_parent || !m_joined )
00197 return;
00198
00199 Tag *m = new Tag( "message" );
00200 m->addAttribute( "to", m_nick.bare() );
00201 Tag *x = new Tag( m, "x" );
00202 x->addAttribute( "xmlns", XMLNS_MUC_USER );
00203 Tag *i = new Tag( x, "invite" );
00204 i->addAttribute( "to", invitee.bare() );
00205 if( !reason.empty() )
00206 new Tag( i, "reason", reason );
00207 if( cont )
00208 new Tag( i, "continue" );
00209
00210 m_parent->send( m );
00211 }
00212
00213 Stanza* MUCRoom::declineInvitation( const JID& room, const JID& invitor, const std::string& reason )
00214 {
00215 Stanza *m = new Stanza( "message" );
00216 m->addAttribute( "to", room.bare() );
00217 Tag *x = new Tag( m, "x" );
00218 x->addAttribute( "xmlns", XMLNS_MUC_USER );
00219 Tag *d = new Tag( x, "decline" );
00220 d->addAttribute( "to", invitor.bare() );
00221 if( !reason.empty() )
00222 new Tag( d, "reason", reason );
00223
00224 return m;
00225 }
00226
00227 void MUCRoom::setPublish( bool publish, bool publishNick )
00228 {
00229 m_publish = publish;
00230 m_publishNick = publishNick;
00231
00232 if( !m_parent )
00233 return;
00234
00235 if( m_publish )
00236 m_parent->disco()->registerNodeHandler( this, XMLNS_MUC_ROOMS );
00237 else
00238 m_parent->disco()->removeNodeHandler( this, XMLNS_MUC_ROOMS );
00239 }
00240
00241 void MUCRoom::addHistory( const std::string& message, const JID& from, const std::string& stamp )
00242 {
00243 if( !m_joined || !m_parent )
00244 return;
00245
00246 Tag *m = new Tag( "message" );
00247 m->addAttribute( "to", m_nick.bare() );
00248 new Tag( m, "body", message );
00249 Tag *x = new Tag( m, "x" );
00250 x->addAttribute( "xmlns", XMLNS_X_DELAY );
00251 x->addAttribute( "from", from.full() );
00252 x->addAttribute( "stamp", stamp );
00253
00254 m_parent->send( m );
00255 }
00256
00257 void MUCRoom::setRequestHistory( int value, MUCRoom::HistoryRequestType type )
00258 {
00259 m_historyType = type;
00260 m_historySince = "";
00261 m_historyValue = value;
00262 }
00263
00264 void MUCRoom::setRequestHistory( const std::string& since )
00265 {
00266 m_historyType = HistorySince;
00267 m_historySince = since;
00268 m_historyValue = 0;
00269 }
00270
00271 Stanza* MUCRoom::createDataForm( const JID& room, const DataForm& df )
00272 {
00273 Stanza *m = new Stanza( "message" );
00274 m->addAttribute( "to", room.bare() );
00275 m->addChild( df.tag() );
00276
00277 return m;
00278 }
00279
00280 void MUCRoom::requestVoice()
00281 {
00282 if( !m_parent || !m_joined )
00283 return;
00284
00285 DataForm df( DataForm::FormTypeSubmit );
00286 DataFormField *field = new DataFormField( DataFormField::FieldTypeNone );
00287 field->setName( "FORM_TYPE" );
00288 field->setValue( XMLNS_MUC_REQUEST );
00289 df.addField( field );
00290 field = new DataFormField( DataFormField::FieldTypeTextSingle );
00291 field->setName( "muc#role" );
00292 field->setLabel( "Requested role" );
00293 field->setValue( "participant" );
00294 df.addField( field );
00295
00296 Tag *m = new Tag( "messsage" );
00297 m->addAttribute( "to", m_nick.bare() );
00298 m->addChild( df.tag() );
00299
00300 m_parent->send( m );
00301 }
00302
00303 void MUCRoom::kick( const std::string& nick, const std::string& reason )
00304 {
00305 setRole( nick, RoleNone, reason );
00306 }
00307
00308 void MUCRoom::grantVoice( const std::string& nick, const std::string& reason )
00309 {
00310 setRole( nick, RoleParticipant, reason );
00311 }
00312
00313 void MUCRoom::revokeVoice( const std::string& nick, const std::string& reason )
00314 {
00315 setRole( nick, RoleVisitor, reason );
00316 }
00317
00318 void MUCRoom::ban( const std::string& nick, const std::string& reason )
00319 {
00320 setAffiliation( nick, AffiliationOutcast, reason );
00321 }
00322
00323 void MUCRoom::setRole( const std::string& nick, MUCRoomRole role, const std::string& reason )
00324 {
00325 modifyOccupant( nick, role, "role", reason );
00326 }
00327
00328 void MUCRoom::setAffiliation( const std::string& nick, MUCRoomAffiliation affiliation,
00329 const std::string& reason )
00330 {
00331 modifyOccupant( nick, affiliation, "affiliation", reason );
00332 }
00333
00334 void MUCRoom::modifyOccupant( const std::string& nick, int state, const std::string roa,
00335 const std::string& reason )
00336 {
00337 if( !m_parent || !m_joined || nick.empty() || roa.empty() )
00338 return;
00339
00340 std::string newRoA;
00341 MUCOperation action = SetRNone;
00342 if( roa == "role" )
00343 {
00344 switch( state )
00345 {
00346 case RoleNone:
00347 newRoA = "none";
00348 action = SetRNone;
00349 break;
00350 case RoleVisitor:
00351 newRoA = "visitor";
00352 action = SetVisitor;
00353 break;
00354 case RoleParticipant:
00355 newRoA = "participant";
00356 action = SetParticipant;
00357 break;
00358 case RoleModerator:
00359 newRoA = "moderator";
00360 action = SetModerator;
00361 break;
00362 }
00363 }
00364 else
00365 {
00366 switch( state )
00367 {
00368 case AffiliationOutcast:
00369 newRoA = "outcast";
00370 action = SetOutcast;
00371 break;
00372 case AffiliationNone:
00373 newRoA = "none";
00374 action = SetANone;
00375 break;
00376 case AffiliationMember:
00377 newRoA = "member";
00378 action = SetMember;
00379 break;
00380 case AffiliationAdmin:
00381 newRoA = "admin";
00382 action = SetAdmin;
00383 break;
00384 case AffiliationOwner:
00385 newRoA = "owner";
00386 action = SetOwner;
00387 break;
00388 }
00389 }
00390 Tag *i = new Tag( "item" );
00391 i->addAttribute( "nick", nick );
00392 i->addAttribute( roa, newRoA );
00393 if( !reason.empty() )
00394 new Tag( i, "reason", reason );
00395
00396 const std::string& id = m_parent->getID();
00397 JID j( m_nick.bare() );
00398 Stanza *k = Stanza::createIqStanza( j, id, StanzaIqSet, XMLNS_MUC_ADMIN, i );
00399
00400 m_parent->trackID( this, id, action );
00401 m_parent->send( k );
00402 }
00403
00404 void MUCRoom::requestList( MUCOperation operation )
00405 {
00406 if( !m_parent || !m_joined || !m_roomConfigHandler )
00407 return;
00408
00409 Tag *i = new Tag( "item" );
00410
00411 switch( operation )
00412 {
00413 case RequestVoiceList:
00414 i->addAttribute( "role", "participant" );
00415 break;
00416 case RequestBanList:
00417 i->addAttribute( "affiliation", "outcast" );
00418 break;
00419 case RequestMemberList:
00420 i->addAttribute( "affiliation", "member" );
00421 break;
00422 case RequestModeratorList:
00423 i->addAttribute( "role", "moderator" );
00424 break;
00425 case RequestOwnerList:
00426 i->addAttribute( "affiliation", "owner" );
00427 break;
00428 case RequestAdminList:
00429 i->addAttribute( "affiliation", "admin" );
00430 break;
00431 default:
00432 delete i;
00433 return;
00434 break;
00435 }
00436
00437 const std::string& id = m_parent->getID();
00438 JID j( m_nick.bare() );
00439 Stanza *iq = Stanza::createIqStanza( j, id, StanzaIqGet, XMLNS_MUC_ADMIN, i );
00440
00441 m_parent->trackID( this, id, operation );
00442 m_parent->send( iq );
00443 }
00444
00445 void MUCRoom::storeList( const MUCListItemList items, MUCOperation operation )
00446 {
00447 if( !m_parent || !m_joined )
00448 return;
00449
00450 std::string roa;
00451 std::string value;
00452 switch( operation )
00453 {
00454 case RequestVoiceList:
00455 roa = "role";
00456 value = "participant";
00457 break;
00458 case RequestBanList:
00459 roa = "affiliation";
00460 value = "outcast";
00461 break;
00462 case RequestMemberList:
00463 roa = "affiliation";
00464 value = "member";
00465 break;
00466 case RequestModeratorList:
00467 roa = "role";
00468 value = "moderator";
00469 break;
00470 case RequestOwnerList:
00471 roa = "affiliation";
00472 value = "owner";
00473 break;
00474 case RequestAdminList:
00475 roa = "affiliation";
00476 value = "admin";
00477 break;
00478 default:
00479 return;
00480 break;
00481 }
00482
00483 const std::string& id = m_parent->getID();
00484 Tag *iq = new Tag( "iq" );
00485 iq->addAttribute( "id", id );
00486 iq->addAttribute( "type", "set" );
00487 iq->addAttribute( "to", m_nick.bare() );
00488 Tag *q = new Tag( iq, "query" );
00489 q->addAttribute( "xmlns", XMLNS_MUC_ADMIN );
00490
00491 MUCListItemList::const_iterator it = items.begin();
00492 for( ; it != items.end(); ++it )
00493 {
00494 if( (*it).nick.empty() )
00495 continue;
00496
00497 Tag *i = new Tag( q, "item" );
00498 i->addAttribute( "nick", (*it).nick );
00499 i->addAttribute( roa, value );
00500 if( !(*it).reason.empty() )
00501 new Tag( i, "reason", (*it).reason );
00502 }
00503
00504 m_parent->trackID( this, id, operation );
00505 m_parent->send( iq );
00506 }
00507
00508 void MUCRoom::handlePresence( Stanza *stanza )
00509 {
00510 if( ( stanza->from().bare() != m_nick.bare() ) || !m_roomHandler )
00511 return;
00512
00513 if( stanza->subtype() == StanzaPresenceError )
00514 {
00515 m_joined = false;
00516 m_roomHandler->handleMUCError( this, stanza->error() );
00517 }
00518 else
00519 {
00520 Tag* x = 0;
00521 if( m_roomHandler && ( x = stanza->findChild( "x", "xmlns", XMLNS_MUC_USER ) ) != 0 )
00522 {
00523 MUCRoomParticipant party;
00524 party.flags = 0;
00525 party.nick = new JID( stanza->from() );
00526 party.jid = 0;
00527 party.actor = 0;
00528 party.alternate = 0;
00529 const Tag::TagList& l = x->children();
00530 Tag::TagList::const_iterator it = l.begin();
00531 for( ; it != l.end(); ++it )
00532 {
00533 if( (*it)->name() == "item" )
00534 {
00535 const std::string& affiliation = (*it)->findAttribute( "affiliation" );
00536 if( affiliation == "owner" )
00537 party.affiliation = AffiliationOwner;
00538 else if( affiliation == "admin" )
00539 party.affiliation = AffiliationAdmin;
00540 else if( affiliation == "member" )
00541 party.affiliation = AffiliationMember;
00542 else if( affiliation == "outcast" )
00543 party.affiliation = AffiliationOutcast;
00544 else
00545 party.affiliation = AffiliationNone;
00546
00547 const std::string& role = (*it)->findAttribute( "role" );
00548 if( role == "moderator" )
00549 party.role = RoleModerator;
00550 else if( role == "participant" )
00551 party.role = RoleParticipant;
00552 else if( role == "visitor" )
00553 party.role = RoleVisitor;
00554 else
00555 party.role = RoleNone;
00556
00557 const std::string& jid = (*it)->findAttribute( "jid" );
00558 if( !jid.empty() )
00559 party.jid = new JID( jid );
00560
00561 if( (*it)->hasChild( "actor" ) )
00562 {
00563 const std::string& actor = (*it)->findChild( "actor" )->findAttribute( "jid" );
00564 if( !actor.empty() )
00565 party.actor = new JID( actor );
00566 }
00567 if( (*it)->hasChild( "reason" ) )
00568 {
00569 party.reason = (*it)->findChild( "reason" )->cdata();
00570 }
00571 party.newNick = (*it)->findAttribute( "nick" );
00572 }
00573 else if( (*it)->name() == "status" )
00574 {
00575 const std::string& code = (*it)->findAttribute( "code" );
00576 if( code == "100" )
00577 setNonAnonymous();
00578 else if( code == "101" )
00579 {
00580
00581 }
00582 else if( code == "110" )
00583 {
00584 party.flags |= UserSelf;
00585 m_role = party.role;
00586 m_affiliation = party.affiliation;
00587 }
00588 else if( code == "201" )
00589 {
00590 m_creationInProgress = true;
00591 if( instantRoomHook() || m_roomHandler->handleMUCRoomCreation( this ) )
00592 acknowledgeInstantRoom();
00593 }
00594 else if( code == "210" )
00595 m_nick.setResource( stanza->from().resource() );
00596 else if( code == "301" )
00597 party.flags |= UserBanned;
00598 else if( code == "303" )
00599 party.flags |= UserNickChanged;
00600 else if( code == "307" )
00601 party.flags |= UserKicked;
00602 else if( code == "321" )
00603 party.flags |= UserAffiliationChanged;
00604 }
00605 else if( (*it)->name() == "destroy" )
00606 {
00607 if( (*it)->hasAttribute( "jid" ) )
00608 party.alternate = new JID( (*it)->findAttribute( "jid" ) );
00609
00610 if( (*it)->hasChild( "reason" ) )
00611 party.reason = (*it)->findChild( "reason" )->cdata();
00612
00613 party.flags |= UserRoomDestroyed;
00614 }
00615 }
00616
00617 if( party.flags & UserNickChanged && !party.newNick.empty()
00618 && m_nick.resource() == stanza->from().resource()
00619 && party.newNick == m_newNick )
00620 party.flags |= UserSelf;
00621
00622 if( party.flags & UserNickChanged && party.flags & UserSelf && !party.newNick.empty() )
00623 m_nick.setResource( party.newNick );
00624
00625 party.status = stanza->status();
00626
00627 m_roomHandler->handleMUCParticipantPresence( this, party, stanza->presence() );
00628 delete party.jid;
00629 delete party.nick;
00630 delete party.actor;
00631 delete party.alternate;
00632 }
00633 }
00634 }
00635
00636 void MUCRoom::acknowledgeInstantRoom()
00637 {
00638 if( !m_creationInProgress || !m_parent || !m_joined )
00639 return;
00640
00641 Tag *x = new Tag( "x" );
00642 x->addAttribute( "xmlns", XMLNS_X_DATA );
00643 x->addAttribute( "type", "submit" );
00644
00645 JID j( m_nick.bare() );
00646 const std::string& id = m_parent->getID();
00647 Stanza *iq = Stanza::createIqStanza( j, id, StanzaIqSet, XMLNS_MUC_OWNER, x );
00648
00649 m_parent->trackID( this, id, CreateInstantRoom );
00650 m_parent->send( iq );
00651
00652 m_creationInProgress = false;
00653 }
00654
00655 void MUCRoom::cancelRoomCreation()
00656 {
00657 if( !m_creationInProgress || !m_parent || !m_joined )
00658 return;
00659
00660 Tag *x = new Tag( "x" );
00661 x->addAttribute( "xmlns", XMLNS_X_DATA );
00662 x->addAttribute( "type", "cancel" );
00663
00664 JID j( m_nick.bare() );
00665 const std::string& id = m_parent->getID();
00666 Stanza *iq = Stanza::createIqStanza( j, id, StanzaIqSet, XMLNS_MUC_OWNER, x );
00667
00668 m_parent->trackID( this, id, CancelRoomCreation );
00669 m_parent->send( iq );
00670
00671 m_creationInProgress = false;
00672 }
00673
00674 void MUCRoom::requestRoomConfig()
00675 {
00676 if( !m_parent || !m_joined )
00677 return;
00678
00679 JID j( m_nick.bare() );
00680 const std::string& id = m_parent->getID();
00681 Stanza *iq = Stanza::createIqStanza( j, id, StanzaIqGet, XMLNS_MUC_OWNER, 0 );
00682
00683 m_parent->trackID( this, id, RequestRoomConfig );
00684 m_parent->send( iq );
00685
00686 if( m_creationInProgress )
00687 m_creationInProgress = false;
00688 }
00689
00690 void MUCRoom::setNonAnonymous()
00691 {
00692 m_flags |= FlagNonAnonymous;
00693 m_flags ^= FlagSemiAnonymous;
00694 m_flags ^= FlagFullyAnonymous;
00695 }
00696
00697 void MUCRoom::setSemiAnonymous()
00698 {
00699 m_flags ^= FlagNonAnonymous;
00700 m_flags |= FlagSemiAnonymous;
00701 m_flags ^= FlagFullyAnonymous;
00702 }
00703
00704 void MUCRoom::setFullyAnonymous()
00705 {
00706 m_flags ^= FlagNonAnonymous;
00707 m_flags ^= FlagSemiAnonymous;
00708 m_flags |= FlagFullyAnonymous;
00709 }
00710
00711 void MUCRoom::handleMessage( Stanza *stanza, MessageSession * )
00712 {
00713 if( !m_roomHandler )
00714 return;
00715
00716 if( stanza->subtype() == StanzaMessageError )
00717 {
00718 m_roomHandler->handleMUCError( this, stanza->error() );
00719 }
00720 else
00721 {
00722 Tag *x;
00723 if( ( x = stanza->findChild( "x", "xmlns", XMLNS_MUC_USER ) ) != 0 )
00724 {
00725 const Tag::TagList& l = x->children();
00726 Tag::TagList::const_iterator it = l.begin();
00727 for( ; it != l.end(); ++it )
00728 {
00729 if( (*it)->name() == "status" )
00730 {
00731 const std::string& code = (*it)->findAttribute( "code" );
00732 if( code == "100" )
00733 {
00734 setNonAnonymous();
00735 }
00736 else if( code == "104" )
00737 (void)true;
00738 else if( code == "170" )
00739 m_flags |= FlagPublicLogging;
00740 else if( code == "171" )
00741 m_flags ^= FlagPublicLogging;
00742 else if( code == "172" )
00743 {
00744 setNonAnonymous();
00745 }
00746 else if( code == "173" )
00747 {
00748 setSemiAnonymous();
00749 }
00750 else if( code == "174" )
00751 {
00752 setFullyAnonymous();
00753 }
00754 }
00755 else if( (*it)->name() == "decline" )
00756 {
00757 std::string reason;
00758 JID invitee( (*it)->findAttribute( "from" ) );
00759 if( (*it)->hasChild( "reason" ) )
00760 reason = (*it)->findChild( "reason" )->cdata();
00761 m_roomHandler->handleMUCInviteDecline( this, invitee, reason );
00762 return;
00763 }
00764
00765 }
00766 }
00767 else if( m_roomConfigHandler && ( x = stanza->findChild( "x", "xmlns", XMLNS_X_DATA ) ) != 0 )
00768 {
00769 DataForm df( x );
00770 m_roomConfigHandler->handleMUCRequest( this, df );
00771 return;
00772 }
00773
00774 if( !stanza->subject().empty() )
00775 {
00776 m_roomHandler->handleMUCSubject( this, stanza->from().resource(), stanza->subject() );
00777 }
00778 else if( !stanza->body().empty() )
00779 {
00780 JID from;
00781 std::string when;
00782 bool privMsg = false;
00783 bool history = false;
00784 if( ( x = stanza->findChild( "x", "xmlns", XMLNS_X_DELAY ) ) != 0 )
00785 {
00786 from.setJID( x->findAttribute( "from" ) );
00787 when = x->findAttribute( "when" );
00788 history = true;
00789 }
00790 if( stanza->subtype() == StanzaMessageChat ||
00791 stanza->subtype() == StanzaMessageNormal )
00792 privMsg = true;
00793
00794 m_roomHandler->handleMUCMessage( this, stanza->from().resource(), stanza->body(),
00795 history, when, privMsg );
00796 }
00797 }
00798 }
00799
00800 bool MUCRoom::handleIqID( Stanza *stanza, int context )
00801 {
00802 if( !m_roomConfigHandler )
00803 return false;
00804
00805 switch( stanza->subtype() )
00806 {
00807 case StanzaIqResult:
00808 return handleIqResult( stanza, context );
00809 break;
00810 case StanzaIqError:
00811 return handleIqError( stanza, context );
00812 break;
00813 default:
00814 break;
00815 }
00816
00817 return false;
00818 }
00819
00820 bool MUCRoom::handleIqResult( Stanza *stanza, int context )
00821 {
00822 switch( context )
00823 {
00824 case SetRNone:
00825 case SetVisitor:
00826 case SetParticipant:
00827 case SetModerator:
00828 case SetANone:
00829 case SetOutcast:
00830 case SetMember:
00831 case SetAdmin:
00832 case SetOwner:
00833 case CreateInstantRoom:
00834 case CancelRoomCreation:
00835 case DestroyRoom:
00836 case StoreVoiceList:
00837 case StoreBanList:
00838 case StoreMemberList:
00839 case StoreModeratorList:
00840 case StoreAdminList:
00841 m_roomConfigHandler->handleMUCConfigResult( this, true, (MUCOperation)context );
00842 return true;
00843 break;
00844 case RequestRoomConfig:
00845 {
00846 Tag *x = 0;
00847 Tag *q = stanza->findChild( "query", "xmlns", XMLNS_MUC_OWNER );
00848 if( q )
00849 x = q->findChild( "x", "xmlns", XMLNS_X_DATA );
00850 if( x )
00851 {
00852 DataForm df( x );
00853 m_roomConfigHandler->handleMUCConfigForm( this, df );
00854 }
00855 return true;
00856 break;
00857 }
00858 case RequestVoiceList:
00859 case RequestBanList:
00860 case RequestMemberList:
00861 case RequestModeratorList:
00862 case RequestOwnerList:
00863 case RequestAdminList:
00864 {
00865 Tag *x = 0;
00866 Tag *q = stanza->findChild( "query", "xmlns", XMLNS_MUC_OWNER );
00867 if( q )
00868 x = q->findChild( "x", "xmlns", XMLNS_X_DATA );
00869 if( x )
00870 {
00871 MUCListItemList itemList;
00872 const Tag::TagList& items = x->findChildren( "item" );
00873 Tag::TagList::const_iterator it = items.begin();
00874 for( ; it != items.end(); ++it )
00875 {
00876 MUCListItem item;
00877 item.jid = 0;
00878 item.role = getEnumRole( (*it)->findAttribute( "role" ) );
00879 item.affiliation = getEnumAffiliation( (*it)->findAttribute( "affiliation" ) );
00880 if( (*it)->hasAttribute( "jid" ) )
00881 item.jid = new JID( (*it)->findAttribute( "jid" ) );
00882 item.nick = (*it)->findAttribute( "nick" );
00883 itemList.push_back( item );
00884 }
00885 m_roomConfigHandler->handleMUCConfigList( this, itemList, (MUCOperation)context );
00886
00887 MUCListItemList::iterator itl = itemList.begin();
00888 for( ; itl != itemList.end(); ++itl )
00889 delete (*itl).jid;
00890 }
00891 return true;
00892 break;
00893 }
00894 default:
00895 break;
00896 }
00897 return false;
00898 }
00899
00900 bool MUCRoom::handleIqError( Stanza * , int context )
00901 {
00902 switch( context )
00903 {
00904 case SetRNone:
00905 case SetVisitor:
00906 case SetParticipant:
00907 case SetModerator:
00908 case SetANone:
00909 case SetOutcast:
00910 case SetMember:
00911 case SetAdmin:
00912 case SetOwner:
00913 case CreateInstantRoom:
00914 case CancelRoomCreation:
00915 case RequestRoomConfig:
00916 case DestroyRoom:
00917 case RequestVoiceList:
00918 case StoreVoiceList:
00919 case RequestBanList:
00920 case StoreBanList:
00921 case RequestMemberList:
00922 case StoreMemberList:
00923 case RequestModeratorList:
00924 case StoreModeratorList:
00925 case RequestOwnerList:
00926 case StoreOwnerList:
00927 case RequestAdminList:
00928 case StoreAdminList:
00929 m_roomConfigHandler->handleMUCConfigResult( this, false, (MUCOperation)context );
00930 break;
00931 }
00932 return false;
00933 }
00934
00935 void MUCRoom::handleDiscoInfoResult( Stanza *stanza, int context )
00936 {
00937 switch( context )
00938 {
00939 case GetRoomInfo:
00940 {
00941 int oldflags = m_flags;
00942 m_flags = 0;
00943 if( oldflags & FlagPublicLogging )
00944 m_flags |= FlagPublicLogging;
00945
00946 std::string name;
00947 DataForm *df = 0;
00948 Tag *q = stanza->findChild( "query" );
00949 if( q )
00950 {
00951 const Tag::TagList& l = q->children();
00952 Tag::TagList::const_iterator it = l.begin();
00953 for( ; it != l.end(); ++it )
00954 {
00955 if( (*it)->name() == "feature" )
00956 {
00957 if( (*it)->findAttribute( "var" ) == "muc_hidden" )
00958 m_flags |= FlagHidden;
00959 else if( (*it)->findAttribute( "var" ) == "muc_membersonly" )
00960 m_flags |= FlagMembersOnly;
00961 else if( (*it)->findAttribute( "var" ) == "muc_moderated" )
00962 m_flags |= FlagModerated;
00963 else if( (*it)->findAttribute( "var" ) == "muc_nonanonymous" )
00964 setNonAnonymous();
00965 else if( (*it)->findAttribute( "var" ) == "muc_open" )
00966 m_flags |= FlagOpen;
00967 else if( (*it)->findAttribute( "var" ) == "muc_passwordprotected" )
00968 m_flags |= FlagPasswordProtected;
00969 else if( (*it)->findAttribute( "var" ) == "muc_persistent" )
00970 m_flags |= FlagPersistent;
00971 else if( (*it)->findAttribute( "var" ) == "muc_public" )
00972 m_flags |= FlagPublic;
00973 else if( (*it)->findAttribute( "var" ) == "muc_semianonymous" )
00974 setSemiAnonymous();
00975 else if( (*it)->findAttribute( "var" ) == "muc_temporary" )
00976 m_flags |= FlagTemporary;
00977 else if( (*it)->findAttribute( "var" ) == "muc_fullyanonymous" )
00978 setFullyAnonymous();
00979 else if( (*it)->findAttribute( "var" ) == "muc_unmoderated" )
00980 m_flags |= FlagUnmoderated;
00981 else if( (*it)->findAttribute( "var" ) == "muc_unsecured" )
00982 m_flags |= FlagUnsecured;
00983 }
00984 else if( (*it)->name() == "identity" )
00985 {
00986 name = (*it)->findAttribute( "name" );
00987 }
00988 else if( (*it)->name() == "x" && (*it)->hasAttribute( "xmlns", XMLNS_X_DATA ) )
00989 {
00990 df = new DataForm( (*it) );
00991 }
00992 }
00993 }
00994 if( m_roomHandler )
00995 m_roomHandler->handleMUCInfo( this, m_flags, name, df );
00996 break;
00997 }
00998 default:
00999 break;
01000 }
01001 }
01002
01003 void MUCRoom::handleDiscoItemsResult( Stanza *stanza, int context )
01004 {
01005 if( !m_roomHandler )
01006 return;
01007
01008 switch( context )
01009 {
01010 case GetRoomItems:
01011 {
01012 Tag *q = stanza->findChild( "query" );
01013 if( q )
01014 {
01015 StringMap items;
01016 const Tag::TagList& l = q->children();
01017 Tag::TagList::const_iterator it = l.begin();
01018 for( ; it != l.end(); ++it )
01019 {
01020 if( (*it)->name() == "item" && (*it)->hasAttribute( "jid" ) )
01021 {
01022 items[(*it)->findAttribute( "name" )] = (*it)->findAttribute( "jid" );
01023 }
01024 }
01025 m_roomHandler->handleMUCItems( this, items );
01026 }
01027 break;
01028 }
01029 default:
01030 break;
01031 }
01032 }
01033
01034 void MUCRoom::handleDiscoError( Stanza * , int context )
01035 {
01036 if( !m_roomHandler )
01037 return;
01038
01039 switch( context )
01040 {
01041 case GetRoomInfo:
01042 m_roomHandler->handleMUCInfo( this, 0, "", 0 );
01043 break;
01044 case GetRoomItems:
01045 {
01046 StringMap items;
01047 m_roomHandler->handleMUCItems( this, items );
01048 break;
01049 }
01050 default:
01051 break;
01052 }
01053 }
01054
01055 StringList MUCRoom::handleDiscoNodeFeatures( const std::string& )
01056 {
01057 return StringList();
01058 }
01059
01060 StringMap MUCRoom::handleDiscoNodeIdentities( const std::string& , std::string& )
01061 {
01062 return StringMap();
01063 }
01064
01065 DiscoNodeItemList MUCRoom::handleDiscoNodeItems( const std::string& node )
01066 {
01067 DiscoNodeItemList l;
01068
01069 if( node != XMLNS_MUC_ROOMS )
01070 return l;
01071
01072 if( m_publish )
01073 {
01074 DiscoNodeItem item;
01075 item.jid = m_nick.bare();
01076 if( m_publishNick )
01077 item.name = m_nick.resource();
01078 l.push_back( item );
01079 }
01080 return l;
01081 }
01082
01083 MUCRoomRole MUCRoom::getEnumRole( const std::string& role )
01084 {
01085 if( role == "moderator" )
01086 return RoleModerator;
01087 if( role == "participant" )
01088 return RoleParticipant;
01089 if( role == "visitor" )
01090 return RoleVisitor;
01091 return RoleNone;
01092 }
01093
01094 MUCRoomAffiliation MUCRoom::getEnumAffiliation( const std::string& affiliation )
01095 {
01096 if( affiliation == "owner" )
01097 return AffiliationOwner;
01098 if( affiliation == "admin" )
01099 return AffiliationAdmin;
01100 if( affiliation == "member" )
01101 return AffiliationMember;
01102 if( affiliation == "outcast" )
01103 return AffiliationOutcast;
01104 return AffiliationNone;
01105 }
01106
01107 }