make gotr plugin visible but not activatable if potr is missing
This commit is contained in:
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user