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 )
347 Tag* parent = tag->parent();
348 if( parent && parent->findAttribute(
"type") ==
"set" )
349 m_ctx = SetSubscriptionOptions;
351 m_ctx = GetSubscriptionOptions;
353 if( m_ctx == SetSubscriptionOptions || m_ctx == GetSubscriptionOptions )
357 m_node = o->findAttribute(
"node" );
358 m_jid.setJID( o->findAttribute(
"jid" ) );
359 m_subid = o->findAttribute(
"subid" );
361 m_options.node = o->findAttribute(
"node" );
362 m_options.df =
new DataForm( o->findChild(
"x",
"xmlns",
XMLNS_X_DATA ) );
364 const Tag* su = tag->findTag(
"pubsub/subscription" );
368 si.jid.setJID( su->findAttribute(
"jid" ) );
369 si.subid = su->findAttribute(
"subid" );
370 si.type = subscriptionType( su->findAttribute(
"type" ) );
371 SubscriptionList& lst = m_subscriptionMap[su->findAttribute(
"node" )];
375 const Tag* i = tag->findTag(
"pubsub/items" );
378 m_ctx = RequestItems;
379 m_node = i->findAttribute(
"node" );
380 m_subid = i->findAttribute(
"subid" );
381 m_maxItems = atoi( i->findAttribute(
"max_items" ).c_str() );
382 const TagList& l = i->children();
383 TagList::const_iterator it = l.begin();
384 for( ; it != l.end(); ++it )
385 m_items.push_back(
new Item( (*it) ) );
388 const Tag* p = tag->findTag(
"pubsub/publish" );
392 m_node = p->findAttribute(
"node" );
393 const TagList& l = p->children();
394 TagList::const_iterator it = l.begin();
395 for( ; it != l.end(); ++it )
396 m_items.push_back(
new Item( (*it) ) );
399 const Tag* r = tag->findTag(
"pubsub/retract" );
403 m_node = r->findAttribute(
"node" );
404 m_notify = r->hasAttribute(
"notify",
"1" ) || r->hasAttribute(
"notify",
"true" );
405 const TagList& l = r->children();
406 TagList::const_iterator it = l.begin();
407 for( ; it != l.end(); ++it )
408 m_items.push_back(
new Item( (*it) ) );
411 const Tag* c = tag->findTag(
"pubsub/create" );
415 m_node = c->findAttribute(
"node" );
416 const Tag* config = tag->findTag(
"pubsub/configure" );
418 m_options.df =
new DataForm( config->findChild(
"x",
XMLNS_X_DATA ) );
422 Manager::PubSub::~PubSub()
428 const std::string& Manager::PubSub::filterString()
const
430 static const std::string filter =
"/iq/pubsub[@xmlns='" +
XMLNS_PUBSUB +
"']";
434 Tag* Manager::PubSub::tag()
const
436 if( m_ctx == InvalidContext )
439 Tag* t =
new Tag(
"pubsub" );
442 if( m_ctx == GetSubscriptionList )
444 Tag* sub =
new Tag( t,
"subscriptions" );
445 SubscriptionMap::const_iterator it = m_subscriptionMap.begin();
446 for( ; it != m_subscriptionMap.end(); ++it )
448 const SubscriptionList& lst = (*it).second;
449 SubscriptionList::const_iterator it2 = lst.begin();
450 for( ; it2 != lst.end(); ++it2 )
452 Tag* s =
new Tag( sub,
"subscription" );
453 s->addAttribute(
"node", (*it).first );
454 s->addAttribute(
"jid", (*it2).jid );
455 s->addAttribute(
"subscription", subscriptionValue( (*it2).type ) );
456 s->addAttribute(
"sid", (*it2).subid );
460 else if( m_ctx == GetAffiliationList )
463 Tag* aff =
new Tag( t,
"affiliations" );
464 AffiliationMap::const_iterator it = m_affiliationMap.begin();
465 for( ; it != m_affiliationMap.end(); ++it )
467 Tag* a =
new Tag( aff,
"affiliation" );
468 a->addAttribute(
"node", (*it).first );
469 a->addAttribute(
"affiliation", affiliationValue( (*it).second ) );
472 else if( m_ctx == Subscription )
474 Tag* s =
new Tag( t,
"subscribe" );
475 s->addAttribute(
"node", m_node );
476 s->addAttribute(
"jid", m_jid.full() );
479 Tag* o =
new Tag( t,
"options" );
480 o->addChild( m_options.df->tag() );
483 else if( m_ctx == Unsubscription )
485 Tag* u =
new Tag( t,
"unsubscribe" );
486 u->addAttribute(
"node", m_node );
487 u->addAttribute(
"jid", m_jid.full() );
488 u->addAttribute(
"subid", m_subid );
490 else if( m_ctx == GetSubscriptionOptions
491 || m_ctx == SetSubscriptionOptions )
493 Tag* o =
new Tag( t,
"options" );
494 o->addAttribute(
"node", m_options.node );
495 o->addAttribute(
"jid", m_jid.full() );
496 if( !m_subid.empty() )
497 o->addAttribute(
"subid", m_subid );
499 o->addChild( m_options.df->tag() );
501 else if( m_ctx == RequestItems )
503 Tag* i =
new Tag( t,
"items" );
504 i->addAttribute(
"node", m_node );
506 i->addAttribute(
"max_items", m_maxItems );
507 i->addAttribute(
"subid", m_subid );
508 ItemList::const_iterator it = m_items.begin();
509 for( ; it != m_items.end(); ++it )
510 i->addChild( (*it)->tag() );
512 else if( m_ctx == PublishItem )
514 Tag* p =
new Tag( t,
"publish" );
515 p->addAttribute(
"node", m_node );
516 ItemList::const_iterator it = m_items.begin();
517 for( ; it != m_items.end(); ++it )
518 p->addChild( (*it)->tag() );
521 Tag* po =
new Tag(
"publish-options" );
522 po->addChild( m_options.df->tag() );
525 else if( m_ctx == DeleteItem )
527 Tag* r =
new Tag( t,
"retract" );
528 r->addAttribute(
"node", m_node );
530 r->addAttribute(
"notify",
"true" );
531 ItemList::const_iterator it = m_items.begin();
532 for( ; it != m_items.end(); ++it )
533 r->addChild( (*it)->tag() );
535 else if( m_ctx == CreateNode )
537 Tag* c =
new Tag( t,
"create" );
538 c->addAttribute(
"node", m_node );
539 Tag* config =
new Tag( t,
"configure" );
541 config->addChild( m_options.df->tag() );
546 StanzaExtension* Manager::PubSub::clone()
const
548 PubSub* p =
new PubSub();
549 p->m_affiliationMap = m_affiliationMap;
550 p->m_subscriptionMap = m_subscriptionMap;
553 p->m_options.node = m_options.node;
554 p->m_options.df = m_options.df ?
new DataForm( *(m_options.df) ) : 0;
558 p->m_subid = m_subid;
559 ItemList::const_iterator it = m_items.begin();
560 for( ; it != m_items.end(); ++it )
561 p->m_items.push_back(
new Item( *(*it) ) );
563 p->m_maxItems = m_maxItems;
564 p->m_notify = m_notify;
581 const std::string Manager::getSubscriptionsOrAffiliations(
const JID& service,
583 TrackContext context )
585 if( !m_parent || !handler || !service || context == InvalidContext )
588 const std::string&
id = m_parent->
getID();
590 iq.addExtension(
new PubSub( context ) );
592 m_trackMapMutex.
lock();
593 m_resultHandlerTrackMap[id] = handler;
595 m_parent->
send( iq,
this, context );
600 const std::string& node,
605 const std::string& expire
608 if( !m_parent || !handler || !service || node.empty() )
626 field->
setValue( util::int2string( depth ) );
629 if( !expire.empty() )
636 return subscribe( service, node, handler, jid, options );
640 const std::string& node,
646 if( !m_parent || !handler || !service || node.empty() )
649 const std::string&
id = m_parent->
getID();
652 ps->setJID( jid ? jid : m_parent->
jid() );
654 if( options != NULL )
655 ps->setOptions( node, options );
658 m_trackMapMutex.
lock();
659 m_resultHandlerTrackMap[id] = handler;
660 m_nopTrackMap[id] = node;
667 const std::string& node,
668 const std::string& subid,
672 if( !m_parent || !handler || !service )
675 const std::string&
id = m_parent->
getID();
677 PubSub* ps =
new PubSub( Unsubscription );
679 ps->setJID( jid ? jid : m_parent->
jid() );
680 ps->setSubscriptionID( subid );
683 m_trackMapMutex.
lock();
684 m_resultHandlerTrackMap[id] = handler;
687 m_parent->
send( iq,
this, Unsubscription );
691 const std::string Manager::subscriptionOptions( TrackContext context,
694 const std::string& node,
697 const std::string& subid )
699 if( !m_parent || !handler || !service )
702 const std::string&
id = m_parent->
getID();
704 PubSub* ps =
new PubSub( context );
705 ps->setJID( jid ? jid : m_parent->
jid() );
707 ps->setSubscriptionID( subid );
708 ps->setOptions( node, df );
709 iq.addExtension( ps );
711 m_trackMapMutex.
lock();
712 m_resultHandlerTrackMap[id] = handler;
714 m_parent->
send( iq,
this, context );
719 const std::string& node,
720 const std::string& subid,
724 if( !m_parent || !service || !handler )
727 const std::string&
id = m_parent->
getID();
729 PubSub* ps =
new PubSub( RequestItems );
731 ps->setSubscriptionID( subid );
732 ps->setMaxItems( maxItems );
735 m_trackMapMutex.
lock();
736 m_resultHandlerTrackMap[id] = handler;
738 m_parent->
send( iq,
this, RequestItems );
743 const std::string& node,
744 const std::string& subid,
745 const ItemList& items,
748 if( !m_parent || !service || !handler )
751 const std::string&
id = m_parent->
getID();
753 PubSub* ps =
new PubSub( RequestItems );
755 ps->setSubscriptionID( subid );
756 ps->setItems( items );
759 m_trackMapMutex.
lock();
760 m_resultHandlerTrackMap[id] = handler;
762 m_parent->
send( iq,
this, RequestItems );
767 const std::string& node,
772 if( !m_parent || !handler )
778 const std::string&
id = m_parent->
getID();
780 PubSub* ps =
new PubSub( PublishItem );
782 ps->setItems( items );
786 m_trackMapMutex.
lock();
787 m_resultHandlerTrackMap[id] = handler;
789 m_parent->
send( iq,
this, PublishItem );
794 const std::string& node,
795 const ItemList& items,
799 if( !m_parent || !handler || !service )
802 const std::string&
id = m_parent->
getID();
804 PubSub* ps =
new PubSub( DeleteItem );
806 ps->setItems( items );
807 ps->setNotify( notify );
810 m_trackMapMutex.
lock();
811 m_resultHandlerTrackMap[id] = handler;
813 m_parent->
send( iq,
this, DeleteItem );
818 const std::string& node,
822 if( !m_parent || !handler || !service || node.empty() )
825 const std::string&
id = m_parent->
getID();
827 PubSub* ps =
new PubSub( CreateNode );
832 m_trackMapMutex.
lock();
833 m_nopTrackMap[id] = node;
834 m_resultHandlerTrackMap[id] = handler;
836 m_parent->
send( iq,
this, CreateNode );
841 const std::string& node,
844 if( !m_parent || !handler || !service || node.empty() )
847 const std::string&
id = m_parent->
getID();
849 PubSubOwner* pso =
new PubSubOwner( DeleteNode );
850 pso->setNode( node );
853 m_trackMapMutex.
lock();
854 m_nopTrackMap[id] = node;
855 m_resultHandlerTrackMap[id] = handler;
857 m_parent->
send( iq,
this, DeleteNode );
865 if( !m_parent || !handler || !service )
868 const std::string&
id = m_parent->
getID();
870 PubSubOwner* pso =
new PubSubOwner( DefaultNodeConfig );
876 pso->setConfig( df );
880 m_trackMapMutex.
lock();
881 m_resultHandlerTrackMap[id] = handler;
883 m_parent->
send( iq,
this, DefaultNodeConfig );
887 const std::string Manager::nodeConfig(
const JID& service,
888 const std::string& node,
892 if( !m_parent || !handler || !service || node.empty() )
895 const std::string&
id = m_parent->
getID();
897 PubSubOwner* pso =
new PubSubOwner( config ? SetNodeConfig : GetNodeConfig );
898 pso->setNode( node );
900 pso->setConfig( config );
901 iq.addExtension( pso );
903 m_trackMapMutex.
lock();
904 m_resultHandlerTrackMap[id] = handler;
906 m_parent->
send( iq,
this, config ? SetNodeConfig : GetNodeConfig );
910 const std::string Manager::subscriberList( TrackContext ctx,
912 const std::string& node,
913 const SubscriberList& subList,
914 ResultHandler* handler )
916 if( !m_parent || !handler || !service || node.empty() )
919 const std::string&
id = m_parent->
getID();
921 PubSubOwner* pso =
new PubSubOwner( ctx );
922 pso->setNode( node );
923 pso->setSubscriberList( subList );
924 iq.addExtension( pso );
926 m_trackMapMutex.
lock();
927 m_nopTrackMap[id] = node;
928 m_resultHandlerTrackMap[id] = handler;
930 m_parent->
send( iq,
this, ctx );
934 const std::string Manager::affiliateList( TrackContext ctx,
936 const std::string& node,
937 const AffiliateList& affList,
938 ResultHandler* handler )
940 if( !m_parent || !handler || !service || node.empty() )
943 const std::string&
id = m_parent->
getID();
944 IQ iq( ctx == SetAffiliateList ?
IQ::Set :
IQ::Get, service,
id );
945 PubSubOwner* pso =
new PubSubOwner( ctx );
946 pso->setNode( node );
947 pso->setAffiliateList( affList );
948 iq.addExtension( pso );
950 m_trackMapMutex.
lock();
951 m_nopTrackMap[id] = node;
952 m_resultHandlerTrackMap[id] = handler;
954 m_parent->
send( iq,
this, ctx );
959 const std::string& node,
962 if( !m_parent || !handler || !service || node.empty() )
965 const std::string&
id = m_parent->
getID();
967 PubSubOwner* pso =
new PubSubOwner( PurgeNodeItems );
968 pso->setNode( node );
971 m_trackMapMutex.
lock();
972 m_nopTrackMap[id] = node;
973 m_resultHandlerTrackMap[id] = handler;
975 m_parent->
send( iq,
this, PurgeNodeItems );
981 m_trackMapMutex.
lock();
982 ResultHandlerTrackMap::iterator ith = m_resultHandlerTrackMap.find(
id );
983 if( ith == m_resultHandlerTrackMap.end() )
988 m_resultHandlerTrackMap.erase( ith );
995 const JID& service = iq.
from();
996 const std::string&
id = iq.
id();
998 m_trackMapMutex.
lock();
999 ResultHandlerTrackMap::iterator ith = m_resultHandlerTrackMap.find(
id );
1000 if( ith == m_resultHandlerTrackMap.end() )
1002 m_trackMapMutex.
unlock();
1006 m_resultHandlerTrackMap.erase( ith );
1007 m_trackMapMutex.
unlock();
1022 SubscriptionMap sm = ps->subscriptions();
1025 SubscriptionMap::const_iterator it = sm.begin();
1026 const SubscriptionList& lst = (*it).second;
1027 if( lst.size() == 1 )
1029 SubscriptionList::const_iterator it2 = lst.begin();
1031 (*it2).type, error );
1036 case Unsubscription:
1041 case GetSubscriptionList:
1048 ps->subscriptions(),
1052 case GetAffiliationList:
1070 ps->items(), error );
1077 ps ? ps->items() : ItemList(),
1093 case DefaultNodeConfig:
1104 case GetSubscriptionOptions:
1105 case GetSubscriberList:
1106 case SetSubscriberList:
1107 case GetAffiliateList:
1108 case SetAffiliateList:
1113 case PurgeNodeItems:
1117 case GetSubscriptionOptions:
1126 ps->subscriptionID(),
1140 case SetSubscriptionOptions:
1141 case SetSubscriberList:
1142 case SetAffiliateList:
1146 case PurgeNodeItems:
1148 m_trackMapMutex.
lock();
1149 NodeOperationTrackMap::iterator it = m_nopTrackMap.find(
id );
1150 if( it != m_nopTrackMap.end() )
1152 const std::string& node = (*it).second;
1155 case SetSubscriptionOptions:
1163 ps->subscriptionID(),
1172 case SetSubscriberList:
1175 case SetAffiliateList:
1187 case PurgeNodeItems:
1191 m_nopTrackMap.erase( it );
1193 m_trackMapMutex.
unlock();
1196 case GetAffiliateList: