From 4a0e5bc2b3615150381a987e26f4284a051f74cb Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Fri, 31 Jul 2009 14:52:01 +0200 Subject: [PATCH] [Link Mauve & I] store bookmarks in pubsub if server supports that. --- src/common/connection.py | 45 ++++++++++------- src/common/connection_handlers.py | 80 +++++++++++++++++++------------ src/common/pubsub.py | 11 +++++ 3 files changed, 88 insertions(+), 48 deletions(-) diff --git a/src/common/connection.py b/src/common/connection.py index 7a0e24f3b..326fc90f1 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -1589,38 +1589,47 @@ class Connection(ConnectionHandlers): self.connection.send(iq) def get_bookmarks(self): - '''Get Bookmarks from storage as described in XEP 0048''' + '''Get Bookmarks from storage or PubSub if supported as described in + XEP 0048''' self.bookmarks = [] #avoid multiple bookmarks when re-connecting if not self.connection: return - iq = common.xmpp.Iq(typ='get') - iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE) - iq2.addChild(name='storage', namespace='storage:bookmarks') - self.connection.send(iq) + if self.pubsub_supported: + self.send_pb_retrieve('', 'storage:bookmarks', self._PrivatePubsubCB) + else: + iq = common.xmpp.Iq(typ='get') + iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE) + iq2.addChild(name='storage', namespace='storage:bookmarks') + self.connection.send(iq) def store_bookmarks(self): - ''' Send bookmarks to the storage namespace ''' + ''' Send bookmarks to the storage namespace or PubSub if supported''' if not self.connection: return - iq = common.xmpp.Iq(typ='set') - iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE) - iq3 = iq2.addChild(name='storage', namespace='storage:bookmarks') + iq = common.xmpp.Node(tag='storage', attrs={'xmlns': 'storage:bookmarks'}) for bm in self.bookmarks: - iq4 = iq3.addChild(name = "conference") - iq4.setAttr('jid', bm['jid']) - iq4.setAttr('autojoin', bm['autojoin']) - iq4.setAttr('minimize', bm['minimize']) - iq4.setAttr('name', bm['name']) + iq2 = iq.addChild(name = "conference") + iq2.setAttr('jid', bm['jid']) + iq2.setAttr('autojoin', bm['autojoin']) + iq2.setAttr('minimize', bm['minimize']) + iq2.setAttr('name', bm['name']) # Only add optional elements if not empty # Note: need to handle both None and '' as empty # thus shouldn't use "is not None" if bm.get('nick', None): - iq4.setTagData('nick', bm['nick']) + iq2.setTagData('nick', bm['nick']) if bm.get('password', None): - iq4.setTagData('password', bm['password']) + iq2.setTagData('password', bm['password']) if bm.get('print_status', None): - iq4.setTagData('print_status', bm['print_status']) - self.connection.send(iq) + iq2.setTagData('print_status', bm['print_status']) + + if self.pubsub_supported: + self.send_pb_publish('', 'storage:bookmarks', iq, 'current') + else: + iqA = common.xmpp.Iq(typ='set') + iqB = iqA.addChild(name='query', namespace=common.xmpp.NS_PRIVATE) + iqB.addChild(node=iq) + self.connection.send(iqA) def get_annotations(self): '''Get Annonations from storage as described in XEP 0048, and XEP 0145''' diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 4fbbf939d..564ccc5f1 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -1527,34 +1527,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, if storage: ns = storage.getNamespace() if ns == 'storage:bookmarks': - # Bookmarked URLs and Conferences - # http://www.xmpp.org/extensions/xep-0048.html - confs = storage.getTags('conference') - for conf in confs: - autojoin_val = conf.getAttr('autojoin') - if autojoin_val is None: # not there (it's optional) - autojoin_val = False - minimize_val = conf.getAttr('minimize') - if minimize_val is None: # not there (it's optional) - minimize_val = False - print_status = conf.getTagData('print_status') - if not print_status: - print_status = conf.getTagData('show_status') - try: - bm = {'name': conf.getAttr('name'), - 'jid': helpers.parse_jid(conf.getAttr('jid')), - 'autojoin': autojoin_val, - 'minimize': minimize_val, - 'password': conf.getTagData('password'), - 'nick': conf.getTagData('nick'), - 'print_status': print_status} - except common.helpers.InvalidFormat: - log.warn('Invalid JID: %s, ignoring it' % conf.getAttr('jid')) - continue - - self.bookmarks.append(bm) - self.dispatch('BOOKMARKS', self.bookmarks) - + self._parse_bookmarks(storage) elif ns == 'gajim:prefs': # Preferences data # http://www.xmpp.org/extensions/xep-0049.html @@ -1573,6 +1546,53 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, annotation = note.getData() self.annotations[jid] = annotation + def _PrivatePubsubCB(self, conn, request): + '''Private data from PubSub''' + gajim.log.debug('_PrivatePubsubCB') + pubsub = request.getTag('pubsub') + if not pubsub: + return + items = pubsub.getTag('items') + if not items: + return + item = items.getTag('item') + if not item: + return + storage = item.getTag('storage') + if storage: + ns = storage.getNamespace() + if ns == 'storage:bookmarks': + self._parse_bookmarks(storage) + + def _parse_bookmarks(self, storage): + # Bookmarked URLs and Conferences + # http://www.xmpp.org/extensions/xep-0048.html + confs = storage.getTags('conference') + for conf in confs: + autojoin_val = conf.getAttr('autojoin') + if autojoin_val is None: # not there (it's optional) + autojoin_val = False + minimize_val = conf.getAttr('minimize') + if minimize_val is None: # not there (it's optional) + minimize_val = False + print_status = conf.getTagData('print_status') + if not print_status: + print_status = conf.getTagData('show_status') + try: + bm = {'name': conf.getAttr('name'), + 'jid': helpers.parse_jid(conf.getAttr('jid')), + 'autojoin': autojoin_val, + 'minimize': minimize_val, + 'password': conf.getTagData('password'), + 'nick': conf.getTagData('nick'), + 'print_status': print_status} + except common.helpers.InvalidFormat: + log.warn('Invalid JID: %s, ignoring it' % conf.getAttr('jid')) + continue + + self.bookmarks.append(bm) + self.dispatch('BOOKMARKS', self.bookmarks) + def _rosterSetCB(self, con, iq_obj): log.debug('rosterSetCB') version = iq_obj.getTagAttr('query', 'ver') @@ -1815,7 +1835,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.dispatch('GMAIL_NOTIFY', (jid, newmsgs, gmail_messages_list)) raise common.xmpp.NodeProcessed - + def _rosterItemExchangeCB(self, con, msg): ''' XEP-0144 Roster Item Echange ''' exchange_items_list = {} @@ -1855,7 +1875,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, if msg.getTag('error') is None: self._pubsubEventCB(con, msg) return - + # check if the message is a roster item exchange (XEP-0144) if msg.getTag('x', namespace=common.xmpp.NS_ROSTERX): self._rosterItemExchangeCB(con, msg) diff --git a/src/common/pubsub.py b/src/common/pubsub.py index c90723ecd..b4792bce2 100644 --- a/src/common/pubsub.py +++ b/src/common/pubsub.py @@ -75,6 +75,17 @@ class ConnectionPubSub: self.connection.send(query) + def send_pb_retrieve(self, jid, node, cb, *args, **kwargs): + '''Get items from a node''' + if not self.connection or self.connected < 2: + return + query = xmpp.Iq('get', to=jid) + r = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB) + r = r.addChild('items', {'node': node}) + id_ = self.connection.send(query) + + self.__callbacks[id_]=(cb, args, kwargs) + def send_pb_retract(self, jid, node, id_): '''Delete item from a node''' if not self.connection or self.connected < 2: