mucroom.cpp

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

Generated on Sat Nov 10 08:50:27 2007 for gloox by  doxygen 1.5.3-20071008