From fba0185e898110a881eb7fd71ebbba3083d5306f Mon Sep 17 00:00:00 2001
From: Nikos Kouremenos <kourem@gmail.com>
Date: Tue, 7 Jun 2005 18:21:36 +0000
Subject: [PATCH] Gajim does bookmarks and private storage [needs better
 UI-side] CONGRATS and thanks to delmonico

---
 src/common/connection.py | 82 ++++++++++++++++++++++++++++++++++++++--
 src/gajim.py             |  9 +++++
 src/groupchat_window.py  | 24 ++++++++++++
 src/gtkgui.glade         | 27 +++++++++++--
 4 files changed, 136 insertions(+), 6 deletions(-)

diff --git a/src/common/connection.py b/src/common/connection.py
index 317d32bd5e..cf23a5f5f2 100644
--- a/src/common/connection.py
+++ b/src/common/connection.py
@@ -118,13 +118,14 @@ def __init__(self, name):
 			'AGENT_INFO_INFO': [], 'QUIT': [], 'ACC_OK': [], 'MYVCARD': [],
 			'OS_INFO': [], 'VCARD': [], 'GC_MSG': [], 'GC_SUBJECT': [],
 			'GC_CONFIG': [], 'BAD_PASSPHRASE': [], 'ROSTER_INFO': [],
-			'ERROR_ANSWER': []}
+			'ERROR_ANSWER': [], 'JOIN_GC': [],}
 		self.name = name
 		self.connected = 0 # offline
 		self.connection = None # xmpppy instance
 		self.gpg = None
 		self.status = ''
 		self.myVCardID = []
+		self.bookmarks = []
 		self.on_purpose = False
 		self.password = gajim.config.get_per('accounts', name, 'password')
 		if USE_GPG:
@@ -542,6 +543,43 @@ def _getRosterCB(self, con, iq_obj):
 			del roster[name + '@' + hostname]
 		self.dispatch('ROSTER', roster)
 
+	def _PrivateCB(self, con, iq_obj):
+		"""
+		Private Data (JEP 048 and 049)
+		"""
+		gajim.log.debug("PrivateCB")
+		storage = iq_obj.getTag("query").getTag("storage")
+		try:
+			ns = storage.getNamespace() 
+		except AttributeError:
+			#Its a result for a 'set' Iq, so we don't do anything here
+			return		
+		
+		if ns=="storage:bookmarks":
+			#Bookmarked URLs and Conferences
+			#http://www.jabber.org/jeps/jep-0048.html
+			confs = storage.getTags("conference")
+			urls = storage.getTags("url")
+			for conf in confs:
+				bm = { 'name':conf.getAttr('name'),
+				       'jid':conf.getAttr('jid'),
+				       'autojoin':conf.getAttr('autojoin'),
+				       'password':conf.getTagData('password'),
+				       'nick':conf.getTagData('nick') }
+
+				if bm['autojoin']=="1":
+					jid = common.xmpp.protocol.JID(conf.getAttr("jid"))
+					server = jid.getDomain()
+					room = jid.getNode()
+					gc = self.join_gc(bm['nick'], room, server, bm['password'])
+					self.dispatch("JOIN_GC", [jid.getStripped(), bm['nick']])
+				self.bookmarks.append(bm)
+		elif ns=="gajim:prefs":
+			#Preferences data
+			#http://www.jabber.org/jeps/jep-0049.html
+			#TODO: implement this
+			pass 
+
 	def _ErrorCB(self, con, iq_obj):
 		errmsg = iq_obj.getError()
 		errcode = iq_obj.getErrorCode()
@@ -613,6 +651,8 @@ def connect(self):
 			common.xmpp.NS_MUC_OWNER)
 		con.RegisterHandler('iq', self._getRosterCB, 'result',
 			common.xmpp.NS_ROSTER)
+		con.RegisterHandler('iq', self._PrivateCB, 'result',
+			common.xmpp.NS_PRIVATE)
 		con.RegisterHandler('iq', self._ErrorCB, 'error')
 
 		gajim.log.debug('Connected to server')
@@ -635,7 +675,7 @@ def connect(self):
 			self.connected = 0
 			self.dispatch('STATUS', 'offline')
 			self.dispatch('ERROR', (_('Authentication failed with "%s"' % name),
-                    _('Please check your login and password for correctness.')))
+				('Please check your login and password for correctness.')))
 			return None
 	# END connect
 
@@ -699,6 +739,10 @@ def change_status(self, show, msg):
 				#ask our VCard
 				iq = self.request_vcard(None)
 				self.myVCardID.append(iq.getID())
+
+				#Get bookmarks from private namespace
+				self.get_bookmarks()
+				
 		elif show == 'offline' and self.connected:
 			self.connected = 0
 			if self.connection:
@@ -897,7 +941,6 @@ def request_vcard(self, jid = None):
 		iq.setTag(common.xmpp.NS_VCARD + ' vCard')
 		self.connection.send(iq)
 		return iq
-
 			#('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...})
 	
 	def send_vcard(self, vcard):
@@ -921,6 +964,39 @@ def send_vcard(self, vcard):
 				iq2.addChild(i).setData(vcard[i])
 		self.connection.send(iq)
 
+	def get_settings(self):
+		''' Get Gajim settings as described in JEP 0049 '''
+		if not self.connection:
+			return
+		iq = common.xmpp.Iq(typ='get')
+		iq2 = iq.addChild(name='query', namespace='jabber:iq:private')
+		iq3 = iq2.addChild(name='gajim', namespace='gajim:prefs')
+		self.connection.send(iq)
+
+	def get_bookmarks(self):
+		''' Get Bookmarks from storage as described in JEP 0048 '''
+		if not self.connection:
+			return
+		iq = common.xmpp.Iq(typ='get')
+		iq2 = iq.addChild(name="query", namespace="jabber:iq:private")
+		iq3 = iq2.addChild(name="storage", namespace="storage:bookmarks")
+		self.connection.send(iq)
+
+	def store_bookmarks(self):
+		''' Send bookmarks to the storage namespace '''
+		iq = common.xmpp.Iq(typ='set')
+		iq2 = iq.addChild(name="query", namespace="jabber:iq:private")
+		iq3 = iq2.addChild(name="storage", namespace="storage:bookmarks")
+		for bm in self.bookmarks:
+			iq4 = iq3.addChild(name="conference")
+			iq4.setAttr('jid',bm['jid'])
+			iq4.setAttr('autojoin',bm['autojoin'])
+			iq4.setAttr('name',bm['name'])
+			iq5 = iq4.setTagData('nick',bm['nick'])
+			iq5 = iq4.setTagData('password',bm['password'])
+		self.connection.send(iq)
+
+
 	def send_agent_status(self, agent, ptype):
 		if not self.connection:
 			return
diff --git a/src/gajim.py b/src/gajim.py
index 11f9a6bf21..673c1035c1 100755
--- a/src/gajim.py
+++ b/src/gajim.py
@@ -570,6 +570,14 @@ def handle_event_roster_info(self, account, array):
 				user.groups = array[4]
 		self.roster.draw_contact(jid, account)
 
+	def handle_event_join_gc(self, account, array):
+		#('JOIN_GC', account, (jid, nick))
+		jid = array[0]
+		nickname = array[1]
+		self.roster.new_room(jid, nickname, account)
+		self.windows[account]['gc'][jid].set_active_tab(jid)
+		self.windows[account]['gc'][jid].window.present()
+
 	def read_sleepy(self):	
 		'''Check if we are idle'''
 		if not self.sleeper.poll():
@@ -732,6 +740,7 @@ def register_handlers(self, conn):
 		conn.register_handler('GC_CONFIG', self.handle_event_gc_config)
 		conn.register_handler('BAD_PASSPHRASE', self.handle_event_bad_passphrase)
 		conn.register_handler('ROSTER_INFO', self.handle_event_roster_info)
+		conn.register_handler('JOIN_GC', self.handle_event_join_gc)
 
 	def process_connections(self):
 		try:
diff --git a/src/groupchat_window.py b/src/groupchat_window.py
index 0703bc85dc..e77b82f569 100644
--- a/src/groupchat_window.py
+++ b/src/groupchat_window.py
@@ -62,6 +62,8 @@ def __init__(self, room_jid, nick, plugin, account):
 			self.on_change_subject_menuitem_activate)
 		self.xml.signal_connect('on_configure_room_menuitem_activate', 
 			self.on_configure_room_menuitem_activate)
+		self.xml.signal_connect('on_add_bookmark_menuitem_activate',
+			self.on_add_bookmark_menuitem_activate)
 		self.xml.signal_connect('on_close_window_activate',
 			self.on_close_window_activate)
 		self.window.show_all()
@@ -290,6 +292,28 @@ def on_configure_room_menuitem_activate(self, widget):
 		room_jid = self.get_active_jid()
 		gajim.connections[self.account].request_gc_config(room_jid)
 
+	def on_add_bookmark_menuitem_activate(self, widget):
+		room_jid = self.get_active_jid()
+		bm = { 'name':"",
+		       'jid':self.get_active_jid(),
+		       'autojoin':"1",
+		       'password':"",
+		       'nick':self.nicks[self.get_active_jid()]
+		     }
+		
+		gajim.connections[self.account].bookmarks.append(bm)
+		gajim.connections[self.account].store_bookmarks()
+		
+		#FIXME: add code to add to Bookmarks group (should be account-specific)
+
+		#FIXME: use join_gc_window [where user can put password] and change the
+		#name of the boookmark [default: fill with room's 'name']
+		dialogs.Information_dialog(
+				_('Bookmark has been added successfully'),
+				_('You can find the bookmark for room "%s" in your roster.') % \
+				room_jid.split('@')[0]).get_response()
+		
+
 	def on_message_textview_key_press_event(self, widget, event):
 		"""When a key is pressed:
 		if enter is pressed without the shit key, message (if not empty) is sent
diff --git a/src/gtkgui.glade b/src/gtkgui.glade
index 4b52af1732..cd3d2c9332 100644
--- a/src/gtkgui.glade
+++ b/src/gtkgui.glade
@@ -8674,7 +8674,7 @@ Custom</property>
 		      <signal name="activate" handler="on_change_subject_menuitem_activate" last_modification_time="Sat, 14 May 2005 00:15:15 GMT"/>
 
 		      <child internal-child="image">
-			<widget class="GtkImage" id="image525">
+			<widget class="GtkImage" id="image607">
 			  <property name="visible">True</property>
 			  <property name="stock">gtk-edit</property>
 			  <property name="icon_size">1</property>
@@ -8696,7 +8696,7 @@ Custom</property>
 		      <signal name="activate" handler="on_configure_room_menuitem_activate" last_modification_time="Fri, 13 May 2005 22:47:03 GMT"/>
 
 		      <child internal-child="image">
-			<widget class="GtkImage" id="image526">
+			<widget class="GtkImage" id="image608">
 			  <property name="visible">True</property>
 			  <property name="stock">gtk-preferences</property>
 			  <property name="icon_size">1</property>
@@ -8709,6 +8709,27 @@ Custom</property>
 		    </widget>
 		  </child>
 
+		  <child>
+		    <widget class="GtkImageMenuItem" id="add_bookmark_menuitem">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">Add _Bookmark</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_add_bookmark_menuitem_activate" last_modification_time="Tue, 07 Jun 2005 15:11:32 GMT"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image609">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-add</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
 		  <child>
 		    <widget class="GtkSeparatorMenuItem" id="separator6">
 		      <property name="visible">True</property>
@@ -8723,7 +8744,7 @@ Custom</property>
 		      <signal name="activate" handler="on_close_window_activate" last_modification_time="Sat, 14 May 2005 01:19:18 GMT"/>
 
 		      <child internal-child="image">
-			<widget class="GtkImage" id="image527">
+			<widget class="GtkImage" id="image610">
 			  <property name="visible">True</property>
 			  <property name="stock">gtk-close</property>
 			  <property name="icon_size">1</property>
-- 
GitLab