Remove GPG code from Gajim

Code moved into plugin
This commit is contained in:
Philipp Hörist 2019-04-16 23:16:41 +02:00
parent 64bac1d910
commit 9d75c77982
30 changed files with 64 additions and 1009 deletions

View File

@ -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()

View File

@ -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 = [

View File

@ -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)

View File

@ -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))

View File

@ -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())

View File

@ -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', ''],

View File

@ -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))

View File

@ -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

View File

@ -23,7 +23,6 @@ class OptionKind(IntEnum):
PRIORITY = 9
FILECHOOSER = 10
CHANGEPASSWORD = 11
GPG = 12
@unique

View File

@ -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)

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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',

View File

@ -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),
]

View File

@ -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):

View File

@ -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)

View File

@ -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 '

View File

@ -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

View File

@ -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=()):
"""

View File

@ -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:

View File

@ -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)

View File

@ -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),

View File

@ -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_)

View File

@ -27,9 +27,6 @@ ignore_missing_imports = True
[mypy-pybonjour.*]
ignore_missing_imports = True
[mypy-gnupg.*]
ignore_missing_imports = True
[mypy-encodings.*]
ignore_missing_imports = True