make gotr plugin visible but not activatable if potr is missing

This commit is contained in:
Yann Leboulanger
2012-05-01 00:48:26 +02:00
parent 8bff21d54b
commit e8f0870878
2 changed files with 136 additions and 129 deletions

View File

@@ -74,148 +74,147 @@ try:
import potr import potr
if not hasattr(potr, 'VERSION') or potr.VERSION < MINVERSION: if not hasattr(potr, 'VERSION') or potr.VERSION < MINVERSION:
raise ImportError('old / unsupported python-otr version') raise ImportError('old / unsupported python-otr version')
except ImportError:
HAS_POTR = False
def get_jid_from_fjid(fjid): def get_jid_from_fjid(fjid):
return gajim.get_room_and_nick_from_fjid(fjid)[0] return gajim.get_room_and_nick_from_fjid(fjid)[0]
class GajimContext(potr.context.Context): class GajimContext(potr.context.Context):
# self.peer is fjid # self.peer is fjid
# self.jid does not contain resource # self.jid does not contain resource
__slots__ = ['smpWindow', 'jid'] __slots__ = ['smpWindow', 'jid']
def __init__(self, account, peer): def __init__(self, account, peer):
super(GajimContext, self).__init__(account, peer) super(GajimContext, self).__init__(account, peer)
self.jid = get_jid_from_fjid(peer) self.jid = get_jid_from_fjid(peer)
self.trustName = self.jid self.trustName = self.jid
self.smpWindow = ui.ContactOtrSmpWindow(self) self.smpWindow = ui.ContactOtrSmpWindow(self)
def inject(self, msg, appdata=None): def inject(self, msg, appdata=None):
log.debug('inject(appdata=%s)', appdata) log.debug('inject(appdata=%s)', appdata)
msg = unicode(msg) msg = unicode(msg)
account = self.user.accountname account = self.user.accountname
stanza = common.xmpp.Message(to=self.peer, body=msg, typ='chat') stanza = common.xmpp.Message(to=self.peer, body=msg, typ='chat')
if appdata is not None: if appdata is not None:
session = appdata.get('session', None) session = appdata.get('session', None)
if session is not None: if session is not None:
stanza.setThread(session.thread_id) stanza.setThread(session.thread_id)
gajim.connections[account].connection.send(stanza, now=True) gajim.connections[account].connection.send(stanza, now=True)
def setState(self, newstate): def setState(self, newstate):
if self.state == potr.context.STATE_ENCRYPTED: if self.state == potr.context.STATE_ENCRYPTED:
# we were encrypted # we were encrypted
if newstate == potr.context.STATE_ENCRYPTED: if newstate == potr.context.STATE_ENCRYPTED:
# and are still -> it's just a refresh # and are still -> it's just a refresh
OtrPlugin.gajim_log( OtrPlugin.gajim_log(
_('Private conversation with %s refreshed.') % self.peer, _('Private conversation with %s refreshed.') % self.peer,
self.user.accountname, self.peer)
elif newstate == potr.context.STATE_FINISHED:
# and aren't anymore -> other side disconnected
OtrPlugin.gajim_log(_('%s has ended his/her private '
'conversation with you. You should do the same.')
% self.peer, self.user.accountname, self.peer)
else:
if newstate == potr.context.STATE_ENCRYPTED:
# we are now encrypted
trust = self.getCurrentTrust()
if trust is None:
fpr = str(self.getCurrentKey())
OtrPlugin.gajim_log(_('New fingerprint for %(peer)s: %(fpr)s')
% {'peer': self.peer, 'fpr': fpr},
self.user.accountname, self.peer) self.user.accountname, self.peer)
self.setCurrentTrust('') elif newstate == potr.context.STATE_FINISHED:
trustStr = 'authenticated' if bool(trust) else '*unauthenticated*' # and aren't anymore -> other side disconnected
OtrPlugin.gajim_log(_('%s has ended his/her private '
'conversation with you. You should do the same.')
% self.peer, self.user.accountname, self.peer)
else:
if newstate == potr.context.STATE_ENCRYPTED:
# we are now encrypted
trust = self.getCurrentTrust()
if trust is None:
fpr = str(self.getCurrentKey())
OtrPlugin.gajim_log(_('New fingerprint for %(peer)s: %(fpr)s')
% {'peer': self.peer, 'fpr': fpr},
self.user.accountname, self.peer)
self.setCurrentTrust('')
trustStr = 'authenticated' if bool(trust) else '*unauthenticated*'
OtrPlugin.gajim_log(
_('%(trustStr)s secured OTR conversation with %(peer)s started')
% {'trustStr': trustStr, 'peer': self.peer},
self.user.accountname, self.peer)
if self.state != potr.context.STATE_PLAINTEXT and \
newstate == potr.context.STATE_PLAINTEXT:
# we are now plaintext
OtrPlugin.gajim_log( OtrPlugin.gajim_log(
_('%(trustStr)s secured OTR conversation with %(peer)s started') _('Private conversation with %s lost.') % self.peer,
% {'trustStr': trustStr, 'peer': self.peer}, self.user.accountname, self.peer)
self.user.accountname, self.peer)
if self.state != potr.context.STATE_PLAINTEXT and \ super(GajimContext, self).setState(newstate)
newstate == potr.context.STATE_PLAINTEXT: OtrPlugin.update_otr(self.peer, self.user.accountname)
# we are now plaintext self.user.plugin.update_context_list()
OtrPlugin.gajim_log(
_('Private conversation with %s lost.') % self.peer,
self.user.accountname, self.peer)
super(GajimContext, self).setState(newstate) def getPolicy(self, key):
OtrPlugin.update_otr(self.peer, self.user.accountname) ret = self.user.plugin.get_flags(self.user.accountname, self.jid)[key]
self.user.plugin.update_context_list() log.debug('getPolicy(key=%s) = %s', key, ret)
return ret
def getPolicy(self, key): class GajimOtrAccount(potr.context.Account):
ret = self.user.plugin.get_flags(self.user.accountname, self.jid)[key] contextclass = GajimContext
log.debug('getPolicy(key=%s) = %s', key, ret) def __init__(self, plugin, accountname):
return ret global PROTOCOL, MMS
self.plugin = plugin
self.accountname = accountname
name = gajim.get_jid_from_account(accountname)
super(GajimOtrAccount, self).__init__(name, PROTOCOL, MMS)
self.keyFilePath = os.path.join(gajim.gajimpaths.data_root, accountname)
class GajimOtrAccount(potr.context.Account): def dropPrivkey(self):
contextclass = GajimContext try:
def __init__(self, plugin, accountname): os.remove(self.keyFilePath + '.key3')
global PROTOCOL, MMS except IOError, e:
self.plugin = plugin if e.errno != 2:
self.accountname = accountname log.exception('IOError occurred when removing key file for %s',
name = gajim.get_jid_from_account(accountname) self.name)
super(GajimOtrAccount, self).__init__(name, PROTOCOL, MMS) self.privkey = None
self.keyFilePath = os.path.join(gajim.gajimpaths.data_root, accountname)
def dropPrivkey(self): def loadPrivkey(self):
try: try:
os.remove(self.keyFilePath + '.key3') with open(self.keyFilePath + '.key3', 'rb') as keyFile:
except IOError, e: return potr.crypt.PK.parsePrivateKey(keyFile.read())[0]
if e.errno != 2: except IOError, e:
log.exception('IOError occurred when removing key file for %s', if e.errno != 2:
self.name) log.exception('IOError occurred when loading key file for %s',
self.privkey = None self.name)
return None
def loadPrivkey(self): def savePrivkey(self):
try: try:
with open(self.keyFilePath + '.key3', 'rb') as keyFile: with open(self.keyFilePath + '.key3', 'wb') as keyFile:
return potr.crypt.PK.parsePrivateKey(keyFile.read())[0] keyFile.write(self.getPrivkey().serializePrivateKey())
except IOError, e: except IOError, e:
if e.errno != 2:
log.exception('IOError occurred when loading key file for %s', log.exception('IOError occurred when loading key file for %s',
self.name) self.name)
return None
def savePrivkey(self): def loadTrusts(self, newCtxCb=None):
try: ''' load the fingerprint trustdb '''
with open(self.keyFilePath + '.key3', 'wb') as keyFile: # it has the same format as libotr, therefore the
keyFile.write(self.getPrivkey().serializePrivateKey()) # redundant account / proto field
except IOError, e: try:
log.exception('IOError occurred when loading key file for %s', with open(self.keyFilePath + '.fpr', 'r') as fprFile:
self.name) for line in fprFile:
ctx, acc, proto, fpr, trust = line[:-1].split('\t')
def loadTrusts(self, newCtxCb=None): if acc != self.name or proto != PROTOCOL:
''' load the fingerprint trustdb ''' continue
# it has the same format as libotr, therefore the
# redundant account / proto field
try:
with open(self.keyFilePath + '.fpr', 'r') as fprFile:
for line in fprFile:
ctx, acc, proto, fpr, trust = line[:-1].split('\t')
if acc != self.name or proto != PROTOCOL: jid = get_jid_from_fjid(ctx)
continue self.setTrust(jid, fpr, trust)
except IOError, e:
if e.errno != 2:
log.exception('IOError occurred when loading fpr file for %s',
self.name)
jid = get_jid_from_fjid(ctx) def saveTrusts(self):
self.setTrust(jid, fpr, trust) try:
except IOError, e: with open(self.keyFilePath + '.fpr', 'w') as fprFile:
if e.errno != 2: for uid, trusts in self.trusts.iteritems():
for fpr, trustVal in trusts.iteritems():
fprFile.write('\t'.join(
(uid, self.name, PROTOCOL, fpr, trustVal)))
fprFile.write('\n')
except IOError, e:
log.exception('IOError occurred when loading fpr file for %s', log.exception('IOError occurred when loading fpr file for %s',
self.name) self.name)
except ImportError:
def saveTrusts(self): HAS_POTR = False
try:
with open(self.keyFilePath + '.fpr', 'w') as fprFile:
for uid, trusts in self.trusts.iteritems():
for fpr, trustVal in trusts.iteritems():
fprFile.write('\t'.join(
(uid, self.name, PROTOCOL, fpr, trustVal)))
fprFile.write('\n')
except IOError, e:
log.exception('IOError occurred when loading fpr file for %s',
self.name)
def otr_dialog_destroy(widget, *args, **kwargs): def otr_dialog_destroy(widget, *args, **kwargs):
widget.destroy() widget.destroy()
@@ -236,15 +235,19 @@ class OtrPlugin(GajimPlugin):
self.gui_extension_points = { self.gui_extension_points = {
'chat_control' : (self.cc_connect, self.cc_disconnect) 'chat_control' : (self.cc_connect, self.cc_disconnect)
} }
if not HAS_POTR:
self.activatable = False
self.available_text = 'potr is not installed. Get it from %s' % \
'https://github.com/afflux/pure-python-otr'
else:
for acc in gajim.contacts.get_accounts():
self.us[acc] = GajimOtrAccount(self, acc)
self.us[acc].loadTrusts()
for acc in gajim.contacts.get_accounts(): acc = str(acc)
self.us[acc] = GajimOtrAccount(self, acc) if acc not in self.config or None not in self.config[acc]:
self.us[acc].loadTrusts() self.config[acc] = {None:DEFAULTFLAGS.copy()}
self.update_context_list()
acc = str(acc)
if acc not in self.config or None not in self.config[acc]:
self.config[acc] = {None:DEFAULTFLAGS.copy()}
self.update_context_list()
@log_calls('OtrPlugin') @log_calls('OtrPlugin')
def activate(self): def activate(self):

View File

@@ -24,7 +24,11 @@ from common import gajim
from plugins.gui import GajimPluginConfigDialog from plugins.gui import GajimPluginConfigDialog
import otrmodule import otrmodule
import potr HAS_PORT = True
try:
import potr
except:
HAS_POTR = False
class OtrPluginConfigDialog(GajimPluginConfigDialog): class OtrPluginConfigDialog(GajimPluginConfigDialog):