Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

mucroom.cpp

00001 /*
00002   Copyright (c) 2006-2008 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
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               // affiliation changed while not in the room. not to be handled here, I guess
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 * /*session*/ )
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               /*m_configChanged =*/ (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           // call some handler?
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 * /*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 * /*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& /*node*/ )
01089   {
01090     return StringList();
01091   }
01092 
01093   StringMap MUCRoom::handleDiscoNodeIdentities( const std::string& /*node*/, std::string& /*name*/ )
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 }

Generated on Sat Oct 31 19:56:15 2009 for gloox by  doxygen 1.4.1