pubsubmanager.cpp

00001 /*
00002   Copyright (c) 2007-2009 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 #include "pubsubmanager.h"
00014 #include "clientbase.h"
00015 #include "dataform.h"
00016 #include "iq.h"
00017 #include "pubsub.h"
00018 #include "pubsubresulthandler.h"
00019 #include "pubsubitem.h"
00020 #include "shim.h"
00021 #include "util.h"
00022 #include "error.h"
00023 
00024 namespace gloox
00025 {
00026 
00027   namespace PubSub
00028   {
00029 
00030     static const std::string
00031       XMLNS_PUBSUB_NODE_CONFIG = "http://jabber.org/protocol/pubsub#node_config",
00032       XMLNS_PUBSUB_SUBSCRIBE_OPTIONS = "http://jabber.org/protocol/pubsub#subscribe_options";
00033 
00040 /*    static PubSubFeature featureType( const std::string& str )
00041     {
00042       static const char* values [] = {
00043         "collections",
00044         "config-node",
00045         "create-and-configure",
00046         "create-nodes",
00047         "delete-any",
00048         "delete-nodes",
00049         "get-pending",
00050         "instant-nodes",
00051         "item-ids",
00052         "leased-subscription",
00053         "manage-subscriptions",
00054         "meta-data",
00055         "modify-affiliations",
00056         "multi-collection",
00057         "multi-subscribe",
00058         "outcast-affiliation",
00059         "persistent-items",
00060         "presence-notifications",
00061         "publish",
00062         "publisher-affiliation",
00063         "purge-nodes",
00064         "retract-items",
00065         "retrieve-affiliations",
00066         "retrieve-default",
00067         "retrieve-items",
00068         "retrieve-subscriptions",
00069         "subscribe",
00070         "subscription-options",
00071         "subscription-notifications",
00072         "owner",
00073         "event",
00074       };
00075       return static_cast< PubSubFeature >( util::lookup2( str, values ) );
00076     }
00077 */
00078 
00079     static const char* subscriptionValues[] = {
00080       "none", "subscribed", "pending", "unconfigured"
00081     };
00082 
00083     static inline SubscriptionType subscriptionType( const std::string& subscription )
00084     {
00085       return (SubscriptionType)util::lookup( subscription, subscriptionValues );
00086     }
00087 
00088     static inline const std::string subscriptionValue( SubscriptionType subscription )
00089     {
00090       return util::lookup( subscription, subscriptionValues );
00091     }
00092 
00093     static const char* affiliationValues[] = {
00094       "none", "publisher", "owner", "outcast"
00095     };
00096 
00097     static inline AffiliationType affiliationType( const std::string& affiliation )
00098     {
00099       return (AffiliationType)util::lookup( affiliation, affiliationValues );
00100     }
00101 
00102     static inline const std::string affiliationValue( AffiliationType affiliation )
00103     {
00104       return util::lookup( affiliation, affiliationValues );
00105     }
00106 
00107     // ---- Manager::PubSubOwner ----
00108     Manager::PubSubOwner::PubSubOwner( TrackContext context )
00109       : StanzaExtension( ExtPubSubOwner ), m_ctx( context ), m_form( 0 )
00110     {
00111     }
00112 
00113     Manager::PubSubOwner::PubSubOwner( const Tag* tag )
00114       : StanzaExtension( ExtPubSubOwner ), m_ctx( InvalidContext ), m_form( 0 )
00115     {
00116       const Tag* d = tag->findTag( "pubsub/delete" );
00117       if( d )
00118       {
00119         m_ctx = DeleteNode;
00120         m_node = d->findAttribute( "node" );
00121         return;
00122       }
00123       const Tag* p = tag->findTag( "pubsub/purge" );
00124       if( p )
00125       {
00126         m_ctx = PurgeNodeItems;
00127         m_node = p->findAttribute( "node" );
00128         return;
00129       }
00130       const Tag* c = tag->findTag( "pubsub/configure" );
00131       if( c )
00132       {
00133         m_ctx = SetNodeConfig;
00134         m_node = c->findAttribute( "node" );
00135         if( c->hasChild( "x", "xmlns", XMLNS_X_DATA ) )
00136         {
00137           m_ctx = GetNodeConfig;
00138           m_form = new DataForm( c->findChild( "x", "xmlns", XMLNS_X_DATA ) );
00139         }
00140         return;
00141       }
00142       const Tag* de = tag->findTag( "pubsub/default" );
00143       if( de )
00144       {
00145         m_ctx = DefaultNodeConfig;
00146         return;
00147       }
00148       const Tag* s = tag->findTag( "pubsub/subscriptions" );
00149       if( s )
00150       {
00151         m_ctx = GetSubscriberList;
00152         m_node = s->findAttribute( "node" );
00153         const TagList& l = s->children();
00154         TagList::const_iterator it =l.begin();
00155         for( ; it != l.end(); ++it )
00156         {
00157           if( (*it)->name() == "subscription" )
00158           {
00159             Subscriber sub( (*it)->findAttribute( "jid" ),
00160                             subscriptionType( (*it)->findAttribute( "subscription" ) ),
00161                             (*it)->findAttribute( "subid" ) );
00162             m_subList.push_back( sub );
00163           }
00164         }
00165         return;
00166       }
00167       const Tag* a = tag->findTag( "pubsub/affiliations" );
00168       if( a )
00169       {
00170         m_ctx = GetAffiliateList;
00171         m_node = a->findAttribute( "node" );
00172         const TagList& l = a->children();
00173         TagList::const_iterator it =l.begin();
00174         for( ; it != l.end(); ++it )
00175         {
00176           if( (*it)->name() == "affiliation" )
00177           {
00178             Affiliate aff( (*it)->findAttribute( "jid" ),
00179                             affiliationType( (*it)->findAttribute( "affiliation" ) ) );
00180             m_affList.push_back( aff );
00181           }
00182         }
00183         return;
00184       }
00185     }
00186 
00187     Manager::PubSubOwner::~PubSubOwner()
00188     {
00189       delete m_form;
00190     }
00191 
00192     const std::string& Manager::PubSubOwner::filterString() const
00193     {
00194       static const std::string filter = "/iq/pubsub[@xmlns='" + XMLNS_PUBSUB_OWNER + "']";
00195       return filter;
00196     }
00197 
00198     Tag* Manager::PubSubOwner::tag() const
00199     {
00200       if( m_ctx == InvalidContext )
00201         return 0;
00202 
00203       Tag* t = new Tag( "pubsub" );
00204       t->setXmlns( XMLNS_PUBSUB_OWNER );
00205       Tag* c = 0;
00206 
00207       switch( m_ctx )
00208       {
00209         case DeleteNode:
00210         {
00211           c = new Tag( t, "delete", "node", m_node );
00212           break;
00213         }
00214         case PurgeNodeItems:
00215         {
00216           c = new Tag( t, "purge", "node", m_node );
00217           break;
00218         }
00219         case GetNodeConfig:
00220         case SetNodeConfig:
00221         {
00222           c = new Tag( t, "configure" );
00223           c->addAttribute( "node", m_node );
00224           if( m_form )
00225             c->addChild( m_form->tag() );
00226           break;
00227         }
00228         case GetSubscriberList:
00229         case SetSubscriberList:
00230 
00231         {
00232           c = new Tag( t, "subscriptions" );
00233           c->addAttribute( "node", m_node );
00234           if( m_subList.size() )
00235           {
00236             Tag* s;
00237             SubscriberList::const_iterator it = m_subList.begin();
00238             for( ; it != m_subList.end(); ++it )
00239             {
00240               s = new Tag( c, "subscription" );
00241               s->addAttribute( "jid", (*it).jid.full() );
00242               s->addAttribute( "subscription", util::lookup( (*it).type, subscriptionValues ) );
00243               if( !(*it).subid.empty() )
00244                 s->addAttribute( "subid", (*it).subid );
00245             }
00246           }
00247           break;
00248         }
00249         case GetAffiliateList:
00250         case SetAffiliateList:
00251         {
00252           c = new Tag( t, "affiliations" );
00253           c->addAttribute( "node", m_node );
00254           if( m_affList.size() )
00255           {
00256             Tag* a;
00257             AffiliateList::const_iterator it = m_affList.begin();
00258             for( ; it != m_affList.end(); ++it )
00259             {
00260               a = new Tag( c, "affiliation", "jid", (*it).jid.full() );
00261               a->addAttribute( "affiliation", util::lookup( (*it).type, affiliationValues ) );
00262             }
00263           }
00264           break;
00265         }
00266         case DefaultNodeConfig:
00267         {
00268           c = new Tag( t, "default" );
00269           break;
00270         }
00271         default:
00272           break;
00273       }
00274 
00275       return t;
00276     }
00277     // ---- ~Manager::PubSubOwner ----
00278 
00279     // ---- Manager::PubSub ----
00280     Manager::PubSub::PubSub( TrackContext context )
00281       : StanzaExtension( ExtPubSub ), m_ctx( context ), m_maxItems( 0 ),
00282         m_notify( false )
00283     {
00284       m_options.df = 0;
00285     }
00286 
00287     Manager::PubSub::PubSub( const Tag* tag )
00288       : StanzaExtension( ExtPubSub ), m_ctx( InvalidContext ),
00289         m_maxItems( 0 ), m_notify( false )
00290     {
00291       m_options.df = 0;
00292       if( !tag )
00293         return;
00294 
00295       ConstTagList l = tag->findTagList( "pubsub/subscriptions/subscription" );
00296       if( l.size() )
00297       {
00298         m_ctx = GetSubscriptionList;
00299         ConstTagList::const_iterator it = l.begin();
00300         for( ; it != l.end(); ++it )
00301         {
00302           const std::string& node = (*it)->findAttribute( "node" );
00303           const std::string& sub  = (*it)->findAttribute( "subscription" );
00304           const std::string& subid = (*it)->findAttribute( "subid" );
00305           SubscriptionInfo si;
00306           si.jid.setJID( (*it)->findAttribute( "jid" ) );
00307           si.type = subscriptionType( sub );
00308           si.subid = subid;
00309           SubscriptionList& lst = m_subscriptionMap[node];
00310           lst.push_back( si );
00311         }
00312         return;
00313       }
00314       l = tag->findTagList( "pubsub/affiliations/affiliation" );
00315       if( l.size() )
00316       {
00317         m_ctx = GetAffiliationList;
00318         ConstTagList::const_iterator it = l.begin();
00319         for( ; it != l.end(); ++it )
00320         {
00321           const std::string& node = (*it)->findAttribute( "node" );
00322           const std::string& aff = (*it)->findAttribute( "affiliation" );
00323           m_affiliationMap[node] = affiliationType( aff );
00324         }
00325         return;
00326       }
00327       const Tag* s = tag->findTag( "pubsub/subscribe" );
00328       if( s )
00329       {
00330         m_ctx = Subscription;
00331         m_node = s->findAttribute( "node" );
00332         m_jid = s->findAttribute( "jid" );
00333       }
00334       const Tag* u = tag->findTag( "pubsub/unsubscribe" );
00335       if( u )
00336       {
00337         m_ctx = Unsubscription;
00338         m_node = u->findAttribute( "node" );
00339         m_jid = u->findAttribute( "jid" );
00340         m_subid = u->findAttribute( "subid" );
00341       }
00342       const Tag* o = tag->findTag( "pubsub/options" );
00343       if( o )
00344       {
00345         if( m_ctx == InvalidContext )
00346           m_ctx = GetSubscriptionOptions;
00347         m_jid.setJID( o->findAttribute( "jid" ) );
00348         m_options.node = o->findAttribute( "node" );
00349         m_options.df = new DataForm( o->findChild( "x", "xmlns", XMLNS_X_DATA ) );
00350       }
00351       const Tag* su = tag->findTag( "pubsub/subscription" );
00352       if( su )
00353       {
00354         SubscriptionInfo si;
00355         si.jid.setJID( su->findAttribute( "jid" ) );
00356         si.subid = su->findAttribute( "subid" );
00357         si.type = subscriptionType( su->findAttribute( "type" ) );
00358         SubscriptionList& lst = m_subscriptionMap[su->findAttribute( "node" )];
00359         lst.push_back( si );
00360         return;
00361       }
00362       const Tag* i = tag->findTag( "pubsub/items" );
00363       if( i )
00364       {
00365         m_ctx = RequestItems;
00366         m_node = i->findAttribute( "node" );
00367         m_subid = i->findAttribute( "subid" );
00368         m_maxItems = atoi( i->findAttribute( "max_items" ).c_str() );
00369         const TagList& l = i->children();
00370         TagList::const_iterator it = l.begin();
00371         for( ; it != l.end(); ++it )
00372           m_items.push_back( new Item( (*it) ) );
00373         return;
00374       }
00375       const Tag* p = tag->findTag( "pubsub/publish" );
00376       if( p )
00377       {
00378         m_ctx = PublishItem;
00379         m_node = p->findAttribute( "node" );
00380         const TagList& l = p->children();
00381         TagList::const_iterator it = l.begin();
00382         for( ; it != l.end(); ++it )
00383           m_items.push_back( new Item( (*it) ) );
00384         return;
00385       }
00386       const Tag* r = tag->findTag( "pubsub/retract" );
00387       if( r )
00388       {
00389         m_ctx = DeleteItem;
00390         m_node = r->findAttribute( "node" );
00391         m_notify = r->hasAttribute( "notify", "1" ) || r->hasAttribute( "notify", "true" );
00392         const TagList& l = p->children();
00393         TagList::const_iterator it = l.begin();
00394         for( ; it != l.end(); ++it )
00395           m_items.push_back( new Item( (*it) ) );
00396         return;
00397       }
00398       const Tag* c = tag->findTag( "pubsub/create" );
00399       if( c )
00400       {
00401         m_ctx = CreateNode;
00402         m_node = c->findAttribute( "node" );
00403         const Tag* config = tag->findTag( "pubsub/configure" );
00404         if( config && config->hasChild( "x", XMLNS_X_DATA ) )
00405           m_options.df = new DataForm( config->findChild( "x", XMLNS_X_DATA ) );
00406       }
00407     }
00408 
00409     Manager::PubSub::~PubSub()
00410     {
00411       delete m_options.df;
00412       util::clearList( m_items );
00413     }
00414 
00415     const std::string& Manager::PubSub::filterString() const
00416     {
00417       static const std::string filter = "/iq/pubsub[@xmlns='" + XMLNS_PUBSUB + "']";
00418       return filter;
00419     }
00420 
00421     Tag* Manager::PubSub::tag() const
00422     {
00423       if( m_ctx == InvalidContext )
00424         return 0;
00425 
00426       Tag* t = new Tag( "pubsub" );
00427       t->setXmlns( XMLNS_PUBSUB );
00428 
00429       if( m_ctx == GetSubscriptionList )
00430       {
00431         Tag* sub = new Tag( t, "subscriptions" );
00432         SubscriptionMap::const_iterator it = m_subscriptionMap.begin();
00433         for( ; it != m_subscriptionMap.end(); ++it )
00434         {
00435           const SubscriptionList& lst = (*it).second;
00436           SubscriptionList::const_iterator it2 = lst.begin();
00437           for( ; it2 != lst.end(); ++it2 )
00438           {
00439             Tag* s = new Tag( sub, "subscription" );
00440             s->addAttribute( "node", (*it).first );
00441             s->addAttribute( "jid", (*it2).jid );
00442             s->addAttribute( "subscription", subscriptionValue( (*it2).type ) );
00443             s->addAttribute( "sid", (*it2).subid );
00444           }
00445         }
00446       }
00447       else if( m_ctx == GetAffiliationList )
00448       {
00449 
00450         Tag* aff = new Tag( t, "affiliations" );
00451         AffiliationMap::const_iterator it = m_affiliationMap.begin();
00452         for( ; it != m_affiliationMap.end(); ++it )
00453         {
00454           Tag* a = new Tag( aff, "affiliation" );
00455           a->addAttribute( "node", (*it).first );
00456           a->addAttribute( "affiliation", affiliationValue( (*it).second ) );
00457         }
00458       }
00459       else if( m_ctx == Subscription )
00460       {
00461         Tag* s = new Tag( t, "subscribe" );
00462         s->addAttribute( "node", m_node );
00463         s->addAttribute( "jid", m_jid.full() );
00464         if( m_options.df )
00465         {
00466           Tag* o = new Tag( t, "options" );
00467           o->addChild( m_options.df->tag() );
00468         }
00469       }
00470       else if( m_ctx == Unsubscription )
00471       {
00472         Tag* u = new Tag( t, "unsubscribe" );
00473         u->addAttribute( "node", m_node );
00474         u->addAttribute( "jid", m_jid.full() );
00475         u->addAttribute( "subid", m_subid );
00476       }
00477       else if( m_ctx == GetSubscriptionOptions
00478                || m_ctx == SetSubscriptionOptions
00479                || ( m_ctx == Subscription && m_options.df ) )
00480       {
00481         Tag* o = new Tag( t, "options" );
00482         o->addAttribute( "node", m_options.node );
00483         o->addAttribute( "jid", m_jid.full() );
00484         if( m_options.df )
00485           o->addChild( m_options.df->tag() );
00486       }
00487       else if( m_ctx == RequestItems )
00488       {
00489         Tag* i = new Tag( t, "items" );
00490         i->addAttribute( "node", m_node );
00491         if( m_maxItems )
00492           i->addAttribute( "max_items", m_maxItems );
00493         i->addAttribute( "subid", m_subid );
00494         ItemList::const_iterator it = m_items.begin();
00495         for( ; it != m_items.end(); ++it )
00496           i->addChild( (*it)->tag() );
00497       }
00498       else if( m_ctx == PublishItem )
00499       {
00500         Tag* p = new Tag( t, "publish" );
00501         p->addAttribute( "node", m_node );
00502         ItemList::const_iterator it = m_items.begin();
00503         for( ; it != m_items.end(); ++it )
00504           p->addChild( (*it)->tag() );
00505         if( m_options.df )
00506         {
00507           Tag* po = new Tag( "publish-options" );
00508           po->addChild( m_options.df->tag() );
00509         }
00510       }
00511       else if( m_ctx == DeleteItem )
00512       {
00513         Tag* r = new Tag( t, "retract" );
00514         r->addAttribute( "node", m_node );
00515         if( m_notify )
00516           r->addAttribute( "notify", "true" );
00517         ItemList::const_iterator it = m_items.begin();
00518         for( ; it != m_items.end(); ++it )
00519           r->addChild( (*it)->tag() );
00520       }
00521       else if( m_ctx == CreateNode )
00522       {
00523         Tag* c = new Tag( t, "create" );
00524         c->addAttribute( "node", m_node );
00525         Tag* config = new Tag( t, "configure" );
00526         if( m_options.df )
00527           config->addChild( m_options.df->tag() );
00528       }
00529       return t;
00530     }
00531 
00532     StanzaExtension* Manager::PubSub::clone() const
00533     {
00534       PubSub* p = new PubSub();
00535       p->m_affiliationMap = m_affiliationMap;
00536       p->m_subscriptionMap = m_subscriptionMap;
00537       p->m_ctx = m_ctx;
00538 
00539       p->m_options.node = m_options.node;
00540       p->m_options.df = m_options.df ? new DataForm( *(m_options.df) ) : 0;
00541 
00542       p->m_jid = m_jid;
00543       p->m_node = m_node;
00544       p->m_subid = m_subid;
00545       ItemList::const_iterator it = m_items.begin();
00546       for( ; it != m_items.end(); ++it )
00547         p->m_items.push_back( new Item( *(*it) ) );
00548 
00549       p->m_maxItems = m_maxItems;
00550       p->m_notify = m_notify;
00551       return p;
00552     }
00553     // ---- ~Manager::PubSub ----
00554 
00555     // ---- Manager ----
00556     Manager::Manager( ClientBase* parent )
00557       : m_parent( parent )
00558     {
00559       if( m_parent )
00560       {
00561         m_parent->registerStanzaExtension( new PubSub() );
00562         m_parent->registerStanzaExtension( new PubSubOwner() );
00563         m_parent->registerStanzaExtension( new SHIM() );
00564       }
00565     }
00566 
00567     const std::string Manager::getSubscriptionsOrAffiliations( const JID& service,
00568                                                                ResultHandler* handler,
00569                                                                TrackContext context )
00570     {
00571       if( !m_parent || !handler || !service || context == InvalidContext )
00572         return EmptyString;
00573 
00574       const std::string& id = m_parent->getID();
00575       IQ iq( IQ::Get, service, id );
00576       iq.addExtension( new PubSub( context ) );
00577 
00578       m_trackMapMutex.lock();
00579       m_resultHandlerTrackMap[id] = handler;
00580       m_trackMapMutex.unlock();
00581       m_parent->send( iq, this, context );
00582       return id;
00583     }
00584 
00585     const std::string Manager::subscribe( const JID& service,
00586                                           const std::string& node,
00587                                           ResultHandler* handler,
00588                                           const JID& jid,
00589                                           SubscriptionObject type,
00590                                           int depth,
00591                                           const std::string& expire
00592                                           )
00593     {
00594       if( !m_parent || !handler || !service || node.empty() )
00595         return EmptyString;
00596 
00597       const std::string& id = m_parent->getID();
00598       IQ iq( IQ::Set, service, id );
00599       PubSub* ps = new PubSub( Subscription );
00600       ps->setJID( jid ? jid : m_parent->jid() );
00601       ps->setNode( node );
00602       if( type != SubscriptionNodes || depth != 1 )
00603       {
00604         DataForm* df = new DataForm( TypeSubmit );
00605         df->addField( DataFormField::TypeHidden, "FORM_TYPE", XMLNS_PUBSUB_SUBSCRIBE_OPTIONS );
00606 
00607         if( type == SubscriptionItems )
00608           df->addField( DataFormField::TypeNone, "pubsub#subscription_type", "items" );
00609 
00610         if( depth != 1 )
00611         {
00612           DataFormField* field = df->addField( DataFormField::TypeNone, "pubsub#subscription_depth" );
00613           if( depth == 0 )
00614             field->setValue( "all" );
00615           else
00616             field->setValue( util::int2string( depth ) );
00617         }
00618 
00619         if( !expire.empty() )
00620         {
00621           DataFormField* field = df->addField( DataFormField::TypeNone, "pubsub#expire" );
00622           field->setValue( expire );
00623         }
00624 
00625         ps->setOptions( node, df );
00626       }
00627       iq.addExtension( ps  );
00628 
00629       m_trackMapMutex.lock();
00630       m_resultHandlerTrackMap[id] = handler;
00631       m_nopTrackMap[id] = node;
00632       m_trackMapMutex.unlock();
00633       m_parent->send( iq, this, Subscription );
00634       return id;
00635     }
00636 
00637     const std::string Manager::unsubscribe( const JID& service,
00638                                             const std::string& node,
00639                                             const std::string& subid,
00640                                             ResultHandler* handler,
00641                                             const JID& jid )
00642     {
00643       if( !m_parent || !handler || !service )
00644         return EmptyString;
00645 
00646       const std::string& id = m_parent->getID();
00647       IQ iq( IQ::Set, service, id );
00648       PubSub* ps = new PubSub( Unsubscription );
00649       ps->setNode( node );
00650       ps->setJID( jid ? jid : m_parent->jid() );
00651       ps->setSubscriptionID( subid );
00652       iq.addExtension( ps );
00653 
00654       m_trackMapMutex.lock();
00655       m_resultHandlerTrackMap[id] = handler;
00656       m_trackMapMutex.unlock();
00657       // FIXME? need to track info for handler
00658       m_parent->send( iq, this, Unsubscription );
00659       return id;
00660     }
00661 
00662     const std::string Manager::subscriptionOptions( TrackContext context,
00663                                                     const JID& service,
00664                                                     const JID& jid,
00665                                                     const std::string& node,
00666                                                     ResultHandler* handler,
00667                                                     DataForm* df )
00668     {
00669       if( !m_parent || !handler || !service )
00670         return EmptyString;
00671 
00672       const std::string& id = m_parent->getID();
00673       IQ iq( df ? IQ::Set : IQ::Get, service, id );
00674       PubSub* ps = new PubSub( context );
00675       ps->setJID( jid ? jid : m_parent->jid() );
00676       ps->setOptions( node, df );
00677       iq.addExtension( ps );
00678 
00679       m_trackMapMutex.lock();
00680       m_resultHandlerTrackMap[id] = handler;
00681       m_trackMapMutex.unlock();
00682       m_parent->send( iq, this, context );
00683       return id;
00684     }
00685 
00686     const std::string Manager::requestItems( const JID& service,
00687                                              const std::string& node,
00688                                              const std::string& subid,
00689                                              int maxItems,
00690                                              ResultHandler* handler )
00691     {
00692       if( !m_parent || !service || !handler )
00693         return EmptyString;
00694 
00695       const std::string& id = m_parent->getID();
00696       IQ iq( IQ::Get, service, id );
00697       PubSub* ps = new PubSub( RequestItems );
00698       ps->setNode( node );
00699       ps->setSubscriptionID( subid );
00700       ps->setMaxItems( maxItems );
00701       iq.addExtension( ps );
00702 
00703       m_trackMapMutex.lock();
00704       m_resultHandlerTrackMap[id] = handler;
00705       m_trackMapMutex.unlock();
00706       m_parent->send( iq, this, RequestItems );
00707       return id;
00708     }
00709 
00710     const std::string Manager::requestItems( const JID& service,
00711                                              const std::string& node,
00712                                              const std::string& subid,
00713                                              const ItemList& items,
00714                                              ResultHandler* handler )
00715     {
00716       if( !m_parent || !service || !handler )
00717         return EmptyString;
00718 
00719       const std::string& id = m_parent->getID();
00720       IQ iq( IQ::Get, service, id );
00721       PubSub* ps = new PubSub( RequestItems );
00722       ps->setNode( node );
00723       ps->setSubscriptionID( subid );
00724       ps->setItems( items );
00725       iq.addExtension( ps );
00726 
00727       m_trackMapMutex.lock();
00728       m_resultHandlerTrackMap[id] = handler;
00729       m_trackMapMutex.unlock();
00730       m_parent->send( iq, this, RequestItems );
00731       return id;
00732     }
00733 
00734     const std::string Manager::publishItem( const JID& service,
00735                                             const std::string& node,
00736                                             ItemList& items,
00737                                             DataForm* options,
00738                                             ResultHandler* handler )
00739     {
00740       if( !m_parent || !handler )
00741       {
00742         util::clearList( items );
00743         return EmptyString;
00744       }
00745 
00746       const std::string& id = m_parent->getID();
00747       IQ iq( IQ::Set, service, id );
00748       PubSub* ps = new PubSub( PublishItem );
00749       ps->setNode( node );
00750       ps->setItems( items );
00751       ps->setOptions( EmptyString, options );
00752       iq.addExtension( ps );
00753 
00754       m_trackMapMutex.lock();
00755       m_resultHandlerTrackMap[id] = handler;
00756       m_trackMapMutex.unlock();
00757       m_parent->send( iq, this, PublishItem );
00758       return id;
00759     }
00760 
00761     const std::string Manager::deleteItem( const JID& service,
00762                                            const std::string& node,
00763                                            const ItemList& items,
00764                                            bool notify,
00765                                            ResultHandler* handler )
00766     {
00767       if( !m_parent || !handler || !service )
00768         return EmptyString;
00769 
00770       const std::string& id = m_parent->getID();
00771       IQ iq( IQ::Set, service, id );
00772       PubSub* ps = new PubSub( DeleteItem );
00773       ps->setNode( node );
00774       ps->setItems( items );
00775       ps->setNotify( notify );
00776       iq.addExtension( ps );
00777 
00778       m_trackMapMutex.lock();
00779       m_resultHandlerTrackMap[id] = handler;
00780       m_trackMapMutex.unlock();
00781       m_parent->send( iq, this, DeleteItem );
00782       return id;
00783     }
00784 
00785     const std::string Manager::createNode( const JID& service,
00786                                            const std::string& node,
00787                                            DataForm* config,
00788                                            ResultHandler* handler )
00789     {
00790       if( !m_parent || !handler || !service || node.empty() )
00791         return EmptyString;
00792 
00793       const std::string& id = m_parent->getID();
00794       IQ iq( IQ::Set, service, id );
00795       PubSub* ps = new PubSub( CreateNode );
00796       ps->setNode( node );
00797       ps->setOptions( EmptyString, config );
00798       iq.addExtension( ps );
00799 
00800       m_trackMapMutex.lock();
00801       m_nopTrackMap[id] = node;
00802       m_resultHandlerTrackMap[id] = handler;
00803       m_trackMapMutex.unlock();
00804       m_parent->send( iq, this, CreateNode );
00805       return id;
00806     }
00807 
00808     const std::string Manager::deleteNode( const JID& service,
00809                                            const std::string& node,
00810                                            ResultHandler* handler )
00811     {
00812       if( !m_parent || !handler || !service || node.empty() )
00813         return EmptyString;
00814 
00815       const std::string& id = m_parent->getID();
00816       IQ iq( IQ::Set, service, id );
00817       PubSubOwner* pso = new PubSubOwner( DeleteNode );
00818       pso->setNode( node );
00819       iq.addExtension( pso );
00820 
00821       m_trackMapMutex.lock();
00822       m_nopTrackMap[id] = node;
00823       m_resultHandlerTrackMap[id] = handler;
00824       m_trackMapMutex.unlock();
00825       m_parent->send( iq, this, DeleteNode );
00826       return id;
00827     }
00828 
00829     const std::string Manager::getDefaultNodeConfig( const JID& service,
00830                                                      NodeType type,
00831                                                      ResultHandler* handler )
00832     {
00833       if( !m_parent || !handler || !service )
00834         return EmptyString;
00835 
00836       const std::string& id = m_parent->getID();
00837       IQ iq( IQ::Get, service, id );
00838       PubSubOwner* pso = new PubSubOwner( DefaultNodeConfig );
00839       if( type == NodeCollection )
00840       {
00841         DataForm* df = new DataForm( TypeSubmit );
00842         df->addField( DataFormField::TypeHidden, "FORM_TYPE", XMLNS_PUBSUB_NODE_CONFIG );
00843         df->addField( DataFormField::TypeNone, "pubsub#node_type", "collection" );
00844         pso->setConfig( df );
00845       }
00846       iq.addExtension( pso );
00847 
00848       m_trackMapMutex.lock();
00849       m_resultHandlerTrackMap[id] = handler;
00850       m_trackMapMutex.unlock();
00851       m_parent->send( iq, this, DefaultNodeConfig );
00852       return id;
00853     }
00854 
00855     const std::string Manager::nodeConfig( const JID& service,
00856                                            const std::string& node,
00857                                            DataForm* config,
00858                                            ResultHandler* handler )
00859     {
00860       if( !m_parent || !handler || !service || node.empty() )
00861         return EmptyString;
00862 
00863       const std::string& id = m_parent->getID();
00864       IQ iq( config ? IQ::Set : IQ::Get, service, id );
00865       PubSubOwner* pso = new PubSubOwner( config ? SetNodeConfig : GetNodeConfig );
00866       pso->setNode( node );
00867       if( config )
00868         pso->setConfig( config );
00869       iq.addExtension( pso );
00870 
00871       m_trackMapMutex.lock();
00872       m_resultHandlerTrackMap[id] = handler;
00873       m_trackMapMutex.unlock();
00874       m_parent->send( iq, this, config ? SetNodeConfig : GetNodeConfig );
00875       return id;
00876     }
00877 
00878     const std::string Manager::subscriberList( TrackContext ctx,
00879                                                const JID& service,
00880                                                const std::string& node,
00881                                                const SubscriberList& subList,
00882                                                ResultHandler* handler )
00883     {
00884       if( !m_parent || !handler || !service || node.empty() )
00885         return EmptyString;
00886 
00887       const std::string& id = m_parent->getID();
00888       IQ iq( ctx == SetSubscriberList ? IQ::Set : IQ::Get, service, id );
00889       PubSubOwner* pso = new PubSubOwner( ctx );
00890       pso->setNode( node );
00891       pso->setSubscriberList( subList );
00892       iq.addExtension( pso );
00893 
00894       m_trackMapMutex.lock();
00895       m_nopTrackMap[id] = node;
00896       m_resultHandlerTrackMap[id] = handler;
00897       m_trackMapMutex.unlock();
00898       m_parent->send( iq, this, ctx );
00899       return id;
00900     }
00901 
00902     const std::string Manager::affiliateList( TrackContext ctx,
00903                                               const JID& service,
00904                                               const std::string& node,
00905                                               const AffiliateList& affList,
00906                                               ResultHandler* handler )
00907     {
00908       if( !m_parent || !handler || !service || node.empty() )
00909         return EmptyString;
00910 
00911       const std::string& id = m_parent->getID();
00912       IQ iq( ctx == SetAffiliateList ? IQ::Set : IQ::Get, service, id );
00913       PubSubOwner* pso = new PubSubOwner( ctx );
00914       pso->setNode( node );
00915       pso->setAffiliateList( affList );
00916       iq.addExtension( pso );
00917 
00918       m_trackMapMutex.lock();
00919       m_nopTrackMap[id] = node;
00920       m_resultHandlerTrackMap[id] = handler;
00921       m_trackMapMutex.unlock();
00922       m_parent->send( iq, this, ctx );
00923       return id;
00924     }
00925 
00926     const std::string Manager::purgeNode( const JID& service,
00927                                           const std::string&  node,
00928                                           ResultHandler* handler  )
00929     {
00930       if( !m_parent || !handler || !service || node.empty() )
00931         return EmptyString;
00932 
00933       const std::string& id = m_parent->getID();
00934       IQ iq( IQ::Set, service, id );
00935       PubSubOwner* pso = new PubSubOwner( PurgeNodeItems );
00936       pso->setNode( node );
00937       iq.addExtension( pso );
00938 
00939       m_trackMapMutex.lock();
00940       m_nopTrackMap[id] = node;
00941       m_resultHandlerTrackMap[id] = handler;
00942       m_trackMapMutex.unlock();
00943       m_parent->send( iq, this, PurgeNodeItems );
00944       return id;
00945     }
00946 
00947     bool Manager::removeID( const std::string& id )
00948     {
00949       m_trackMapMutex.lock();
00950       ResultHandlerTrackMap::iterator ith = m_resultHandlerTrackMap.find( id );
00951       if( ith == m_resultHandlerTrackMap.end() )
00952       {
00953         m_trackMapMutex.unlock();
00954         return false;
00955       }
00956       m_resultHandlerTrackMap.erase( ith );
00957       m_trackMapMutex.unlock();
00958       return true;
00959     }
00960 
00961     void Manager::handleIqID( const IQ& iq, int context )
00962     {
00963       const JID& service = iq.from();
00964       const std::string& id = iq.id();
00965 
00966       m_trackMapMutex.lock();
00967       ResultHandlerTrackMap::iterator ith = m_resultHandlerTrackMap.find( id );
00968       if( ith == m_resultHandlerTrackMap.end() )
00969       {
00970         m_trackMapMutex.unlock();
00971         return;
00972       }
00973       ResultHandler* rh = (*ith).second;
00974       m_resultHandlerTrackMap.erase( ith );
00975       m_trackMapMutex.unlock();
00976 
00977       switch( iq.subtype() )
00978       {
00979         case IQ::Error:
00980         case IQ::Result:
00981         {
00982           const Error* error = iq.error();
00983           switch( context )
00984           {
00985             case Subscription:
00986             {
00987               const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
00988               if( !ps )
00989                 return;
00990               SubscriptionMap sm = ps->subscriptions();
00991               if( !sm.empty() )
00992               {
00993                 SubscriptionMap::const_iterator it = sm.begin();
00994                 const SubscriptionList& lst = (*it).second;
00995                 if( lst.size() == 1 )
00996                 {
00997                   SubscriptionList::const_iterator it2 = lst.begin();
00998                   rh->handleSubscriptionResult( id, service, (*it).first, (*it2).subid, (*it2).jid,
00999                                                 (*it2).type, error );
01000                 }
01001               }
01002               break;
01003             }
01004             case Unsubscription:
01005             {
01006               rh->handleUnsubscriptionResult( iq.id(), service, error );
01007               break;
01008             }
01009             case GetSubscriptionList:
01010             {
01011               const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
01012               if( !ps )
01013                 return;
01014 
01015               rh->handleSubscriptions( id, service,
01016                                        ps->subscriptions(),
01017                                        error );
01018               break;
01019             }
01020             case GetAffiliationList:
01021             {
01022               const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
01023               if( !ps )
01024                 return;
01025 
01026               rh->handleAffiliations( id, service,
01027                                       ps->affiliations(),
01028                                       error );
01029               break;
01030             }
01031             case RequestItems:
01032             {
01033               const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
01034               if( !ps )
01035                 return;
01036 
01037               rh->handleItems( id, service, ps->node(),
01038                                ps->items(), error );
01039               break;
01040             }
01041             case PublishItem:
01042             {
01043               const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
01044               if( ps && ps->items().size())
01045               {
01046                 const ItemList il = ps->items();
01047                 rh->handleItemPublication( id, service, "",
01048                                            il, error );
01049               }
01050               break;
01051             }
01052             case DeleteItem:
01053             {
01054               const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
01055               if( ps )
01056               {
01057                 rh->handleItemDeletion( id, service,
01058                                         ps->node(),
01059                                         ps->items(),
01060                                         error );
01061               }
01062               break;
01063             }
01064             case DefaultNodeConfig:
01065             {
01066               const PubSubOwner* pso = iq.findExtension<PubSubOwner>( ExtPubSubOwner );
01067               if( pso )
01068               {
01069                 rh->handleDefaultNodeConfig( id, service,
01070                                              pso->config(),
01071                                              error );
01072               }
01073               break;
01074             }
01075             case GetSubscriptionOptions:
01076             case GetSubscriberList:
01077             case SetSubscriberList:
01078             case GetAffiliateList:
01079             case SetAffiliateList:
01080             case GetNodeConfig:
01081             case SetNodeConfig:
01082             case CreateNode:
01083             case DeleteNode:
01084             case PurgeNodeItems:
01085             {
01086               switch( context )
01087               {
01088                 case GetSubscriptionOptions:
01089                 {
01090                   const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
01091                   if( ps )
01092                   {
01093                     rh->handleSubscriptionOptions( id, service,
01094                                                    ps->jid(),
01095                                                    ps->node(),
01096                                                    ps->options(),
01097                                                    error );
01098                   }
01099                   break;
01100                 }
01101 //                 case GetSubscriberList:
01102 //                 {
01103 //                   const PubSub* ps = iq.findExtension<PubSub>( ExtPubSub );
01104 //                   if( ps )
01105 //                   {
01106 //                     rh->handleSubscribers( service, ps->node(), ps->subscriptions() );
01107 //                   }
01108 //                   break;
01109 //                 }
01110                 case SetSubscriptionOptions:
01111                 case SetSubscriberList:
01112                 case SetAffiliateList:
01113                 case SetNodeConfig:
01114                 case CreateNode:
01115                 case DeleteNode:
01116                 case PurgeNodeItems:
01117                 {
01118                   m_trackMapMutex.lock();
01119                   NodeOperationTrackMap::iterator it = m_nopTrackMap.find( id );
01120                   if( it != m_nopTrackMap.end() )
01121                   {
01122                     const std::string& node = (*it).second;
01123                     switch( context )
01124                     {
01125                       case SetSubscriptionOptions:
01126                         rh->handleSubscriptionOptionsResult( id, service, JID( /* FIXME */ ), node, error );
01127                         break;
01128                       case SetSubscriberList:
01129                         rh->handleSubscribersResult( id, service, node, 0, error );
01130                         break;
01131                       case SetAffiliateList:
01132                         rh->handleAffiliatesResult( id, service, node, 0, error );
01133                         break;
01134                       case SetNodeConfig:
01135                         rh->handleNodeConfigResult( id, service, node, error );
01136                         break;
01137                       case CreateNode:
01138                         rh->handleNodeCreation( id, service, node, error );
01139                         break;
01140                       case DeleteNode:
01141                         rh->handleNodeDeletion( id, service, node, error );
01142                         break;
01143                       case PurgeNodeItems:
01144                         rh->handleNodePurge( id, service, node, error );
01145                         break;
01146                     }
01147                     m_nopTrackMap.erase( it );
01148                   }
01149                   m_trackMapMutex.unlock();
01150                   break;
01151                 }
01152                 case GetAffiliateList:
01153                 {
01154 //                   const PubSub
01155 
01156                  /* const TagList& affiliates = query->children();
01157                   AffiliateList affList;
01158                   TagList::const_iterator it = affiliates.begin();
01159                   for( ; it != affiliates.end(); ++it )
01160                   {
01161                     Affiliate aff( (*it)->findAttribute( "jid" ),
01162                                    affiliationType( (*it)->findAttribute( "affiliation" ) ) );
01163                     affList.push_back( aff );
01164                   }
01165                   rh->handleAffiliates( service, query->findAttribute( "node" ), &affList );
01166                  */
01167                   break;
01168                 }
01169                 case GetNodeConfig:
01170                 {
01171                   const PubSubOwner* pso = iq.findExtension<PubSubOwner>( ExtPubSubOwner );
01172                   if( pso )
01173                   {
01174                     rh->handleNodeConfig( id, service,
01175                                           pso->node(),
01176                                           pso->config(),
01177                                           error );
01178                   }
01179                   break;
01180                 }
01181                 default:
01182                   break;
01183               }
01184 
01185               break;
01186             }
01187           }
01188           break;
01189         }
01190         default:
01191           break;
01192       }
01193 
01194     }
01195 
01196   }
01197 
01198 }
01199 
Generated on Tue Jun 8 23:37:54 2010 for gloox by  doxygen 1.6.3