encrypt and decrypt GPG messages in a thread, and call a callback when it's finished (sending a message is now asyncronous). Fixes #4445
This commit is contained in:
parent
36f8280620
commit
e0123f0c24
|
@ -312,6 +312,7 @@ class ChatControlBase(MessageControl):
|
||||||
spell.set_language(lang)
|
spell.set_language(lang)
|
||||||
except (gobject.GError, RuntimeError):
|
except (gobject.GError, RuntimeError):
|
||||||
dialogs.AspellDictError(lang)
|
dialogs.AspellDictError(lang)
|
||||||
|
|
||||||
def on_msg_textview_populate_popup(self, textview, menu):
|
def on_msg_textview_populate_popup(self, textview, menu):
|
||||||
'''we override the default context menu and we prepend an option to switch languages'''
|
'''we override the default context menu and we prepend an option to switch languages'''
|
||||||
def _on_select_dictionary(widget, lang):
|
def _on_select_dictionary(widget, lang):
|
||||||
|
@ -594,21 +595,19 @@ class ChatControlBase(MessageControl):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def send_message(self, message, keyID = '', type_ = 'chat', chatstate = None,
|
def send_message(self, message, keyID='', type_='chat', chatstate=None,
|
||||||
msg_id = None, composing_xep = None, resource = None,
|
msg_id=None, composing_xep=None, resource=None, process_command=True,
|
||||||
process_command = True, xhtml = None):
|
xhtml=None, callback=None, callback_args=[]):
|
||||||
'''Send the given message to the active tab. Doesn't return None if error
|
'''Send the given message to the active tab. Doesn't return None if error
|
||||||
'''
|
'''
|
||||||
if not message or message == '\n':
|
if not message or message == '\n':
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ret = None
|
|
||||||
|
|
||||||
if not process_command or not self._process_command(message):
|
if not process_command or not self._process_command(message):
|
||||||
ret = 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_xep=composing_xep,
|
||||||
composing_xep = composing_xep, resource = resource,
|
resource=resource, user_nick=self.user_nick, xhtml=xhtml,
|
||||||
user_nick = self.user_nick, xhtml = xhtml)
|
callback=callback, callback_args=callback_args)
|
||||||
|
|
||||||
# Record message history
|
# Record message history
|
||||||
self.save_sent_message(message)
|
self.save_sent_message(message)
|
||||||
|
@ -620,8 +619,6 @@ class ChatControlBase(MessageControl):
|
||||||
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)
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def save_sent_message(self, message):
|
def save_sent_message(self, message):
|
||||||
# save the message, so user can scroll though the list with key up/down
|
# save the message, so user can scroll though the list with key up/down
|
||||||
size = len(self.sent_history)
|
size = len(self.sent_history)
|
||||||
|
@ -1802,11 +1799,7 @@ class ChatControl(ChatControlBase):
|
||||||
gobject.source_remove(self.possible_inactive_timeout_id)
|
gobject.source_remove(self.possible_inactive_timeout_id)
|
||||||
self._schedule_activity_timers()
|
self._schedule_activity_timers()
|
||||||
|
|
||||||
id_ = ChatControlBase.send_message(self, message, keyID,
|
def _on_sent(id_, contact, message, encrypted, xhtml):
|
||||||
type_ = 'chat', chatstate = chatstate_to_send,
|
|
||||||
composing_xep = composing_xep,
|
|
||||||
process_command = process_command, xhtml = xhtml)
|
|
||||||
if id_:
|
|
||||||
# XXX: Once we have fallback to disco, remove notexistant check
|
# XXX: Once we have fallback to disco, remove notexistant check
|
||||||
if gajim.capscache.is_supported(contact, NS_RECEIPTS) \
|
if gajim.capscache.is_supported(contact, NS_RECEIPTS) \
|
||||||
and not gajim.capscache.is_supported(contact,
|
and not gajim.capscache.is_supported(contact,
|
||||||
|
@ -1820,6 +1813,11 @@ class ChatControl(ChatControlBase):
|
||||||
encrypted = encrypted, xep0184_id = xep0184_id,
|
encrypted = encrypted, xep0184_id = xep0184_id,
|
||||||
xhtml = xhtml)
|
xhtml = xhtml)
|
||||||
|
|
||||||
|
ChatControlBase.send_message(self, message, keyID, type_='chat',
|
||||||
|
chatstate=chatstate_to_send, composing_xep=composing_xep,
|
||||||
|
process_command=process_command, xhtml=xhtml, callback=_on_sent,
|
||||||
|
callback_args=[contact, message, encrypted, xhtml])
|
||||||
|
|
||||||
def check_for_possible_paused_chatstate(self, arg):
|
def check_for_possible_paused_chatstate(self, arg):
|
||||||
''' did we move mouse of that window or write something in message
|
''' did we move mouse of that window or write something in message
|
||||||
textview in the last 5 seconds?
|
textview in the last 5 seconds?
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ class Connection(ConnectionHandlers):
|
||||||
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):
|
original_message=None, delayed=None, callback=None, callback_args=[]):
|
||||||
if not self.connection or self.connected < 2:
|
if not self.connection or self.connected < 2:
|
||||||
return 1
|
return 1
|
||||||
try:
|
try:
|
||||||
|
@ -1151,7 +1151,7 @@ class Connection(ConnectionHandlers):
|
||||||
from common.rst_xhtml_generator import create_xhtml
|
from common.rst_xhtml_generator import create_xhtml
|
||||||
xhtml = create_xhtml(msg)
|
xhtml = create_xhtml(msg)
|
||||||
if not msg and chatstate is None and form_node is None:
|
if not msg and chatstate is None and form_node is None:
|
||||||
return 2
|
return
|
||||||
fjid = jid
|
fjid = jid
|
||||||
if resource:
|
if resource:
|
||||||
fjid += '/' + resource
|
fjid += '/' + resource
|
||||||
|
@ -1168,30 +1168,61 @@ class Connection(ConnectionHandlers):
|
||||||
elif keyID.endswith('MISMATCH'):
|
elif keyID.endswith('MISMATCH'):
|
||||||
error = _('The contact\'s key (%s) does not match the key assigned in Gajim.' % keyID[:8])
|
error = _('The contact\'s key (%s) does not match the key assigned in Gajim.' % keyID[:8])
|
||||||
else:
|
else:
|
||||||
#encrypt
|
def encrypt_thread(msg, keyID):
|
||||||
msgenc, error = self.gpg.encrypt(msg, [keyID])
|
# encrypt message. This function returns (msgenc, error)
|
||||||
if msgenc and not error:
|
return self.gpg.encrypt(msg, [keyID])
|
||||||
msgtxt = '[This message is *encrypted* (See :XEP:`27`]'
|
gajim.thread_interface(encrypt_thread, [msg, keyID],
|
||||||
lang = os.getenv('LANG')
|
self._on_message_encrypted, [type_, msg, msgtxt,
|
||||||
if lang is not None and lang != 'en': # we're not english
|
original_message, fjid, resource, jid, xhtml, subject,
|
||||||
# one in locale and one en
|
chatstate, composing_xep, forward_from, delayed, session,
|
||||||
msgtxt = _('[This message is *encrypted* (See :XEP:`27`]') + \
|
form_node, user_nick, keyID, callback, callback_args])
|
||||||
' (' + msgtxt + ')'
|
return
|
||||||
else:
|
|
||||||
# Encryption failed, do not send message
|
self._on_message_encrypted(self, ('', error), type_, msg, msgtxt,
|
||||||
tim = localtime()
|
original_message, fjid, resource, jid, xhtml, subject, chatstate,
|
||||||
self.dispatch('MSGNOTSENT', (jid, error, msgtxt, tim, session))
|
composing_xep, forward_from, delayed, session, form_node, user_nick,
|
||||||
return 3
|
keyID, callback, callback_args)
|
||||||
|
|
||||||
|
self._on_continue_message(type_, msg, msgtxt, original_message, fjid,
|
||||||
|
resource, jid, xhtml, subject, msgenc, keyID, chatstate, composing_xep,
|
||||||
|
forward_from, delayed, session, form_node, user_nick, callback,
|
||||||
|
callback_args)
|
||||||
|
|
||||||
|
def _on_message_encrypted(self, output, type_, msg, msgtxt, original_message,
|
||||||
|
fjid, resource, jid, xhtml, subject, chatstate, composing_xep, forward_from,
|
||||||
|
delayed, session, form_node, user_nick, keyID, callback, callback_args):
|
||||||
|
msgenc, error = output
|
||||||
|
|
||||||
|
if msgenc and not error:
|
||||||
|
msgtxt = '[This message is *encrypted* (See :XEP:`27`]'
|
||||||
|
lang = os.getenv('LANG')
|
||||||
|
if lang is not None and lang != 'en': # we're not english
|
||||||
|
# one in locale and one en
|
||||||
|
msgtxt = _('[This message is *encrypted* (See :XEP:`27`]') + \
|
||||||
|
' (' + msgtxt + ')'
|
||||||
|
self._on_continue_message(type_, msg, msgtxt, original_message, fjid,
|
||||||
|
resource, jid, xhtml, subject, msgenc, keyID, chatstate,
|
||||||
|
composing_xep, forward_from, delayed, session, form_node, user_nick,
|
||||||
|
callback, callback_args)
|
||||||
|
return
|
||||||
|
# Encryption failed, do not send message
|
||||||
|
tim = localtime()
|
||||||
|
self.dispatch('MSGNOTSENT', (jid, error, msgtxt, tim, session))
|
||||||
|
|
||||||
|
def _on_continue_message(self, type_, msg, msgtxt, original_message, fjid,
|
||||||
|
resource, jid, xhtml, subject, msgenc, keyID, chatstate, composing_xep,
|
||||||
|
forward_from, delayed, session, form_node, user_nick, callback,
|
||||||
|
callback_args):
|
||||||
if type_ == 'chat':
|
if type_ == 'chat':
|
||||||
msg_iq = common.xmpp.Message(to = fjid, body = msgtxt, typ = type_,
|
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ=type_,
|
||||||
xhtml = xhtml)
|
xhtml=xhtml)
|
||||||
else:
|
else:
|
||||||
if subject:
|
if subject:
|
||||||
msg_iq = common.xmpp.Message(to = fjid, body = msgtxt,
|
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ='normal',
|
||||||
typ = 'normal', subject = subject, xhtml = xhtml)
|
subject=subject, xhtml=xhtml)
|
||||||
else:
|
else:
|
||||||
msg_iq = common.xmpp.Message(to = fjid, body = msgtxt,
|
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ='normal',
|
||||||
typ = 'normal', xhtml = xhtml)
|
xhtml=xhtml)
|
||||||
if msgenc:
|
if msgenc:
|
||||||
msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc)
|
msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc)
|
||||||
|
|
||||||
|
@ -1206,11 +1237,9 @@ class Connection(ConnectionHandlers):
|
||||||
# TODO: We might want to write a function so we don't need to
|
# TODO: We might want to write a function so we don't need to
|
||||||
# reproduce that ugly if somewhere else.
|
# reproduce that ugly if somewhere else.
|
||||||
if resource:
|
if resource:
|
||||||
contact = gajim.contacts.get_contact(self.name, jid,
|
contact = gajim.contacts.get_contact(self.name, jid, resource)
|
||||||
resource)
|
|
||||||
else:
|
else:
|
||||||
contact = gajim.contacts. \
|
contact = gajim.contacts.get_contact_with_highest_priority(self.name,
|
||||||
get_contact_with_highest_priority(self.name,
|
|
||||||
jid)
|
jid)
|
||||||
|
|
||||||
# chatstates - if peer supports xep85 or xep22, send chatstates
|
# chatstates - if peer supports xep85 or xep22, send chatstates
|
||||||
|
@ -1226,16 +1255,13 @@ class Connection(ConnectionHandlers):
|
||||||
not gajim.capscache.is_supported(contact,
|
not gajim.capscache.is_supported(contact,
|
||||||
'notexistant')):
|
'notexistant')):
|
||||||
# XEP-0085
|
# XEP-0085
|
||||||
msg_iq.setTag(chatstate,
|
msg_iq.setTag(chatstate, namespace=common.xmpp.NS_CHATSTATES)
|
||||||
namespace = common.xmpp.NS_CHATSTATES)
|
|
||||||
if composing_xep in ('XEP-0022', 'asked_once') or \
|
if composing_xep in ('XEP-0022', 'asked_once') or \
|
||||||
not composing_xep:
|
not composing_xep:
|
||||||
# XEP-0022
|
# XEP-0022
|
||||||
chatstate_node = msg_iq.setTag('x',
|
chatstate_node = msg_iq.setTag('x', namespace=common.xmpp.NS_EVENT)
|
||||||
namespace = common.xmpp.NS_EVENT)
|
|
||||||
if chatstate is 'composing' or msgtxt:
|
if chatstate is 'composing' or msgtxt:
|
||||||
chatstate_node.addChild(
|
chatstate_node.addChild(name='composing')
|
||||||
name = 'composing')
|
|
||||||
|
|
||||||
if forward_from:
|
if forward_from:
|
||||||
addresses = msg_iq.addChild('addresses',
|
addresses = msg_iq.addChild('addresses',
|
||||||
|
@ -1255,8 +1281,7 @@ class Connection(ConnectionHandlers):
|
||||||
if msgtxt and gajim.config.get_per('accounts', self.name,
|
if msgtxt and gajim.config.get_per('accounts', self.name,
|
||||||
'request_receipt') and gajim.capscache.is_supported(contact,
|
'request_receipt') and gajim.capscache.is_supported(contact,
|
||||||
common.xmpp.NS_RECEIPTS):
|
common.xmpp.NS_RECEIPTS):
|
||||||
msg_iq.setTag('request',
|
msg_iq.setTag('request', namespace=common.xmpp.NS_RECEIPTS)
|
||||||
namespace=common.xmpp.NS_RECEIPTS)
|
|
||||||
|
|
||||||
if session:
|
if session:
|
||||||
# XEP-0201
|
# XEP-0201
|
||||||
|
@ -1294,7 +1319,8 @@ class Connection(ConnectionHandlers):
|
||||||
common.logger.LOG_DB_PATH
|
common.logger.LOG_DB_PATH
|
||||||
self.dispatch('MSGSENT', (jid, msg, keyID))
|
self.dispatch('MSGSENT', (jid, msg, keyID))
|
||||||
|
|
||||||
return msg_id
|
if callback:
|
||||||
|
callback(msg_id, *callback_args)
|
||||||
|
|
||||||
def send_stanza(self, stanza):
|
def send_stanza(self, stanza):
|
||||||
''' send a stanza untouched '''
|
''' send a stanza untouched '''
|
||||||
|
|
|
@ -1772,6 +1772,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
|
||||||
encrypted = False
|
encrypted = False
|
||||||
xep_200_encrypted = msg.getTag('c', namespace=common.xmpp.NS_STANZA_CRYPTO)
|
xep_200_encrypted = msg.getTag('c', namespace=common.xmpp.NS_STANZA_CRYPTO)
|
||||||
|
|
||||||
|
session = None
|
||||||
if mtype != 'groupchat':
|
if mtype != 'groupchat':
|
||||||
session = self.get_or_create_session(frm, thread_id)
|
session = self.get_or_create_session(frm, thread_id)
|
||||||
|
|
||||||
|
@ -1853,10 +1854,22 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
|
||||||
|
|
||||||
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
|
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
|
||||||
if keyID:
|
if keyID:
|
||||||
decmsg = self.gpg.decrypt(encmsg, keyID)
|
def decrypt_thread(encmsg, keyID):
|
||||||
# \x00 chars are not allowed in C (so in GTK)
|
decmsg = self.gpg.decrypt(encmsg, keyID)
|
||||||
msgtxt = decmsg.replace('\x00', '')
|
# \x00 chars are not allowed in C (so in GTK)
|
||||||
encrypted = 'xep27'
|
msgtxt = decmsg.replace('\x00', '')
|
||||||
|
encrypted = 'xep27'
|
||||||
|
return (msgtxt, encrypted)
|
||||||
|
gajim.thread_interface(decrypt_thread, [encmsg, keyID],
|
||||||
|
self._on_message_decrypted, [mtype, msg, session, frm, jid,
|
||||||
|
invite, tim])
|
||||||
|
return
|
||||||
|
self._on_message_decrypted((msgtxt, encrypted), mtype, msg, session, frm,
|
||||||
|
jid, invite, tim)
|
||||||
|
|
||||||
|
def _on_message_decrypted(self, output, mtype, msg, session, frm, jid,
|
||||||
|
invite, tim):
|
||||||
|
msgtxt, encrypted = output
|
||||||
if mtype == 'error':
|
if mtype == 'error':
|
||||||
self.dispatch_error_message(msg, msgtxt, session, frm, tim)
|
self.dispatch_error_message(msg, msgtxt, session, frm, tim)
|
||||||
elif mtype == 'groupchat':
|
elif mtype == 'groupchat':
|
||||||
|
|
|
@ -63,6 +63,7 @@ If you start gajim from svn:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
interface = None # The actual interface (the gtk one for the moment)
|
interface = None # The actual interface (the gtk one for the moment)
|
||||||
|
thread_interface = None # Interface to run a thread and then a callback
|
||||||
config = config.Config()
|
config = config.Config()
|
||||||
version = config.get('version')
|
version = config.get('version')
|
||||||
connections = {} # 'account name': 'account (connection.Connection) instance'
|
connections = {} # 'account name': 'account (connection.Connection) instance'
|
||||||
|
|
|
@ -134,7 +134,10 @@ class XMPPDispatcher(PlugIn):
|
||||||
self._owner.lastErrNode = None
|
self._owner.lastErrNode = None
|
||||||
self._owner.lastErr = None
|
self._owner.lastErr = None
|
||||||
self._owner.lastErrCode = None
|
self._owner.lastErrCode = None
|
||||||
self.StreamInit()
|
if hasattr(self._owner, 'StreamInit'):
|
||||||
|
self._owner.StreamInit()
|
||||||
|
else:
|
||||||
|
self.StreamInit()
|
||||||
|
|
||||||
def plugout(self):
|
def plugout(self):
|
||||||
''' Prepares instance to be destructed. '''
|
''' Prepares instance to be destructed. '''
|
||||||
|
|
|
@ -155,11 +155,16 @@ class P2PClient(IdleObject):
|
||||||
if on_not_ok:
|
if on_not_ok:
|
||||||
on_not_ok('Connection to host could not be established.')
|
on_not_ok('Connection to host could not be established.')
|
||||||
return
|
return
|
||||||
id = stanza.getThread()
|
thread_id = stanza.getThread()
|
||||||
|
id_ = stanza.getID()
|
||||||
|
if not id_:
|
||||||
|
id_ = self.Dispatcher.getAnID()
|
||||||
if self.conn_holder.ids_of_awaiting_messages.has_key(self.fd):
|
if self.conn_holder.ids_of_awaiting_messages.has_key(self.fd):
|
||||||
self.conn_holder.ids_of_awaiting_messages[self.fd].append(id)
|
self.conn_holder.ids_of_awaiting_messages[self.fd].append((id_,
|
||||||
|
thread_id))
|
||||||
else:
|
else:
|
||||||
self.conn_holder.ids_of_awaiting_messages[self.fd] = [id]
|
self.conn_holder.ids_of_awaiting_messages[self.fd] = [(id_,
|
||||||
|
thread_id)]
|
||||||
|
|
||||||
def add_stanza(self, stanza, is_message=False):
|
def add_stanza(self, stanza, is_message=False):
|
||||||
if self.Connection:
|
if self.Connection:
|
||||||
|
@ -170,24 +175,32 @@ class P2PClient(IdleObject):
|
||||||
self.stanzaqueue.append((stanza, is_message))
|
self.stanzaqueue.append((stanza, is_message))
|
||||||
|
|
||||||
if is_message:
|
if is_message:
|
||||||
id = stanza.getThread()
|
id_ = stanza.getID()
|
||||||
|
if not id_:
|
||||||
|
id_ = self.Dispatcher.getAnID()
|
||||||
if self.conn_holder.ids_of_awaiting_messages.has_key(self.fd):
|
if self.conn_holder.ids_of_awaiting_messages.has_key(self.fd):
|
||||||
self.conn_holder.ids_of_awaiting_messages[self.fd].append(id)
|
self.conn_holder.ids_of_awaiting_messages[self.fd].append((id_,
|
||||||
|
thread_id))
|
||||||
else:
|
else:
|
||||||
self.conn_holder.ids_of_awaiting_messages[self.fd] = [id]
|
self.conn_holder.ids_of_awaiting_messages[self.fd] = [(id_,
|
||||||
|
thread_id)]
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_message_sent(self, connection_id):
|
def on_message_sent(self, connection_id):
|
||||||
self.conn_holder.ids_of_awaiting_messages[connection_id].pop(0)
|
id_, thread_id = \
|
||||||
|
self.conn_holder.ids_of_awaiting_messages[connection_id].pop(0)
|
||||||
|
if self.on_ok:
|
||||||
|
self.on_ok(id_)
|
||||||
|
# use on_ok only on first message. For others it's called in
|
||||||
|
# ClientZeroconf
|
||||||
|
self.on_ok = None
|
||||||
|
|
||||||
def on_connect(self, conn):
|
def on_connect(self, conn):
|
||||||
self.Connection = conn
|
self.Connection = conn
|
||||||
self.Connection.PlugIn(self)
|
self.Connection.PlugIn(self)
|
||||||
dispatcher_nb.Dispatcher().PlugIn(self)
|
dispatcher_nb.Dispatcher().PlugIn(self)
|
||||||
self._register_handlers()
|
self._register_handlers()
|
||||||
if self.on_ok:
|
|
||||||
self.on_ok()
|
|
||||||
|
|
||||||
def StreamInit(self):
|
def StreamInit(self):
|
||||||
''' Send an initial stream header. '''
|
''' Send an initial stream header. '''
|
||||||
|
@ -393,8 +406,9 @@ class P2PConnection(IdleObject, PlugIn):
|
||||||
def read_timeout(self):
|
def read_timeout(self):
|
||||||
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 in ids[self.fd]:
|
for (id_, thread_id) in ids[self.fd]:
|
||||||
self._owner.Dispatcher.Event('', DATA_ERROR, (self.client.to, id))
|
self._owner.Dispatcher.Event('', DATA_ERROR, (self.client.to,
|
||||||
|
thread_id))
|
||||||
ids[self.fd] = []
|
ids[self.fd] = []
|
||||||
self.pollend()
|
self.pollend()
|
||||||
|
|
||||||
|
@ -679,8 +693,7 @@ class ClientZeroconf:
|
||||||
stanza.setID(id_)
|
stanza.setID(id_)
|
||||||
if conn.add_stanza(stanza, is_message):
|
if conn.add_stanza(stanza, is_message):
|
||||||
if on_ok:
|
if on_ok:
|
||||||
on_ok()
|
on_ok(id_)
|
||||||
return id_
|
|
||||||
|
|
||||||
if item['address'] in self.ip_to_hash:
|
if item['address'] in self.ip_to_hash:
|
||||||
hash_ = self.ip_to_hash[item['address']]
|
hash_ = self.ip_to_hash[item['address']]
|
||||||
|
@ -690,14 +703,11 @@ class ClientZeroconf:
|
||||||
stanza.setID(id_)
|
stanza.setID(id_)
|
||||||
if conn.add_stanza(stanza, is_message):
|
if conn.add_stanza(stanza, is_message):
|
||||||
if on_ok:
|
if on_ok:
|
||||||
on_ok()
|
on_ok(id_)
|
||||||
return id_
|
|
||||||
|
|
||||||
# otherwise open new connection
|
# otherwise open new connection
|
||||||
stanza.setID('zero')
|
stanza.setID('zero')
|
||||||
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)
|
||||||
|
|
||||||
return 'zero'
|
|
||||||
|
|
||||||
# vim: se ts=3:
|
# vim: se ts=3:
|
||||||
|
|
|
@ -364,7 +364,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
|
||||||
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):
|
original_message=None, delayed=None, callback=None, callback_args=[]):
|
||||||
fjid = jid
|
fjid = jid
|
||||||
|
|
||||||
if msg and not xhtml and gajim.config.get(
|
if msg and not xhtml and gajim.config.get(
|
||||||
|
@ -402,7 +402,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
|
||||||
# Encryption failed, do not send message
|
# Encryption failed, do not send message
|
||||||
tim = time.localtime()
|
tim = time.localtime()
|
||||||
self.dispatch('MSGNOTSENT', (jid, error, msgtxt, tim, session))
|
self.dispatch('MSGNOTSENT', (jid, error, msgtxt, tim, session))
|
||||||
return 3
|
return
|
||||||
|
|
||||||
if type_ == 'chat':
|
if type_ == 'chat':
|
||||||
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ=type_,
|
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ=type_,
|
||||||
|
@ -458,7 +458,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
|
||||||
if session.enable_encryption:
|
if session.enable_encryption:
|
||||||
msg_iq = session.encrypt_stanza(msg_iq)
|
msg_iq = session.encrypt_stanza(msg_iq)
|
||||||
|
|
||||||
def on_send_ok():
|
def on_send_ok(id):
|
||||||
no_log_for = gajim.config.get_per('accounts', self.name, 'no_log_for')
|
no_log_for = gajim.config.get_per('accounts', self.name, 'no_log_for')
|
||||||
ji = gajim.get_jid_without_resource(jid)
|
ji = gajim.get_jid_without_resource(jid)
|
||||||
if session.is_loggable() and self.name not in no_log_for and\
|
if session.is_loggable() and self.name not in no_log_for and\
|
||||||
|
@ -473,9 +473,12 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
|
||||||
else:
|
else:
|
||||||
kind = 'single_msg_sent'
|
kind = 'single_msg_sent'
|
||||||
gajim.logger.write(kind, jid, log_msg)
|
gajim.logger.write(kind, jid, log_msg)
|
||||||
|
|
||||||
self.dispatch('MSGSENT', (jid, msg, keyID))
|
self.dispatch('MSGSENT', (jid, msg, keyID))
|
||||||
|
|
||||||
|
if callback:
|
||||||
|
callback(id, *callback_args)
|
||||||
|
|
||||||
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])
|
||||||
|
@ -484,8 +487,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
|
||||||
if ret == -1:
|
if ret == -1:
|
||||||
# Contact Offline
|
# Contact Offline
|
||||||
self.dispatch('MSGERROR', [jid, -1, _('Contact is offline. Your message could not be sent.'), None, None, session])
|
self.dispatch('MSGERROR', [jid, -1, _('Contact is offline. Your message could not be sent.'), None, None, session])
|
||||||
return ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def send_stanza(self, stanza):
|
def send_stanza(self, stanza):
|
||||||
|
|
18
src/gajim.py
18
src/gajim.py
|
@ -423,6 +423,7 @@ parser = optparser.OptionsParser(config_filename)
|
||||||
import roster_window
|
import roster_window
|
||||||
import profile_window
|
import profile_window
|
||||||
import config
|
import config
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
|
||||||
class PassphraseRequest:
|
class PassphraseRequest:
|
||||||
|
@ -482,6 +483,22 @@ class PassphraseRequest:
|
||||||
cancel_handler=_cancel)
|
cancel_handler=_cancel)
|
||||||
self.dialog_created = True
|
self.dialog_created = True
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadInterface:
|
||||||
|
def __init__(self, func, func_args, callback, callback_args):
|
||||||
|
'''Call a function in a thread
|
||||||
|
|
||||||
|
:param func: the function to call in the thread
|
||||||
|
:param func_args: list or arguments for this function
|
||||||
|
:param callback: callback to call once function is finished
|
||||||
|
:param callback_args: list of arguments for this callback
|
||||||
|
'''
|
||||||
|
def thread_function(func, func_args, callback, callback_args):
|
||||||
|
output = func(*func_args)
|
||||||
|
gobject.idle_add(callback, output, *callback_args)
|
||||||
|
Thread(target=thread_function, args=(func, func_args, callback,
|
||||||
|
callback_args)).start()
|
||||||
|
|
||||||
class Interface:
|
class Interface:
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -3071,6 +3088,7 @@ class Interface:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
gajim.interface = self
|
gajim.interface = self
|
||||||
|
gajim.thread_interface = ThreadInterface
|
||||||
# This is the manager and factory of message windows set by the module
|
# This is the manager and factory of message windows set by the module
|
||||||
self.msg_win_mgr = None
|
self.msg_win_mgr = None
|
||||||
self.jabber_state_images = {'16': {}, '32': {}, 'opened': {},
|
self.jabber_state_images = {'16': {}, '32': {}, 'opened': {},
|
||||||
|
|
|
@ -158,9 +158,9 @@ class MessageControl:
|
||||||
if crypto_changed:
|
if crypto_changed:
|
||||||
self.print_esession_details()
|
self.print_esession_details()
|
||||||
|
|
||||||
def send_message(self, message, keyID = '', type_ = 'chat',
|
def send_message(self, message, keyID='', type_='chat', chatstate=None,
|
||||||
chatstate = None, msg_id = None, composing_xep = None, resource = None,
|
msg_id=None, composing_xep=None, resource=None, user_nick=None, xhtml=None,
|
||||||
user_nick = None, xhtml = None):
|
callback=None, callback_args=[]):
|
||||||
# Send the given message to the active tab.
|
# Send the given message to the active tab.
|
||||||
# Doesn't return None if error
|
# Doesn't return None if error
|
||||||
jid = self.contact.jid
|
jid = self.contact.jid
|
||||||
|
@ -182,11 +182,10 @@ class MessageControl:
|
||||||
self.set_session(sess)
|
self.set_session(sess)
|
||||||
|
|
||||||
# Send and update history
|
# Send and update history
|
||||||
return conn.send_message(jid, message, keyID, type_ = type_,
|
conn.send_message(jid, message, keyID, type_=type_, chatstate=chatstate,
|
||||||
chatstate = chatstate, msg_id = msg_id,
|
msg_id=msg_id, composing_xep=composing_xep, resource=self.resource,
|
||||||
composing_xep = composing_xep,
|
user_nick=user_nick, session=self.session,
|
||||||
resource = self.resource, user_nick = user_nick,
|
original_message=original_message, xhtml=xhtml, callback=callback,
|
||||||
session = self.session,
|
callback_args=callback_args)
|
||||||
original_message = original_message, xhtml = xhtml)
|
|
||||||
|
|
||||||
# vim: se ts=3:
|
# vim: se ts=3:
|
||||||
|
|
Loading…
Reference in New Issue