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