parent
64bac1d910
commit
9d75c77982
|
@ -179,11 +179,6 @@ def on_merge_accounts(action, param):
|
|||
app.interface.roster.setup_and_draw_roster()
|
||||
|
||||
|
||||
def on_use_pgp_agent(action, param):
|
||||
action.set_state(param)
|
||||
app.config.set('use_gpg_agent', param.get_boolean())
|
||||
|
||||
|
||||
def on_add_account(action, param):
|
||||
if 'account_creation_wizard' in app.interface.instances:
|
||||
app.interface.instances['account_creation_wizard'].window.present()
|
||||
|
|
|
@ -388,12 +388,6 @@ class GajimApplication(Gtk.Application):
|
|||
act.connect('change-state', app_actions.on_merge_accounts)
|
||||
self.add_action(act)
|
||||
|
||||
act = Gio.SimpleAction.new_stateful(
|
||||
'agent', None,
|
||||
GLib.Variant.new_boolean(app.config.get('use_gpg_agent')))
|
||||
act.connect('change-state', app_actions.on_use_pgp_agent)
|
||||
self.add_action(act)
|
||||
|
||||
# General Actions
|
||||
|
||||
general_actions = [
|
||||
|
|
|
@ -399,12 +399,8 @@ class ChatControl(ChatControlBase):
|
|||
'Show a list of formattings'))
|
||||
else:
|
||||
self._formattings_button.set_sensitive(False)
|
||||
if self.contact.supports(NS_XHTML_IM):
|
||||
self._formattings_button.set_tooltip_text(_('Formatting is not '
|
||||
'available so long as GPG is active'))
|
||||
else:
|
||||
self._formattings_button.set_tooltip_text(_('This contact does '
|
||||
'not support HTML'))
|
||||
self._formattings_button.set_tooltip_text(
|
||||
_('This contact does not support HTML'))
|
||||
|
||||
# Jingle detection
|
||||
if self.contact.supports(NS_JINGLE_ICE_UDP) and \
|
||||
|
@ -922,7 +918,7 @@ class ChatControl(ChatControlBase):
|
|||
correct_id=obj.correct_id,
|
||||
additional_data=obj.additional_data)
|
||||
|
||||
def send_message(self, message, keyID='', xhtml=None,
|
||||
def send_message(self, message, xhtml=None,
|
||||
process_commands=True, attention=False):
|
||||
"""
|
||||
Send a message to contact
|
||||
|
@ -939,12 +935,8 @@ class ChatControl(ChatControlBase):
|
|||
if message in ('', None, '\n'):
|
||||
return None
|
||||
|
||||
contact = self.contact
|
||||
keyID = contact.keyID
|
||||
|
||||
ChatControlBase.send_message(self,
|
||||
message,
|
||||
keyID,
|
||||
type_='chat',
|
||||
xhtml=xhtml,
|
||||
process_commands=process_commands,
|
||||
|
@ -1426,9 +1418,6 @@ class ChatControl(ChatControlBase):
|
|||
self.update_actions()
|
||||
|
||||
def update_status_display(self, name, uf_show, status):
|
||||
"""
|
||||
Print the contact's status and update the status/GPG image
|
||||
"""
|
||||
self.update_ui()
|
||||
self.parent_win.redraw_tab(self)
|
||||
|
||||
|
|
|
@ -773,7 +773,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
label = labels[lname]
|
||||
return label
|
||||
|
||||
def send_message(self, message, keyID='', type_='chat',
|
||||
def send_message(self, message, type_='chat',
|
||||
resource=None, xhtml=None, process_commands=True, attention=False):
|
||||
"""
|
||||
Send the given message to the active tab. Doesn't return None if error
|
||||
|
@ -797,7 +797,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
|
||||
app.nec.push_outgoing_event(MessageOutgoingEvent(None,
|
||||
account=self.account, jid=self.contact.jid, message=message,
|
||||
keyID=keyID, type_=type_, chatstate=chatstate,
|
||||
type_=type_, chatstate=chatstate,
|
||||
resource=resource, user_nick=self.user_nick, xhtml=xhtml,
|
||||
label=label, control=self, attention=attention, correct_id=correct_id,
|
||||
automatic_message=False, encryption=self.encryption))
|
||||
|
|
|
@ -35,7 +35,6 @@ import sys
|
|||
import logging
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from distutils.version import LooseVersion as V
|
||||
from collections import namedtuple
|
||||
|
||||
import nbxmpp
|
||||
|
@ -191,8 +190,6 @@ caps_hash = {} # type: Dict[str, List[str]]
|
|||
_dependencies = {
|
||||
'AVAHI': False,
|
||||
'PYBONJOUR': False,
|
||||
'PYGPG': False,
|
||||
'GPG_BINARY': False,
|
||||
'FARSTREAM': False,
|
||||
'GEOCLUE': False,
|
||||
'UPNP': False,
|
||||
|
@ -203,9 +200,6 @@ _dependencies = {
|
|||
|
||||
|
||||
def is_installed(dependency):
|
||||
if dependency == 'GPG':
|
||||
# Alias for checking python-gnupg and the GPG binary
|
||||
return _dependencies['PYGPG'] and _dependencies['GPG_BINARY']
|
||||
if dependency == 'ZEROCONF':
|
||||
# Alias for checking zeroconf libs
|
||||
return _dependencies['AVAHI'] or _dependencies['PYBONJOUR']
|
||||
|
@ -246,40 +240,6 @@ def detect_dependencies():
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
# python-gnupg
|
||||
try:
|
||||
import gnupg
|
||||
# We need https://pypi.python.org/pypi/python-gnupg
|
||||
# but https://pypi.python.org/pypi/gnupg shares the same package name.
|
||||
# It cannot be used as a drop-in replacement.
|
||||
# We test with a version check if python-gnupg is installed as it is
|
||||
# on a much lower version number than gnupg
|
||||
# Also we need at least python-gnupg 0.3.8
|
||||
v_gnupg = gnupg.__version__
|
||||
if V(v_gnupg) < V('0.3.8') or V(v_gnupg) > V('1.0.0'):
|
||||
log('gajim').info('Gajim needs python-gnupg >= 0.3.8')
|
||||
raise ImportError
|
||||
_dependencies['PYGPG'] = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# GPG BINARY
|
||||
import subprocess
|
||||
|
||||
def test_gpg(binary='gpg'):
|
||||
if os.name == 'nt':
|
||||
gpg_cmd = binary + ' -h >nul 2>&1'
|
||||
else:
|
||||
gpg_cmd = binary + ' -h >/dev/null 2>&1'
|
||||
if subprocess.call(gpg_cmd, shell=True):
|
||||
return False
|
||||
return True
|
||||
|
||||
if test_gpg(binary='gpg2'):
|
||||
_dependencies['GPG_BINARY'] = 'gpg2'
|
||||
elif test_gpg(binary='gpg'):
|
||||
_dependencies['GPG_BINARY'] = 'gpg'
|
||||
|
||||
# FARSTREAM
|
||||
try:
|
||||
if os.name == 'nt':
|
||||
|
@ -354,9 +314,6 @@ def detect_dependencies():
|
|||
|
||||
log('gajim').info('Used language: %s', LANG)
|
||||
|
||||
def get_gpg_binary():
|
||||
return _dependencies['GPG_BINARY']
|
||||
|
||||
def get_an_id():
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
|
|
@ -167,7 +167,6 @@ class Config:
|
|||
'time_stamp': [opt_str, '[%X] ', _('This option let you customize timestamp that is printed in conversation. For example "[%H:%M] " will show "[hour:minute] ". See python doc on strftime for full documentation: http://docs.python.org/lib/module-time.html')],
|
||||
'before_nickname': [opt_str, '', _('Characters that are printed before the nickname in conversations')],
|
||||
'after_nickname': [opt_str, ':', _('Characters that are printed after the nickname in conversations')],
|
||||
'use_gpg_agent': [opt_bool, False],
|
||||
'change_roster_title': [opt_bool, True, _('Add * and [n] in roster title?')],
|
||||
'restore_lines': [opt_int, 10, _('How many history messages should be restored when a chat tab/window is reopened?')],
|
||||
'restore_timeout': [opt_int, -1, _('How far back in time (minutes) history is restored. -1 means no limit.')],
|
||||
|
@ -285,7 +284,6 @@ class Config:
|
|||
'positive_184_ack': [opt_bool, False, _('If enabled, Gajim will show an icon to show that sent message has been received by your contact')],
|
||||
'show_avatar_in_tabs': [opt_bool, False, _('Show a mini avatar in chat window tabs and in window icon')],
|
||||
'use_keyring': [opt_bool, True, _('If true, Gajim will use the Systems Keyring to store account passwords.')],
|
||||
'pgp_encoding': [opt_str, '', _('Sets the encoding used by python-gnupg'), True],
|
||||
'remote_commands': [opt_bool, False, _('If true, Gajim will execute XEP-0146 Commands.')],
|
||||
'dark_theme': [opt_int, 2, _('2: System, 1: Enabled, 0: Disabled')],
|
||||
'threshold_options': [opt_str, '1, 2, 4, 10, 0', _('Options in days which can be chosen in the sync threshold menu'), True],
|
||||
|
@ -325,7 +323,6 @@ class Config:
|
|||
'active': [opt_bool, True, _('If False, this account will be disabled and will not appear in roster window.'), True],
|
||||
'proxy': [opt_str, '', '', True],
|
||||
'keyid': [opt_str, '', '', True],
|
||||
'gpg_sign_presence': [opt_bool, True, _('If disabled, don\'t sign presences with GPG key, even if GPG is configured.')],
|
||||
'keyname': [opt_str, '', '', True],
|
||||
'allow_plaintext_connection': [opt_bool, False, _('Allow plaintext connections')],
|
||||
'tls_version': [opt_str, '1.2', ''],
|
||||
|
|
|
@ -55,7 +55,6 @@ from nbxmpp.const import Event
|
|||
from gajim import common
|
||||
from gajim.common import helpers
|
||||
from gajim.common import app
|
||||
from gajim.common import gpg
|
||||
from gajim.common import passwords
|
||||
from gajim.common import idle
|
||||
from gajim.common import modules
|
||||
|
@ -66,8 +65,6 @@ from gajim.common.nec import NetworkEvent
|
|||
from gajim.common.contacts import GC_Contact
|
||||
from gajim.common.connection_handlers import ConnectionHandlers
|
||||
from gajim.common.connection_handlers_events import OurShowEvent
|
||||
from gajim.common.connection_handlers_events import BadGPGPassphraseEvent
|
||||
from gajim.common.connection_handlers_events import GPGPasswordRequiredEvent
|
||||
from gajim.common.connection_handlers_events import InformationEvent
|
||||
from gajim.common.connection_handlers_events import StanzaMessageOutgoingEvent
|
||||
from gajim.common.connection_handlers_events import GcStanzaMessageOutgoingEvent
|
||||
|
@ -105,11 +102,6 @@ class CommonConnection:
|
|||
self.is_zeroconf = False
|
||||
self.password = None
|
||||
self.server_resource = self._compute_resource()
|
||||
self.gpg = None
|
||||
self.USE_GPG = False
|
||||
if app.is_installed('GPG'):
|
||||
self.USE_GPG = True
|
||||
self.gpg = gpg.GnuPG()
|
||||
self.status = ''
|
||||
self.old_show = ''
|
||||
self.priority = app.get_priority(name, 'offline')
|
||||
|
@ -187,43 +179,6 @@ class CommonConnection:
|
|||
if kill_core and app.account_is_connected(self.name):
|
||||
self.disconnect(reconnect=False)
|
||||
|
||||
def test_gpg_passphrase(self, password):
|
||||
"""
|
||||
Returns 'ok', 'bad_pass' or 'expired'
|
||||
"""
|
||||
if not self.gpg:
|
||||
return False
|
||||
self.gpg.passphrase = password
|
||||
keyID = app.config.get_per('accounts', self.name, 'keyid')
|
||||
signed = self.gpg.sign('test', keyID)
|
||||
self.gpg.password = None
|
||||
if signed == 'KEYEXPIRED':
|
||||
return 'expired'
|
||||
if signed == 'BAD_PASSPHRASE':
|
||||
return 'bad_pass'
|
||||
return 'ok'
|
||||
|
||||
def get_signed_msg(self, msg, callback=None):
|
||||
"""
|
||||
Returns the signed message if possible or an empty string if gpg is not
|
||||
used or None if waiting for passphrase
|
||||
|
||||
callback is the function to call when user give the passphrase
|
||||
"""
|
||||
signed = ''
|
||||
keyID = app.config.get_per('accounts', self.name, 'keyid')
|
||||
if keyID and self.USE_GPG:
|
||||
if self.gpg.passphrase is None and not self.gpg.use_agent:
|
||||
# We didn't set a passphrase
|
||||
return None
|
||||
signed = self.gpg.sign(msg, keyID)
|
||||
if signed == 'BAD_PASSPHRASE':
|
||||
self.USE_GPG = False
|
||||
signed = ''
|
||||
app.nec.push_incoming_event(BadGPGPassphraseEvent(None,
|
||||
conn=self))
|
||||
return signed
|
||||
|
||||
def get_status(self):
|
||||
return app.SHOW_LIST[self.connected]
|
||||
|
||||
|
@ -432,25 +387,6 @@ class CommonConnection:
|
|||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def gpg_passphrase(self, passphrase):
|
||||
if self.gpg:
|
||||
if self.gpg.use_agent:
|
||||
self.gpg.passphrase = None
|
||||
else:
|
||||
self.gpg.passphrase = passphrase
|
||||
|
||||
def ask_gpg_keys(self, keyID=None):
|
||||
if self.gpg:
|
||||
if keyID:
|
||||
return self.gpg.get_key(keyID)
|
||||
return self.gpg.get_keys()
|
||||
return None
|
||||
|
||||
def ask_gpg_secrete_keys(self):
|
||||
if self.gpg:
|
||||
return self.gpg.get_secret_keys()
|
||||
return None
|
||||
|
||||
def _event_dispatcher(self, realm, event, data):
|
||||
if realm == '':
|
||||
if event == 'STANZA RECEIVED':
|
||||
|
@ -467,9 +403,7 @@ class CommonConnection:
|
|||
def change_status(self, show, msg, auto=False):
|
||||
if not msg:
|
||||
msg = ''
|
||||
sign_msg = False
|
||||
if not auto and not show == 'offline':
|
||||
sign_msg = True
|
||||
|
||||
if show != 'invisible':
|
||||
# We save it only when privacy list is accepted
|
||||
self.status = msg
|
||||
|
@ -478,10 +412,7 @@ class CommonConnection:
|
|||
# recconect before we auth to server
|
||||
self.old_show = show
|
||||
self.server_resource = self._compute_resource()
|
||||
if app.is_installed('GPG'):
|
||||
self.USE_GPG = True
|
||||
self.gpg = gpg.GnuPG()
|
||||
self.connect_and_init(show, msg, sign_msg)
|
||||
self.connect_and_init(show, msg)
|
||||
return
|
||||
|
||||
if show == 'offline':
|
||||
|
@ -615,7 +546,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
|
||||
show='connecting'))
|
||||
self.retrycount += 1
|
||||
self.connect_and_init(self.old_show, self.status, self.USE_GPG)
|
||||
self.connect_and_init(self.old_show, self.status)
|
||||
else:
|
||||
log.info('Reconnect successfull')
|
||||
# reconnect succeeded
|
||||
|
@ -784,9 +715,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
app.nec.push_incoming_event(NetworkEvent(
|
||||
'account-not-created', conn=self, reason=reason))
|
||||
return
|
||||
if app.is_installed('GPG'):
|
||||
self.USE_GPG = True
|
||||
self.gpg = gpg.GnuPG()
|
||||
|
||||
app.nec.push_incoming_event(
|
||||
NetworkEvent('account-created',
|
||||
conn=self,
|
||||
|
@ -1439,7 +1368,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
if self.connection:
|
||||
self.connection.send(' ')
|
||||
|
||||
def send_invisible_presence(self, msg, signed, initial=False):
|
||||
def send_invisible_presence(self, msg, initial=False):
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
if not self.get_module('PrivacyLists').supported:
|
||||
|
@ -1461,7 +1390,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.get_module('PrivacyLists').set_invisible_rule(
|
||||
callback=self._continue_invisible,
|
||||
msg=msg,
|
||||
signed=signed,
|
||||
initial=initial)
|
||||
|
||||
def _continue_invisible(self, con, iq_obj, msg, signed, initial):
|
||||
|
@ -1475,8 +1403,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
|
||||
self.get_module('Presence').send_presence(
|
||||
priority=priority,
|
||||
status=msg,
|
||||
sign=signed)
|
||||
status=msg)
|
||||
|
||||
self.priority = priority
|
||||
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
|
||||
|
@ -1501,19 +1428,14 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
# Inform GUI we just signed in
|
||||
app.nec.push_incoming_event(NetworkEvent('signed-in', conn=self))
|
||||
|
||||
def get_signed_presence(self, msg, callback=None):
|
||||
if app.config.get_per('accounts', self.name, 'gpg_sign_presence'):
|
||||
return self.get_signed_msg(msg, callback)
|
||||
return ''
|
||||
|
||||
def connect_and_auth(self):
|
||||
self.on_connect_success = self._connect_success
|
||||
self.on_connect_failure = self._connect_failure
|
||||
self.connect()
|
||||
|
||||
def connect_and_init(self, show, msg, sign_msg):
|
||||
def connect_and_init(self, show, msg):
|
||||
self.disable_reconnect_timer()
|
||||
self.continue_connect_info = [show, msg, sign_msg]
|
||||
self.continue_connect_info = [show, msg]
|
||||
self.connect_and_auth()
|
||||
|
||||
def _discover_server(self):
|
||||
|
@ -1564,40 +1486,16 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
app.proxy65_manager.resolve(proxy, self.connection, our_jid,
|
||||
testit=testit)
|
||||
|
||||
def send_first_presence(self):
|
||||
if self.connected > 1 and self.continue_connect_info:
|
||||
msg = self.continue_connect_info[1]
|
||||
sign_msg = self.continue_connect_info[2]
|
||||
signed = ''
|
||||
send_first_presence = True
|
||||
if sign_msg:
|
||||
signed = self.get_signed_presence(msg,
|
||||
self._send_first_presence)
|
||||
if signed is None:
|
||||
app.nec.push_incoming_event(GPGPasswordRequiredEvent(None,
|
||||
conn=self, callback=self._send_first_presence))
|
||||
# _send_first_presence will be called when user enter
|
||||
# passphrase
|
||||
send_first_presence = False
|
||||
if send_first_presence:
|
||||
self._send_first_presence(signed)
|
||||
|
||||
def _send_first_presence(self, signed=''):
|
||||
def send_first_presence(self, signed=''):
|
||||
if self.connected <= 1 or not self.continue_connect_info:
|
||||
return
|
||||
show = self.continue_connect_info[0]
|
||||
msg = self.continue_connect_info[1]
|
||||
sign_msg = self.continue_connect_info[2]
|
||||
if sign_msg and not signed:
|
||||
signed = self.get_signed_presence(msg)
|
||||
if signed is None:
|
||||
app.nec.push_incoming_event(BadGPGPassphraseEvent(None,
|
||||
conn=self))
|
||||
self.USE_GPG = False
|
||||
signed = ''
|
||||
self.connected = app.SHOW_LIST.index(show)
|
||||
sshow = helpers.get_xmpp_show(show)
|
||||
# send our presence
|
||||
if show == 'invisible':
|
||||
self.send_invisible_presence(msg, signed, True)
|
||||
self.send_invisible_presence(msg, True)
|
||||
return
|
||||
if show not in ['offline', 'online', 'chat', 'away', 'xa', 'dnd']:
|
||||
return
|
||||
|
@ -1606,8 +1504,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.get_module('Presence').send_presence(
|
||||
priority=priority,
|
||||
show=sshow,
|
||||
status=msg,
|
||||
sign=signed)
|
||||
status=msg)
|
||||
|
||||
if self.connection:
|
||||
self.priority = priority
|
||||
|
@ -1643,18 +1540,15 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
status=msg)
|
||||
|
||||
else:
|
||||
signed = self.get_signed_presence(msg)
|
||||
priority = app.get_priority(self.name, sshow)
|
||||
self.get_module('Presence').send_presence(
|
||||
jid,
|
||||
priority=priority,
|
||||
show=sshow,
|
||||
status=msg,
|
||||
sign=signed)
|
||||
status=msg)
|
||||
|
||||
def _change_to_invisible(self, msg):
|
||||
signed = self.get_signed_presence(msg)
|
||||
self.send_invisible_presence(msg, signed)
|
||||
self.send_invisible_presence(msg)
|
||||
|
||||
def _change_from_invisible(self):
|
||||
if self.get_module('PrivacyLists').supported:
|
||||
|
@ -1663,13 +1557,11 @@ 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)
|
||||
signed = self.get_signed_presence(msg)
|
||||
|
||||
self.get_module('Presence').send_presence(
|
||||
priority=priority,
|
||||
show=xmpp_show,
|
||||
status=msg,
|
||||
sign=signed,
|
||||
idle_time=idle_time)
|
||||
|
||||
if self.connection:
|
||||
|
@ -1862,7 +1754,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
def send_gc_message(self, obj):
|
||||
obj.stanza_id = self.connection.send(obj.msg_iq)
|
||||
app.nec.push_incoming_event(MessageSentEvent(
|
||||
None, conn=self, jid=obj.jid, message=obj.message, keyID=None,
|
||||
None, conn=self, jid=obj.jid, message=obj.message,
|
||||
automatic_message=obj.automatic_message,
|
||||
stanza_id=obj.stanza_id, additional_data=obj.additional_data))
|
||||
|
||||
|
|
|
@ -153,15 +153,6 @@ class NewAccountConnectedEvent(nec.NetworkIncomingEvent):
|
|||
class NewAccountNotConnectedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'new-account-not-connected'
|
||||
|
||||
class BadGPGPassphraseEvent(nec.NetworkIncomingEvent):
|
||||
name = 'bad-gpg-passphrase'
|
||||
|
||||
def generate(self):
|
||||
self.account = self.conn.name
|
||||
self.use_gpg_agent = app.config.get('use_gpg_agent')
|
||||
self.keyID = app.config.get_per('accounts', self.conn.name, 'keyid')
|
||||
return True
|
||||
|
||||
class ConnectionLostEvent(nec.NetworkIncomingEvent):
|
||||
name = 'connection-lost'
|
||||
|
||||
|
@ -170,13 +161,6 @@ class ConnectionLostEvent(nec.NetworkIncomingEvent):
|
|||
show='offline'))
|
||||
return True
|
||||
|
||||
class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent):
|
||||
name = 'gpg-password-required'
|
||||
|
||||
def generate(self):
|
||||
self.keyid = app.config.get_per('accounts', self.conn.name, 'keyid')
|
||||
return True
|
||||
|
||||
class FileRequestReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'file-request-received'
|
||||
|
||||
|
@ -610,7 +594,6 @@ class MessageOutgoingEvent(nec.NetworkOutgoingEvent):
|
|||
def init(self):
|
||||
self.additional_data = AdditionalDataDict()
|
||||
self.message = None
|
||||
self.keyID = None
|
||||
self.type_ = 'chat'
|
||||
self.kind = None
|
||||
self.timestamp = None
|
||||
|
|
|
@ -23,7 +23,6 @@ class OptionKind(IntEnum):
|
|||
PRIORITY = 9
|
||||
FILECHOOSER = 10
|
||||
CHANGEPASSWORD = 11
|
||||
GPG = 12
|
||||
|
||||
|
||||
@unique
|
||||
|
|
|
@ -137,7 +137,7 @@ class Contact(CommonContact):
|
|||
Information concerning a contact
|
||||
"""
|
||||
def __init__(self, jid, account, name='', groups=None, show='', status='',
|
||||
sub='', ask='', resource='', priority=0, keyID='', client_caps=None,
|
||||
sub='', ask='', resource='', priority=0, client_caps=None,
|
||||
chatstate=None, idle_time=None, avatar_sha=None, groupchat=False,
|
||||
is_pm_contact=False):
|
||||
if not isinstance(jid, str):
|
||||
|
@ -159,7 +159,6 @@ class Contact(CommonContact):
|
|||
self.ask = ask
|
||||
|
||||
self.priority = priority
|
||||
self.keyID = keyID
|
||||
self.idle_time = idle_time
|
||||
|
||||
self.pep = {}
|
||||
|
@ -306,7 +305,7 @@ class LegacyContactsAPI:
|
|||
self._metacontact_manager.remove_account(account)
|
||||
|
||||
def create_contact(self, jid, account, name='', groups=None, show='',
|
||||
status='', sub='', ask='', resource='', priority=0, keyID='',
|
||||
status='', sub='', ask='', resource='', priority=0,
|
||||
client_caps=None, chatstate=None, idle_time=None,
|
||||
avatar_sha=None, groupchat=False):
|
||||
if groups is None:
|
||||
|
@ -315,36 +314,36 @@ class LegacyContactsAPI:
|
|||
account = self._accounts.get(account, account)
|
||||
return Contact(jid=jid, account=account, name=name, groups=groups,
|
||||
show=show, status=status, sub=sub, ask=ask, resource=resource,
|
||||
priority=priority, keyID=keyID, client_caps=client_caps,
|
||||
priority=priority, client_caps=client_caps,
|
||||
chatstate=chatstate, idle_time=idle_time, avatar_sha=avatar_sha,
|
||||
groupchat=groupchat)
|
||||
|
||||
def create_self_contact(self, jid, account, resource, show, status, priority,
|
||||
name='', keyID=''):
|
||||
name=''):
|
||||
conn = common.app.connections[account]
|
||||
nick = name or common.app.nicks[account]
|
||||
account = self._accounts.get(account, account) # Use Account object if available
|
||||
self_contact = self.create_contact(jid=jid, account=account,
|
||||
name=nick, groups=['self_contact'], show=show, status=status,
|
||||
sub='both', ask='none', priority=priority, keyID=keyID,
|
||||
sub='both', ask='none', priority=priority,
|
||||
resource=resource)
|
||||
self_contact.pep = conn.pep
|
||||
return self_contact
|
||||
|
||||
def create_not_in_roster_contact(self, jid, account, resource='', name='',
|
||||
keyID='', groupchat=False):
|
||||
groupchat=False):
|
||||
# Use Account object if available
|
||||
account = self._accounts.get(account, account)
|
||||
return self.create_contact(jid=jid, account=account, resource=resource,
|
||||
name=name, groups=[_('Not in Roster')], show='not in roster',
|
||||
status='', sub='none', keyID=keyID, groupchat=groupchat)
|
||||
status='', sub='none', groupchat=groupchat)
|
||||
|
||||
def copy_contact(self, contact):
|
||||
return self.create_contact(contact.jid, contact.account,
|
||||
name=contact.name, groups=contact.groups, show=contact.show,
|
||||
status=contact.status, sub=contact.sub, ask=contact.ask,
|
||||
resource=contact.resource, priority=contact.priority,
|
||||
keyID=contact.keyID, client_caps=contact.client_caps,
|
||||
client_caps=contact.client_caps,
|
||||
chatstate=contact.chatstate_enum,
|
||||
idle_time=contact.idle_time, avatar_sha=contact.avatar_sha)
|
||||
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
# Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
|
||||
# Copyright (C) 2005 Alex Mauer <hawke AT hawkesnest.net>
|
||||
# Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
|
||||
# Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de>
|
||||
# Copyright (C) 2008 Jean-Marie Traissard <jim AT lapin.org>
|
||||
# Jonathan Schleifer <js-gajim AT webkeks.org>
|
||||
#
|
||||
# This file is part of Gajim.
|
||||
#
|
||||
# Gajim is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation; version 3 only.
|
||||
#
|
||||
# Gajim is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from gajim.common import app
|
||||
|
||||
if app.is_installed('GPG'):
|
||||
import gnupg
|
||||
|
||||
class GnuPG(gnupg.GPG):
|
||||
def __init__(self):
|
||||
use_agent = app.config.get('use_gpg_agent')
|
||||
gnupg.GPG.__init__(self, gpgbinary=app.get_gpg_binary(), use_agent=use_agent)
|
||||
encoding = app.config.get('pgp_encoding')
|
||||
if encoding:
|
||||
self.encoding = encoding
|
||||
self.decode_errors = 'replace'
|
||||
self.passphrase = None
|
||||
self.always_trust = [] # list of keyID to always trust
|
||||
|
||||
def encrypt(self, str_, recipients, always_trust=False):
|
||||
trust = always_trust
|
||||
if not trust:
|
||||
# check if we trust all keys
|
||||
trust = True
|
||||
for key in recipients:
|
||||
if key not in self.always_trust:
|
||||
trust = False
|
||||
if not trust:
|
||||
# check that we'll be able to encrypt
|
||||
result = super(GnuPG, self).list_keys(keys=recipients)
|
||||
for key in result:
|
||||
if key['trust'] not in ('f', 'u'):
|
||||
if key['keyid'][-8:] not in self.always_trust:
|
||||
return '', 'NOT_TRUSTED ' + key['keyid'][-8:]
|
||||
trust = True
|
||||
result = super(GnuPG, self).encrypt(str_.encode('utf8'), recipients,
|
||||
always_trust=trust, passphrase=self.passphrase)
|
||||
|
||||
if result.ok:
|
||||
error = ''
|
||||
else:
|
||||
error = result.status
|
||||
|
||||
return self._stripHeaderFooter(str(result)), error
|
||||
|
||||
def decrypt(self, str_, keyID):
|
||||
data = self._addHeaderFooter(str_, 'MESSAGE')
|
||||
result = super(GnuPG, self).decrypt(data.encode('utf8'),
|
||||
passphrase=self.passphrase)
|
||||
|
||||
return result.data.decode('utf8')
|
||||
|
||||
def sign(self, str_, keyID):
|
||||
result = super(GnuPG, self).sign(str_.encode('utf8'), keyid=keyID, detach=True,
|
||||
passphrase=self.passphrase)
|
||||
|
||||
if result.fingerprint:
|
||||
return self._stripHeaderFooter(str(result))
|
||||
if hasattr(result, 'status') and result.status == 'key expired':
|
||||
return 'KEYEXPIRED'
|
||||
return 'BAD_PASSPHRASE'
|
||||
|
||||
def verify(self, str_, sign):
|
||||
if str_ is None:
|
||||
return ''
|
||||
# Hash algorithm is not transfered in the signed presence stanza so try
|
||||
# all algorithms. Text name for hash algorithms from RFC 4880 - section 9.4
|
||||
hash_algorithms = ['SHA512', 'SHA384', 'SHA256', 'SHA224', 'SHA1', 'RIPEMD160']
|
||||
for algo in hash_algorithms:
|
||||
data = os.linesep.join(
|
||||
['-----BEGIN PGP SIGNED MESSAGE-----',
|
||||
'Hash: ' + algo,
|
||||
'',
|
||||
str_,
|
||||
self._addHeaderFooter(sign, 'SIGNATURE')]
|
||||
)
|
||||
result = super(GnuPG, self).verify(data.encode('utf8'))
|
||||
if result.valid:
|
||||
return result.key_id
|
||||
|
||||
return ''
|
||||
|
||||
def get_key(self, keyID):
|
||||
return super(GnuPG, self).list_keys(keys=[keyID])
|
||||
|
||||
def get_keys(self, secret=False):
|
||||
keys = {}
|
||||
result = super(GnuPG, self).list_keys(secret=secret)
|
||||
|
||||
for key in result:
|
||||
# Take first not empty uid
|
||||
keys[key['keyid'][8:]] = [uid for uid in key['uids'] if uid][0]
|
||||
return keys
|
||||
|
||||
def get_secret_keys(self):
|
||||
return self.get_keys(True)
|
||||
|
||||
def _stripHeaderFooter(self, data):
|
||||
"""
|
||||
Remove header and footer from data
|
||||
"""
|
||||
if not data:
|
||||
return ''
|
||||
lines = data.splitlines()
|
||||
while lines[0] != '':
|
||||
lines.remove(lines[0])
|
||||
while lines[0] == '':
|
||||
lines.remove(lines[0])
|
||||
i = 0
|
||||
for line in lines:
|
||||
if line:
|
||||
if line[0] == '-':
|
||||
break
|
||||
i = i+1
|
||||
line = '\n'.join(lines[0:i])
|
||||
return line
|
||||
|
||||
def _addHeaderFooter(self, data, type_):
|
||||
"""
|
||||
Add header and footer from data
|
||||
"""
|
||||
out = "-----BEGIN PGP %s-----" % type_ + os.linesep
|
||||
out = out + "Version: PGP" + os.linesep
|
||||
out = out + os.linesep
|
||||
out = out + data + os.linesep
|
||||
out = out + "-----END PGP %s-----" % type_ + os.linesep
|
||||
return out
|
|
@ -1108,54 +1108,6 @@ def get_current_show(account):
|
|||
status = app.connections[account].connected
|
||||
return app.SHOW_LIST[status]
|
||||
|
||||
def prepare_and_validate_gpg_keyID(account, jid, keyID):
|
||||
"""
|
||||
Return an eight char long keyID that can be used with for GPG encryption
|
||||
with this contact
|
||||
|
||||
If the given keyID is None, return UNKNOWN; if the key does not match the
|
||||
assigned key XXXXXXXXMISMATCH is returned. If the key is trusted and not yet
|
||||
assigned, assign it.
|
||||
"""
|
||||
if app.connections[account].USE_GPG:
|
||||
if keyID and len(keyID) == 16:
|
||||
keyID = keyID[8:]
|
||||
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
|
||||
if jid in attached_keys and keyID:
|
||||
attachedkeyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
if attachedkeyID != keyID:
|
||||
# Get signing subkeys for the attached key
|
||||
subkeys = []
|
||||
for key in app.connections[account].gpg.list_keys():
|
||||
if key['keyid'][8:] == attachedkeyID:
|
||||
subkeys = [subkey[0][8:] for subkey in key['subkeys'] \
|
||||
if subkey[1] == 's']
|
||||
break
|
||||
|
||||
if keyID not in subkeys:
|
||||
# Mismatch! Another gpg key was expected
|
||||
keyID += 'MISMATCH'
|
||||
elif jid in attached_keys:
|
||||
# An unsigned presence, just use the assigned key
|
||||
keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
elif keyID:
|
||||
full_key = app.connections[account].ask_gpg_keys(keyID=keyID)
|
||||
# Assign the corresponding key, if we have it in our keyring
|
||||
if full_key:
|
||||
for u in app.contacts.get_contacts(account, jid):
|
||||
u.keyID = keyID
|
||||
keys_str = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys')
|
||||
keys_str += jid + ' ' + keyID + ' '
|
||||
app.config.set_per('accounts', account, 'attached_gpg_keys',
|
||||
keys_str)
|
||||
elif keyID is None:
|
||||
keyID = 'UNKNOWN'
|
||||
return keyID
|
||||
|
||||
def update_optional_features(account=None):
|
||||
if account is not None:
|
||||
accounts = [account]
|
||||
|
|
|
@ -329,7 +329,7 @@ class HTTPUpload(BaseModule):
|
|||
else:
|
||||
app.nec.push_outgoing_event(MessageOutgoingEvent(
|
||||
None, account=self._account, jid=file.contact.jid,
|
||||
message=message, keyID=file.key_id, type_='chat',
|
||||
message=message, type_='chat',
|
||||
automatic_message=False, session=file.session))
|
||||
|
||||
else:
|
||||
|
@ -353,9 +353,6 @@ class File:
|
|||
setattr(self, key, val)
|
||||
self.encrypted = False
|
||||
self.contact = contact
|
||||
self.key_id = None
|
||||
if hasattr(contact, 'keyID'):
|
||||
self.key_id = contact.keyID
|
||||
self.stream = None
|
||||
self.path = path
|
||||
self.put = None
|
||||
|
|
|
@ -25,7 +25,6 @@ from gajim.common.i18n import _
|
|||
from gajim.common.nec import NetworkEvent
|
||||
from gajim.common.const import KindConstant
|
||||
from gajim.common.const import ShowConstant
|
||||
from gajim.common.helpers import prepare_and_validate_gpg_keyID
|
||||
from gajim.common.modules.base import BaseModule
|
||||
|
||||
|
||||
|
@ -94,12 +93,6 @@ class Presence(BaseModule):
|
|||
self._log.warning(stanza)
|
||||
return
|
||||
|
||||
key_id = ''
|
||||
if properties.signed is not None and self._con.USE_GPG:
|
||||
key_id = self._con.gpg.verify(properties.status, properties.signed)
|
||||
key_id = prepare_and_validate_gpg_keyID(
|
||||
self._account, properties.jid.getBare(), key_id)
|
||||
|
||||
show = properties.show.value
|
||||
if properties.type.is_unavailable:
|
||||
show = 'offline'
|
||||
|
@ -107,7 +100,6 @@ class Presence(BaseModule):
|
|||
event_attrs = {
|
||||
'conn': self._con,
|
||||
'stanza': stanza,
|
||||
'keyID': key_id,
|
||||
'prio': properties.priority,
|
||||
'need_add_in_roster': False,
|
||||
'popup': False,
|
||||
|
@ -185,13 +177,6 @@ class Presence(BaseModule):
|
|||
contact.show = event.show
|
||||
contact.status = properties.status
|
||||
contact.priority = properties.priority
|
||||
attached_keys = app.config.get_per('accounts', self._account,
|
||||
'attached_gpg_keys').split()
|
||||
if jid in attached_keys:
|
||||
contact.keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
else:
|
||||
# Do not override assigned key
|
||||
contact.keyID = event.keyID
|
||||
contact.idle_time = properties.idle_timestamp
|
||||
|
||||
event.contact = contact
|
||||
|
@ -355,7 +340,7 @@ class Presence(BaseModule):
|
|||
|
||||
def get_presence(self, to=None, typ=None, priority=None,
|
||||
show=None, status=None, nick=None, caps=True,
|
||||
sign=None, idle_time=None):
|
||||
idle_time=None):
|
||||
if show not in ('chat', 'away', 'xa', 'dnd'):
|
||||
# Gajim sometimes passes invalid show values here
|
||||
# until this is fixed this is a workaround
|
||||
|
@ -365,9 +350,6 @@ class Presence(BaseModule):
|
|||
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)
|
||||
|
|
|
@ -156,7 +156,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
|
|||
def _on_remove_service(self, jid):
|
||||
self.roster.delItem(jid)
|
||||
# 'NOTIFY' (account, (jid, status, status message, resource, priority,
|
||||
# keyID, timestamp))
|
||||
# timestamp))
|
||||
self._on_presence(jid, show='offline', status='')
|
||||
|
||||
def _on_presence(self, jid, show=None, status=None):
|
||||
|
@ -169,7 +169,6 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
|
|||
|
||||
event_attrs = {
|
||||
'conn': self,
|
||||
'keyID': None,
|
||||
'prio': 0,
|
||||
'need_add_in_roster': False,
|
||||
'popup': False,
|
||||
|
@ -216,13 +215,6 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
|
|||
contact.show = event.show
|
||||
contact.status = event.status
|
||||
contact.priority = event.prio
|
||||
attached_keys = app.config.get_per('accounts', self.name,
|
||||
'attached_gpg_keys').split()
|
||||
if jid in attached_keys:
|
||||
contact.keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
else:
|
||||
# Do not override assigned key
|
||||
contact.keyID = event.keyID
|
||||
contact.idle_time = event.idle_time
|
||||
|
||||
event.contact = contact
|
||||
|
@ -363,7 +355,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
|
|||
else:
|
||||
self.reannounce()
|
||||
|
||||
def connect_and_init(self, show, msg, sign_msg):
|
||||
def connect_and_init(self, show, msg):
|
||||
# to check for errors from zeroconf
|
||||
check = True
|
||||
if not self.connect(show, msg):
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.18.3 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.12"/>
|
||||
<object class="GtkDialog" id="choose_gpg_key_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="default_width">550</property>
|
||||
<property name="default_height">300</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="vbox33">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="hbuttonbox14">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button26">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button27">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="has_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="vbox91">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="prompt_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow20">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="keys_treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-6">button26</action-widget>
|
||||
<action-widget response="-5">button27</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.12"/>
|
||||
<object class="GtkAccelGroup" id="accelgroup1"/>
|
||||
|
@ -100,14 +100,6 @@
|
|||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="assign_openpgp_key_menuitem">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Assign Open_PGP Key...</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_assign_openpgp_key_menuitem_activate" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="add_special_notification_menuitem">
|
||||
<property name="can_focus">False</property>
|
||||
|
|
|
@ -182,32 +182,6 @@
|
|||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pgp_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">OpenPGP:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pgp">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="sub_label">
|
||||
<property name="visible">True</property>
|
||||
|
@ -300,5 +274,11 @@
|
|||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
|
@ -284,73 +284,6 @@ class PassphraseDialog:
|
|||
if self.cancel_handler and not self.ok:
|
||||
self.cancel_handler()
|
||||
|
||||
class ChooseGPGKeyDialog:
|
||||
"""
|
||||
Class for GPG key dialog
|
||||
"""
|
||||
|
||||
def __init__(self, title_text, prompt_text, secret_keys, on_response,
|
||||
selected=None, transient_for=None):
|
||||
'''secret_keys : {keyID: userName, ...}'''
|
||||
self.on_response = on_response
|
||||
xml = get_builder('choose_gpg_key_dialog.ui')
|
||||
self.window = xml.get_object('choose_gpg_key_dialog')
|
||||
self.window.set_title(title_text)
|
||||
self.window.set_transient_for(transient_for)
|
||||
self.keys_treeview = xml.get_object('keys_treeview')
|
||||
prompt_label = xml.get_object('prompt_label')
|
||||
prompt_label.set_text(prompt_text)
|
||||
model = Gtk.ListStore(str, str)
|
||||
model.set_sort_func(1, self.sort_keys)
|
||||
model.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||
self.keys_treeview.set_model(model)
|
||||
#columns
|
||||
renderer = Gtk.CellRendererText()
|
||||
self.keys_treeview.insert_column_with_attributes(-1, _('KeyID'),
|
||||
renderer, text=0)
|
||||
col = self.keys_treeview.get_column(0)
|
||||
col.set_sort_column_id(0)
|
||||
renderer = Gtk.CellRendererText()
|
||||
self.keys_treeview.insert_column_with_attributes(-1, _('Contact name'),
|
||||
renderer, text=1)
|
||||
col = self.keys_treeview.get_column(1)
|
||||
col.set_sort_column_id(1)
|
||||
self.keys_treeview.set_search_column(1)
|
||||
self.fill_tree(secret_keys, selected)
|
||||
self.window.connect('response', self.on_dialog_response)
|
||||
self.window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
|
||||
self.window.show_all()
|
||||
|
||||
def sort_keys(self, model, iter1, iter2, data=None):
|
||||
value1 = model[iter1][1]
|
||||
value2 = model[iter2][1]
|
||||
if value1 == _('None'):
|
||||
return -1
|
||||
if value2 == _('None'):
|
||||
return 1
|
||||
if value1 < value2:
|
||||
return -1
|
||||
return 1
|
||||
|
||||
def on_dialog_response(self, dialog, response):
|
||||
selection = self.keys_treeview.get_selection()
|
||||
(model, iter_) = selection.get_selected()
|
||||
if iter_ and response == Gtk.ResponseType.OK:
|
||||
keyID = [model[iter_][0], model[iter_][1]]
|
||||
else:
|
||||
keyID = None
|
||||
self.on_response(keyID)
|
||||
self.window.destroy()
|
||||
|
||||
def fill_tree(self, list_, selected):
|
||||
model = self.keys_treeview.get_model()
|
||||
for keyID in list_.keys():
|
||||
iter_ = model.append((keyID, list_[keyID]))
|
||||
if keyID == selected:
|
||||
path = model.get_path(iter_)
|
||||
self.keys_treeview.set_cursor(path)
|
||||
|
||||
|
||||
class ChangeActivityDialog:
|
||||
PAGELIST = [
|
||||
'doing_chores', 'drinking', 'eating', 'exercising', 'grooming',
|
||||
|
|
|
@ -115,28 +115,21 @@ class GajimRemote:
|
|||
]
|
||||
],
|
||||
'send_chat_message': [
|
||||
_('Sends new chat message to a contact in the roster. Both OpenPGP key '
|
||||
'and account are optional. If you want to set only \'account\', '
|
||||
'without \'OpenPGP key\', just set \'OpenPGP key\' to \'\'.'),
|
||||
_('Sends new chat message to a contact in the roster. Account is optional.'),
|
||||
[
|
||||
('jid', _('JID of the contact that will receive the message'), True),
|
||||
(Q_('?CLI:message'), _('message contents'), True),
|
||||
(_('PGP key'), _('if specified, the message will be encrypted '
|
||||
'using this public key'), False),
|
||||
(Q_('?CLI:account'), _('if specified, the message will be sent '
|
||||
'using this account'), False),
|
||||
]
|
||||
],
|
||||
'send_single_message': [
|
||||
_('Sends a chat message to someone on your roster. '
|
||||
'Optionally with OpenPGP key and account. If you want '
|
||||
'to only set the latter, set OpenPGP key to "".'),
|
||||
'Account is optional.'),
|
||||
[
|
||||
('jid', _('JID of the contact that will receive the message'), True),
|
||||
(_('subject'), _('message subject'), True),
|
||||
(Q_('?CLI:message'), _('message contents'), True),
|
||||
(_('PGP key'), _('if specified, the message will be encrypted '
|
||||
'using this public key'), False),
|
||||
(Q_('?CLI:account'), _('if specified, the message will be sent '
|
||||
'using this account'), False),
|
||||
]
|
||||
|
|
|
@ -537,8 +537,6 @@ class AccountCreationWizard:
|
|||
config['use_custom_host'] = False
|
||||
config['custom_port'] = 0
|
||||
config['custom_host'] = ''
|
||||
config['keyname'] = ''
|
||||
config['keyid'] = ''
|
||||
return config
|
||||
|
||||
def save_account(self, login, server, savepass, password, anonymous=False):
|
||||
|
|
|
@ -183,11 +183,10 @@ class AccountsWindow(Gtk.ApplicationWindow):
|
|||
def get_relogin_options(account):
|
||||
if account == app.ZEROCONF_ACC_NAME:
|
||||
options = ['zeroconf_first_name', 'zeroconf_last_name',
|
||||
'zeroconf_jabber_id', 'zeroconf_email', 'keyid']
|
||||
'zeroconf_jabber_id', 'zeroconf_email']
|
||||
else:
|
||||
options = ['client_cert', 'proxy', 'resource',
|
||||
'use_custom_host', 'custom_host', 'custom_port',
|
||||
'keyid']
|
||||
'use_custom_host', 'custom_host', 'custom_port']
|
||||
|
||||
values = []
|
||||
for option in options:
|
||||
|
@ -567,9 +566,6 @@ class PreferencesPage(GenericOptionPage):
|
|||
options = [
|
||||
Option(OptionKind.SWITCH, _('Merge Accounts'),
|
||||
OptionType.ACTION, 'merge'),
|
||||
|
||||
Option(OptionKind.SWITCH, _('Use PGP Agent'),
|
||||
OptionType.ACTION, 'agent'),
|
||||
]
|
||||
|
||||
GenericOptionPage.__init__(self, None, None, options)
|
||||
|
@ -605,9 +601,6 @@ class AccountPage(GenericOptionPage):
|
|||
|
||||
Option(OptionKind.DIALOG, _('Client Certificate'),
|
||||
OptionType.DIALOG, props={'dialog': CertificateDialog}),
|
||||
|
||||
Option(OptionKind.GPG, _('OpenPGP Key'), OptionType.DIALOG,
|
||||
props={'dialog': None}),
|
||||
]
|
||||
|
||||
GenericOptionPage.__init__(self, account, parent, options)
|
||||
|
@ -704,9 +697,6 @@ class ZeroConfPage(GenericOptionPage):
|
|||
Option(OptionKind.SWITCH, _('Global Status'),
|
||||
OptionType.ACCOUNT_CONFIG, 'sync_with_global_status',
|
||||
desc=_('Synchronize the status of all accounts')),
|
||||
|
||||
Option(OptionKind.GPG, _('OpenPGP Key'),
|
||||
OptionType.DIALOG, props={'dialog': None}),
|
||||
]
|
||||
|
||||
GenericOptionPage.__init__(self, account, parent, options)
|
||||
|
|
|
@ -112,13 +112,6 @@ class FeaturesDialog(Gtk.Dialog):
|
|||
_('Requires: pybonjour and bonjour SDK running (%(url)s)')
|
||||
% {'url': 'https://developer.apple.com/opensource/)'},
|
||||
None),
|
||||
Feature(_('OpenPGP Message Encryption'),
|
||||
app.is_installed('GPG'),
|
||||
_('Enables Gajim to encrypt chat messages with OpenPGP'),
|
||||
_('Requires: gpg and python-gnupg (%(url)s)')
|
||||
% {'url': 'https://bitbucket.org/vinay.sajip/python-gnupg'},
|
||||
_('Requires: gpg.exe in your PATH environment variable'),
|
||||
None),
|
||||
Feature(_('RST XHTML Generator'),
|
||||
self.docutils_available(),
|
||||
_('Enables Gajim to generate XHTML output from RST '
|
||||
|
|
|
@ -335,9 +335,7 @@ class RosterTooltip(StatusTable):
|
|||
status=connection.status,
|
||||
resource=connection.server_resource,
|
||||
priority=connection.priority)
|
||||
if app.connections[account].gpg:
|
||||
contact.keyID = app.config.get_per(
|
||||
'accounts', connection.name, 'keyid')
|
||||
|
||||
contacts.append(contact)
|
||||
|
||||
# Username/Account/Groupchat
|
||||
|
@ -438,17 +436,6 @@ class RosterTooltip(StatusTable):
|
|||
self._ui.sub.show()
|
||||
self._ui.sub_label.show()
|
||||
|
||||
if self.prim_contact.keyID:
|
||||
key_id = None
|
||||
if len(self.prim_contact.keyID) == 8:
|
||||
key_id = self.prim_contact.keyID
|
||||
elif len(self.prim_contact.keyID) == 16:
|
||||
key_id = self.prim_contact.keyID[8:]
|
||||
if key_id:
|
||||
self._ui.pgp.set_text(key_id)
|
||||
self._ui.pgp.show()
|
||||
self._ui.pgp_label.show()
|
||||
|
||||
self._set_idle_time(contact)
|
||||
|
||||
# Avatar
|
||||
|
|
|
@ -230,9 +230,7 @@ class Interface:
|
|||
if name in self.instances[account]['online_dialog']:
|
||||
# destroy handler may have already removed it
|
||||
del self.instances[account]['online_dialog'][name]
|
||||
for request in self.gpg_passphrase.values():
|
||||
if request:
|
||||
request.interrupt(account=account)
|
||||
|
||||
if account in self.pass_dialog:
|
||||
self.pass_dialog[account].window.destroy()
|
||||
if obj.show == 'offline':
|
||||
|
@ -306,7 +304,7 @@ class Interface:
|
|||
|
||||
def handle_event_presence(self, obj):
|
||||
# 'NOTIFY' (account, (jid, status, status message, resource,
|
||||
# priority, # keyID, timestamp))
|
||||
# priority, timestamp))
|
||||
#
|
||||
# Contact changed show
|
||||
account = obj.conn.name
|
||||
|
@ -390,7 +388,7 @@ class Interface:
|
|||
|
||||
@staticmethod
|
||||
def handle_event_msgsent(obj):
|
||||
#('MSGSENT', account, (jid, msg, keyID))
|
||||
#('MSGSENT', account, (jid, msg))
|
||||
# do not play sound when standalone chatstate message (eg no msg)
|
||||
if obj.message and app.config.get_per('soundevents', 'message_sent',
|
||||
'enabled'):
|
||||
|
@ -438,16 +436,11 @@ class Interface:
|
|||
self.roster.remove_contact_from_groups(c.jid, account,
|
||||
[_('Not in Roster'), _('Observers')], update=False)
|
||||
else:
|
||||
keyID = ''
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
if obj.jid in attached_keys:
|
||||
keyID = attached_keys[attached_keys.index(obj.jid) + 1]
|
||||
name = obj.jid.split('@', 1)[0]
|
||||
name = name.split('%', 1)[0]
|
||||
contact1 = app.contacts.create_contact(jid=obj.jid,
|
||||
account=account, name=name, groups=[], show='online',
|
||||
status='online', ask='to', resource=obj.resource, keyID=keyID)
|
||||
status='online', ask='to', resource=obj.resource)
|
||||
app.contacts.add_contact(account, contact1)
|
||||
self.roster.add_contact(obj.jid, account)
|
||||
InformationDialog(_('Authorization accepted'),
|
||||
|
@ -571,28 +564,6 @@ class Interface:
|
|||
text,
|
||||
room_jid=muc)
|
||||
|
||||
def forget_gpg_passphrase(self, keyid):
|
||||
if keyid in self.gpg_passphrase:
|
||||
del self.gpg_passphrase[keyid]
|
||||
return False
|
||||
|
||||
def handle_event_bad_gpg_passphrase(self, obj):
|
||||
#('BAD_PASSPHRASE', account, ())
|
||||
if obj.use_gpg_agent:
|
||||
sectext = _('You configured Gajim to use OpenPGP agent, but there '
|
||||
'is no OpenPGP agent running or it returned a wrong passphrase.'
|
||||
'\n')
|
||||
sectext += _('You are currently connected without your OpenPGP '
|
||||
'key.')
|
||||
WarningDialog(_('Wrong passphrase'), sectext)
|
||||
else:
|
||||
account = obj.conn.name
|
||||
app.notification.popup(
|
||||
'warning', account, account, '', 'dialog-warning',
|
||||
_('Wrong OpenPGP passphrase'),
|
||||
_('You are currently connected without your OpenPGP key.'))
|
||||
self.forget_gpg_passphrase(obj.keyID)
|
||||
|
||||
@staticmethod
|
||||
def handle_event_client_cert_passphrase(obj):
|
||||
def on_ok(passphrase, checked):
|
||||
|
@ -607,15 +578,6 @@ class Interface:
|
|||
_('Enter the certificate passphrase for account %s') % \
|
||||
obj.conn.name, ok_handler=on_ok, cancel_handler=on_cancel)
|
||||
|
||||
def handle_event_gpg_password_required(self, obj):
|
||||
#('GPG_PASSWORD_REQUIRED', account, (callback,))
|
||||
if obj.keyid in self.gpg_passphrase:
|
||||
request = self.gpg_passphrase[obj.keyid]
|
||||
else:
|
||||
request = PassphraseRequest(obj.keyid)
|
||||
self.gpg_passphrase[obj.keyid] = request
|
||||
request.add_callback(obj.conn.name, obj.callback)
|
||||
|
||||
def handle_event_password_required(self, obj):
|
||||
#('PASSWORD_REQUIRED', account, None)
|
||||
account = obj.conn.name
|
||||
|
@ -652,14 +614,10 @@ class Interface:
|
|||
if obj.sub == 'remove':
|
||||
return
|
||||
# Add new contact to roster
|
||||
keyID = ''
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
if obj.jid in attached_keys:
|
||||
keyID = attached_keys[attached_keys.index(obj.jid) + 1]
|
||||
|
||||
contact = app.contacts.create_contact(jid=obj.jid,
|
||||
account=account, name=obj.nickname, groups=obj.groups,
|
||||
show='offline', sub=obj.sub, ask=obj.ask, keyID=keyID,
|
||||
show='offline', sub=obj.sub, ask=obj.ask,
|
||||
avatar_sha=obj.avatar_sha)
|
||||
app.contacts.add_contact(account, contact)
|
||||
self.roster.add_contact(obj.jid, account)
|
||||
|
@ -750,13 +708,8 @@ class Interface:
|
|||
def handle_event_file_request(self, obj):
|
||||
account = obj.conn.name
|
||||
if obj.jid not in app.contacts.get_jid_list(account):
|
||||
keyID = ''
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
if obj.jid in attached_keys:
|
||||
keyID = attached_keys[attached_keys.index(obj.jid) + 1]
|
||||
contact = app.contacts.create_not_in_roster_contact(jid=obj.jid,
|
||||
account=account, keyID=keyID)
|
||||
account=account)
|
||||
app.contacts.add_contact(account, contact)
|
||||
self.roster.add_contact(obj.jid, account)
|
||||
contact = app.contacts.get_first_contact_from_jid(account, obj.jid)
|
||||
|
@ -1287,7 +1240,6 @@ class Interface:
|
|||
self.handlers = {
|
||||
'DB_ERROR': [self.handle_event_db_error],
|
||||
'file-send-error': [self.handle_event_file_send_error],
|
||||
'bad-gpg-passphrase': [self.handle_event_bad_gpg_passphrase],
|
||||
'bookmarks-received': [self.handle_event_bookmarks],
|
||||
'client-cert-passphrase': [
|
||||
self.handle_event_client_cert_passphrase],
|
||||
|
@ -1296,7 +1248,6 @@ class Interface:
|
|||
'file-request-received': [self.handle_event_file_request],
|
||||
'muc-invitation': [self.handle_event_gc_invitation],
|
||||
'muc-decline': [self.handle_event_gc_decline],
|
||||
'gpg-password-required': [self.handle_event_gpg_password_required],
|
||||
'http-auth-received': [self.handle_event_http_auth],
|
||||
'information': [self.handle_event_information],
|
||||
'iq-error-received': [self.handle_event_iq_error],
|
||||
|
@ -2326,7 +2277,6 @@ class Interface:
|
|||
self.minimized_controls = {}
|
||||
self.status_sent_to_users = {}
|
||||
self.status_sent_to_groups = {}
|
||||
self.gpg_passphrase = {}
|
||||
self.pass_dialog = {}
|
||||
self.db_error_dialog = None
|
||||
|
||||
|
@ -2492,89 +2442,6 @@ class Interface:
|
|||
self.network_state = self.network_monitor.get_network_available()
|
||||
|
||||
|
||||
class PassphraseRequest:
|
||||
def __init__(self, keyid):
|
||||
self.keyid = keyid
|
||||
self.callbacks = []
|
||||
self.dialog_created = False
|
||||
self.dialog = None
|
||||
self.passphrase = None
|
||||
self.completed = False
|
||||
|
||||
def interrupt(self, account=None):
|
||||
if account:
|
||||
for (acct, cb) in self.callbacks:
|
||||
if acct == account:
|
||||
self.callbacks.remove((acct, cb))
|
||||
else:
|
||||
self.callbacks = []
|
||||
if not self.callbacks:
|
||||
self.dialog.window.destroy()
|
||||
|
||||
def run_callback(self, account, callback):
|
||||
app.connections[account].gpg_passphrase(self.passphrase)
|
||||
callback()
|
||||
|
||||
def add_callback(self, account, cb):
|
||||
if self.completed:
|
||||
self.run_callback(account, cb)
|
||||
else:
|
||||
self.callbacks.append((account, cb))
|
||||
if not self.dialog_created:
|
||||
self.create_dialog(account)
|
||||
|
||||
def complete(self, passphrase):
|
||||
self.passphrase = passphrase
|
||||
self.completed = True
|
||||
if passphrase is not None:
|
||||
GLib.timeout_add_seconds(30, app.interface.forget_gpg_passphrase,
|
||||
self.keyid)
|
||||
for (account, cb) in self.callbacks:
|
||||
self.run_callback(account, cb)
|
||||
self.callbacks = []
|
||||
|
||||
def create_dialog(self, account):
|
||||
title = _('Passphrase Required')
|
||||
second = _('Enter OpenPGP key passphrase for key %(keyid)s '
|
||||
'(account %(account)s).') % {'keyid': self.keyid,
|
||||
'account': account}
|
||||
|
||||
def _cancel():
|
||||
# user cancelled, continue without GPG
|
||||
self.complete(None)
|
||||
|
||||
def _ok(passphrase, checked, count):
|
||||
result = app.connections[account].test_gpg_passphrase(passphrase)
|
||||
if result == 'ok':
|
||||
# passphrase is good
|
||||
self.complete(passphrase)
|
||||
return
|
||||
|
||||
if result == 'expired':
|
||||
ErrorDialog(
|
||||
_('OpenPGP key expired'),
|
||||
_('Your OpenPGP key has expired, you will be connected to '
|
||||
'%s without OpenPGP.') % account)
|
||||
# Don't try to connect with GPG
|
||||
app.connections[account].continue_connect_info[2] = False
|
||||
self.complete(None)
|
||||
return
|
||||
|
||||
if count < 3:
|
||||
# ask again
|
||||
dialogs.PassphraseDialog(
|
||||
_('Wrong Passphrase'),
|
||||
_('Please retype your OpenPGP passphrase or press Cancel.'),
|
||||
ok_handler=(_ok, count + 1), cancel_handler=_cancel)
|
||||
else:
|
||||
# user failed 3 times, continue without GPG
|
||||
self.complete(None)
|
||||
|
||||
self.dialog = dialogs.PassphraseDialog(
|
||||
title, second, ok_handler=(_ok, 1), cancel_handler=_cancel)
|
||||
self.dialog_created = True
|
||||
|
||||
|
||||
class ThreadInterface:
|
||||
def __init__(self, func, func_args=(), callback=None, callback_args=()):
|
||||
"""
|
||||
|
|
|
@ -217,7 +217,6 @@ control=None, gc_contact=None, is_anonymous=True):
|
|||
rename_menuitem = xml.get_object('rename_menuitem')
|
||||
edit_groups_menuitem = xml.get_object('edit_groups_menuitem')
|
||||
send_file_menuitem = xml.get_object('send_file_menuitem')
|
||||
assign_openpgp_key_menuitem = xml.get_object('assign_openpgp_key_menuitem')
|
||||
information_menuitem = xml.get_object('information_menuitem')
|
||||
history_menuitem = xml.get_object('history_menuitem')
|
||||
send_custom_status_menuitem = xml.get_object('send_custom_status_menuitem')
|
||||
|
@ -290,16 +289,9 @@ control=None, gc_contact=None, is_anonymous=True):
|
|||
# contact is in normal group
|
||||
edit_groups_menuitem.connect('activate', roster.on_edit_groups, [(contact,
|
||||
account)])
|
||||
|
||||
if app.connections[account].gpg:
|
||||
assign_openpgp_key_menuitem.connect('activate',
|
||||
roster.on_assign_pgp_key, contact, account)
|
||||
else:
|
||||
assign_openpgp_key_menuitem.set_sensitive(False)
|
||||
else:
|
||||
# contact is in group 'Not in Roster'
|
||||
edit_groups_menuitem.set_sensitive(False)
|
||||
assign_openpgp_key_menuitem.set_sensitive(False)
|
||||
|
||||
# Hide items when it's self contact row
|
||||
if our_jid:
|
||||
|
|
|
@ -5,8 +5,6 @@ from gajim.common.i18n import _
|
|||
from gajim import gtkgui_helpers
|
||||
from gajim.common.const import OptionKind, OptionType
|
||||
from gajim.common.exceptions import GajimGeneralException
|
||||
from gajim import dialogs
|
||||
from gajim.gtk.dialogs import ErrorDialog
|
||||
from gajim.gtk.dialogs import ChangePasswordDialog
|
||||
from gajim.gtk.util import get_image_button
|
||||
|
||||
|
@ -74,7 +72,6 @@ class OptionsBox(Gtk.ListBox):
|
|||
OptionKind.PRIORITY: PriorityOption,
|
||||
OptionKind.HOSTNAME: CutstomHostnameOption,
|
||||
OptionKind.CHANGEPASSWORD: ChangePasswordOption,
|
||||
OptionKind.GPG: GPGOption,
|
||||
}
|
||||
|
||||
if extend is not None:
|
||||
|
@ -566,55 +563,3 @@ class ChangePasswordOption(DialogOption):
|
|||
con = app.connections[self.account]
|
||||
activatable = con.connected >= 2 and con.register_supported
|
||||
self.get_parent().set_activatable(activatable)
|
||||
|
||||
|
||||
class GPGOption(DialogOption):
|
||||
def __init__(self, *args, **kwargs):
|
||||
DialogOption.__init__(self, *args, **kwargs)
|
||||
|
||||
def show_dialog(self, parent):
|
||||
secret_keys = app.connections[self.account].ask_gpg_secrete_keys()
|
||||
secret_keys[_('None')] = _('None')
|
||||
|
||||
if not secret_keys:
|
||||
ErrorDialog(
|
||||
_('Failed to get secret keys'),
|
||||
_('There is no OpenPGP secret key available.'),
|
||||
transient_for=parent)
|
||||
return
|
||||
|
||||
dialog = dialogs.ChooseGPGKeyDialog(
|
||||
_('OpenPGP Key Selection'), _('Choose your OpenPGP key'),
|
||||
secret_keys, self.on_key_selected, transient_for=parent)
|
||||
dialog.window.connect('destroy', self.on_destroy)
|
||||
|
||||
def on_key_selected(self, keyID):
|
||||
if keyID is None:
|
||||
return
|
||||
keyid_new, keyname_new = keyID
|
||||
|
||||
keyid = app.config.get_per('accounts', self.account, 'keyid')
|
||||
|
||||
if keyid_new == _('None'):
|
||||
if keyid == '':
|
||||
return
|
||||
app.config.set_per('accounts', self.account, 'keyname', '')
|
||||
app.config.set_per('accounts', self.account, 'keyid', '')
|
||||
else:
|
||||
if keyid == keyid_new:
|
||||
return
|
||||
app.config.set_per(
|
||||
'accounts', self.account, 'keyname', keyname_new)
|
||||
app.config.set_per(
|
||||
'accounts', self.account, 'keyid', keyid_new)
|
||||
|
||||
def get_option_value(self):
|
||||
keyid = app.config.get_per('accounts', self.account, 'keyid')
|
||||
keyname = app.config.get_per('accounts', self.account, 'keyname')
|
||||
if keyid is not None:
|
||||
return '\n'.join((keyid, keyname))
|
||||
return ''
|
||||
|
||||
def set_activatable(self, name, value):
|
||||
active = self.account in app.connections
|
||||
self.get_parent().set_activatable(app.is_installed('GPG') and active)
|
||||
|
|
|
@ -194,7 +194,6 @@ class GajimRemote(Server):
|
|||
<method name='send_chat_message'>
|
||||
<arg name='jid' type='s' />
|
||||
<arg name='message' type='s' />
|
||||
<arg name='keyID' type='s' />
|
||||
<arg name='account' type='s' />
|
||||
<arg direction='out' type='b' />
|
||||
</method>
|
||||
|
@ -214,7 +213,6 @@ class GajimRemote(Server):
|
|||
<arg name='jid' type='s' />
|
||||
<arg name='subject' type='s' />
|
||||
<arg name='message' type='s' />
|
||||
<arg name='keyID' type='s' />
|
||||
<arg name='account' type='s' />
|
||||
<arg direction='out' type='b' />
|
||||
</method>
|
||||
|
@ -339,7 +337,7 @@ class GajimRemote(Server):
|
|||
except AttributeError:
|
||||
chatstate = ''
|
||||
self.raise_signal('MessageSent', (obj.conn.name, [
|
||||
obj.jid, obj.message, obj.keyID, chatstate]))
|
||||
obj.jid, obj.message, chatstate]))
|
||||
|
||||
def on_time(self, obj):
|
||||
self.raise_signal('EntityTime', (obj.conn.name, [obj.jid.getStripped(),
|
||||
|
@ -360,7 +358,7 @@ class GajimRemote(Server):
|
|||
else:
|
||||
return
|
||||
self.raise_signal(event, (obj.conn.name, [obj.jid, obj.show,
|
||||
obj.status, obj.resource, obj.prio, obj.keyID, obj.timestamp]))
|
||||
obj.status, obj.resource, obj.prio, obj.timestamp]))
|
||||
|
||||
def on_subscribe_presence_received(self, obj):
|
||||
self.raise_signal('Subscribe', (obj.conn.name, [obj.jid, obj.status,
|
||||
|
@ -504,7 +502,6 @@ class GajimRemote(Server):
|
|||
def _send_message(self,
|
||||
jid,
|
||||
message,
|
||||
keyID,
|
||||
account,
|
||||
type_='chat',
|
||||
subject=None):
|
||||
|
@ -514,8 +511,6 @@ class GajimRemote(Server):
|
|||
"""
|
||||
if not jid or not message:
|
||||
return False
|
||||
if not keyID:
|
||||
keyID = ''
|
||||
|
||||
connected_account = self._get_account_and_contact(account, jid)[0]
|
||||
if connected_account:
|
||||
|
@ -534,29 +529,25 @@ class GajimRemote(Server):
|
|||
account=connected_account,
|
||||
jid=jid,
|
||||
message=message,
|
||||
keyID=keyID,
|
||||
type_=type_,
|
||||
control=ctrl))
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
def send_chat_message(self, jid, message, keyID, account):
|
||||
def send_chat_message(self, jid, message, account):
|
||||
"""
|
||||
Send chat 'message' to 'jid', using account (optional) 'account'. If keyID
|
||||
is specified, encrypt the message with the pgp key
|
||||
Send chat 'message' to 'jid', using account (optional) 'account'.
|
||||
"""
|
||||
jid = self._get_real_jid(jid, account)
|
||||
return self._send_message(jid, message, keyID, account)
|
||||
return self._send_message(jid, message, account)
|
||||
|
||||
def send_single_message(self, jid, subject, message, keyID, account):
|
||||
def send_single_message(self, jid, subject, message, account):
|
||||
"""
|
||||
Send single 'message' to 'jid', using account (optional) 'account'. If
|
||||
keyID is specified, encrypt the message with the pgp key
|
||||
Send single 'message' to 'jid', using account (optional) 'account'.
|
||||
"""
|
||||
jid = self._get_real_jid(jid, account)
|
||||
return self._send_message(jid, message, keyID, account, 'normal',
|
||||
subject)
|
||||
return self._send_message(jid, message, account, 'normal', subject)
|
||||
|
||||
def send_groupchat_message(self, room_jid, message, account):
|
||||
"""
|
||||
|
@ -879,14 +870,7 @@ class GajimRemote(Server):
|
|||
contact_dict['name'] = GLib.Variant('s', name)
|
||||
contact_dict['show'] = GLib.Variant('s', prim_contact.show)
|
||||
contact_dict['jid'] = GLib.Variant('s', prim_contact.jid)
|
||||
if prim_contact.keyID:
|
||||
keyID = None
|
||||
if len(prim_contact.keyID) == 8:
|
||||
keyID = prim_contact.keyID
|
||||
elif len(prim_contact.keyID) == 16:
|
||||
keyID = prim_contact.keyID[8:]
|
||||
if keyID:
|
||||
contact_dict['openpgp'] = GLib.Variant('s', keyID)
|
||||
|
||||
resources = GLib.VariantBuilder(GLib.VariantType('a(sis)'))
|
||||
for contact in contacts:
|
||||
resource_props = (contact.resource, int(contact.priority),
|
||||
|
|
|
@ -998,14 +998,9 @@ class RosterWindow:
|
|||
# FIXME: integrate into add_contact()
|
||||
def add_to_not_in_the_roster(self, account, jid, nick='', resource='',
|
||||
groupchat=False):
|
||||
keyID = ''
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
if jid in attached_keys:
|
||||
keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
contact = app.contacts.create_not_in_roster_contact(
|
||||
jid=jid, account=account, resource=resource, name=nick,
|
||||
keyID=keyID, groupchat=groupchat)
|
||||
groupchat=groupchat)
|
||||
app.contacts.add_contact(account, contact)
|
||||
self.add_contact(contact.jid, account)
|
||||
return contact
|
||||
|
@ -1871,19 +1866,13 @@ class RosterWindow:
|
|||
show = 'offline' # show is offline by default
|
||||
status = '' # no status message by default
|
||||
|
||||
keyID = ''
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
if jid in attached_keys:
|
||||
keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
|
||||
if app.jid_is_transport(jid):
|
||||
array[jid]['groups'] = [_('Transports')]
|
||||
#TRANSP - potential
|
||||
contact1 = app.contacts.create_contact(jid=ji, account=account,
|
||||
name=name, groups=array[jid]['groups'], show=show,
|
||||
status=status, sub=array[jid]['subscription'],
|
||||
ask=array[jid]['ask'], resource=resource, keyID=keyID)
|
||||
ask=array[jid]['ask'], resource=resource)
|
||||
app.contacts.add_contact(account, contact1)
|
||||
|
||||
# If we already have chat windows opened, update them with new
|
||||
|
@ -2031,14 +2020,9 @@ class RosterWindow:
|
|||
jid, txt, nickname, groups_list, auto_auth)
|
||||
contact = app.contacts.get_contact_with_highest_priority(account, jid)
|
||||
if not contact:
|
||||
keyID = ''
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
if jid in attached_keys:
|
||||
keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
contact = app.contacts.create_contact(jid=jid, account=account,
|
||||
name=nickname, groups=groups_list, show='requested', status='',
|
||||
ask='none', sub='subscribe', keyID=keyID)
|
||||
ask='none', sub='subscribe')
|
||||
app.contacts.add_contact(account, contact)
|
||||
else:
|
||||
if not _('Not in Roster') in contact.get_shown_groups():
|
||||
|
@ -2079,13 +2063,6 @@ class RosterWindow:
|
|||
if app.connections[account].connected < 2:
|
||||
self.set_connecting_state(account)
|
||||
|
||||
keyid = app.config.get_per('accounts', account, 'keyid')
|
||||
if keyid and not app.connections[account].gpg:
|
||||
WarningDialog(_('OpenPGP is not usable'),
|
||||
_('Gajim needs python-gnupg >= 0.3.8\n'
|
||||
'Beware there is an incompatible Python package called gnupg.\n'
|
||||
'You will be connected to %s without OpenPGP.') % account)
|
||||
|
||||
self.send_status_continue(account, status, txt, auto, to)
|
||||
|
||||
def send_pep(self, account, pep_dict):
|
||||
|
@ -2941,46 +2918,6 @@ class RosterWindow:
|
|||
_('Also remove all contacts in this group from your roster'),
|
||||
on_response_ok=on_ok)
|
||||
|
||||
def on_assign_pgp_key(self, widget, contact, account):
|
||||
attached_keys = app.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
keys = {}
|
||||
keyID = _('None')
|
||||
for i in range(len(attached_keys) // 2):
|
||||
keys[attached_keys[2*i]] = attached_keys[2*i+1]
|
||||
if attached_keys[2*i] == contact.jid:
|
||||
keyID = attached_keys[2*i+1]
|
||||
public_keys = app.connections[account].ask_gpg_keys()
|
||||
public_keys[_('None')] = _('None')
|
||||
|
||||
def on_key_selected(keyID):
|
||||
if keyID is None:
|
||||
return
|
||||
if keyID[0] == _('None'):
|
||||
if contact.jid in keys:
|
||||
del keys[contact.jid]
|
||||
keyID = ''
|
||||
else:
|
||||
keyID = keyID[0]
|
||||
keys[contact.jid] = keyID
|
||||
|
||||
ctrl = app.interface.msg_win_mgr.get_control(contact.jid, account)
|
||||
if ctrl:
|
||||
ctrl.update_ui()
|
||||
|
||||
keys_str = ''
|
||||
for jid in keys:
|
||||
keys_str += jid + ' ' + keys[jid] + ' '
|
||||
app.config.set_per('accounts', account, 'attached_gpg_keys',
|
||||
keys_str)
|
||||
for u in app.contacts.get_contacts(account, contact.jid):
|
||||
u.keyID = helpers.prepare_and_validate_gpg_keyID(account,
|
||||
contact.jid, keyID)
|
||||
|
||||
dialogs.ChooseGPGKeyDialog(_('Assign OpenPGP Key'),
|
||||
_('Select a key to apply to the contact'), public_keys,
|
||||
on_key_selected, selected=keyID, transient_for=self.window)
|
||||
|
||||
def on_edit_groups(self, widget, list_):
|
||||
dialogs.EditGroupsDialog(list_)
|
||||
|
||||
|
|
Loading…
Reference in New Issue