diff options
Diffstat (limited to 'plugins/otr.py')
-rw-r--r-- | plugins/otr.py | 162 |
1 files changed, 121 insertions, 41 deletions
diff --git a/plugins/otr.py b/plugins/otr.py index 96792a4d..c0cd8637 100644 --- a/plugins/otr.py +++ b/plugins/otr.py @@ -66,8 +66,9 @@ Command added to Conversation Tabs and Private Tabs: .. warning:: - With ``drop``, the private key is only removed from the filesystem, *NOT* with multiple rewrites in a secure - manner, you should do that yourself if you want to be sure. + With ``drop``, the private key is only removed from the filesystem, + *NOT* with multiple rewrites in a secure manner, you should do that + yourself if you want to be sure. To use OTR, make sure the plugin is loaded (if not, then do ``/load otr``). @@ -160,8 +161,8 @@ nick is used by different people). .. _Off The Record messaging: http://wiki.xmpp.org/web/OTR """ +from gettext import gettext as _ import potr -import theming import logging log = logging.getLogger(__name__) @@ -172,10 +173,11 @@ from potr.context import NotEncryptedError, UnencryptedMessage, ErrorReceived, N STATE_ENCRYPTED, STATE_PLAINTEXT, STATE_FINISHED, Context, Account, crypt import xhtml -from plugin import BasePlugin -from tabs import ConversationTab, DynamicConversationTab, PrivateTab from common import safeJID from config import config +from plugin import BasePlugin +from tabs import ConversationTab, DynamicConversationTab, PrivateTab +from theming import get_theme, dump_tuple OTR_DIR = os.path.join(os.getenv('XDG_DATA_HOME') or '~/.local/share', 'poezio', 'otr') @@ -198,7 +200,7 @@ def hl(tab): conv_jid = safeJID(tab.name) if 'private' in config.get('beep_on', 'highlight private').split(): - if config.get_by_tabname('disable_beep', 'false', conv_jid.bare, False).lower() != 'true': + if config.get_by_tabname('disable_beep', False, conv_jid.bare, False): curses.beep() class PoezioContext(Context): @@ -216,14 +218,20 @@ class PoezioContext(Context): return False def inject(self, msg, appdata=None): - message = self.xmpp.make_message(mto=self.peer, mbody=msg.decode('ascii'), mtype='chat') + message = self.xmpp.make_message(mto=self.peer, + mbody=msg.decode('ascii'), + mtype='chat') message.enable('carbon_private') message.send() def setState(self, newstate): + color_jid = '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID) + color_info = '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT) + tab = self.core.get_tab_by_name(self.peer) if not tab: - tab = self.core.get_tab_by_name(safeJID(self.peer).bare, DynamicConversationTab) + tab = self.core.get_tab_by_name(safeJID(self.peer).bare, + DynamicConversationTab) if not tab.locked_resource == safeJID(self.peer).resource: tab = None if self.state == STATE_ENCRYPTED: @@ -231,24 +239,50 @@ class PoezioContext(Context): log.debug('OTR conversation with %s refreshed', self.peer) if tab: if self.getCurrentTrust(): - tab.add_message('Refreshed \x19btrusted\x19o OTR conversation with %s' % self.peer, typ=self.log) + msg = _('%(info)sRefreshed \x19btrusted\x19o%(info)s' + ' OTR conversation with %(jid_c)s%(jid)s') % { + 'info': color_info, + 'jid_c': color_jid, + 'jid': self.peer + } + tab.add_message(msg, typ=self.log) else: - tab.add_message('Refreshed \x19buntrusted\x19o OTR conversation with %s (key: %s)' % - (self.peer, self.getCurrentKey()), typ=self.log) + msg = _('%(info)sRefreshed \x19buntrusted\x19o%(info)s' + ' OTR conversation with %(jid_c)s%(jid)s' + '%(info)s, key: \x19o%(key)s') % { + 'jid': self.peer, + 'key': self.getCurrentKey(), + 'info': color_info, + 'jid_c': color_jid} + + tab.add_message(msg, typ=self.log) hl(tab) elif newstate == STATE_FINISHED or newstate == STATE_PLAINTEXT: log.debug('OTR conversation with %s finished', self.peer) if tab: - tab.add_message('Ended OTR conversation with %s' % self.peer, typ=self.log) + tab.add_message('%sEnded OTR conversation with %s%s' % ( + color_info, color_jid, self.peer), + typ=self.log) hl(tab) else: if newstate == STATE_ENCRYPTED: if tab: if self.getCurrentTrust(): - tab.add_message('Started \x19btrusted\x19o OTR conversation with %s' % self.peer, typ=self.log) + msg = _('%(info)sStarted a \x19btrusted\x19o%(info)s ' + 'OTR conversation with %(jid_c)s%(jid)s') % { + 'jid': self.peer, + 'info': color_info, + 'jid_c': color_jid} + tab.add_message(msg, typ=self.log) else: - tab.add_message('Started \x19buntrusted\x19o OTR conversation with %s (key: %s)' % - (self.peer, self.getCurrentKey()), typ=self.log) + msg = _('%(info)sStarted an \x19buntrusted\x19o%(info)s' + ' OTR conversation with %(jid_c)s%(jid)s' + '%(info)s, key: \x19o%(key)s') % { + 'jid': self.peer, + 'key': self.getCurrentKey(), + 'info': color_info, + 'jid_c': color_jid} + tab.add_message(msg, typ=self.log) hl(tab) log.debug('Set encryption state of %s to %s', self.peer, states[newstate]) @@ -325,10 +359,10 @@ class Plugin(BasePlugin): def init(self): # set the default values from the config - allow_v2 = self.config.get('allow_v2', 'true').lower() - POLICY_FLAGS['ALLOW_V2'] = (allow_v2 != 'false') - allow_v1 = self.config.get('allow_v1', 'false').lower() - POLICY_FLAGS['ALLOW_v1'] = (allow_v1 == 'true') + allow_v2 = self.config.get('allow_v2', True) + POLICY_FLAGS['ALLOW_V2'] = allow_v2 + allow_v1 = self.config.get('allow_v1', False) + POLICY_FLAGS['ALLOW_v1'] = allow_v1 global OTR_DIR OTR_DIR = os.path.expanduser(self.config.get('keys_dir', '') or OTR_DIR) @@ -395,14 +429,23 @@ class Plugin(BasePlugin): return self.contexts[jid] def on_conversation_msg(self, msg, tab): + color_jid = '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID) + color_info = '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT) try: ctx = self.get_context(msg['from']) txt, tlvs = ctx.receiveMessage(msg["body"].encode('utf-8')) except UnencryptedMessage as err: # received an unencrypted message inside an OTR session - tab.add_message('The following message from %s was not encrypted:\n%s' % (msg['from'], err.args[0].decode('utf-8')), - jid=msg['from'], nick_color=theming.get_theme().COLOR_REMOTE_USER, - typ=0) + text = _('%(info)sThe following message from %(jid_c)s%(jid)s' + '%(info)s was \x19bnot\x19o%(info)s encrypted:' + '\x19o\n%(msg)s') % { + 'info': color_info, + 'jid_c': color_jid, + 'jid': msg['from'], + 'msg': err.args[0].decode('utf-8')} + tab.add_message(text, jid=msg['from'], + nick_color=get_theme().COLOR_REMOTE_USER, + typ=0) del msg['body'] del msg['html'] hl(tab) @@ -410,7 +453,14 @@ class Plugin(BasePlugin): return except ErrorReceived as err: # Received an OTR error - tab.add_message('Received the following error from %s: %s' % (msg['from'], err.args[0]), typ=0) + text = _('%(info)sReceived the following error from ' + '%(jid_c)s%(jid)s%(info)s:\x19o %(err)s') % { + 'jid': msg['from'], + 'err': err.args[0], + 'info': color_info, + 'jid_c': color_jid} + + tab.add_message(text, typ=0) del msg['body'] del msg['html'] hl(tab) @@ -423,9 +473,16 @@ class Plugin(BasePlugin): # but do an additional check because of a bug with py3k if ctx.state != STATE_PLAINTEXT or ctx.getPolicy('REQUIRE_ENCRYPTION'): - tab.add_message('The following message from %s was not encrypted:\n%s' % (msg['from'], err.args[0].decode('utf-8')), - jid=msg['from'], nick_color=theming.get_theme().COLOR_REMOTE_USER, - typ=ctx.log) + text = _('%(info)sThe following message from ' + '%(jid_c)s%(jid)s%(info)s was \x19b' + 'not\x19o%(info)s encrypted:\x19o\n%(msg)s') % { + 'jid': msg['from'], + 'msg': err.args[0].decode('utf-8'), + 'info': color_info, + 'jid_c': color_jid} + tab.add_message(text, jid=msg['from'], + nick_color=get_theme().COLOR_REMOTE_USER, + typ=ctx.log) del msg['body'] del msg['html'] hl(tab) @@ -433,27 +490,34 @@ class Plugin(BasePlugin): return return except NotEncryptedError as err: - tab.add_message('An encrypted message from %s was received but is ' - 'unreadable, as you are not currently communicating' - ' privately.' % msg['from'], jid=msg['from'], - nick_color=theming.get_theme().COLOR_REMOTE_USER, - typ=0) + text = _('%(info)sAn encrypted message from %(jid_c)s%(jid)s' + '%(info)s was received but is unreadable, as you are' + ' not currently communicating privately.') % { + 'info': color_info, + 'jid_c': color_jid, + 'jid': msg['from']} + tab.add_message(text, jid=msg['from'], + nick_color=get_theme().COLOR_REMOTE_USER, + typ=0) hl(tab) del msg['body'] del msg['html'] self.core.refresh_window() return except crypt.InvalidParameterError: - tab.add_message('The message from %s could not be decrypted' % - msg['from'], jid=msg['from'], typ=0, - nick_color=theming.get_theme().COLOR_REMOTE_USER) + tab.add_message('%sThe message from %s%s%s could not be decrypted.' + % (color_info, color_jid, msg['from'], color_info), + jid=msg['from'], typ=0, + nick_color=get_theme().COLOR_REMOTE_USER) hl(tab) del msg['body'] del msg['html'] self.core.refresh_window() return except: - tab.add_message('An unspecified error in the OTR plugin occured', typ=0) + tab.add_message('%sAn unspecified error in the OTR plugin occured' + % color_info, + typ=0) log.error('Unspecified error in the OTR plugin', exc_info=True) return @@ -476,7 +540,7 @@ class Plugin(BasePlugin): pass tab.add_message(body, nickname=tab.nick, jid=msg['from'], forced_user=user, typ=ctx.log, - nick_color=theming.get_theme().COLOR_REMOTE_USER) + nick_color=get_theme().COLOR_REMOTE_USER) hl(tab) self.core.refresh_window() del msg['body'] @@ -499,7 +563,7 @@ class Plugin(BasePlugin): tab.add_message(msg['body'], nickname=self.core.own_nick or tab.own_nick, - nick_color=theming.get_theme().COLOR_OWN_NICK, + nick_color=get_theme().COLOR_OWN_NICK, identifier=msg['id'], jid=self.core.xmpp.boundjid, typ=ctx.log) @@ -520,6 +584,8 @@ class Plugin(BasePlugin): arg = arg.strip() tab = self.api.current_tab() name = tab.name + color_jid = '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID) + color_info = '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT) if isinstance(tab, DynamicConversationTab) and tab.locked_resource: name = safeJID(tab.name) name.resource = tab.locked_resource @@ -544,7 +610,7 @@ class Plugin(BasePlugin): if context.state not in (STATE_FINISHED, STATE_PLAINTEXT): context.disconnect() self.account.drop_privkey() - tab.add_message('Private key dropped.', typ=0) + tab.add_message('%sPrivate key dropped.' % color_info, typ=0) elif arg == 'trust': ctx = self.get_context(name) key = ctx.getCurrentKey() @@ -555,7 +621,13 @@ class Plugin(BasePlugin): if not ctx.getCurrentTrust(): ctx.setTrust(fpr, 'verified') self.account.saveTrusts() - tab.add_message('You added \x19b%s\x19o with key %s to your trusted list.' % (ctx.trustName, key), typ=0) + text = _('%(info)sYou added %(jid_c)s%(jid)s%(info)s with key ' + '\x19o%(key)s%(info)s to your trusted list.') % { + 'jid': ctx.trustName, + 'key': key, + 'info': color_info, + 'jid_c': color_jid} + tab.add_message(text, typ=0) elif arg == 'untrust': ctx = self.get_context(name) key = ctx.getCurrentKey() @@ -566,9 +638,17 @@ class Plugin(BasePlugin): if ctx.getCurrentTrust(): ctx.setTrust(fpr, '') self.account.saveTrusts() - tab.add_message('You removed \x19b%s\x19o with key %s from your trusted list.' % (ctx.trustName, key), typ=0) + text = _('%(info)sYou removed %(jid_c)s%(jid)s%(info)s with ' + 'key \x19o%(key)s%(info)s from your trusted list.') % { + 'jid': ctx.trustName, + 'key': key, + 'info': color_info, + 'jid_c': color_jid} + + tab.add_message(text, typ=0) self.core.refresh_window() def completion_otr(self, the_input): - return the_input.new_completion(['start', 'fpr', 'ourfpr', 'refresh', 'end', 'trust', 'untrust'], 1, quotify=False) + comp = ['start', 'fpr', 'ourfpr', 'refresh', 'end', 'trust', 'untrust'] + return the_input.new_completion(comp, 1, quotify=False) |