gloox  0.9.9.12
mucroom.cpp
1 /*
2  Copyright (c) 2006-2008 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 
15 #include "mucroom.h"
16 #include "clientbase.h"
17 #include "dataform.h"
18 #include "stanza.h"
19 #include "disco.h"
20 #include "mucmessagesession.h"
21 
22 namespace gloox
23 {
24 
25  MUCRoom::MUCRoom( ClientBase *parent, const JID& nick, MUCRoomHandler *mrh,
26  MUCRoomConfigHandler *mrch )
27  : m_parent( parent ), m_nick( nick ), m_joined( false ), m_roomHandler( mrh ),
28  m_roomConfigHandler( mrch ), m_affiliation( AffiliationNone ), m_role( RoleNone ),
29  m_historyType( HistoryUnknown ), m_historyValue( 0 ), m_flags( 0 ),
30  m_creationInProgress( false ), m_configChanged( false ),
31  m_publishNick( false ), m_publish( false ), m_unique( false )
32  {
33  }
34 
36  {
37  if( m_joined )
38  leave();
39 
40  if( m_parent )
41  {
42  if(m_publish )
43  m_parent->disco()->removeNodeHandler( this, XMLNS_MUC_ROOMS );
44 
45  m_parent->removeIDHandler( this );
46  m_parent->removePresenceHandler( m_nick.bareJID(), this );
47  m_parent->disco()->removeDiscoHandler( this );
48  }
49  }
50 
52  {
53  if( m_joined || !m_parent )
54  return;
55 
56  m_parent->registerPresenceHandler( m_nick.bareJID(), this );
57 
58  m_session = new MUCMessageSession( m_parent, m_nick.bareJID() );
59  m_session->registerMessageHandler( this );
60 
61  Stanza *s = Stanza::createPresenceStanza( m_nick );
62  Tag *x = new Tag( s, "x" );
63  x->addAttribute( "xmlns", XMLNS_MUC );
64  if( !m_password.empty() )
65  new Tag( x, "password", m_password );
66  if( m_historyType != HistoryUnknown )
67  {
68  switch( m_historyType )
69  {
70  case HistoryMaxChars:
71  {
72  Tag *h = new Tag( x, "history" );
73  h->addAttribute( "maxchars", m_historyValue );
74  break;
75  }
76  case HistoryMaxStanzas:
77  {
78  Tag *h = new Tag( x, "history" );
79  h->addAttribute( "maxstanzas", m_historyValue );
80  break;
81  }
82  case HistorySeconds:
83  {
84  Tag *h = new Tag( x, "history" );
85  h->addAttribute( "seconds", m_historyValue );
86  break;
87  }
88  case HistorySince:
89  {
90  Tag *h = new Tag( x, "history" );
91  h->addAttribute( "since", m_historySince );
92  break;
93  }
94  default:
95  break;
96  }
97  }
98 
99  if( m_parent )
100  m_parent->send( s );
101 
102  m_joined = true;
103  }
104 
105  void MUCRoom::leave( const std::string& msg )
106  {
107  if( !m_joined )
108  return;
109 
111  Tag *x = new Tag( s, "x" );
112  x->addAttribute( "xmlns", XMLNS_MUC );
113 
114  if( m_parent )
115  {
116  m_parent->send( s );
117 
118  m_parent->removePresenceHandler( m_nick.bareJID(), this );
119  m_parent->disposeMessageSession( m_session );
120  m_session = 0;
121  }
122 
123  m_joined = false;
124  }
125 
126  void MUCRoom::destroy( const std::string& reason, const JID* alternate, const std::string& password )
127  {
128  if( !m_parent )
129  return;
130 
131  Tag *d = new Tag( "destroy" );
132  if( alternate )
133  d->addAttribute( "jid", alternate->bare() );
134 
135  if( !reason.empty() )
136  new Tag( d, "reason", reason );
137 
138  if( !password.empty() )
139  new Tag( d, "password", password );
140 
141  const std::string& id = m_parent->getID();
142 
143  JID j( m_nick.bare() );
145 
146  m_parent->trackID( this, id, DestroyRoom );
147  m_parent->send( iq );
148  }
149 
150  void MUCRoom::send( const std::string& message )
151  {
152  if( m_session && m_joined )
153  m_session->send( message );
154  }
155 
156  void MUCRoom::setSubject( const std::string& subject )
157  {
158  if( m_session && m_joined )
159  m_session->setSubject( subject );
160  }
161 
162  void MUCRoom::setNick( const std::string& nick )
163  {
164  if( m_parent && m_joined )
165  {
166  m_newNick = nick;
167 
168  Tag *p = new Tag( "presence" );
169  p->addAttribute( "to", m_nick.bare() + "/" + m_newNick );
170  m_parent->send( p );
171  }
172  else
173  m_nick.setResource( nick );
174  }
175 
177  {
178  if( m_parent )
179  {
180  JID j( m_nick.bare() );
181  m_parent->disco()->getDiscoInfo( j, "", this, GetRoomInfo );
182  }
183  }
184 
186  {
187  if( m_parent )
188  {
189  JID j( m_nick.bare() );
190  m_parent->disco()->getDiscoItems( j, "", this, GetRoomItems );
191  }
192  }
193 
194  void MUCRoom::setPresence( Presence presence, const std::string& msg )
195  {
196  if( m_parent && presence != PresenceUnavailable && m_joined )
197  {
198  Stanza *p = Stanza::createPresenceStanza( m_nick, msg, presence );
199  m_parent->send( p );
200  }
201  }
202 
203  void MUCRoom::invite( const JID& invitee, const std::string& reason, bool cont )
204  {
205  if( !m_parent || !m_joined )
206  return;
207 
208  Tag *m = new Tag( "message" );
209  m->addAttribute( "to", m_nick.bare() );
210  Tag *x = new Tag( m, "x" );
211  x->addAttribute( "xmlns", XMLNS_MUC_USER );
212  Tag *i = new Tag( x, "invite" );
213  i->addAttribute( "to", invitee.bare() );
214  if( !reason.empty() )
215  new Tag( i, "reason", reason );
216  if( cont )
217  new Tag( i, "continue" );
218 
219  m_parent->send( m );
220  }
221 
222  Stanza* MUCRoom::declineInvitation( const JID& room, const JID& invitor, const std::string& reason )
223  {
224  Stanza *m = new Stanza( "message" );
225  m->addAttribute( "to", room.bare() );
226  Tag *x = new Tag( m, "x" );
227  x->addAttribute( "xmlns", XMLNS_MUC_USER );
228  Tag *d = new Tag( x, "decline" );
229  d->addAttribute( "to", invitor.bare() );
230  if( !reason.empty() )
231  new Tag( d, "reason", reason );
232 
233  return m;
234  }
235 
236  void MUCRoom::setPublish( bool publish, bool publishNick )
237  {
238  m_publish = publish;
239  m_publishNick = publishNick;
240 
241  if( !m_parent )
242  return;
243 
244  if( m_publish )
245  m_parent->disco()->registerNodeHandler( this, XMLNS_MUC_ROOMS );
246  else
247  m_parent->disco()->removeNodeHandler( this, XMLNS_MUC_ROOMS );
248  }
249 
250  void MUCRoom::addHistory( const std::string& message, const JID& from, const std::string& stamp )
251  {
252  if( !m_joined || !m_parent )
253  return;
254 
255  Tag *m = new Tag( "message" );
256  m->addAttribute( "to", m_nick.bare() );
257  m->addAttribute( "type", "groupchat" );
258  new Tag( m, "body", message );
259  Tag *x = new Tag( m, "x" );
260  x->addAttribute( "xmlns", XMLNS_X_DELAY );
261  x->addAttribute( "from", from.full() );
262  x->addAttribute( "stamp", stamp );
263 
264  m_parent->send( m );
265  }
266 
268  {
269  m_historyType = type;
270  m_historySince = "";
271  m_historyValue = value;
272  }
273 
274  void MUCRoom::setRequestHistory( const std::string& since )
275  {
276  m_historyType = HistorySince;
277  m_historySince = since;
278  m_historyValue = 0;
279  }
280 
281  Stanza* MUCRoom::createDataForm( const JID& room, const DataForm& df )
282  {
283  Stanza *m = new Stanza( "message" );
284  m->addAttribute( "to", room.bare() );
285  m->addChild( df.tag() );
286 
287  return m;
288  }
289 
291  {
292  if( !m_parent || !m_joined )
293  return;
294 
297  field->setName( "FORM_TYPE" );
298  field->setValue( XMLNS_MUC_REQUEST );
299  df.addField( field );
301  field->setName( "muc#role" );
302  field->setLabel( "Requested role" );
303  field->setValue( "participant" );
304  df.addField( field );
305 
306  Tag *m = new Tag( "messsage" );
307  m->addAttribute( "to", m_nick.bare() );
308  m->addChild( df.tag() );
309 
310  m_parent->send( m );
311  }
312 
313  void MUCRoom::kick( const std::string& nick, const std::string& reason )
314  {
315  setRole( nick, RoleNone, reason );
316  }
317 
318  void MUCRoom::grantVoice( const std::string& nick, const std::string& reason )
319  {
320  setRole( nick, RoleParticipant, reason );
321  }
322 
323  void MUCRoom::revokeVoice( const std::string& nick, const std::string& reason )
324  {
325  setRole( nick, RoleVisitor, reason );
326  }
327 
328  void MUCRoom::ban( const std::string& nick, const std::string& reason )
329  {
330  setAffiliation( nick, AffiliationOutcast, reason );
331  }
332 
333  void MUCRoom::setRole( const std::string& nick, MUCRoomRole role, const std::string& reason )
334  {
335  modifyOccupant( nick, role, "role", reason );
336  }
337 
338  void MUCRoom::setAffiliation( const std::string& nick, MUCRoomAffiliation affiliation,
339  const std::string& reason )
340  {
341  modifyOccupant( nick, affiliation, "affiliation", reason );
342  }
343 
344  void MUCRoom::modifyOccupant( const std::string& nick, int state, const std::string roa,
345  const std::string& reason )
346  {
347  if( !m_parent || !m_joined || nick.empty() || roa.empty() )
348  return;
349 
350  std::string newRoA;
351  MUCOperation action = SetRNone;
352  if( roa == "role" )
353  {
354  switch( state )
355  {
356  case RoleNone:
357  newRoA = "none";
358  action = SetRNone;
359  break;
360  case RoleVisitor:
361  newRoA = "visitor";
362  action = SetVisitor;
363  break;
364  case RoleParticipant:
365  newRoA = "participant";
366  action = SetParticipant;
367  break;
368  case RoleModerator:
369  newRoA = "moderator";
370  action = SetModerator;
371  break;
372  }
373  }
374  else
375  {
376  switch( state )
377  {
378  case AffiliationOutcast:
379  newRoA = "outcast";
380  action = SetOutcast;
381  break;
382  case AffiliationNone:
383  newRoA = "none";
384  action = SetANone;
385  break;
386  case AffiliationMember:
387  newRoA = "member";
388  action = SetMember;
389  break;
390  case AffiliationAdmin:
391  newRoA = "admin";
392  action = SetAdmin;
393  break;
394  case AffiliationOwner:
395  newRoA = "owner";
396  action = SetOwner;
397  break;
398  }
399  }
400  Tag *i = new Tag( "item" );
401  i->addAttribute( "nick", nick );
402  i->addAttribute( roa, newRoA );
403  if( !reason.empty() )
404  new Tag( i, "reason", reason );
405 
406  const std::string& id = m_parent->getID();
407  JID j( m_nick.bare() );
408  Stanza *k = Stanza::createIqStanza( j, id, StanzaIqSet, XMLNS_MUC_ADMIN, i );
409 
410  m_parent->trackID( this, id, action );
411  m_parent->send( k );
412  }
413 
415  {
416  if( !m_parent || !m_joined || !m_roomConfigHandler )
417  return;
418 
419  Tag *i = new Tag( "item" );
420 
421  switch( operation )
422  {
423  case RequestVoiceList:
424  i->addAttribute( "role", "participant" );
425  break;
426  case RequestBanList:
427  i->addAttribute( "affiliation", "outcast" );
428  break;
429  case RequestMemberList:
430  i->addAttribute( "affiliation", "member" );
431  break;
433  i->addAttribute( "role", "moderator" );
434  break;
435  case RequestOwnerList:
436  i->addAttribute( "affiliation", "owner" );
437  break;
438  case RequestAdminList:
439  i->addAttribute( "affiliation", "admin" );
440  break;
441  default:
442  delete i;
443  return;
444  break;
445  }
446 
447  const std::string& id = m_parent->getID();
448  JID j( m_nick.bare() );
450 
451  m_parent->trackID( this, id, operation );
452  m_parent->send( iq );
453  }
454 
455  void MUCRoom::storeList( const MUCListItemList items, MUCOperation operation )
456  {
457  if( !m_parent || !m_joined )
458  return;
459 
460  std::string roa;
461  std::string value;
462  switch( operation )
463  {
464  case RequestVoiceList:
465  roa = "role";
466  value = "participant";
467  break;
468  case RequestBanList:
469  roa = "affiliation";
470  value = "outcast";
471  break;
472  case RequestMemberList:
473  roa = "affiliation";
474  value = "member";
475  break;
477  roa = "role";
478  value = "moderator";
479  break;
480  case RequestOwnerList:
481  roa = "affiliation";
482  value = "owner";
483  break;
484  case RequestAdminList:
485  roa = "affiliation";
486  value = "admin";
487  break;
488  default:
489  return;
490  break;
491  }
492 
493  const std::string& id = m_parent->getID();
494  Tag *iq = new Tag( "iq" );
495  iq->addAttribute( "id", id );
496  iq->addAttribute( "type", "set" );
497  iq->addAttribute( "to", m_nick.bare() );
498  Tag *q = new Tag( iq, "query" );
499  q->addAttribute( "xmlns", XMLNS_MUC_ADMIN );
500 
501  MUCListItemList::const_iterator it = items.begin();
502  for( ; it != items.end(); ++it )
503  {
504  if( (*it).nick.empty() )
505  continue;
506 
507  Tag *i = new Tag( q, "item" );
508  i->addAttribute( "nick", (*it).nick );
509  i->addAttribute( roa, value );
510  if( !(*it).reason.empty() )
511  new Tag( i, "reason", (*it).reason );
512  }
513 
514  m_parent->trackID( this, id, operation );
515  m_parent->send( iq );
516  }
517 
518  void MUCRoom::handlePresence( Stanza *stanza )
519  {
520  if( ( stanza->from().bare() != m_nick.bare() ) || !m_roomHandler )
521  return;
522 
523  if( stanza->subtype() == StanzaPresenceError )
524  {
525  if( m_newNick.empty() )
526  {
527  m_parent->removePresenceHandler( m_nick.bareJID(), this );
528  m_parent->disposeMessageSession( m_session );
529  m_joined = false;
530  m_session = 0;
531  }
532  else
533  m_newNick = "";
534  m_roomHandler->handleMUCError( this, stanza->error() );
535  }
536  else
537  {
538  Tag* x = 0;
539  if( m_roomHandler && ( x = stanza->findChild( "x", "xmlns", XMLNS_MUC_USER ) ) != 0 )
540  {
541  MUCRoomParticipant party;
542  party.flags = 0;
543  party.nick = new JID( stanza->from() );
544  party.jid = 0;
545  party.actor = 0;
546  party.alternate = 0;
547  const Tag::TagList& l = x->children();
548  Tag::TagList::const_iterator it = l.begin();
549  for( ; it != l.end(); ++it )
550  {
551  if( (*it)->name() == "item" )
552  {
553  const std::string& affiliation = (*it)->findAttribute( "affiliation" );
554  if( affiliation == "owner" )
555  party.affiliation = AffiliationOwner;
556  else if( affiliation == "admin" )
557  party.affiliation = AffiliationAdmin;
558  else if( affiliation == "member" )
559  party.affiliation = AffiliationMember;
560  else if( affiliation == "outcast" )
561  party.affiliation = AffiliationOutcast;
562  else
563  party.affiliation = AffiliationNone;
564 
565  const std::string& role = (*it)->findAttribute( "role" );
566  if( role == "moderator" )
567  party.role = RoleModerator;
568  else if( role == "participant" )
569  party.role = RoleParticipant;
570  else if( role == "visitor" )
571  party.role = RoleVisitor;
572  else
573  party.role = RoleNone;
574 
575  const std::string& jid = (*it)->findAttribute( "jid" );
576  if( !jid.empty() )
577  party.jid = new JID( jid );
578 
579  if( (*it)->hasChild( "actor" ) )
580  {
581  const std::string& actor = (*it)->findChild( "actor" )->findAttribute( "jid" );
582  if( !actor.empty() )
583  party.actor = new JID( actor );
584  }
585  if( (*it)->hasChild( "reason" ) )
586  {
587  party.reason = (*it)->findChild( "reason" )->cdata();
588  }
589  party.newNick = (*it)->findAttribute( "nick" );
590  }
591  else if( (*it)->name() == "status" )
592  {
593  const std::string& code = (*it)->findAttribute( "code" );
594  if( code == "100" )
595  setNonAnonymous();
596  else if( code == "101" )
597  {
598  // affiliation changed while not in the room. not to be handled here, I guess
599  }
600  else if( code == "110" )
601  {
602  party.flags |= UserSelf;
603  m_role = party.role;
604  m_affiliation = party.affiliation;
605  }
606  else if( code == "201" )
607  {
608  m_creationInProgress = true;
609  if( instantRoomHook() || m_roomHandler->handleMUCRoomCreation( this ) )
611  }
612  else if( code == "210" )
613  m_nick.setResource( stanza->from().resource() );
614  else if( code == "301" )
615  party.flags |= UserBanned;
616  else if( code == "303" )
617  party.flags |= UserNickChanged;
618  else if( code == "307" )
619  party.flags |= UserKicked;
620  else if( code == "321" )
621  party.flags |= UserAffiliationChanged;
622  }
623  else if( (*it)->name() == "destroy" )
624  {
625  if( (*it)->hasAttribute( "jid" ) )
626  party.alternate = new JID( (*it)->findAttribute( "jid" ) );
627 
628  if( (*it)->hasChild( "reason" ) )
629  party.reason = (*it)->findChild( "reason" )->cdata();
630 
631  party.flags |= UserRoomDestroyed;
632  }
633  }
634 
635  if( party.flags & UserNickChanged && !party.newNick.empty()
636  && m_nick.resource() == stanza->from().resource()
637  && party.newNick == m_newNick )
638  party.flags |= UserSelf;
639 
640  if( party.flags & UserNickChanged && party.flags & UserSelf && !party.newNick.empty() )
641  m_nick.setResource( party.newNick );
642 
643  party.status = stanza->status();
644 
645  m_roomHandler->handleMUCParticipantPresence( this, party, stanza->presence() );
646  delete party.jid;
647  delete party.nick;
648  delete party.actor;
649  delete party.alternate;
650  }
651  }
652  }
653 
655  {
656  if( !m_creationInProgress || !m_parent || !m_joined )
657  return;
658 
659  Tag *x = new Tag( "x" );
660  x->addAttribute( "xmlns", XMLNS_X_DATA );
661  x->addAttribute( "type", "submit" );
662 
663  JID j( m_nick.bare() );
664  const std::string& id = m_parent->getID();
666 
667  m_parent->trackID( this, id, CreateInstantRoom );
668  m_parent->send( iq );
669 
670  m_creationInProgress = false;
671  }
672 
674  {
675  if( !m_creationInProgress || !m_parent || !m_joined )
676  return;
677 
678  Tag *x = new Tag( "x" );
679  x->addAttribute( "xmlns", XMLNS_X_DATA );
680  x->addAttribute( "type", "cancel" );
681 
682  JID j( m_nick.bare() );
683  const std::string& id = m_parent->getID();
685 
686  m_parent->trackID( this, id, CancelRoomCreation );
687  m_parent->send( iq );
688 
689  m_creationInProgress = false;
690  }
691 
693  {
694  if( !m_parent || !m_joined )
695  return;
696 
697  JID j( m_nick.bare() );
698  const std::string& id = m_parent->getID();
700 
701  m_parent->trackID( this, id, RequestRoomConfig );
702  m_parent->send( iq );
703 
704  if( m_creationInProgress )
705  m_creationInProgress = false;
706  }
707 
709  {
710  if( !m_parent || !m_joined )
711  return;
712 
713  JID j( m_nick.bare() );
714  const std::string& id = m_parent->getID();
715  Stanza *iq = Stanza::createIqStanza( j, id, StanzaIqSet, XMLNS_MUC_OWNER, form->tag() );
716  delete form;
717 
718  m_parent->trackID( this, id, SendRoomConfig );
719  m_parent->send( iq );
720 
721  if( m_creationInProgress )
722  m_creationInProgress = false;
723  }
724 
725  void MUCRoom::setNonAnonymous()
726  {
727  m_flags |= FlagNonAnonymous;
728  m_flags &= ~FlagSemiAnonymous;
729  m_flags &= ~FlagFullyAnonymous;
730  }
731 
732  void MUCRoom::setSemiAnonymous()
733  {
734  m_flags &= ~FlagNonAnonymous;
735  m_flags |= FlagSemiAnonymous;
736  m_flags &= ~FlagFullyAnonymous;
737  }
738 
739  void MUCRoom::setFullyAnonymous()
740  {
741  m_flags &= ~FlagNonAnonymous;
742  m_flags &= ~FlagSemiAnonymous;
743  m_flags |= FlagFullyAnonymous;
744  }
745 
746  void MUCRoom::handleMessage( Stanza *stanza, MessageSession * /*session*/ )
747  {
748  if( !m_roomHandler )
749  return;
750 
751  if( stanza->subtype() == StanzaMessageError )
752  {
753  m_roomHandler->handleMUCError( this, stanza->error() );
754  }
755  else
756  {
757  Tag *x;
758  if( ( x = stanza->findChild( "x", "xmlns", XMLNS_MUC_USER ) ) != 0 )
759  {
760  const Tag::TagList& l = x->children();
761  Tag::TagList::const_iterator it = l.begin();
762  for( ; it != l.end(); ++it )
763  {
764  if( (*it)->name() == "status" )
765  {
766  const std::string& code = (*it)->findAttribute( "code" );
767  if( code == "100" )
768  {
769  setNonAnonymous();
770  }
771  else if( code == "104" )
772  /*m_configChanged =*/ (void)true;
773  else if( code == "170" )
774  m_flags |= FlagPublicLogging;
775  else if( code == "171" )
776  m_flags &= ~FlagPublicLogging;
777  else if( code == "172" )
778  {
779  setNonAnonymous();
780  }
781  else if( code == "173" )
782  {
783  setSemiAnonymous();
784  }
785  else if( code == "174" )
786  {
787  setFullyAnonymous();
788  }
789  }
790  else if( (*it)->name() == "decline" )
791  {
792  std::string reason;
793  JID invitee( (*it)->findAttribute( "from" ) );
794  if( (*it)->hasChild( "reason" ) )
795  reason = (*it)->findChild( "reason" )->cdata();
796  m_roomHandler->handleMUCInviteDecline( this, invitee, reason );
797  return;
798  }
799  // call some handler?
800  }
801  }
802  else if( m_roomConfigHandler && ( x = stanza->findChild( "x", "xmlns", XMLNS_X_DATA ) ) != 0 )
803  {
804  DataForm df( x );
805  m_roomConfigHandler->handleMUCRequest( this, df );
806  return;
807  }
808 
809  if( !stanza->subject().empty() )
810  {
811  m_roomHandler->handleMUCSubject( this, stanza->from().resource(), stanza->subject() );
812  }
813  else if( !stanza->body().empty() )
814  {
815  JID from;
816  std::string when;
817  bool privMsg = false;
818  bool history = false;
819  if( ( x = stanza->findChild( "x", "xmlns", XMLNS_X_DELAY ) ) != 0 )
820  {
821  from.setJID( x->findAttribute( "from" ) );
822  when = x->findAttribute( "stamp" );
823  history = true;
824  }
825  if( stanza->subtype() == StanzaMessageChat ||
826  stanza->subtype() == StanzaMessageNormal )
827  privMsg = true;
828 
829  m_roomHandler->handleMUCMessage( this, stanza->from().resource(), stanza->body(),
830  history, when, privMsg );
831  }
832  }
833  }
834 
835  bool MUCRoom::handleIqID( Stanza *stanza, int context )
836  {
837  if( !m_roomConfigHandler )
838  return false;
839 
840  switch( stanza->subtype() )
841  {
842  case StanzaIqResult:
843  return handleIqResult( stanza, context );
844  break;
845  case StanzaIqError:
846  return handleIqError( stanza, context );
847  break;
848  default:
849  break;
850  }
851 
852  return false;
853  }
854 
855  bool MUCRoom::handleIqResult( Stanza *stanza, int context )
856  {
857  switch( context )
858  {
859  case SetRNone:
860  case SetVisitor:
861  case SetParticipant:
862  case SetModerator:
863  case SetANone:
864  case SetOutcast:
865  case SetMember:
866  case SetAdmin:
867  case SetOwner:
868  case CreateInstantRoom:
869  case CancelRoomCreation:
870  case DestroyRoom:
871  case StoreVoiceList:
872  case StoreBanList:
873  case StoreMemberList:
874  case StoreModeratorList:
875  case StoreAdminList:
876  m_roomConfigHandler->handleMUCConfigResult( this, true, (MUCOperation)context );
877  return true;
878  break;
879  case RequestRoomConfig:
880  {
881  Tag *x = 0;
882  Tag *q = stanza->findChild( "query", "xmlns", XMLNS_MUC_OWNER );
883  if( q )
884  x = q->findChild( "x", "xmlns", XMLNS_X_DATA );
885  if( x )
886  {
887  DataForm df( x );
888  m_roomConfigHandler->handleMUCConfigForm( this, df );
889  }
890  return true;
891  break;
892  }
893  case RequestVoiceList:
894  case RequestBanList:
895  case RequestMemberList:
897  case RequestOwnerList:
898  case RequestAdminList:
899  {
900  Tag *x = 0;
901  Tag *q = stanza->findChild( "query", "xmlns", XMLNS_MUC_ADMIN );
902  if( !q )
903  break;
904  MUCListItemList itemList;
905  const Tag::TagList& items = x->findChildren( "item" );
906  Tag::TagList::const_iterator it = items.begin();
907  for( ; it != items.end(); ++it )
908  {
909  MUCListItem item;
910  item.jid = 0;
911  item.role = getEnumRole( (*it)->findAttribute( "role" ) );
912  item.affiliation = getEnumAffiliation( (*it)->findAttribute( "affiliation" ) );
913  if( (*it)->hasAttribute( "jid" ) )
914  item.jid = new JID( (*it)->findAttribute( "jid" ) );
915  item.nick = (*it)->findAttribute( "nick" );
916  itemList.push_back( item );
917  }
918  m_roomConfigHandler->handleMUCConfigList( this, itemList, (MUCOperation)context );
919 
920  MUCListItemList::iterator itl = itemList.begin();
921  for( ; itl != itemList.end(); ++itl )
922  delete (*itl).jid;
923 
924  return true;
925  break;
926  }
927  default:
928  break;
929  }
930  return false;
931  }
932 
933  bool MUCRoom::handleIqError( Stanza * /*stanza*/, int context )
934  {
935  switch( context )
936  {
937  case SetRNone:
938  case SetVisitor:
939  case SetParticipant:
940  case SetModerator:
941  case SetANone:
942  case SetOutcast:
943  case SetMember:
944  case SetAdmin:
945  case SetOwner:
946  case CreateInstantRoom:
947  case CancelRoomCreation:
948  case RequestRoomConfig:
949  case DestroyRoom:
950  case RequestVoiceList:
951  case StoreVoiceList:
952  case RequestBanList:
953  case StoreBanList:
954  case RequestMemberList:
955  case StoreMemberList:
957  case StoreModeratorList:
958  case RequestOwnerList:
959  case StoreOwnerList:
960  case RequestAdminList:
961  case StoreAdminList:
962  m_roomConfigHandler->handleMUCConfigResult( this, false, (MUCOperation)context );
963  break;
964  }
965  return false;
966  }
967 
968  void MUCRoom::handleDiscoInfoResult( Stanza *stanza, int context )
969  {
970  switch( context )
971  {
972  case GetRoomInfo:
973  {
974  int oldflags = m_flags;
975  m_flags = 0;
976  if( oldflags & FlagPublicLogging )
977  m_flags |= FlagPublicLogging;
978 
979  std::string name;
980  DataForm *df = 0;
981  Tag *q = stanza->findChild( "query" );
982  if( q )
983  {
984  const Tag::TagList& l = q->children();
985  Tag::TagList::const_iterator it = l.begin();
986  for( ; it != l.end(); ++it )
987  {
988  if( (*it)->name() == "feature" )
989  {
990  if( (*it)->findAttribute( "var" ) == "muc_hidden" )
991  m_flags |= FlagHidden;
992  else if( (*it)->findAttribute( "var" ) == "muc_membersonly" )
993  m_flags |= FlagMembersOnly;
994  else if( (*it)->findAttribute( "var" ) == "muc_moderated" )
995  m_flags |= FlagModerated;
996  else if( (*it)->findAttribute( "var" ) == "muc_nonanonymous" )
997  setNonAnonymous();
998  else if( (*it)->findAttribute( "var" ) == "muc_open" )
999  m_flags |= FlagOpen;
1000  else if( (*it)->findAttribute( "var" ) == "muc_passwordprotected" )
1001  m_flags |= FlagPasswordProtected;
1002  else if( (*it)->findAttribute( "var" ) == "muc_persistent" )
1003  m_flags |= FlagPersistent;
1004  else if( (*it)->findAttribute( "var" ) == "muc_public" )
1005  m_flags |= FlagPublic;
1006  else if( (*it)->findAttribute( "var" ) == "muc_semianonymous" )
1007  setSemiAnonymous();
1008  else if( (*it)->findAttribute( "var" ) == "muc_temporary" )
1009  m_flags |= FlagTemporary;
1010  else if( (*it)->findAttribute( "var" ) == "muc_fullyanonymous" )
1011  setFullyAnonymous();
1012  else if( (*it)->findAttribute( "var" ) == "muc_unmoderated" )
1013  m_flags |= FlagUnmoderated;
1014  else if( (*it)->findAttribute( "var" ) == "muc_unsecured" )
1015  m_flags |= FlagUnsecured;
1016  }
1017  else if( (*it)->name() == "identity" )
1018  {
1019  name = (*it)->findAttribute( "name" );
1020  }
1021  else if( (*it)->name() == "x" && (*it)->hasAttribute( "xmlns", XMLNS_X_DATA ) )
1022  {
1023  df = new DataForm( (*it) );
1024  }
1025  }
1026  }
1027  if( m_roomHandler )
1028  m_roomHandler->handleMUCInfo( this, m_flags, name, df );
1029  break;
1030  }
1031  default:
1032  break;
1033  }
1034  }
1035 
1036  void MUCRoom::handleDiscoItemsResult( Stanza *stanza, int context )
1037  {
1038  if( !m_roomHandler )
1039  return;
1040 
1041  switch( context )
1042  {
1043  case GetRoomItems:
1044  {
1045  Tag *q = stanza->findChild( "query" );
1046  if( q )
1047  {
1048  StringMap items;
1049  const Tag::TagList& l = q->children();
1050  Tag::TagList::const_iterator it = l.begin();
1051  for( ; it != l.end(); ++it )
1052  {
1053  if( (*it)->name() == "item" && (*it)->hasAttribute( "jid" ) )
1054  {
1055  items[(*it)->findAttribute( "name" )] = (*it)->findAttribute( "jid" );
1056  }
1057  }
1058  m_roomHandler->handleMUCItems( this, items );
1059  }
1060  break;
1061  }
1062  default:
1063  break;
1064  }
1065  }
1066 
1067  void MUCRoom::handleDiscoError( Stanza * /*stanza*/, int context )
1068  {
1069  if( !m_roomHandler )
1070  return;
1071 
1072  switch( context )
1073  {
1074  case GetRoomInfo:
1075  m_roomHandler->handleMUCInfo( this, 0, "", 0 );
1076  break;
1077  case GetRoomItems:
1078  {
1079  StringMap items;
1080  m_roomHandler->handleMUCItems( this, items );
1081  break;
1082  }
1083  default:
1084  break;
1085  }
1086  }
1087 
1088  StringList MUCRoom::handleDiscoNodeFeatures( const std::string& /*node*/ )
1089  {
1090  return StringList();
1091  }
1092 
1093  StringMap MUCRoom::handleDiscoNodeIdentities( const std::string& /*node*/, std::string& /*name*/ )
1094  {
1095  return StringMap();
1096  }
1097 
1098  DiscoNodeItemList MUCRoom::handleDiscoNodeItems( const std::string& node )
1099  {
1101 
1102  if( node != XMLNS_MUC_ROOMS )
1103  return l;
1104 
1105  if( m_publish )
1106  {
1107  DiscoNodeItem item;
1108  item.jid = m_nick.bare();
1109  if( m_publishNick )
1110  item.name = m_nick.resource();
1111  l.push_back( item );
1112  }
1113  return l;
1114  }
1115 
1116  MUCRoomRole MUCRoom::getEnumRole( const std::string& role )
1117  {
1118  if( role == "moderator" )
1119  return RoleModerator;
1120  if( role == "participant" )
1121  return RoleParticipant;
1122  if( role == "visitor" )
1123  return RoleVisitor;
1124  return RoleNone;
1125  }
1126 
1127  MUCRoomAffiliation MUCRoom::getEnumAffiliation( const std::string& affiliation )
1128  {
1129  if( affiliation == "owner" )
1130  return AffiliationOwner;
1131  if( affiliation == "admin" )
1132  return AffiliationAdmin;
1133  if( affiliation == "member" )
1134  return AffiliationMember;
1135  if( affiliation == "outcast" )
1136  return AffiliationOutcast;
1137  return AffiliationNone;
1138  }
1139 
1140 }