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

Generated on Fri Oct 10 15:26:11 2008 for gloox by  doxygen 1.5.6