Send all presence through the presence module

This commit is contained in:
Philipp Hörist 2018-09-01 17:07:30 +02:00 committed by Philipp Hörist
parent 42a7dbc79a
commit d4d29f8309
7 changed files with 169 additions and 183 deletions

View File

@ -241,7 +241,6 @@ class Config:
'roster_window_skip_taskbar': [opt_bool, False, _('Don\'t show roster in the system taskbar.')],
'use_urgency_hint': [opt_bool, True, _('If true, make the window flash (the default behaviour in most Window Managers) when holding pending events.')],
'notification_timeout': [opt_int, 5],
'send_sha_in_gc_presence': [opt_bool, True, _('Jabberd1.4 does not like sha info when one join a password protected group chat. Turn this option to False to stop sending sha info in group chat presences.')],
'one_message_window': [opt_str, 'always',
#always, never, peracct, pertype should not be translated
_('Controls the window where new messages are placed.\n\'always\' - All messages are sent to a single window.\n\'always_with_roster\' - Like \'always\' but the messages are in a single window along with the roster.\n\'never\' - All messages get their own window.\n\'peracct\' - Messages for each account are sent to a specific window.\n\'pertype\' - Each message type (e.g. chats vs. groupchats) is sent to a specific window.')],

View File

@ -38,7 +38,6 @@ import socket
import operator
import string
import time
import hmac
import hashlib
import json
import logging
@ -60,12 +59,10 @@ from gajim.common import helpers
from gajim.common import app
from gajim.common import gpg
from gajim.common import passwords
from gajim.common import i18n
from gajim.common import idle
from gajim.common.connection_handlers import *
from gajim.common.contacts import GC_Contact
from gajim.common import modules
from gajim.gtkgui_helpers import get_action
log = logging.getLogger('gajim.c.connection')
@ -474,10 +471,11 @@ class CommonConnection:
if self.connection:
app.nec.push_incoming_event(BeforeChangeShowEvent(None,
conn=self, show=show, message=msg))
p = nbxmpp.Presence(typ = 'unavailable')
p = self.add_sha(p, False)
if msg:
p.setStatus(msg)
p = self.get_module('Presence').get_presence(
typ='unavailable',
status=msg,
caps=False)
self.connection.RegisterDisconnectHandler(self._on_disconnected)
self.connection.send(p, now=True)
@ -542,7 +540,6 @@ class Connection(CommonConnection, ConnectionHandlers):
# server {'icq': ['icq.server.com', 'icq2.server.com'], }
self.streamError = ''
self.secret_hmac = str(random.random())[2:].encode('utf-8')
self.removing_account = False
# We only request POSH once
@ -1351,9 +1348,6 @@ class Connection(CommonConnection, ConnectionHandlers):
self.on_connect_auth = None
# END connect
def add_lang(self, stanza):
stanza.setAttr('xml:lang', i18n.LANG)
def send_keepalive(self):
# nothing received for the last foo seconds
if self.connection:
@ -1372,15 +1366,15 @@ class Connection(CommonConnection, ConnectionHandlers):
# offline presence first as it's required by XEP-0126
if self.connected > 1 and self.get_module('PrivacyLists').supported:
self.on_purpose = True
p = nbxmpp.Presence(typ='unavailable')
p = self.add_sha(p, False)
if msg:
p.setStatus(msg)
self.remove_all_transfers()
self.connection.send(p)
self.get_module('Presence').send_presence(
typ='unavailable',
status=msg,
caps=False)
# try to set the privacy rule
iq = self.get_module('PrivacyLists').set_invisible_rule(
self.get_module('PrivacyLists').set_invisible_rule(
callback=self._continue_invisible,
msg=msg,
signed=signed,
@ -1394,13 +1388,12 @@ class Connection(CommonConnection, ConnectionHandlers):
self.connected = app.SHOW_LIST.index('invisible')
self.status = msg
priority = app.get_priority(self.name, 'invisible')
p = nbxmpp.Presence(priority=priority)
p = self.add_sha(p, True)
if msg:
p.setStatus(msg)
if signed:
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
self.connection.send(p)
self.get_module('Presence').send_presence(
priority=priority,
status=msg,
sign=signed)
self.priority = priority
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
show='invisible'))
@ -1486,20 +1479,21 @@ class Connection(CommonConnection, ConnectionHandlers):
if not msg:
msg = ''
if show == 'offline':
p = nbxmpp.Presence(typ='unavailable', to=jid)
p = self.add_sha(p, False)
if msg:
p.setStatus(msg)
self.get_module('Presence').send_presence(
jid,
'unavailable',
caps=False,
status=msg)
else:
signed = self.get_signed_presence(msg)
priority = app.get_priority(self.name, sshow)
p = nbxmpp.Presence(typ=None, priority=priority, show=sshow, to=jid)
p = self.add_sha(p)
if msg:
p.setStatus(msg)
if signed:
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
self.connection.send(p)
self.get_module('Presence').send_presence(
jid,
priority=priority,
show=sshow,
status=msg,
sign=signed)
def _change_to_invisible(self, msg):
signed = self.get_signed_presence(msg)
@ -1512,18 +1506,16 @@ class Connection(CommonConnection, ConnectionHandlers):
def _update_status(self, show, msg, idle_time=None):
xmpp_show = helpers.get_xmpp_show(show)
priority = app.get_priority(self.name, xmpp_show)
p = nbxmpp.Presence(typ=None, priority=priority, show=xmpp_show)
p = self.add_sha(p)
if msg:
p.setStatus(msg)
signed = self.get_signed_presence(msg)
if signed:
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
if idle_time:
idle_node = p.setTag('idle', namespace=nbxmpp.NS_IDLE)
idle_node.setAttr('since', idle_time)
self.get_module('Presence').send_presence(
priority=priority,
show=xmpp_show,
status=msg,
sign=signed,
idle_time=idle_time)
if self.connection:
self.connection.send(p)
self.priority = priority
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
show=show))
@ -1654,9 +1646,12 @@ class Connection(CommonConnection, ConnectionHandlers):
if not app.account_is_connected(self.name):
return
show = helpers.get_xmpp_show(app.SHOW_LIST[self.connected])
p = nbxmpp.Presence(to=agent, typ=ptype, show=show)
p = self.add_sha(p, ptype != 'unavailable')
self.connection.send(p)
self.get_module('Presence').send_presence(
agent,
ptype,
show=show,
caps=ptype != 'unavailable')
def send_captcha(self, jid, form_node):
if not app.account_is_connected(self.name):
@ -1697,56 +1692,19 @@ class Connection(CommonConnection, ConnectionHandlers):
password, change_nick, rejoin))
def _join_gc(self, nick, show, room_jid, password, change_nick, rejoin):
# Check time first in the FAST table
last_date = app.logger.get_room_last_message_time(
self.name, room_jid)
if not last_date:
last_date = 0
p = nbxmpp.Presence(to='%s/%s' % (room_jid, nick),
show=show, status=self.status)
h = hmac.new(self.secret_hmac, room_jid.encode('utf-8'), hashlib.md5).\
hexdigest()[:6]
id_ = self.connection.getAnID()
id_ = 'gajim_muc_' + id_ + '_' + h
p.setID(id_)
if app.config.get('send_sha_in_gc_presence'):
p = self.add_sha(p)
self.add_lang(p)
if change_nick:
self.connection.send(p)
return
t = p.setTag(nbxmpp.NS_MUC + ' x')
if muc_caps_cache.has_mam(room_jid):
# The room is MAM capable dont get MUC History
t.setTag('history', {'maxchars': '0'})
self.get_module('Presence').send_presence(
'%s/%s' % (room_jid, nick),
show=show,
status=self.status)
else:
# Request MUC History (not MAM)
tags = {}
timeout = app.config.get_per('rooms', room_jid,
'muc_restore_timeout')
if timeout is None or timeout == -2:
timeout = app.config.get('muc_restore_timeout')
if last_date == 0 and timeout >= 0:
last_date = time.time() - timeout * 60
elif not rejoin and timeout >= 0:
last_date = max(last_date, time.time() - timeout * 60)
last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(
last_date))
tags['since'] = last_date
nb = app.config.get_per('rooms', room_jid, 'muc_restore_lines')
if nb is None or nb == -2:
nb = app.config.get('muc_restore_lines')
if nb >= 0:
tags['maxstanzas'] = nb
if tags:
t.setTag('history', tags)
if password:
t.setTagData('password', password)
self.connection.send(p)
self.get_module('MUC').send_muc_join_presence(
'%s/%s' % (room_jid, nick),
show=show,
status=self.status,
room_jid=room_jid,
password=password,
rejoin=rejoin)
def _nec_gc_message_outgoing(self, obj):
if obj.account != self.name:
@ -1809,26 +1767,20 @@ class Connection(CommonConnection, ConnectionHandlers):
if show == 'offline':
ptype = 'unavailable'
xmpp_show = helpers.get_xmpp_show(show)
p = nbxmpp.Presence(to='%s/%s' % (jid, nick), typ=ptype,
show=xmpp_show, status=status)
h = hmac.new(self.secret_hmac, jid.encode('utf-8'), hashlib.md5).\
hexdigest()[:6]
id_ = self.connection.getAnID()
id_ = 'gajim_muc_' + id_ + '_' + h
p.setID(id_)
if app.config.get('send_sha_in_gc_presence') and show != 'offline':
p = self.add_sha(p, ptype != 'unavailable')
self.add_lang(p)
if auto:
if app.is_installed('IDLE') and app.config.get('autoaway'):
idle_sec = idle.Monitor.get_idle_sec()
idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ',
time.gmtime(time.time() - idle_sec))
idle_node = p.setTag('idle', namespace=nbxmpp.NS_IDLE)
idle_node.setAttr('since', idle_time)
# send instantly so when we go offline, status is sent to gc before we
# disconnect from jabber server
self.connection.send(p)
idle_time = None
if auto and app.is_installed('IDLE') and app.config.get('autoaway'):
idle_sec = idle.Monitor.get_idle_sec()
idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ',
time.gmtime(time.time() - idle_sec))
self.get_module('Presence').send_presence(
'%s/%s' % (jid, nick),
typ=ptype,
show=xmpp_show,
status=status,
caps=ptype != 'unavailable',
idle_time=idle_time)
def get_password(self, callback, type_):
if app.config.get_per('accounts', self.name, 'anonymous_auth') and \

View File

@ -422,20 +422,6 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
app.ged.remove_event_handler('agent-removed', ged.CORE,
self._nec_agent_removed)
def add_sha(self, p, send_caps=True):
p = self.get_module('VCardAvatars').add_update_node(p)
if send_caps:
return self._add_caps(p)
return p
def _add_caps(self, p):
''' advertise our capabilities in presence stanza (xep-0115)'''
c = p.setTag('c', namespace=nbxmpp.NS_CAPS)
c.setAttr('hash', 'sha-1')
c.setAttr('node', 'http://gajim.org')
c.setAttr('ver', app.caps_hash[self.name])
return p
def _ErrorCB(self, con, iq_obj):
log.debug('ErrorCB')
app.nec.push_incoming_event(IqErrorReceivedEvent(None, conn=self,
@ -582,15 +568,14 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
if show not in ['offline', 'online', 'chat', 'away', 'xa', 'dnd']:
return
priority = app.get_priority(self.name, sshow)
p = nbxmpp.Presence(typ=None, priority=priority, show=sshow)
if msg:
p.setStatus(msg)
if signed:
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
p = self.add_sha(p)
self.get_module('Presence').send_presence(
priority=priority,
show=sshow,
status=msg,
sign=signed)
if self.connection:
self.connection.send(p)
self.priority = priority
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
show=show))

View File

@ -288,7 +288,7 @@ PresenceHelperEvent):
xtags = self.stanza.getTags('x')
for x in xtags:
namespace = x.getNamespace()
if namespace == nbxmpp.NS_MUC_USER:
if namespace in (nbxmpp.NS_MUC_USER, nbxmpp.NS_MUC):
self.is_gc = True
elif namespace == nbxmpp.NS_SIGNED:
sig_tag = x
@ -296,14 +296,6 @@ PresenceHelperEvent):
# XEP-0091
self._generate_timestamp(self.stanza.timestamp)
if not self.is_gc and self.id_ and self.id_.startswith('gajim_muc_') \
and self.ptype == 'error':
# Error presences may not include sent stanza, so we don't detect
# it's a muc presence. So detect it by ID
h = hmac.new(self.conn.secret_hmac, self.jid.encode('utf-8'),
hashlib.md5).hexdigest()[:6]
if self.id_.split('_')[-1] == h:
self.is_gc = True
self.status = self.stanza.getStatus() or ''
self._generate_show()
self._generate_prio()

View File

@ -15,6 +15,7 @@
# XEP-0045: Multi-User Chat
# XEP-0249: Direct MUC Invitations
import time
import logging
import nbxmpp
@ -23,6 +24,7 @@ from gajim.common import i18n
from gajim.common.modules import dataforms
from gajim.common import app
from gajim.common import helpers
from gajim.common.caps_cache import muc_caps_cache
from gajim.common.nec import NetworkIncomingEvent
log = logging.getLogger('gajim.c.m.muc')
@ -50,6 +52,56 @@ class MUC:
self._con.muc_jid['jabber'] = from_
raise nbxmpp.NodeProcessed
def send_muc_join_presence(self, *args, room_jid=None, password=None,
rejoin=False, **kwargs):
if not app.account_is_connected(self._account):
return
presence = self._con.get_module('Presence').get_presence(
*args, **kwargs)
if room_jid is not None:
self._add_history_query(presence, room_jid, rejoin)
if password is not None:
presence.setTagData('password', password)
log.debug('Send MUC join presence:\n%s', presence)
self._con.connection.send(presence)
def _add_history_query(self, presence, room_jid, rejoin):
last_date = app.logger.get_room_last_message_time(
self._account, room_jid)
if not last_date:
last_date = 0
history = presence.setTag(nbxmpp.NS_MUC + ' x')
if muc_caps_cache.has_mam(room_jid):
# The room is MAM capable dont get MUC History
history.setTag('history', {'maxchars': '0'})
else:
# Request MUC History (not MAM)
tags = {}
timeout = app.config.get_per('rooms', room_jid,
'muc_restore_timeout')
if timeout is None or timeout == -2:
timeout = app.config.get('muc_restore_timeout')
if last_date == 0 and timeout >= 0:
last_date = time.time() - timeout * 60
elif not rejoin and timeout >= 0:
last_date = max(last_date, time.time() - timeout * 60)
last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(
last_date))
tags['since'] = last_date
nb = app.config.get_per('rooms', room_jid, 'muc_restore_lines')
if nb is None or nb == -2:
nb = app.config.get('muc_restore_lines')
if nb >= 0:
tags['maxstanzas'] = nb
if tags:
history.setTag('history', tags)
def set_subject(self, room_jid, subject):
if not app.account_is_connected(self._account):
return

View File

@ -75,9 +75,7 @@ class Presence:
raise nbxmpp.NodeProcessed
if auto_auth or is_transport or jid in self.jids_for_auto_auth:
presence = nbxmpp.Presence(fjid, 'subscribed')
presence = self._add_sha(presence)
self._con.connection.send(presence)
self.send_presence(fjid, 'subscribed')
if not status:
status = _('I would like to add you to my roster.')
@ -124,17 +122,13 @@ class Presence:
if not app.account_is_connected(self._account):
return
log.info('Subscribed: %s', jid)
presence = nbxmpp.Presence(jid, 'subscribed')
presence = self._add_sha(presence)
self._con.connection.send(presence)
self.send_presence(jid, 'subscribed')
def unsubscribed(self, jid):
if not app.account_is_connected(self._account):
return
log.info('Unsubscribed: %s', jid)
presence = nbxmpp.Presence(jid, 'unsubscribed')
presence = self._add_sha(presence)
self._con.connection.send(presence)
self.send_presence(jid, 'unsubscribed')
def unsubscribe(self, jid, remove_auth=True):
if not app.account_is_connected(self._account):
@ -150,7 +144,7 @@ class Presence:
self._con.getRoster().Unsubscribe(jid)
self._con.getRoster().setItem(jid)
def subscribe(self, jid, msg='', name='', groups=None,
def subscribe(self, jid, msg=None, name='', groups=None,
auto_auth=False, user_nick=''):
if not app.account_is_connected(self._account):
return
@ -172,29 +166,40 @@ class Presence:
item.addChild('group').setData(group)
self._con.connection.send(iq)
presence = nbxmpp.Presence(jid, 'subscribe')
if user_nick:
nick = presence.setTag('nick', namespace=nbxmpp.NS_NICK)
nick.setData(user_nick)
presence = self._add_sha(presence)
if msg:
presence.setStatus(msg)
self.send_presence(jid, 'subscribe', msg)
def get_presence(self, to=None, typ=None, priority=None,
show=None, status=None, nick=None, caps=True,
sign=None, idle_time=None):
presence = nbxmpp.Presence(to, typ, priority, show, status)
if nick is not None:
nick_tag = presence.setTag('nick', namespace=nbxmpp.NS_NICK)
nick_tag.setData(nick)
if sign:
presence.setTag(nbxmpp.NS_SIGNED + ' x').setData(sign)
if idle_time is not None:
idle_node = presence.setTag('idle', namespace=nbxmpp.NS_IDLE)
idle_node.setAttr('since', idle_time)
self._con.get_module('VCardAvatars').add_update_node(presence)
if caps:
attrs = {'hash': 'sha-1',
'node': 'http://gajim.org',
'ver': app.caps_hash[self._account]}
presence.setTag('c', namespace=nbxmpp.NS_CAPS, attrs=attrs)
return presence
def send_presence(self, *args, **kwargs):
if not app.account_is_connected(self._account):
return
presence = self.get_presence(*args, **kwargs)
log.debug('Send presence:\n%s', presence)
self._con.connection.send(presence)
def _add_sha(self, presence, send_caps=True):
vcard = self._con.get_module('VCardAvatars')
presence = vcard.add_update_node(presence)
if send_caps:
return self._add_caps(presence)
return presence
def _add_caps(self, presence):
c = presence.setTag('c', namespace=nbxmpp.NS_CAPS)
c.setAttr('hash', 'sha-1')
c.setAttr('node', 'http://gajim.org')
c.setAttr('ver', app.caps_hash[self._account])
return presence
def parse_show(stanza):
show = stanza.getShow()

View File

@ -173,10 +173,12 @@ class VCardAvatars:
log.debug('Avatar already advertised')
return
show = helpers.get_xmpp_show(app.SHOW_LIST[self._con.connected])
pres = nbxmpp.Presence(typ=None, priority=self._con.priority,
show=show, status=self._con.status)
pres = self._con.add_sha(pres)
self._con.connection.send(pres)
self._con.get_module('Presence').send_presence(
priority=self._con.priority,
show=show,
status=self._con.status)
self.avatar_advertised = True
app.interface.update_avatar(self._account,
self._con.get_own_jid().getStripped())
@ -189,7 +191,6 @@ class VCardAvatars:
log.info('Send avatar presence to: %s %s',
node.getTo() or own_jid, sha or 'no sha advertised')
update.setTagData('photo', sha)
return node
def get_instance(*args, **kwargs):