From 2ffd6cbcb8f5927373fb0765adc6a4624b66544d Mon Sep 17 00:00:00 2001
From: Yann Leboulanger <asterix@lagaule.org>
Date: Fri, 31 Jul 2009 17:11:55 +0200
Subject: [PATCH] store bookmarks in both pubsub and xml, and copy those from
 xml to pubsub on startup

---
 src/common/connection.py          | 20 +++++++++--------
 src/common/connection_handlers.py | 36 +++++++++++++------------------
 src/common/pubsub.py              | 21 ++++++++++++++++--
 3 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/src/common/connection.py b/src/common/connection.py
index 7c07bdef49..d15e62b176 100644
--- a/src/common/connection.py
+++ b/src/common/connection.py
@@ -1589,22 +1589,24 @@ class Connection(ConnectionHandlers):
 		iq2.addChild(name='gajim', namespace='gajim:prefs')
 		self.connection.send(iq)
 
-	def get_bookmarks(self):
+	def get_bookmarks(self, storage_type=None):
 		'''Get Bookmarks from storage or PubSub if supported as described in
-		XEP 0048'''
-		self.bookmarks = [] #avoid multiple bookmarks when re-connecting
+		XEP 0048
+		storage_type can be set to xml to force request to xml storage'''
 		if not self.connection:
 			return
-		if self.pubsub_supported:
-			self.send_pb_retrieve('', 'storage:bookmarks', self._PrivatePubsubCB)
+		if self.pubsub_supported and storage_type != 'xml':
+			self.send_pb_retrieve('', 'storage:bookmarks')
 		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 or PubSub if supported'''
+	def store_bookmarks(self, storage_type=None):
+		''' Send bookmarks to the storage namespace or PubSub if supported
+		storage_type can be set to 'pubsub' or 'xml' so store in only one method
+		else it will be stored on both'''
 		if not self.connection:
 			return
 		iq = common.xmpp.Node(tag='storage', attrs={'xmlns': 'storage:bookmarks'})
@@ -1624,7 +1626,7 @@ class Connection(ConnectionHandlers):
 			if bm.get('print_status', None):
 				iq2.setTagData('print_status', bm['print_status'])
 
-		if self.pubsub_supported:
+		if self.pubsub_supported and storage_type != 'xml':
 			if self.pubsub_publish_options_supported:
 				options = common.xmpp.Node(common.xmpp.NS_DATA + ' x',
 					attrs={'type': 'submit'})
@@ -1639,7 +1641,7 @@ class Connection(ConnectionHandlers):
 				options = None
 			self.send_pb_publish('', 'storage:bookmarks', iq, 'current',
 				options=options)
-		else:
+		if storage_type != 'pubsub':
 			iqA = common.xmpp.Iq(typ='set')
 			iqB = iqA.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
 			iqB.addChild(node=iq)
diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py
index be525b0f31..af4894a9d7 100644
--- a/src/common/connection_handlers.py
+++ b/src/common/connection_handlers.py
@@ -1529,7 +1529,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
 		if storage:
 			ns = storage.getNamespace()
 			if ns == 'storage:bookmarks':
-				self._parse_bookmarks(storage)
+				self._parse_bookmarks(storage, 'xml')
 			elif ns == 'gajim:prefs':
 				# Preferences data
 				# http://www.xmpp.org/extensions/xep-0049.html
@@ -1548,27 +1548,12 @@ 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):
+	def _parse_bookmarks(self, storage, storage_type):
+		'''storage_type can be 'pubsub' or 'xml' to tell from where we got
+		bookmarks'''
 		# Bookmarked URLs and Conferences
 		# http://www.xmpp.org/extensions/xep-0048.html
+		resend_to_pubsub = False
 		confs = storage.getTags('conference')
 		for conf in confs:
 			autojoin_val = conf.getAttr('autojoin')
@@ -1592,8 +1577,17 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
 				log.warn('Invalid JID: %s, ignoring it' % conf.getAttr('jid'))
 				continue
 
-			self.bookmarks.append(bm)
+			if bm not in self.bookmarks:
+				self.bookmarks.append(bm)
+				if storage_type == 'xml':
+					# We got a bookmark that was not in pubsub
+					resend_to_pubsub = True
 		self.dispatch('BOOKMARKS', self.bookmarks)
+		if storage_type == 'pubsub':
+			# We gor bookmarks from pubsub, now get those from xml to merge them
+			self.get_bookmarks(storage_type='xml')
+		if self.pubsub_supported and resend_to_pubsub:
+			self.store_bookmarks('pubsub')
 
 	def _rosterSetCB(self, con, iq_obj):
 		log.debug('rosterSetCB')
diff --git a/src/common/pubsub.py b/src/common/pubsub.py
index 105294af78..354d6f97e1 100644
--- a/src/common/pubsub.py
+++ b/src/common/pubsub.py
@@ -78,7 +78,7 @@ class ConnectionPubSub:
 
 		self.connection.send(query)
 
-	def send_pb_retrieve(self, jid, node, cb, *args, **kwargs): 
+	def send_pb_retrieve(self, jid, node, cb=None, *args, **kwargs): 
 		'''Get items from a node''' 
 		if not self.connection or self.connected < 2: 
 			return 
@@ -87,7 +87,8 @@ class ConnectionPubSub:
 		r = r.addChild('items', {'node': node}) 
 		id_ = self.connection.send(query)
 
-		self.__callbacks[id_]=(cb, args, kwargs)
+		if cb:
+			self.__callbacks[id_]=(cb, args, kwargs)
 
 	def send_pb_retract(self, jid, node, id_):
 		'''Delete item from a node'''
@@ -143,12 +144,28 @@ class ConnectionPubSub:
 		self.connection.send(query)
 
 	def _PubSubCB(self, conn, stanza):
+		gajim.log.debug('_PubsubCB')
 		try:
 			cb, args, kwargs = self.__callbacks.pop(stanza.getID())
 			cb(conn, stanza, *args, **kwargs)
 		except Exception:
 			pass
 
+		pubsub = stanza.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, 'pubsub')
+
 	def request_pb_configuration(self, jid, node):
 		if not self.connection or self.connected < 2:
 			return
-- 
GitLab