refactor normal and zeroconf Connection objects with a CommonConnection class

This commit is contained in:
Yann Leboulanger 2009-11-18 11:06:09 +01:00
parent 960e402cf0
commit 88f3104c4e
5 changed files with 691 additions and 775 deletions

File diff suppressed because it is too large Load Diff

View File

@ -92,6 +92,7 @@ RECV_BUFSIZE = 32768 # 2x maximum size of ssl packet, should be plenty
DATA_RECEIVED = 'DATA RECEIVED' DATA_RECEIVED = 'DATA RECEIVED'
DATA_SENT = 'DATA SENT' DATA_SENT = 'DATA SENT'
DATA_ERROR = 'DATA ERROR'
DISCONNECTED = 'DISCONNECTED' DISCONNECTED = 'DISCONNECTED'
DISCONNECTING = 'DISCONNECTING' DISCONNECTING = 'DISCONNECTING'

View File

@ -23,7 +23,7 @@ from common.xmpp.idlequeue import IdleObject
from common.xmpp import dispatcher_nb, simplexml from common.xmpp import dispatcher_nb, simplexml
from common.xmpp.plugin import * from common.xmpp.plugin import *
from common.xmpp.simplexml import ustr from common.xmpp.simplexml import ustr
from common.xmpp.transports_nb import DATA_RECEIVED, DATA_SENT from common.xmpp.transports_nb import DATA_RECEIVED, DATA_SENT, DATA_ERROR
from common.zeroconf import zeroconf from common.zeroconf import zeroconf
from common.xmpp.protocol import * from common.xmpp.protocol import *
@ -395,6 +395,7 @@ class P2PConnection(IdleObject, PlugIn):
False, else send it instantly. False, else send it instantly.
If supplied data is unicode string, encode it to utf-8. If supplied data is unicode string, encode it to utf-8.
''' '''
print 'ici'
if self.state <= 0: if self.state <= 0:
return return
@ -416,8 +417,11 @@ class P2PConnection(IdleObject, PlugIn):
ids = self.client.conn_holder.ids_of_awaiting_messages ids = self.client.conn_holder.ids_of_awaiting_messages
if self.fd in ids and len(ids[self.fd]) > 0: if self.fd in ids and len(ids[self.fd]) > 0:
for (id_, thread_id) in ids[self.fd]: for (id_, thread_id) in ids[self.fd]:
self._owner.Dispatcher.Event('', DATA_ERROR, (self.client.to, if hasattr(self._owner, 'Dispatcher'):
thread_id)) self._owner.Dispatcher.Event('', DATA_ERROR, (self.client.to,
thread_id))
else:
self._owner.on_not_ok('conenction timeout')
ids[self.fd] = [] ids[self.fd] = []
self.pollend() self.pollend()
@ -578,6 +582,8 @@ class ClientZeroconf:
self.hash_to_port = {} self.hash_to_port = {}
self.listener = None self.listener = None
self.ids_of_awaiting_messages = {} self.ids_of_awaiting_messages = {}
self.disconnect_handlers = []
self.disconnecting = False
def connect(self, show, msg): def connect(self, show, msg):
self.port = self.start_listener(self.caller.port) self.port = self.start_listener(self.caller.port)
@ -632,6 +638,9 @@ class ClientZeroconf:
self.last_msg = msg self.last_msg = msg
def disconnect(self): def disconnect(self):
# to avoid recursive calls
if self.disconnecting:
return
if self.listener: if self.listener:
self.listener.disconnect() self.listener.disconnect()
self.listener = None self.listener = None
@ -642,6 +651,14 @@ class ClientZeroconf:
self.roster.zeroconf = None self.roster.zeroconf = None
self.roster._data = None self.roster._data = None
self.roster = None self.roster = None
self.disconnecting = True
for i in reversed(self.disconnect_handlers):
log.debug('Calling disconnect handler %s' % i)
i()
self.disconnecting = False
def start_disconnect(self):
self.disconnect()
def kill_all_connections(self): def kill_all_connections(self):
for connection in self.connections.values(): for connection in self.connections.values():
@ -720,6 +737,14 @@ class ClientZeroconf:
P2PClient(None, item['address'], item['port'], self, P2PClient(None, item['address'], item['port'], self,
[(stanza, is_message)], to, on_ok=on_ok, on_not_ok=on_not_ok) [(stanza, is_message)], to, on_ok=on_ok, on_not_ok=on_not_ok)
def RegisterDisconnectHandler(self, handler):
''' Register handler that will be called on disconnect.'''
self.disconnect_handlers.append(handler)
def UnregisterDisconnectHandler(self, handler):
''' Unregister handler that is called on disconnect.'''
self.disconnect_handlers.remove(handler)
def SendAndWaitForResponse(self, stanza, timeout=None, func=None, args=None): def SendAndWaitForResponse(self, stanza, timeout=None, func=None, args=None):
''' '''
Send stanza and wait for recipient's response to it. Will call transports Send stanza and wait for recipient's response to it. Will call transports

View File

@ -57,10 +57,10 @@ from session import ChatControlSession
class ConnectionVcard(connection_handlers.ConnectionVcard): class ConnectionVcard(connection_handlers.ConnectionVcard):
def add_sha(self, p, send_caps = True): def add_sha(self, p, send_caps = True):
pass return p
def add_caps(self, p): def add_caps(self, p):
pass return p
def request_vcard(self, jid = None, is_fake_jid = False): def request_vcard(self, jid = None, is_fake_jid = False):
pass pass

View File

@ -5,7 +5,7 @@
## - Nikos Kouremenos <nkour@jabber.org> ## - Nikos Kouremenos <nkour@jabber.org>
## - Dimitur Kirov <dkirov@gmail.com> ## - Dimitur Kirov <dkirov@gmail.com>
## - Travis Shirk <travis@pobox.com> ## - Travis Shirk <travis@pobox.com>
## - Stefan Bethge <stefan@lanpartei.de> ## - Stefan Bethge <stefan@lanpartei.de>
## ##
## Copyright (C) 2003-2004 Yann Leboulanger <asterix@lagaule.org> ## Copyright (C) 2003-2004 Yann Leboulanger <asterix@lagaule.org>
## Vincent Hanquez <tab@snarc.org> ## Vincent Hanquez <tab@snarc.org>
@ -43,64 +43,29 @@ if os.name != 'nt':
import getpass import getpass
import gobject import gobject
from common.connection import CommonConnection
from common import gajim from common import gajim
from common import GnuPG from common import GnuPG
from common.zeroconf import client_zeroconf from common.zeroconf import client_zeroconf
from common.zeroconf import zeroconf from common.zeroconf import zeroconf
from connection_handlers_zeroconf import * from connection_handlers_zeroconf import *
class ConnectionZeroconf(ConnectionHandlersZeroconf): class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
'''Connection class''' '''Connection class'''
def __init__(self, name): def __init__(self, name):
CommonConnection.__init__(self, name)
ConnectionHandlersZeroconf.__init__(self) ConnectionHandlersZeroconf.__init__(self)
# system username # system username
self.username = None self.username = None
self.name = name
self.server_resource = '' # zeroconf has no resource, fake an empty one self.server_resource = '' # zeroconf has no resource, fake an empty one
self.connected = 0 # offline
self.connection = None
self.gpg = None
self.USE_GPG = False
if gajim.HAVE_GPG:
self.USE_GPG = True
self.gpg = GnuPG.GnuPG(gajim.config.get('use_gpg_agent'))
self.is_zeroconf = True self.is_zeroconf = True
self.privacy_rules_supported = False
self.blocked_list = []
self.blocked_contacts = []
self.blocked_groups = []
self.blocked_all = False
self.status = ''
self.old_show = ''
self.priority = 0
self.call_resolve_timeout = False self.call_resolve_timeout = False
# we don't need a password, but must be non-empty
self.time_to_reconnect = None
#self.new_account_info = None
self.bookmarks = []
#we don't need a password, but must be non-empty
self.password = 'zeroconf' self.password = 'zeroconf'
self.autoconnect = False self.autoconnect = False
self.sync_with_global_status = True
self.no_log_for = False
self.pep_supported = False
self.pep = {}
# Do we continue connection when we get roster (send presence,get vcard...)
self.continue_connect_info = None
if gajim.HAVE_GPG:
self.USE_GPG = True
self.gpg = GnuPG.GnuPG(gajim.config.get('use_gpg_agent'))
self.get_config_values_or_default() self.get_config_values_or_default()
self.muc_jid = {} # jid of muc server for each transport type
self.vcard_supported = False
self.private_storage_supported = False
def get_config_values_or_default(self): def get_config_values_or_default(self):
''' get name, host, port from config, or ''' get name, host, port from config, or
create zeroconf account with default values''' create zeroconf account with default values'''
@ -108,79 +73,61 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
if not gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'name'): if not gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'name'):
gajim.log.debug('Creating zeroconf account') gajim.log.debug('Creating zeroconf account')
gajim.config.add_per('accounts', gajim.ZEROCONF_ACC_NAME) gajim.config.add_per('accounts', gajim.ZEROCONF_ACC_NAME)
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'autoconnect', True) gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME,
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'no_log_for', '') 'autoconnect', True)
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'password', 'zeroconf') gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'no_log_for',
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'sync_with_global_status', True) '')
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'password',
'zeroconf')
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME,
'sync_with_global_status', True)
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'custom_port', 5298) gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME,
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'is_zeroconf', True) 'custom_port', 5298)
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME,
'is_zeroconf', True)
#XXX make sure host is US-ASCII #XXX make sure host is US-ASCII
self.host = unicode(socket.gethostname()) self.host = unicode(socket.gethostname())
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'hostname', self.host) gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'hostname',
self.port = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'custom_port') self.host)
self.autoconnect = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'autoconnect') self.port = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
self.sync_with_global_status = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'sync_with_global_status') 'custom_port')
self.no_log_for = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'no_log_for') self.autoconnect = gajim.config.get_per('accounts',
self.first = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_first_name') gajim.ZEROCONF_ACC_NAME, 'autoconnect')
self.last = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_last_name') self.sync_with_global_status = gajim.config.get_per('accounts',
self.jabber_id = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_jabber_id') gajim.ZEROCONF_ACC_NAME, 'sync_with_global_status')
self.email = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_email') self.first = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
'zeroconf_first_name')
self.last = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
'zeroconf_last_name')
self.jabber_id = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
'zeroconf_jabber_id')
self.email = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
'zeroconf_email')
if not self.username: if not self.username:
self.username = unicode(getpass.getuser()) self.username = unicode(getpass.getuser())
gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'name', self.username) gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, 'name',
self.username)
else: else:
self.username = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'name') self.username = gajim.config.get_per('accounts',
gajim.ZEROCONF_ACC_NAME, 'name')
# END __init__ # END __init__
def dispatch(self, event, data): def check_jid(self, jid):
gajim.interface.dispatch(event, self.name, data) return jid
def _reconnect(self): def _reconnect(self):
# Do not try to reco while we are already trying # Do not try to reco while we are already trying
self.time_to_reconnect = None self.time_to_reconnect = None
gajim.log.debug('reconnect') gajim.log.debug('reconnect')
# signed = self.get_signed_msg(self.status)
self.disconnect() self.disconnect()
self.change_status(self.old_show, self.status) self.change_status(self.old_show, self.status)
def quit(self, kill_core):
if kill_core and self.connected > 1:
self.disconnect()
def disable_account(self): def disable_account(self):
self.disconnect() self.disconnect()
def test_gpg_passphrase(self, password):
self.gpg.passphrase = password
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
signed = self.gpg.sign('test', keyID)
self.gpg.password = None
return signed != 'BAD_PASSPHRASE'
def get_signed_msg(self, msg):
signed = ''
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
if keyID and self.USE_GPG:
use_gpg_agent = gajim.config.get('use_gpg_agent')
if self.connected < 2 and self.gpg.passphrase is None and \
not use_gpg_agent:
# We didn't set a passphrase
self.dispatch('ERROR', (_('OpenPGP passphrase was not given'),
#%s is the account name here
_('You will be connected to %s without OpenPGP.') % self.name))
self.USE_GPG = False
elif self.gpg.passphrase is not None or use_gpg_agent:
signed = self.gpg.sign(msg, keyID)
if signed == 'BAD_PASSPHRASE':
self.USE_GPG = False
signed = ''
if self.connected < 2:
self.dispatch('BAD_PASSPHRASE', ())
return signed
def _on_resolve_timeout(self): def _on_resolve_timeout(self):
if self.connected: if self.connected:
self.connection.resolve_all() self.connection.resolve_all()
@ -197,8 +144,10 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
# callbacks called from zeroconf # callbacks called from zeroconf
def _on_new_service(self, jid): def _on_new_service(self, jid):
self.roster.setItem(jid) self.roster.setItem(jid)
self.dispatch('ROSTER_INFO', (jid, self.roster.getName(jid), 'both', 'no', self.roster.getGroups(jid))) self.dispatch('ROSTER_INFO', (jid, self.roster.getName(jid), 'both', 'no',
self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid), self.roster.getMessage(jid), 'local', 0, None, 0, None)) self.roster.getGroups(jid)))
self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid),
self.roster.getMessage(jid), 'local', 0, None, 0, None))
def _on_remove_service(self, jid): def _on_remove_service(self, jid):
self.roster.delItem(jid) self.roster.delItem(jid)
@ -206,15 +155,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
# keyID, timestamp, contact_nickname)) # keyID, timestamp, contact_nickname))
self.dispatch('NOTIFY', (jid, 'offline', '', 'local', 0, None, 0, None)) self.dispatch('NOTIFY', (jid, 'offline', '', 'local', 0, None, 0, None))
def _on_disconnected(self):
self.disconnect()
self.dispatch('STATUS', 'offline')
self.dispatch('CONNECTION_LOST',
(_('Connection with account "%s" has been lost') % self.name,
_('To continue sending and receiving messages, you will need to reconnect.')))
self.status = 'offline'
self.disconnect()
def _disconnectedReconnCB(self): def _disconnectedReconnCB(self):
'''Called when we are disconnected. Comes from network manager for example '''Called when we are disconnected. Comes from network manager for example
we don't try to reconnect, network manager will tell us when we can''' we don't try to reconnect, network manager will tell us when we can'''
@ -234,9 +174,10 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.dispatch('ZC_NAME_CONFLICT', alt_name) self.dispatch('ZC_NAME_CONFLICT', alt_name)
def _on_error(self, message): def _on_error(self, message):
self.dispatch('ERROR', (_('Avahi error'), _("%s\nLink-local messaging might not work properly.") % message)) self.dispatch('ERROR', (_('Avahi error'),
_('%s\nLink-local messaging might not work properly.') % message))
def connect(self, show = 'online', msg = ''): def connect(self, show='online', msg=''):
self.get_config_values_or_default() self.get_config_values_or_default()
if not self.connection: if not self.connection:
self.connection = client_zeroconf.ClientZeroconf(self) self.connection = client_zeroconf.ClientZeroconf(self)
@ -267,10 +208,12 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.roster = self.connection.getRoster() self.roster = self.connection.getRoster()
self.dispatch('ROSTER', self.roster) self.dispatch('ROSTER', self.roster)
#display contacts already detected and resolved # display contacts already detected and resolved
for jid in self.roster.keys(): for jid in self.roster.keys():
self.dispatch('ROSTER_INFO', (jid, self.roster.getName(jid), 'both', 'no', self.roster.getGroups(jid))) self.dispatch('ROSTER_INFO', (jid, self.roster.getName(jid), 'both',
self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid), self.roster.getMessage(jid), 'local', 0, None, 0, None)) 'no', self.roster.getGroups(jid)))
self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid),
self.roster.getMessage(jid), 'local', 0, None, 0, None))
self.connected = STATUS_LIST.index(show) self.connected = STATUS_LIST.index(show)
@ -279,7 +222,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
gobject.timeout_add_seconds(5, self._on_resolve_timeout) gobject.timeout_add_seconds(5, self._on_resolve_timeout)
return True return True
def disconnect(self, on_purpose = False): def disconnect(self, on_purpose=False):
self.connected = 0 self.connected = 0
self.time_to_reconnect = None self.time_to_reconnect = None
if self.connection: if self.connection:
@ -291,15 +234,20 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
def reannounce(self): def reannounce(self):
if self.connected: if self.connected:
txt = {} txt = {}
txt['1st'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_first_name') txt['1st'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
txt['last'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_last_name') 'zeroconf_first_name')
txt['jid'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_jabber_id') txt['last'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
txt['email'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_email') 'zeroconf_last_name')
txt['jid'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
'zeroconf_jabber_id')
txt['email'] = gajim.config.get_per('accounts',
gajim.ZEROCONF_ACC_NAME, 'zeroconf_email')
self.connection.reannounce(txt) self.connection.reannounce(txt)
def update_details(self): def update_details(self):
if self.connection: if self.connection:
port = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'custom_port') port = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME,
'custom_port')
if port != self.port: if port != self.port:
self.port = port self.port = port
last_msg = self.connection.last_msg last_msg = self.connection.last_msg
@ -311,41 +259,18 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
else: else:
self.reannounce() self.reannounce()
def change_status(self, show, msg, sync = False, auto = False): def connect_and_init(self, show, msg, sign_msg):
if not show in STATUS_LIST: # to check for errors from zeroconf
return -1 check = True
self.status = show if not self.connect(show, msg):
return
check = True #to check for errors from zeroconf if show != 'invisible':
# 'connect' check = self.connection.announce()
if show != 'offline' and not self.connected: else:
if not self.connect(show, msg):
return
if show != 'invisible':
check = self.connection.announce()
else:
self.connected = STATUS_LIST.index(show)
self.dispatch('SIGNED_IN', ())
# 'disconnect'
elif show == 'offline' and self.connected:
self.disconnect()
self.time_to_reconnect = None
# update status
elif show != 'offline' and self.connected:
was_invisible = self.connected == STATUS_LIST.index('invisible')
self.connected = STATUS_LIST.index(show) self.connected = STATUS_LIST.index(show)
if show == 'invisible': self.dispatch('SIGNED_IN', ())
check = check and self.connection.remove_announce()
elif was_invisible:
if not self.connected:
check = check and self.connect(show, msg)
check = check and self.connection.announce()
if self.connection and not show == 'invisible':
check = check and self.connection.set_show_msg(show, msg)
#stay offline when zeroconf does something wrong # stay offline when zeroconf does something wrong
if check: if check:
self.dispatch('STATUS', show) self.dispatch('STATUS', show)
else: else:
@ -356,136 +281,63 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
(_('Could not change status of account "%s"') % self.name, (_('Could not change status of account "%s"') % self.name,
_('Please check if avahi-daemon is running.'))) _('Please check if avahi-daemon is running.')))
def get_status(self): def _change_to_invisible(self, msg):
return STATUS_LIST[self.connected] if self.connection.remove_announce():
self.dispatch('STATUS', 'invisible')
else:
# show notification that avahi or system bus is down
self.dispatch('STATUS', 'offline')
self.status = 'offline'
self.dispatch('CONNECTION_LOST',
(_('Could not change status of account "%s"') % self.name,
_('Please check if avahi-daemon is running.')))
def _change_from_invisible(self):
self.connection.announce()
def _update_status(self, show, msg):
if self.connection.set_show_msg(show, msg):
self.dispatch('STATUS', show)
else:
# show notification that avahi or system bus is down
self.dispatch('STATUS', 'offline')
self.status = 'offline'
self.dispatch('CONNECTION_LOST',
(_('Could not change status of account "%s"') % self.name,
_('Please check if avahi-daemon is running.')))
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_xep=None, resource=None, chatstate=None, msg_id=None, composing_xep=None, resource=None,
user_nick=None, xhtml=None, session=None, forward_from=None, form_node=None, user_nick=None, xhtml=None, session=None, forward_from=None, form_node=None,
original_message=None, delayed=None, callback=None, callback_args=[]): original_message=None, delayed=None, callback=None, callback_args=[]):
fjid = jid
if msg and not xhtml and gajim.config.get(
'rst_formatting_outgoing_messages'):
from common.rst_xhtml_generator import create_xhtml
xhtml = create_xhtml(msg)
if not self.connection:
return
if not msg and chatstate is None:
return
if self.status in ('invisible', 'offline'):
self.dispatch('MSGERROR', [unicode(jid), -1,
_('You are not connected or not visible to others. Your message '
'could not be sent.'), None, None, session])
return
msgtxt = msg
msgenc = ''
if keyID and self.USE_GPG:
if keyID == 'UNKNOWN':
error = _('Neither the remote presence is signed, nor a key was assigned.')
elif keyID.endswith('MISMATCH'):
error = _('The contact\'s key (%s) does not match the key assigned in Gajim.' % keyID[:8])
else:
# encrypt
msgenc, error = self.gpg.encrypt(msg, [keyID])
if msgenc and not error:
msgtxt = '[This message is encrypted]'
lang = os.getenv('LANG')
if lang is not None or lang != 'en': # we're not english
msgtxt = _('[This message is encrypted]') +\
' ([This message is encrypted])' # one in locale and one en
else:
# Encryption failed, do not send message
tim = time.localtime()
self.dispatch('MSGNOTSENT', (jid, error, msgtxt, tim, session))
return
if type_ == 'chat':
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ=type_,
xhtml=xhtml)
else:
if subject:
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ='normal',
subject=subject, xhtml=xhtml)
else:
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ='normal',
xhtml=xhtml)
if msgenc:
msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc)
# chatstates - if peer supports jep85 or jep22, send chatstates
# please note that the only valid tag inside a message containing a <body>
# tag is the active event
if chatstate is not None:
if composing_xep == 'XEP-0085' or not composing_xep:
# JEP-0085
msg_iq.setTag(chatstate, namespace = common.xmpp.NS_CHATSTATES)
if composing_xep == 'XEP-0022' or not composing_xep:
# JEP-0022
chatstate_node = msg_iq.setTag('x', namespace = common.xmpp.NS_EVENT)
if not msgtxt: # when no <body>, add <id>
if not msg_id: # avoid putting 'None' in <id> tag
msg_id = ''
chatstate_node.setTagData('id', msg_id)
# when msgtxt, requests JEP-0022 composing notification
if chatstate is 'composing' or msgtxt:
chatstate_node.addChild(name = 'composing')
if forward_from:
addresses = msg_iq.addChild('addresses',
namespace=common.xmpp.NS_ADDRESS)
addresses.addChild('address', attrs = {'type': 'ofrom',
'jid': forward_from})
# XEP-0203
if delayed:
our_jid = gajim.get_jid_from_account(self.name) + '/' + \
self.server_resource
timestamp = time.strftime('%Y-%m-%dT%TZ', time.gmtime(delayed))
msg_iq.addChild('delay', namespace=common.xmpp.NS_DELAY2,
attrs={'from': our_jid, 'stamp': timestamp})
if session:
session.last_send = time.time()
msg_iq.setThread(session.thread_id)
if session.enable_encryption:
msg_iq = session.encrypt_stanza(msg_iq)
def on_send_ok(id):
no_log_for = gajim.config.get_per('accounts', self.name, 'no_log_for')
ji = gajim.get_jid_without_resource(jid)
if session.is_loggable() and self.name not in no_log_for and\
ji not in no_log_for:
log_msg = msg
if subject:
log_msg = _('Subject: %(subject)s\n%(message)s') % \
{'subject': subject, 'message': msg}
if log_msg:
if type_ == 'chat':
kind = 'chat_msg_sent'
else:
kind = 'single_msg_sent'
gajim.logger.write(kind, jid, log_msg)
def on_send_ok(msg_id):
self.dispatch('MSGSENT', (jid, msg, keyID)) self.dispatch('MSGSENT', (jid, msg, keyID))
if callback: if callback:
callback(id, *callback_args) callback(msg_id, *callback_args)
self.log_message(jid, msg, forward_from, session, original_message,
subject, type_)
def on_send_not_ok(reason): def on_send_not_ok(reason):
reason += ' ' + _('Your message could not be sent.') reason += ' ' + _('Your message could not be sent.')
self.dispatch('MSGERROR', [jid, -1, reason, None, None, session]) self.dispatch('MSGERROR', [jid, -1, reason, None, None, session])
ret = self.connection.send(msg_iq, msg is not None, on_ok=on_send_ok,
on_not_ok=on_send_not_ok)
if ret == -1:
# Contact Offline
self.dispatch('MSGERROR', [jid, -1, _('Contact is offline. Your message could not be sent.'), None, None, session])
def cb(jid, msg, keyID, forward_from, session, original_message, subject,
type_, msg_iq):
ret = self.connection.send(msg_iq, msg is not None, on_ok=on_send_ok,
on_not_ok=on_send_not_ok)
if ret == -1:
# Contact Offline
self.dispatch('MSGERROR', [jid, -1, _('Contact is offline. Your '
'message could not be sent.'), None, None, session])
self._prepare_message(jid, msg, keyID, type_=type_, subject=subject,
chatstate=chatstate, msg_id=msg_id, composing_xep=composing_xep,
resource=resource, user_nick=user_nick, xhtml=xhtml, session=session,
forward_from=forward_from, form_node=form_node,
original_message=original_message, delayed=delayed, callback=cb)
def send_stanza(self, stanza): def send_stanza(self, stanza):
# send a stanza untouched # send a stanza untouched
@ -495,95 +347,10 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
stanza = common.xmpp.Protocol(node=stanza) stanza = common.xmpp.Protocol(node=stanza)
self.connection.send(stanza) self.connection.send(stanza)
def ack_subscribed(self, jid):
gajim.log.debug('This should not happen (ack_subscribed)')
def ack_unsubscribed(self, jid):
gajim.log.debug('This should not happen (ack_unsubscribed)')
def request_subscription(self, jid, msg = '', name = '', groups = [],
auto_auth = False):
gajim.log.debug('This should not happen (request_subscription)')
def send_authorization(self, jid):
gajim.log.debug('This should not happen (send_authorization)')
def refuse_authorization(self, jid):
gajim.log.debug('This should not happen (refuse_authorization)')
def unsubscribe(self, jid, remove_auth = True):
gajim.log.debug('This should not happen (unsubscribe)')
def unsubscribe_agent(self, agent):
gajim.log.debug('This should not happen (unsubscribe_agent)')
def update_contact(self, jid, name, groups):
if self.connection:
self.connection.getRoster().setItem(jid = jid, name = name,
groups = groups)
def update_contacts(self, contacts):
'''update multiple roster items'''
if self.connection:
self.connection.getRoster().setItemMulti(contacts)
def new_account(self, name, config, sync = False):
gajim.log.debug('This should not happen (new_account)')
def _on_new_account(self, con = None, con_type = None):
gajim.log.debug('This should not happen (_on_new_account)')
def account_changed(self, new_name):
self.name = new_name
def request_last_status_time(self, jid, resource):
gajim.log.debug('This should not happen (request_last_status_time)')
def request_os_info(self, jid, resource):
gajim.log.debug('This should not happen (request_os_info)')
def get_settings(self):
gajim.log.debug('This should not happen (get_settings)')
def get_bookmarks(self):
gajim.log.debug('This should not happen (get_bookmarks)')
def store_bookmarks(self):
gajim.log.debug('This should not happen (store_bookmarks)')
def get_metacontacts(self):
gajim.log.debug('This should not happen (get_metacontacts)')
def send_agent_status(self, agent, ptype):
gajim.log.debug('This should not happen (send_agent_status)')
def gpg_passphrase(self, passphrase):
if self.gpg:
use_gpg_agent = gajim.config.get('use_gpg_agent')
if use_gpg_agent:
self.gpg.passphrase = None
else:
self.gpg.passphrase = passphrase
def ask_gpg_keys(self):
if self.gpg:
keys = self.gpg.get_keys()
return keys
return None
def ask_gpg_secrete_keys(self):
if self.gpg:
keys = self.gpg.get_secret_keys()
return keys
return None
def _event_dispatcher(self, realm, event, data): def _event_dispatcher(self, realm, event, data):
CommonConnection._event_dispatcher(self, realm, event, data)
if realm == '': if realm == '':
if event == common.xmpp.transports_nb.DATA_RECEIVED: if event == common.xmpp.transports_nb.DATA_ERROR:
self.dispatch('STANZA_ARRIVED', unicode(data, errors = 'ignore'))
elif event == common.xmpp.transports_nb.DATA_SENT:
self.dispatch('STANZA_SENT', unicode(data))
elif event == common.xmpp.transports.DATA_ERROR:
thread_id = data[1] thread_id = data[1]
frm = unicode(data[0]) frm = unicode(data[0])
session = self.get_or_create_session(frm, thread_id) session = self.get_or_create_session(frm, thread_id)
@ -591,9 +358,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
_('Connection to host could not be established: Timeout while ' _('Connection to host could not be established: Timeout while '
'sending data.'), None, None, session]) 'sending data.'), None, None, session])
def load_roster_from_db(self):
return
# END ConnectionZeroconf # END ConnectionZeroconf
# vim: se ts=3: # vim: se ts=3: