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