JEP 172 support (user nickname) Fixes #464 and #884

This commit is contained in:
Yann Leboulanger 2006-06-01 15:23:38 +00:00
parent 25e6d9f4aa
commit 59c3b7b3c8
8 changed files with 91 additions and 29 deletions

View File

@ -97,7 +97,8 @@ class ChatControlBase(MessageControl):
event_keymod): event_keymod):
pass # Derived should implement this rather than connecting to the event itself. pass # Derived should implement this rather than connecting to the event itself.
def __init__(self, type_id, parent_win, widget_name, display_names, contact, acct, resource = None): def __init__(self, type_id, parent_win, widget_name, display_names, contact,
acct, resource = None):
MessageControl.__init__(self, type_id, parent_win, widget_name, MessageControl.__init__(self, type_id, parent_win, widget_name,
display_names, contact, acct, resource = resource); display_names, contact, acct, resource = resource);
# when/if we do XHTML we will but formatting buttons back # when/if we do XHTML we will but formatting buttons back
@ -175,6 +176,10 @@ class ChatControlBase(MessageControl):
self.style_event_id = 0 self.style_event_id = 0
self.conv_textview.tv.show() self.conv_textview.tv.show()
# For JEP-0172
self.user_nick = None
# moved from ChatControl # moved from ChatControl
def _on_banner_eventbox_button_press_event(self, widget, event): def _on_banner_eventbox_button_press_event(self, widget, event):
'''If right-clicked, show popup''' '''If right-clicked, show popup'''
@ -425,13 +430,18 @@ class ChatControlBase(MessageControl):
if not message or message == '\n': if not message or message == '\n':
return return
if not self._process_command(message): if not self._process_command(message):
MessageControl.send_message(self, message, keyID, type = type, MessageControl.send_message(self, message, keyID, type = type,
chatstate = chatstate, msg_id = msg_id, chatstate = chatstate, msg_id = msg_id,
composing_jep = composing_jep, resource = resource) composing_jep = composing_jep, resource = resource,
user_nick = self.user_nick)
# Record message history # Record message history
self.save_sent_message(message) self.save_sent_message(message)
# Be sure to send user nickname only once according to JEP-0172
self.user_nick = None
# Clear msg input # Clear msg input
message_buffer = self.msg_textview.get_buffer() message_buffer = self.msg_textview.get_buffer()
message_buffer.set_text('') # clear message buffer (and tv of course) message_buffer.set_text('') # clear message buffer (and tv of course)

View File

@ -87,8 +87,18 @@ class Connection(ConnectionHandlers):
self.on_connect_failure = None self.on_connect_failure = None
self.retrycount = 0 self.retrycount = 0
self.jids_for_auto_auth = [] # list of jid to auto-authorize self.jids_for_auto_auth = [] # list of jid to auto-authorize
# END __init__ # END __init__
def build_user_nick(self, user_nick):
df = common.xmpp.DataForm(typ = 'result')
field = df.setField('FORM_TYPE')
field.setType('hidden')
field.setValue(common.xmpp.NS_PROFILE)
field = df.setField('nickname')
field.delAttr('type')
field.setValue(user_nick)
return df
def put_event(self, ev): def put_event(self, ev):
if gajim.handlers.has_key(ev[0]): if gajim.handlers.has_key(ev[0]):
gajim.handlers[ev[0]](self.name, ev[1]) gajim.handlers[ev[0]](self.name, ev[1])
@ -606,7 +616,8 @@ class Connection(ConnectionHandlers):
self.connection.send(msg_iq) self.connection.send(msg_iq)
def send_message(self, jid, msg, keyID, type = 'chat', subject='', def send_message(self, jid, msg, keyID, type = 'chat', subject='',
chatstate = None, msg_id = None, composing_jep = None, resource = None): chatstate = None, msg_id = None, composing_jep = None, resource = None,
user_nick = None):
if not self.connection: if not self.connection:
return return
if not msg and chatstate is None: if not msg and chatstate is None:
@ -637,6 +648,11 @@ class Connection(ConnectionHandlers):
if msgenc: if msgenc:
msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc) msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc)
# JEP-0172: user_nickname
if user_nick:
df = self.build_user_nick(user_nick)
msg_iq.addChild(node = df)
# chatstates - if peer supports jep85 or jep22, send chatstates # chatstates - if peer supports jep85 or jep22, send chatstates
# please note that the only valid tag inside a message containing a <body> # please note that the only valid tag inside a message containing a <body>
# tag is the active event # tag is the active event
@ -691,7 +707,7 @@ class Connection(ConnectionHandlers):
self.connection.send(p) self.connection.send(p)
def request_subscription(self, jid, msg = '', name = '', groups = [], def request_subscription(self, jid, msg = '', name = '', groups = [],
auto_auth = False): auto_auth = False, user_nick = ''):
if not self.connection: if not self.connection:
return return
gajim.log.debug('subscription request for %s' % jid) gajim.log.debug('subscription request for %s' % jid)
@ -709,6 +725,9 @@ class Connection(ConnectionHandlers):
self.connection.send(iq) self.connection.send(iq)
p = common.xmpp.Presence(jid, 'subscribe') p = common.xmpp.Presence(jid, 'subscribe')
if user_nick:
df = self.build_user_nick(user_nick)
p.addChild(node = df)
p = self.add_sha(p) p = self.add_sha(p)
if not msg: if not msg:
msg = _('I would like to add you to my roster.') msg = _('I would like to add you to my roster.')

View File

@ -1295,6 +1295,16 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco)
composing_jep = 'JEP-0022' composing_jep = 'JEP-0022'
if not msgtxt and chatstate_child.getTag('composing'): if not msgtxt and chatstate_child.getTag('composing'):
chatstate = 'composing' chatstate = 'composing'
# JEP-0172 User Nickname
user_nick = ''
xtags = msg.getTags('x', attrs = {'type': 'result'},
namespace = common.xmpp.NS_DATA)
for xtag in xtags:
df = common.xmpp.DataForm(node = xtag)
field = df.getField('FORM_TYPE')
if not field or field.getValue() != common.xmpp.NS_PROFILE:
continue
user_nick = df.getField('nickname').getValue()
if encTag and GnuPG.USE_GPG: if encTag and GnuPG.USE_GPG:
#decrypt #decrypt
@ -1338,7 +1348,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco)
msg_id = gajim.logger.write('chat_msg_recv', frm, msgtxt, tim = tim, msg_id = gajim.logger.write('chat_msg_recv', frm, msgtxt, tim = tim,
subject = subject) subject = subject)
self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, subject, self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, subject,
chatstate, msg_id, composing_jep)) chatstate, msg_id, composing_jep, user_nick))
else: # it's single message else: # it's single message
if self.name not in no_log_for and jid not in no_log_for and msgtxt: if self.name not in no_log_for and jid not in no_log_for and msgtxt:
gajim.logger.write('single_msg_recv', frm, msgtxt, tim = tim, gajim.logger.write('single_msg_recv', frm, msgtxt, tim = tim,
@ -1352,7 +1362,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco)
self.dispatch('GC_INVITATION',(frm, jid_from, reason, password)) self.dispatch('GC_INVITATION',(frm, jid_from, reason, password))
else: else:
self.dispatch('MSG', (frm, msgtxt, tim, encrypted, 'normal', self.dispatch('MSG', (frm, msgtxt, tim, encrypted, 'normal',
subject, chatstate, msg_id, composing_jep)) subject, chatstate, msg_id, composing_jep, user_nick))
# END messageCB # END messageCB
def _presenceCB(self, con, prs): def _presenceCB(self, con, prs):
@ -1367,25 +1377,36 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco)
is_gc = False # is it a GC presence ? is_gc = False # is it a GC presence ?
sigTag = None sigTag = None
avatar_sha = None avatar_sha = None
user_nick = '' # for JEP-0172
transport_auto_auth = False transport_auto_auth = False
xtags = prs.getTags('x') xtags = prs.getTags('x')
for x in xtags: for x in xtags:
if x.getNamespace().startswith(common.xmpp.NS_MUC): namespace = x.getNamespace()
if namespace.startswith(common.xmpp.NS_MUC):
is_gc = True is_gc = True
if x.getNamespace() == common.xmpp.NS_SIGNED: if namespace == common.xmpp.NS_SIGNED:
sigTag = x sigTag = x
if x.getNamespace() == common.xmpp.NS_VCARD_UPDATE: if namespace == common.xmpp.NS_VCARD_UPDATE:
avatar_sha = x.getTagData('photo') avatar_sha = x.getTagData('photo')
if x.getNamespace() == common.xmpp.NS_DELAY: if namespace == common.xmpp.NS_DELAY:
# JEP-0091 # JEP-0091
tim = prs.getTimestamp() tim = prs.getTimestamp()
tim = time.strptime(tim, '%Y%m%dT%H:%M:%S') tim = time.strptime(tim, '%Y%m%dT%H:%M:%S')
timestamp = time.localtime(timegm(tim)) timestamp = time.localtime(timegm(tim))
if x.getNamespace() == 'http://delx.cjb.net/protocol/roster-subsync': if namespace == 'http://delx.cjb.net/protocol/roster-subsync':
# see http://trac.gajim.org/ticket/326 # see http://trac.gajim.org/ticket/326
agent = gajim.get_server_from_jid(jid_stripped) agent = gajim.get_server_from_jid(jid_stripped)
if self.connection.getRoster().getItem(agent): # to be sure it's a transport contact if self.connection.getRoster().getItem(agent): # to be sure it's a transport contact
transport_auto_auth = True transport_auto_auth = True
if namespace == common.xmpp.NS_DATA:
# JEP-0172
df = common.xmpp.DataForm(node = x)
if df.getType() != 'result':
continue
field = df.getField('FORM_TYPE')
if not field or field.getValue() != common.xmpp.NS_PROFILE:
continue
user_nick = df.getField('nickname').getValue()
no_log_for = gajim.config.get_per('accounts', self.name, no_log_for = gajim.config.get_per('accounts', self.name,
'no_log_for').split() 'no_log_for').split()
@ -1475,11 +1496,11 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco)
resource, prio, keyID, timestamp)) resource, prio, keyID, timestamp))
if transport_auto_auth: if transport_auto_auth:
self.automatically_added.append(jid_stripped) self.automatically_added.append(jid_stripped)
self.request_subscription(jid_stripped) self.request_subscription(jid_stripped, name = user_nick)
else: else:
if not status: if not status:
status = _('I would like to add you to my roster.') status = _('I would like to add you to my roster.')
self.dispatch('SUBSCRIBE', (who, status)) self.dispatch('SUBSCRIBE', (who, status, user_nick))
elif ptype == 'subscribed': elif ptype == 'subscribed':
if jid_stripped in self.automatically_added: if jid_stripped in self.automatically_added:
self.automatically_added.remove(jid_stripped) self.automatically_added.remove(jid_stripped)

View File

@ -67,6 +67,7 @@ NS_PHYSLOC ='http://jabber.org/protocol/physloc' # JEP-01
NS_PRESENCE ='presence' # Jabberd2 NS_PRESENCE ='presence' # Jabberd2
NS_PRIVACY ='jabber:iq:privacy' NS_PRIVACY ='jabber:iq:privacy'
NS_PRIVATE ='jabber:iq:private' NS_PRIVATE ='jabber:iq:private'
NS_PROFILE ='http://jabber.org/protocol/profile' # JEP-0154
NS_PUBSUB ='http://jabber.org/protocol/pubsub' # JEP-0060 NS_PUBSUB ='http://jabber.org/protocol/pubsub' # JEP-0060
NS_REGISTER ='jabber:iq:register' NS_REGISTER ='jabber:iq:register'
NS_ROSTER ='jabber:iq:roster' NS_ROSTER ='jabber:iq:roster'

View File

@ -362,7 +362,7 @@ class ChangeStatusMessageDialog:
class AddNewContactWindow: class AddNewContactWindow:
'''Class for AddNewContactWindow''' '''Class for AddNewContactWindow'''
def __init__(self, account = None, jid = None): def __init__(self, account = None, jid = None, user_nick = None):
self.account = account self.account = account
if account == None: if account == None:
# fill accounts with active accounts # fill accounts with active accounts
@ -431,7 +431,10 @@ _('Please fill in the data of the contact you want to add in account %s') %accou
else: else:
self.uid_entry.set_text(jid) self.uid_entry.set_text(jid)
self.protocol_combobox.set_active(0) self.protocol_combobox.set_active(0)
self.set_nickname() if user_nick:
self.nickname_entry.set_text(user_nick)
else:
self.set_nickname()
self.nickname_entry.grab_focus() self.nickname_entry.grab_focus()
self.group_comboboxentry = self.xml.get_widget('group_comboboxentry') self.group_comboboxentry = self.xml.get_widget('group_comboboxentry')
liststore = gtk.ListStore(str) liststore = gtk.ListStore(str)
@ -860,11 +863,12 @@ ok_handler = None):
return response return response
class SubscriptionRequestWindow: class SubscriptionRequestWindow:
def __init__(self, jid, text, account): def __init__(self, jid, text, account, user_nick = None):
xml = gtkgui_helpers.get_glade('subscription_request_window.glade') xml = gtkgui_helpers.get_glade('subscription_request_window.glade')
self.window = xml.get_widget('subscription_request_window') self.window = xml.get_widget('subscription_request_window')
self.jid = jid self.jid = jid
self.account = account self.account = account
self.user_nick = user_nick
if len(gajim.connections) >= 2: if len(gajim.connections) >= 2:
prompt_text = _('Subscription request for account %s from %s')\ prompt_text = _('Subscription request for account %s from %s')\
% (account, self.jid) % (account, self.jid)
@ -883,7 +887,7 @@ class SubscriptionRequestWindow:
gajim.connections[self.account].send_authorization(self.jid) gajim.connections[self.account].send_authorization(self.jid)
self.window.destroy() self.window.destroy()
if self.jid not in gajim.contacts.get_jid_list(self.account): if self.jid not in gajim.contacts.get_jid_list(self.account):
AddNewContactWindow(self.account, self.jid) AddNewContactWindow(self.account, self.jid, self.user_nick)
def on_contact_info_button_clicked(self, widget): def on_contact_info_button_clicked(self, widget):
'''ask vcard''' '''ask vcard'''

View File

@ -468,7 +468,7 @@ class Interface:
def handle_event_msg(self, account, array): def handle_event_msg(self, account, array):
# 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject, # 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject,
# chatstate)) # chatstate, msg_id, composing_jep, user_nick)) user_nick is JEP-0172
full_jid_with_resource = array[0] full_jid_with_resource = array[0]
jid = gajim.get_jid_without_resource(full_jid_with_resource) jid = gajim.get_jid_without_resource(full_jid_with_resource)
@ -555,7 +555,7 @@ class Interface:
else: else:
# array: (jid, msg, time, encrypted, msg_type, subject) # array: (jid, msg, time, encrypted, msg_type, subject)
self.roster.on_message(jid, message, array[2], account, array[3], self.roster.on_message(jid, message, array[2], account, array[3],
msg_type, array[5], resource, msg_id) msg_type, array[5], resource, msg_id, array[9])
nickname = gajim.get_name_from_jid(account, jid) nickname = gajim.get_name_from_jid(account, jid)
# Check and do wanted notifications # Check and do wanted notifications
notify.notify('new_message', jid, account, [msg_type, first, nickname, message]) notify.notify('new_message', jid, account, [msg_type, first, nickname, message])
@ -611,8 +611,8 @@ class Interface:
helpers.play_sound('message_sent') helpers.play_sound('message_sent')
def handle_event_subscribe(self, account, array): def handle_event_subscribe(self, account, array):
#('SUBSCRIBE', account, (jid, text)) #('SUBSCRIBE', account, (jid, text, user_nick)) user_nick is JEP-0172
dialogs.SubscriptionRequestWindow(array[0], array[1], account) dialogs.SubscriptionRequestWindow(array[0], array[1], account, array[2])
if self.remote_ctrl: if self.remote_ctrl:
self.remote_ctrl.raise_signal('Subscribe', (account, array)) self.remote_ctrl.raise_signal('Subscribe', (account, array))

View File

@ -131,10 +131,12 @@ class MessageControl:
return n return n
def send_message(self, message, keyID = '', type = 'chat', def send_message(self, message, keyID = '', type = 'chat',
chatstate = None, msg_id = None, composing_jep = None, resource = None): chatstate = None, msg_id = None, composing_jep = None, resource = None,
user_nick = None):
'''Send the given message to the active tab''' '''Send the given message to the active tab'''
jid = self.contact.jid jid = self.contact.jid
# Send and update history # Send and update history
gajim.connections[self.account].send_message(jid, message, keyID, gajim.connections[self.account].send_message(jid, message, keyID,
type = type, chatstate = chatstate, msg_id = msg_id, type = type, chatstate = chatstate, msg_id = msg_id,
composing_jep = composing_jep, resource = self.resource) composing_jep = composing_jep, resource = self.resource,
user_nick = user_nick)

View File

@ -1606,7 +1606,7 @@ class RosterWindow:
menu.popup(None, self.tree, None, event_button, event.time) menu.popup(None, self.tree, None, event_button, event.time)
def on_add_to_roster(self, widget, contact, account): def on_add_to_roster(self, widget, contact, account):
dialogs.AddNewContactWindow(account, contact.jid) dialogs.AddNewContactWindow(account, contact.jid, contact.name)
def authorize(self, widget, jid, account): def authorize(self, widget, jid, account):
'''Authorize a contact (by re-sending auth menuitem)''' '''Authorize a contact (by re-sending auth menuitem)'''
@ -1622,7 +1622,7 @@ class RosterWindow:
else: else:
group = [] group = []
gajim.connections[account].request_subscription(jid, txt, pseudo, group, gajim.connections[account].request_subscription(jid, txt, pseudo, group,
auto_auth) auto_auth, gajim.nicks[account])
contact = gajim.contacts.get_contact_with_highest_priority(account, jid) contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
if not contact: if not contact:
keyID = '' keyID = ''
@ -2118,7 +2118,8 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
mw.new_tab(gc_control) mw.new_tab(gc_control)
def on_message(self, jid, msg, tim, account, encrypted = False, def on_message(self, jid, msg, tim, account, encrypted = False,
msg_type = '', subject = None, resource = '', msg_id = None): msg_type = '', subject = None, resource = '', msg_id = None,
user_nick = ''):
'''when we receive a message''' '''when we receive a message'''
contact = None contact = None
# if chat window will be for specific resource # if chat window will be for specific resource
@ -2141,8 +2142,12 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
'attached_gpg_keys').split() 'attached_gpg_keys').split()
if jid in attached_keys: if jid in attached_keys:
keyID = attached_keys[attached_keys.index(jid) + 1] keyID = attached_keys[attached_keys.index(jid) + 1]
if user_nick:
nick = user_nick
else:
nick = jid.split('@')[0]
contact = gajim.contacts.create_contact(jid = jid, contact = gajim.contacts.create_contact(jid = jid,
name = jid.split('@')[0], groups = [_('Not in Roster')], name = nick, groups = [_('Not in Roster')],
show = 'not in roster', status = '', ask = 'none', show = 'not in roster', status = '', ask = 'none',
keyID = keyID, resource = resource) keyID = keyID, resource = resource)
gajim.contacts.add_contact(account, contact) gajim.contacts.add_contact(account, contact)