handle correctly vcards in groupchats : ask them to real jid if we know it, but considere it arrive from fake jid. Fixes #3172, #3173
This commit is contained in:
parent
241a0f3fda
commit
a45a14546a
|
@ -1674,24 +1674,34 @@ class ChatControl(ChatControlBase):
|
|||
if not gajim.config.get('show_avatar_in_chat'):
|
||||
return
|
||||
|
||||
jid = self.contact.jid
|
||||
jid_with_resource = jid
|
||||
if resource:
|
||||
jid_with_resource += '/' + resource
|
||||
is_fake = False
|
||||
if self.TYPE_ID == message_control.TYPE_PM:
|
||||
is_fake = True
|
||||
jid_with_resource = self.contact.jid # fake jid
|
||||
else:
|
||||
jid_with_resource = self.contact.jid
|
||||
if resource:
|
||||
jid_with_resource += '/' + resource
|
||||
|
||||
# we assume contact has no avatar
|
||||
scaled_pixbuf = None
|
||||
|
||||
pixbuf = None
|
||||
is_fake = False
|
||||
if gajim.contacts.is_pm_from_jid(self.account, jid):
|
||||
is_fake = True
|
||||
pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(jid_with_resource,
|
||||
is_fake)
|
||||
if pixbuf == 'ask':
|
||||
# we don't have the vcard
|
||||
gajim.connections[self.account].request_vcard(jid_with_resource,
|
||||
is_fake)
|
||||
if self.TYPE_ID == message_control.TYPE_PM:
|
||||
if self.gc_contact.jid:
|
||||
# We know the real jid of this contact
|
||||
real_jid = self.gc_contact.jid
|
||||
if self.gc_contact.resource:
|
||||
real_jid += '/' + self.gc_contact.resource
|
||||
else:
|
||||
real_jid = jid_with_resource
|
||||
gajim.connections[self.account].request_vcard(real_jid,
|
||||
jid_with_resource)
|
||||
else:
|
||||
gajim.connections[self.account].request_vcard(jid_with_resource)
|
||||
return
|
||||
if pixbuf is not None:
|
||||
scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'chat')
|
||||
|
|
|
@ -811,6 +811,7 @@ class ConnectionVcard:
|
|||
self.vcard_sha = None
|
||||
self.vcard_shas = {} # sha of contacts
|
||||
self.room_jids = [] # list of gc jids so that vcard are saved in a folder
|
||||
self.groupchat_jids = {} # {ID : groupchat_jid}
|
||||
|
||||
def add_sha(self, p, send_caps = True):
|
||||
c = p.setTag('x', namespace = common.xmpp.NS_VCARD_UPDATE)
|
||||
|
@ -906,9 +907,10 @@ class ConnectionVcard:
|
|||
vcard['resource'] = gajim.get_resource_from_jid(fjid)
|
||||
return vcard
|
||||
|
||||
def request_vcard(self, jid = None, is_fake_jid = False):
|
||||
'''request the VCARD. If is_fake_jid is True, it means we request a vcard
|
||||
to a fake jid, like in private messages in groupchat'''
|
||||
def request_vcard(self, jid = None, groupchat_jid = None):
|
||||
'''request the VCARD. If groupchat_jid is not nul, it means we request a vcard
|
||||
to a fake jid, like in private messages in groupchat. jid can be the
|
||||
real jid of the contact, but we want to consider it comes from a fake jid'''
|
||||
if not self.connection:
|
||||
return
|
||||
iq = common.xmpp.Iq(typ = 'get')
|
||||
|
@ -921,13 +923,13 @@ class ConnectionVcard:
|
|||
j = jid
|
||||
if not j:
|
||||
j = gajim.get_jid_from_account(self.name)
|
||||
self.awaiting_answers[id] = (VCARD_ARRIVED, j)
|
||||
if is_fake_jid:
|
||||
room_jid, nick = gajim.get_room_and_nick_from_fjid(jid)
|
||||
self.awaiting_answers[id] = (VCARD_ARRIVED, j, groupchat_jid)
|
||||
if groupchat_jid:
|
||||
room_jid, nick = gajim.get_room_and_nick_from_fjid(groupchat_jid)
|
||||
if not room_jid in self.room_jids:
|
||||
self.room_jids.append(room_jid)
|
||||
self.groupchat_jids[id] = groupchat_jid
|
||||
self.connection.send(iq)
|
||||
#('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...})
|
||||
|
||||
def send_vcard(self, vcard):
|
||||
if not self.connection:
|
||||
|
@ -1010,17 +1012,22 @@ class ConnectionVcard:
|
|||
# If vcard is empty, we send to the interface an empty vcard so that
|
||||
# it knows it arrived
|
||||
jid = self.awaiting_answers[id][1]
|
||||
groupchat_jid = self.awaiting_answers[id][2]
|
||||
frm = jid
|
||||
if groupchat_jid:
|
||||
# We do as if it comes from the fake_jid
|
||||
frm = groupchat_jid
|
||||
our_jid = gajim.get_jid_from_account(self.name)
|
||||
if iq_obj.getType() == 'error' and jid == our_jid:
|
||||
# our server doesn't support vcard
|
||||
self.vcard_supported = False
|
||||
if not iq_obj.getTag('vCard') or iq_obj.getType() == 'error':
|
||||
if jid and jid != our_jid:
|
||||
if frm and frm != our_jid:
|
||||
# Write an empty file
|
||||
self.save_vcard_to_hd(jid, '')
|
||||
self.dispatch('VCARD', {'jid': jid})
|
||||
elif jid == our_jid:
|
||||
self.dispatch('MYVCARD', {'jid': jid})
|
||||
self.save_vcard_to_hd(frm, '')
|
||||
self.dispatch('VCARD', {'jid': frm})
|
||||
elif frm == our_jid:
|
||||
self.dispatch('MYVCARD', {'jid': frm})
|
||||
elif self.awaiting_answers[id][0] == AGENT_REMOVED:
|
||||
jid = self.awaiting_answers[id][1]
|
||||
self.dispatch('AGENT_REMOVED', jid)
|
||||
|
@ -1064,10 +1071,15 @@ class ConnectionVcard:
|
|||
return
|
||||
if not vc.getTag('vCard').getNamespace() == common.xmpp.NS_VCARD:
|
||||
return
|
||||
id = vc.getID()
|
||||
frm_iq = vc.getFrom()
|
||||
our_jid = gajim.get_jid_from_account(self.name)
|
||||
resource = ''
|
||||
if frm_iq:
|
||||
if id in self.groupchat_jids:
|
||||
who = self.groupchat_jids[id]
|
||||
frm, resource = gajim.get_room_and_nick_from_fjid(who)
|
||||
del self.groupchat_jids[id]
|
||||
elif frm_iq:
|
||||
who = helpers.get_full_jid_from_iq(vc)
|
||||
frm, resource = gajim.get_room_and_nick_from_fjid(who)
|
||||
else:
|
||||
|
@ -1139,6 +1151,7 @@ class ConnectionVcard:
|
|||
p = self.add_sha(p)
|
||||
self.connection.send(p)
|
||||
else:
|
||||
#('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...})
|
||||
self.dispatch('VCARD', vcard)
|
||||
|
||||
class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ConnectionCommands, ConnectionPubSub):
|
||||
|
@ -1655,7 +1668,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
|
|||
if not ptype or ptype == 'unavailable':
|
||||
if gajim.config.get('log_contact_status_changes') and self.name\
|
||||
not in no_log_for and jid_stripped not in no_log_for:
|
||||
gc_c = gajim.contacts.get_gc_contact(self.name, jid_stripped, resource)
|
||||
gc_c = gajim.contacts.get_gc_contact(self.name, jid_stripped,
|
||||
resource)
|
||||
st = status or ''
|
||||
if gc_c:
|
||||
jid = gc_c.jid
|
||||
|
@ -1672,25 +1686,6 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
|
|||
gajim.interface.remove_avatar_files(jid_stripped, puny_nick)
|
||||
# if it's a gc presence, don't ask vcard here. We may ask it to
|
||||
# real jid in gui part.
|
||||
if self.vcard_shas.has_key(who) and not is_gc:
|
||||
# Verify sha cached in mem
|
||||
if avatar_sha != self.vcard_shas[who]:
|
||||
# avatar has been updated
|
||||
self.request_vcard(who, True)
|
||||
elif not is_gc: # Verify sha cached in hdd
|
||||
cached_vcard = self.get_cached_vcard(who, True)
|
||||
if cached_vcard and cached_vcard.has_key('PHOTO') and \
|
||||
cached_vcard['PHOTO'].has_key('SHA'):
|
||||
cached_sha = cached_vcard['PHOTO']['SHA']
|
||||
else:
|
||||
cached_sha = ''
|
||||
if cached_sha != avatar_sha:
|
||||
# avatar has been updated
|
||||
# sha in mem will be updated later
|
||||
self.request_vcard(who, True)
|
||||
else:
|
||||
# save sha in mem NOW
|
||||
self.vcard_shas[who] = avatar_sha
|
||||
if ns_muc_user_x:
|
||||
# Room has been destroyed. see
|
||||
# http://www.xmpp.org/extensions/xep-0045.html#destroyroom
|
||||
|
@ -1708,7 +1703,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
|
|||
statusCode = prs.getStatusCode()
|
||||
self.dispatch('GC_NOTIFY', (jid_stripped, show, status, resource,
|
||||
prs.getRole(), prs.getAffiliation(), prs.getJid(),
|
||||
reason, prs.getActor(), statusCode, prs.getNewNick()))
|
||||
reason, prs.getActor(), statusCode, prs.getNewNick(),
|
||||
avatar_sha))
|
||||
return
|
||||
|
||||
if ptype == 'subscribe':
|
||||
|
|
|
@ -814,8 +814,7 @@ class Interface:
|
|||
show = 'offline'
|
||||
gc_c = gajim.contacts.create_gc_contact(room_jid = jid,
|
||||
name = nick, show = show)
|
||||
c = gajim.contacts.contact_from_gc_contact(gc_c)
|
||||
self.roster.new_chat(c, account, private_chat = True)
|
||||
self.roster.new_private_chat(gc_c, account)
|
||||
ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account)
|
||||
ctrl.print_conversation('Error %s: %s' % (array[1], array[2]),
|
||||
'status')
|
||||
|
@ -1053,7 +1052,7 @@ class Interface:
|
|||
|
||||
def handle_event_gc_notify(self, account, array):
|
||||
#'GC_NOTIFY' (account, (room_jid, show, status, nick,
|
||||
# role, affiliation, jid, reason, actor, statusCode, newNick))
|
||||
# role, affiliation, jid, reason, actor, statusCode, newNick, avatar_sha))
|
||||
nick = array[3]
|
||||
if not nick:
|
||||
return
|
||||
|
@ -1074,7 +1073,7 @@ class Interface:
|
|||
return
|
||||
if control:
|
||||
control.chg_contact_status(nick, show, status, array[4], array[5],
|
||||
array[6], array[7], array[8], array[9], array[10])
|
||||
array[6], array[7], array[8], array[9], array[10], array[11])
|
||||
if control and not control.parent_win:
|
||||
gajim.interface.roster.draw_contact(room_jid, account)
|
||||
|
||||
|
|
|
@ -97,10 +97,11 @@ def tree_cell_data_func(column, renderer, model, iter, tv=None):
|
|||
class PrivateChatControl(ChatControl):
|
||||
TYPE_ID = message_control.TYPE_PM
|
||||
|
||||
def __init__(self, parent_win, contact, acct):
|
||||
def __init__(self, parent_win, gc_contact, contact, acct):
|
||||
room_jid = contact.jid.split('/')[0]
|
||||
room_ctrl = gajim.interface.msg_win_mgr.get_control(room_jid, acct)
|
||||
self.room_name = room_ctrl.name
|
||||
self.gc_contact = gc_contact
|
||||
ChatControl.__init__(self, parent_win, contact, acct)
|
||||
self.TYPE_ID = 'pm'
|
||||
|
||||
|
@ -852,7 +853,7 @@ class GroupchatControl(ChatControlBase):
|
|||
model[iter][C_AVATAR] = scaled_pixbuf
|
||||
|
||||
def chg_contact_status(self, nick, show, status, role, affiliation, jid,
|
||||
reason, actor, statusCode, new_nick, tim = None):
|
||||
reason, actor, statusCode, new_nick, avatar_sha, tim = None):
|
||||
'''When an occupant changes his or her status'''
|
||||
if show == 'invisible':
|
||||
return
|
||||
|
@ -861,7 +862,7 @@ class GroupchatControl(ChatControlBase):
|
|||
role = 'visitor'
|
||||
if not affiliation:
|
||||
affiliation = 'none'
|
||||
|
||||
fake_jid = self.room_jid + '/' + nick
|
||||
newly_created = False
|
||||
if show in ('offline', 'error'):
|
||||
if statusCode == '307':
|
||||
|
@ -924,8 +925,7 @@ class GroupchatControl(ChatControlBase):
|
|||
elif statusCode == 'destroyed': # Room has been destroyed
|
||||
self.print_conversation(reason, 'info', tim)
|
||||
|
||||
if len(gajim.events.get_events(self.account,
|
||||
self.room_jid + '/' + nick)) == 0:
|
||||
if len(gajim.events.get_events(self.account, fake_jid)) == 0:
|
||||
self.remove_contact(nick)
|
||||
else:
|
||||
c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
|
||||
|
@ -948,20 +948,48 @@ class GroupchatControl(ChatControlBase):
|
|||
if statusCode == '201': # We just created the room
|
||||
gajim.connections[self.account].request_gc_config(self.room_jid)
|
||||
else:
|
||||
gc_c = gajim.contacts.get_gc_contact(self.account, self.room_jid,
|
||||
nick)
|
||||
# Re-get vcard if avatar has changed
|
||||
# We do that here because we may request it to the real JID if we
|
||||
# knows it. connections.py doesn't know it.
|
||||
con = gajim.connections[self.account]
|
||||
if gc_c.jid:
|
||||
real_jid = gc_c.jid
|
||||
if gc_c.resource:
|
||||
real_jid += '/' + gc_c.resource
|
||||
else:
|
||||
real_jid = fake_jid
|
||||
if con.vcard_shas.has_key(fake_jid):
|
||||
if avatar_sha != con.vcard_shas[fake_jid]:
|
||||
con.request_vcard(real_jid, fake_jid)
|
||||
else:
|
||||
cached_vcard = con.get_cached_vcard(fake_jid, True)
|
||||
if cached_vcard and cached_vcard.has_key('PHOTO') and \
|
||||
cached_vcard['PHOTO'].has_key('SHA'):
|
||||
cached_sha = cached_vcard['PHOTO']['SHA']
|
||||
else:
|
||||
cached_sha = ''
|
||||
if cached_sha != avatar_sha:
|
||||
# avatar has been updated
|
||||
# sha in mem will be updated later
|
||||
con.request_vcard(real_jid, fake_jid)
|
||||
else:
|
||||
# save sha in mem NOW
|
||||
self.vcard_shas[fake_jid] = avatar_sha
|
||||
|
||||
actual_role = self.get_role(nick)
|
||||
if role != actual_role:
|
||||
self.remove_contact(nick)
|
||||
self.add_contact_to_roster(nick, show, role,
|
||||
affiliation, status, jid)
|
||||
else:
|
||||
c = gajim.contacts.get_gc_contact(self.account, self.room_jid,
|
||||
nick)
|
||||
if c.show == show and c.status == status and \
|
||||
c.affiliation == affiliation: #no change
|
||||
if gc_c.show == show and gc_c.status == status and \
|
||||
gc_c.affiliation == affiliation: # no change
|
||||
return
|
||||
c.show = show
|
||||
c.affiliation = affiliation
|
||||
c.status = status
|
||||
gc_c.show = show
|
||||
gc_c.affiliation = affiliation
|
||||
gc_c.status = status
|
||||
self.draw_contact(nick)
|
||||
if self.parent_win:
|
||||
self.parent_win.redraw_tab(self)
|
||||
|
@ -1028,21 +1056,16 @@ class GroupchatControl(ChatControlBase):
|
|||
server = gajim.get_server_from_jid(self.room_jid)
|
||||
if gajim.config.get('ask_avatars_on_startup') and \
|
||||
not server.startswith('irc'):
|
||||
if j:
|
||||
fjid = j
|
||||
if resource:
|
||||
fjid += '/' + resource
|
||||
else:
|
||||
fjid = self.room_jid + '/' + nick
|
||||
if j:
|
||||
pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(fjid)
|
||||
else:
|
||||
pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(fjid, True)
|
||||
fake_jid = self.room_jid + '/' + nick
|
||||
pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(fake_jid, True)
|
||||
if pixbuf == 'ask':
|
||||
if j:
|
||||
gajim.connections[self.account].request_vcard(fjid)
|
||||
fjid = j
|
||||
if resource:
|
||||
fjid += '/' + resource
|
||||
gajim.connections[self.account].request_vcard(fjid, fake_jid)
|
||||
else:
|
||||
gajim.connections[self.account].request_vcard(fjid, True)
|
||||
gajim.connections[self.account].request_vcard(fake_jid, fake_jid)
|
||||
if nick == self.nick: # we became online
|
||||
self.got_connected()
|
||||
self.list_treeview.expand_row((model.get_path(role_iter)), False)
|
||||
|
@ -1789,12 +1812,11 @@ class GroupchatControl(ChatControlBase):
|
|||
|
||||
def _start_private_message(self, nick):
|
||||
gc_c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
|
||||
c = gajim.contacts.contact_from_gc_contact(gc_c)
|
||||
nick_jid = c.jid
|
||||
nick_jid = gc_c.get_full_jid()
|
||||
|
||||
win = gajim.interface.msg_win_mgr.get_window(nick_jid, self.account)
|
||||
if not win:
|
||||
gajim.interface.roster.new_chat(c, self.account, private_chat = True)
|
||||
gajim.interface.roster.new_private_chat(gc_c, self.account)
|
||||
win = gajim.interface.msg_win_mgr.get_window(nick_jid, self.account)
|
||||
win.set_active_tab(nick_jid, self.account)
|
||||
win.window.present()
|
||||
|
@ -2008,9 +2030,6 @@ class GroupchatControl(ChatControlBase):
|
|||
'''Call vcard_information_window class to display user's information'''
|
||||
c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
|
||||
c2 = gajim.contacts.contact_from_gc_contact(c)
|
||||
if c.jid:
|
||||
c2.jid = c.jid
|
||||
c2.resource = c.resource
|
||||
if gajim.interface.instances[self.account]['infos'].has_key(c2.jid):
|
||||
gajim.interface.instances[self.account]['infos'][c2.jid].window.\
|
||||
present()
|
||||
|
|
|
@ -3464,12 +3464,23 @@ class RosterWindow:
|
|||
self.actions_menu_needs_rebuild = True
|
||||
self.update_status_combobox()
|
||||
|
||||
def new_chat(self, contact, account, private_chat = False, resource = None):
|
||||
def new_private_chat(self, gc_contact, account):
|
||||
contact = gajim.contacts.contact_from_gc_contact(gc_contact)
|
||||
type_ = message_control.TYPE_PM
|
||||
fjid = gc_contact.room_jid + '/' + gc_contact.name
|
||||
mw = gajim.interface.msg_win_mgr.get_window(fjid, account)
|
||||
if not mw:
|
||||
mw = gajim.interface.msg_win_mgr.create_window(contact, account, type_)
|
||||
|
||||
chat_control = PrivateChatControl(mw, gc_contact, contact, account)
|
||||
mw.new_tab(chat_control)
|
||||
if len(gajim.events.get_events(account, fjid)):
|
||||
# We call this here to avoid race conditions with widget validation
|
||||
chat_control.read_queue()
|
||||
|
||||
def new_chat(self, contact, account, resource = None):
|
||||
# Get target window, create a control, and associate it with the window
|
||||
if not private_chat:
|
||||
type_ = message_control.TYPE_CHAT
|
||||
else:
|
||||
type_ = message_control.TYPE_PM
|
||||
type_ = message_control.TYPE_CHAT
|
||||
|
||||
fjid = contact.jid
|
||||
if resource:
|
||||
|
@ -3478,10 +3489,7 @@ class RosterWindow:
|
|||
if not mw:
|
||||
mw = gajim.interface.msg_win_mgr.create_window(contact, account, type_)
|
||||
|
||||
if not private_chat:
|
||||
chat_control = ChatControl(mw, contact, account, resource)
|
||||
else:
|
||||
chat_control = PrivateChatControl(mw, contact, account)
|
||||
chat_control = ChatControl(mw, contact, account, resource)
|
||||
|
||||
mw.new_tab(chat_control)
|
||||
|
||||
|
|
|
@ -453,8 +453,11 @@ class VcardWindow:
|
|||
|
||||
self.fill_status_label()
|
||||
|
||||
gajim.connections[self.account].request_vcard(self.contact.jid,
|
||||
(self.gc_contact is not None and not self.gc_contact.jid))
|
||||
if self.gc_contact:
|
||||
gajim.connections[self.account].request_vcard(self.contact.jid,
|
||||
self.gc_contact.get_full_jid())
|
||||
else:
|
||||
gajim.connections[self.account].request_vcard(self.contact.jid)
|
||||
|
||||
def on_close_button_clicked(self, widget):
|
||||
self.window.destroy()
|
||||
|
|
Loading…
Reference in New Issue