13 #include "pubsubmanager.h"
14 #include "clientbase.h"
18 #include "pubsubresulthandler.h"
19 #include "pubsubitem.h"
30 static const std::string
31 XMLNS_PUBSUB_NODE_CONFIG =
"http://jabber.org/protocol/pubsub#node_config",
32 XMLNS_PUBSUB_SUBSCRIBE_OPTIONS =
"http://jabber.org/protocol/pubsub#subscribe_options";
79 static const char* subscriptionValues[] = {
80 "none",
"subscribed",
"pending",
"unconfigured"
83 static inline SubscriptionType subscriptionType(
const std::string& subscription )
88 static inline const std::string subscriptionValue(
SubscriptionType subscription )
90 return util::lookup( subscription, subscriptionValues );
93 static const char* affiliationValues[] = {
94 "none",
"publisher",
"owner",
"outcast"
97 static inline AffiliationType affiliationType(
const std::string& affiliation )
102 static inline const std::string affiliationValue(
AffiliationType affiliation )
104 return util::lookup( affiliation, affiliationValues );
108 Manager::PubSubOwner::PubSubOwner( TrackContext context )
109 : StanzaExtension(
ExtPubSubOwner ), m_ctx( context ), m_form( 0 )
113 Manager::PubSubOwner::PubSubOwner(
const Tag* tag )
114 : StanzaExtension(
ExtPubSubOwner ), m_ctx( InvalidContext ), m_form( 0 )
116 const Tag* d = tag->findTag(
"pubsub/delete" );
120 m_node = d->findAttribute(
"node" );
123 const Tag* p = tag->findTag(
"pubsub/purge" );
126 m_ctx = PurgeNodeItems;
127 m_node = p->findAttribute(
"node" );
130 const Tag* c = tag->findTag(
"pubsub/configure" );
133 m_ctx = SetNodeConfig;
134 m_node = c->findAttribute(
"node" );
137 m_ctx = GetNodeConfig;
138 m_form =
new DataForm( c->findChild(
"x",
"xmlns",
XMLNS_X_DATA ) );
142 const Tag* de = tag->findTag(
"pubsub/default" );
145 m_ctx = DefaultNodeConfig;
148 const Tag* s = tag->findTag(
"pubsub/subscriptions" );
151 m_ctx = GetSubscriberList;
152 m_node = s->findAttribute(
"node" );
153 const TagList& l = s->children();
154 TagList::const_iterator it =l.begin();
155 for( ; it != l.end(); ++it )
157 if( (*it)->name() ==
"subscription" )
159 Subscriber sub( (*it)->findAttribute(
"jid" ),
160 subscriptionType( (*it)->findAttribute(
"subscription" ) ),
161 (*it)->findAttribute(
"subid" ) );
162 m_subList.push_back( sub );
167 const Tag* a = tag->findTag(
"pubsub/affiliations" );
170 m_ctx = GetAffiliateList;
171 m_node = a->findAttribute(
"node" );
172 const TagList& l = a->children();
173 TagList::const_iterator it =l.begin();
174 for( ; it != l.end(); ++it )
176 if( (*it)->name() ==
"affiliation" )
178 Affiliate aff( (*it)->findAttribute(
"jid" ),
179 affiliationType( (*it)->findAttribute(
"affiliation" ) ) );
180 m_affList.push_back( aff );
187 Manager::PubSubOwner::~PubSubOwner()
192 const std::string& Manager::PubSubOwner::filterString()
const
198 Tag* Manager::PubSubOwner::tag()
const
200 if( m_ctx == InvalidContext )
203 Tag* t =
new Tag(
"pubsub" );
211 c =
new Tag( t,
"delete",
"node", m_node );
216 c =
new Tag( t,
"purge",
"node", m_node );
222 c =
new Tag( t,
"configure" );
223 c->addAttribute(
"node", m_node );
225 c->addChild( m_form->tag() );
228 case GetSubscriberList:
229 case SetSubscriberList:
232 c =
new Tag( t,
"subscriptions" );
233 c->addAttribute(
"node", m_node );
234 if( m_subList.size() )
237 SubscriberList::const_iterator it = m_subList.begin();
238 for( ; it != m_subList.end(); ++it )
240 s =
new Tag( c,
"subscription" );
241 s->addAttribute(
"jid", (*it).jid.full() );
242 s->addAttribute(
"subscription", util::lookup( (*it).type, subscriptionValues ) );
243 if( !(*it).subid.empty() )
244 s->addAttribute(
"subid", (*it).subid );
249 case GetAffiliateList:
250 case SetAffiliateList:
252 c =
new Tag( t,
"affiliations" );
253 c->addAttribute(
"node", m_node );
254 if( m_affList.size() )
257 AffiliateList::const_iterator it = m_affList.begin();
258 for( ; it != m_affList.end(); ++it )
260 a =
new Tag( c,
"affiliation",
"jid", (*it).jid.full() );
261 a->addAttribute(
"affiliation", util::lookup( (*it).type, affiliationValues ) );
266 case DefaultNodeConfig:
268 c =
new Tag( t,
"default" );
280 Manager::PubSub::PubSub( TrackContext context )
281 : StanzaExtension(
ExtPubSub ), m_ctx( context ), m_maxItems( 0 ),
287 Manager::PubSub::PubSub(
const Tag* tag )
288 : StanzaExtension(
ExtPubSub ), m_ctx( InvalidContext ),
289 m_maxItems( 0 ), m_notify( false )
295 ConstTagList l = tag->findTagList(
"pubsub/subscriptions/subscription" );
298 m_ctx = GetSubscriptionList;
299 ConstTagList::const_iterator it = l.begin();
300 for( ; it != l.end(); ++it )
302 const std::string& node = (*it)->findAttribute(
"node" );
303 const std::string& sub = (*it)->findAttribute(
"subscription" );
304 const std::string& subid = (*it)->findAttribute(
"subid" );
306 si.jid.setJID( (*it)->findAttribute(
"jid" ) );
307 si.type = subscriptionType( sub );
309 SubscriptionList& lst = m_subscriptionMap[node];
314 l = tag->findTagList(
"pubsub/affiliations/affiliation" );
317 m_ctx = GetAffiliationList;
318 ConstTagList::const_iterator it = l.begin();
319 for( ; it != l.end(); ++it )
321 const std::string& node = (*it)->findAttribute(
"node" );
322 const std::string& aff = (*it)->findAttribute(
"affiliation" );
323 m_affiliationMap[node] = affiliationType( aff );
327 const Tag* s = tag->findTag(
"pubsub/subscribe" );
330 m_ctx = Subscription;
331 m_node = s->findAttribute(
"node" );
332 m_jid = s->findAttribute(
"jid" );
334 const Tag* u = tag->findTag(
"pubsub/unsubscribe" );
337 m_ctx = Unsubscription;
338 m_node = u->findAttribute(
"node" );
339 m_jid = u->findAttribute(
"jid" );
340 m_subid = u->findAttribute(
"subid" );
342 const Tag* o = tag->findTag(
"pubsub/options" );
345 if( m_ctx == InvalidContext )
346 m_ctx = GetSubscriptionOptions;
347 m_jid.setJID( o->findAttribute(
"jid" ) );
348 m_options.node = o->findAttribute(
"node" );
349 m_options.df =
new DataForm( o->findChild(
"x",
"xmlns",
XMLNS_X_DATA ) );
351 const Tag* su = tag->findTag(
"pubsub/subscription" );
355 si.jid.setJID( su->findAttribute(
"jid" ) );
356 si.subid = su->findAttribute(
"subid" );
357 si.type = subscriptionType( su->findAttribute(
"type" ) );
358 SubscriptionList& lst = m_subscriptionMap[su->findAttribute(
"node" )];
362 const Tag* i = tag->findTag(
"pubsub/items" );
365 m_ctx = RequestItems;
366 m_node = i->findAttribute(
"node" );
367 m_subid = i->findAttribute(
"subid" );
368 m_maxItems = atoi( i->findAttribute(
"max_items" ).c_str() );
369 const TagList& l = i->children();
370 TagList::const_iterator it = l.begin();
371 for( ; it != l.end(); ++it )
372 m_items.push_back(
new Item( (*it) ) );
375 const Tag* p = tag->findTag(
"pubsub/publish" );
379 m_node = p->findAttribute(
"node" );
380 const TagList& l = p->children();
381 TagList::const_iterator it = l.begin();
382 for( ; it != l.end(); ++it )
383 m_items.push_back(
new Item( (*it) ) );
386 const Tag* r = tag->findTag(
"pubsub/retract" );
390 m_node = r->findAttribute(
"node" );
391 m_notify = r->hasAttribute(
"notify",
"1" ) || r->hasAttribute(
"notify",
"true" );
392 const TagList& l = p->children();
393 TagList::const_iterator it = l.begin();
394 for( ; it != l.end(); ++it )
395 m_items.push_back(
new Item( (*it) ) );
398 const Tag* c = tag->findTag(
"pubsub/create" );
402 m_node = c->findAttribute(
"node" );
403 const Tag* config = tag->findTag(
"pubsub/configure" );
405 m_options.df =
new DataForm( config->findChild(
"x",
XMLNS_X_DATA ) );
409 Manager::PubSub::~PubSub()
415 const std::string& Manager::PubSub::filterString()
const
417 static const std::string filter =
"/iq/pubsub[@xmlns='" +
XMLNS_PUBSUB +
"']";
421 Tag* Manager::PubSub::tag()
const
423 if( m_ctx == InvalidContext )
426 Tag* t =
new Tag(
"pubsub" );
429 if( m_ctx == GetSubscriptionList )
431 Tag* sub =
new Tag( t,
"subscriptions" );
432 SubscriptionMap::const_iterator it = m_subscriptionMap.begin();
433 for( ; it != m_subscriptionMap.end(); ++it )
435 const SubscriptionList& lst = (*it).second;
436 SubscriptionList::const_iterator it2 = lst.begin();
437 for( ; it2 != lst.end(); ++it2 )
439 Tag* s =
new Tag( sub,
"subscription" );
440 s->addAttribute(
"node", (*it).first );
441 s->addAttribute(
"jid", (*it2).jid );
442 s->addAttribute(
"subscription", subscriptionValue( (*it2).type ) );
443 s->addAttribute(
"sid", (*it2).subid );
447 else if( m_ctx == GetAffiliationList )
450 Tag* aff =
new Tag( t,
"affiliations" );
451 AffiliationMap::const_iterator it = m_affiliationMap.begin();
452 for( ; it != m_affiliationMap.end(); ++it )
454 Tag* a =
new Tag( aff,
"affiliation" );
455 a->addAttribute(
"node", (*it).first );
456 a->addAttribute(
"affiliation", affiliationValue( (*it).second ) );
459 else if( m_ctx == Subscription )
461 Tag* s =
new Tag( t,
"subscribe" );
462 s->addAttribute(
"node", m_node );
463 s->addAttribute(
"jid", m_jid.full() );
466 Tag* o =
new Tag( t,
"options" );
467 o->addChild( m_options.df->tag() );
470 else if( m_ctx == Unsubscription )
472 Tag* u =
new Tag( t,
"unsubscribe" );
473 u->addAttribute(
"node", m_node );
474 u->addAttribute(
"jid", m_jid.full() );
475 u->addAttribute(
"subid", m_subid );
477 else if( m_ctx == GetSubscriptionOptions
478 || m_ctx == SetSubscriptionOptions
479 || ( m_ctx == Subscription && m_options.df ) )
481 Tag* o =
new Tag( t,
"options" );
482 o->addAttribute(
"node", m_options.node );
483 o->addAttribute(
"jid", m_jid.full() );
485 o->addChild( m_options.df->tag() );
487 else if( m_ctx == RequestItems )
489 Tag* i =
new Tag( t,
"items" );
490 i->addAttribute(
"node", m_node );
492 i->addAttribute(
"max_items", m_maxItems );
493 i->addAttribute(
"subid", m_subid );
494 ItemList::const_iterator it = m_items.begin();
495 for( ; it != m_items.end(); ++it )
496 i->addChild( (*it)->tag() );
498 else if( m_ctx == PublishItem )
500 Tag* p =
new Tag( t,
"publish" );
501 p->addAttribute(
"node", m_node );
502 ItemList::const_iterator it = m_items.begin();
503 for( ; it != m_items.end(); ++it )
504 p->addChild( (*it)->tag() );
507 Tag* po =
new Tag(
"publish-options" );
508 po->addChild( m_options.df->tag() );
511 else if( m_ctx == DeleteItem )
513 Tag* r =
new Tag( t,
"retract" );
514 r->addAttribute(
"node", m_node );
516 r->addAttribute(
"notify",
"true" );
517 ItemList::const_iterator it = m_items.begin();
518 for( ; it != m_items.end(); ++it )
519 r->addChild( (*it)->tag() );
521 else if( m_ctx == CreateNode )
523 Tag* c =
new Tag( t,
"create" );
524 c->addAttribute(
"node", m_node );
525 Tag* config =
new Tag( t,
"configure" );
527 config->addChild( m_options.df->tag() );
532 StanzaExtension* Manager::PubSub::clone()
const
534 PubSub* p =
new PubSub();
535 p->m_affiliationMap = m_affiliationMap;
536 p->m_subscriptionMap = m_subscriptionMap;
539 p->m_options.node = m_options.node;
540 p->m_options.df = m_options.df ?
new DataForm( *(m_options.df) ) : 0;
544 p->m_subid = m_subid;
545 ItemList::const_iterator it = m_items.begin();
546 for( ; it != m_items.end(); ++it )
547 p->m_items.push_back(
new Item( *(*it) ) );
549 p->m_maxItems = m_maxItems;
550 p->m_notify = m_notify;
567 const std::string Manager::getSubscriptionsOrAffiliations(
const JID& service,
569 TrackContext context )
571 if( !m_parent || !handler || !service || context == InvalidContext )
574 const std::string&
id = m_parent->
getID();
576 iq.addExtension(
new PubSub( context ) );
578 m_trackMapMutex.
lock();
579 m_resultHandlerTrackMap[id] = handler;
581 m_parent->
send( iq,
this, context );
586 const std::string& node,
591 const std::string& expire
594 if( !m_parent || !handler || !service || node.empty() )
597 const std::string&
id = m_parent->
getID();
600 ps->setJID( jid ? jid : m_parent->
jid() );
616 field->
setValue( util::int2string( depth ) );
619 if( !expire.empty() )
625 ps->setOptions( node, df );
629 m_trackMapMutex.
lock();
630 m_resultHandlerTrackMap[id] = handler;
631 m_nopTrackMap[id] = node;
638 const std::string& node,
639 const std::string& subid,
643 if( !m_parent || !handler || !service )
646 const std::string&
id = m_parent->
getID();
648 PubSub* ps =
new PubSub( Unsubscription );
650 ps->setJID( jid ? jid : m_parent->
jid() );
651 ps->setSubscriptionID( subid );
654 m_trackMapMutex.
lock();
655 m_resultHandlerTrackMap[id] = handler;
658 m_parent->
send( iq,
this, Unsubscription );
662 const std::string Manager::subscriptionOptions( TrackContext context,
665 const std::string& node,
669 if( !m_parent || !handler || !service )
672 const std::string&
id = m_parent->
getID();
674 PubSub* ps =
new PubSub( context );
675 ps->setJID( jid ? jid : m_parent->
jid() );
676 ps->setOptions( node, df );
677 iq.addExtension( ps );
679 m_trackMapMutex.
lock();
680 m_resultHandlerTrackMap[id] = handler;
682 m_parent->
send( iq,
this, context );
687 const std::string& node,
688 const std::string& subid,
692 if( !m_parent || !service || !handler )
695 const std::string&
id = m_parent->
getID();
697 PubSub* ps =
new PubSub( RequestItems );
699 ps->setSubscriptionID( subid );
700 ps->setMaxItems( maxItems );
703 m_trackMapMutex.
lock();
704 m_resultHandlerTrackMap[id] = handler;
706 m_parent->
send( iq,
this, RequestItems );
711 const std::string& node,
712 const std::string& subid,
713 const ItemList& items,
716 if( !m_parent || !service || !handler )
719 const std::string&
id = m_parent->
getID();
721 PubSub* ps =
new PubSub( RequestItems );
723 ps->setSubscriptionID( subid );
724 ps->setItems( items );
727 m_trackMapMutex.
lock();
728 m_resultHandlerTrackMap[id] = handler;
730 m_parent->
send( iq,
this, RequestItems );
735 const std::string& node,
740 if( !m_parent || !handler )
746 const std::string&
id = m_parent->
getID();
748 PubSub* ps =
new PubSub( PublishItem );
750 ps->setItems( items );
754 m_trackMapMutex.
lock();
755 m_resultHandlerTrackMap[id] = handler;
757 m_parent->
send( iq,
this, PublishItem );
762 const std::string& node,
763 const ItemList& items,
767 if( !m_parent || !handler || !service )
770 const std::string&
id = m_parent->
getID();
772 PubSub* ps =
new PubSub( DeleteItem );
774 ps->setItems( items );
775 ps->setNotify( notify );
778 m_trackMapMutex.
lock();
779 m_resultHandlerTrackMap[id] = handler;
781 m_parent->
send( iq,
this, DeleteItem );
786 const std::string& node,
790 if( !m_parent || !handler || !service || node.empty() )
793 const std::string&
id = m_parent->
getID();
795 PubSub* ps =
new PubSub( CreateNode );
800 m_trackMapMutex.
lock();
801 m_nopTrackMap[id] = node;
802 m_resultHandlerTrackMap[id] = handler;
804 m_parent->
send( iq,
this, CreateNode );
809 const std::string& node,
812 if( !m_parent || !handler || !service || node.empty() )
815 const std::string&
id = m_parent->
getID();
817 PubSubOwner* pso =
new PubSubOwner( DeleteNode );
818 pso->setNode( node );
821 m_trackMapMutex.
lock();
822 m_nopTrackMap[id] = node;
823 m_resultHandlerTrackMap[id] = handler;
825 m_parent->
send( iq,
this, DeleteNode );
833 if( !m_parent || !handler || !service )
836 const std::string&
id = m_parent->
getID();
838 PubSubOwner* pso =
new PubSubOwner( DefaultNodeConfig );
844 pso->setConfig( df );
848 m_trackMapMutex.
lock();
849 m_resultHandlerTrackMap[id] = handler;
851 m_parent->
send( iq,
this, DefaultNodeConfig );
855 const std::string Manager::nodeConfig(
const JID& service,
856 const std::string& node,
860 if( !m_parent || !handler || !service || node.empty() )
863 const std::string&
id = m_parent->
getID();
865 PubSubOwner* pso =
new PubSubOwner( config ? SetNodeConfig : GetNodeConfig );
866 pso->setNode( node );
868 pso->setConfig( config );
869 iq.addExtension( pso );
871 m_trackMapMutex.
lock();
872 m_resultHandlerTrackMap[id] = handler;
874 m_parent->
send( iq,
this, config ? SetNodeConfig : GetNodeConfig );
878 const std::string Manager::subscriberList( TrackContext ctx,
880 const std::string& node,
881 const SubscriberList& subList,
882 ResultHandler* handler )
884 if( !m_parent || !handler || !service || node.empty() )
887 const std::string&
id = m_parent->
getID();
889 PubSubOwner* pso =
new PubSubOwner( ctx );
890 pso->setNode( node );
891 pso->setSubscriberList( subList );
892 iq.addExtension( pso );
894 m_trackMapMutex.
lock();
895 m_nopTrackMap[id] = node;
896 m_resultHandlerTrackMap[id] = handler;
898 m_parent->
send( iq,
this, ctx );
902 const std::string Manager::affiliateList( TrackContext ctx,
904 const std::string& node,
905 const AffiliateList& affList,
906 ResultHandler* handler )
908 if( !m_parent || !handler || !service || node.empty() )
911 const std::string&
id = m_parent->
getID();
912 IQ iq( ctx == SetAffiliateList ?
IQ::Set :
IQ::Get, service,
id );
913 PubSubOwner* pso =
new PubSubOwner( ctx );
914 pso->setNode( node );
915 pso->setAffiliateList( affList );
916 iq.addExtension( pso );
918 m_trackMapMutex.
lock();
919 m_nopTrackMap[id] = node;
920 m_resultHandlerTrackMap[id] = handler;
922 m_parent->
send( iq,
this, ctx );
927 const std::string& node,
930 if( !m_parent || !handler || !service || node.empty() )
933 const std::string&
id = m_parent->
getID();
935 PubSubOwner* pso =
new PubSubOwner( PurgeNodeItems );
936 pso->setNode( node );
939 m_trackMapMutex.
lock();
940 m_nopTrackMap[id] = node;
941 m_resultHandlerTrackMap[id] = handler;
943 m_parent->
send( iq,
this, PurgeNodeItems );
949 m_trackMapMutex.
lock();
950 ResultHandlerTrackMap::iterator ith = m_resultHandlerTrackMap.find(
id );
951 if( ith == m_resultHandlerTrackMap.end() )
956 m_resultHandlerTrackMap.erase( ith );
963 const JID& service = iq.
from();
964 const std::string&
id = iq.
id();
966 m_trackMapMutex.
lock();
967 ResultHandlerTrackMap::iterator ith = m_resultHandlerTrackMap.find(
id );
968 if( ith == m_resultHandlerTrackMap.end() )
974 m_resultHandlerTrackMap.erase( ith );
990 SubscriptionMap sm = ps->subscriptions();
993 SubscriptionMap::const_iterator it = sm.begin();
994 const SubscriptionList& lst = (*it).second;
995 if( lst.size() == 1 )
997 SubscriptionList::const_iterator it2 = lst.begin();
999 (*it2).type, error );
1004 case Unsubscription:
1009 case GetSubscriptionList:
1016 ps->subscriptions(),
1020 case GetAffiliationList:
1038 ps->items(), error );
1044 if( ps && ps->items().size())
1046 const ItemList il = ps->items();
1064 case DefaultNodeConfig:
1075 case GetSubscriptionOptions:
1076 case GetSubscriberList:
1077 case SetSubscriberList:
1078 case GetAffiliateList:
1079 case SetAffiliateList:
1084 case PurgeNodeItems:
1088 case GetSubscriptionOptions:
1110 case SetSubscriptionOptions:
1111 case SetSubscriberList:
1112 case SetAffiliateList:
1116 case PurgeNodeItems:
1118 m_trackMapMutex.
lock();
1119 NodeOperationTrackMap::iterator it = m_nopTrackMap.find(
id );
1120 if( it != m_nopTrackMap.end() )
1122 const std::string& node = (*it).second;
1125 case SetSubscriptionOptions:
1128 case SetSubscriberList:
1131 case SetAffiliateList:
1143 case PurgeNodeItems:
1147 m_nopTrackMap.erase( it );
1149 m_trackMapMutex.
unlock();
1152 case GetAffiliateList: