gloox 1.0
|
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