changeset b14e72db6e7a in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=b14e72db6e7a
description: switch from GnuPGInterface to python-gnupg, so gpg is available
under windows. Fixes #5096, #3615, #1890, #996
diffstat:
debian/rules | 1 -
src/common/GnuPG.py | 200 ++-------
src/common/GnuPGInterface.py | 673 -------------------------------
src/common/connection.py | 19 +-
src/common/gajim.py | 2 +-
src/common/gnupg.py | 921 +++++++++++++++++++++++++++++++++++++++++++
src/features_window.py | 6 +-
7 files changed, 977 insertions(+), 845 deletions(-)
diffs (truncated from 1938 to 300 lines):
diff -r c3f1f5f7d238 -r b14e72db6e7a debian/rules
--- a/debian/rules Mon Nov 29 18:44:16 2010 +0300
+++ b/debian/rules Mon Nov 29 18:44:22 2010 +0100
@@ -12,6 +12,5 @@
DEB_MAKE_INSTALL_TARGET = install DESTDIR=$(DEB_DESTDIR)
binary-install/gajim::
- rm $(DEB_DESTDIR)/usr/share/gajim/src/common/GnuPGInterface.py*
dh_pysupport -pgajim
convert $(DEB_DESTDIR)/usr/share/icons/hicolor/64x64/apps/gajim.png
-resize 32x32 $(DEB_DESTDIR)/usr/share/pixmaps/gajim.xpm
diff -r c3f1f5f7d238 -r b14e72db6e7a src/common/GnuPG.py
--- a/src/common/GnuPG.py Mon Nov 29 18:44:16 2010 +0300
+++ b/src/common/GnuPG.py Mon Nov 29 18:44:22 2010 +0100
@@ -23,17 +23,17 @@
##
import gajim
+import os
from os import tmpfile
-from common import helpers
if gajim.HAVE_GPG:
- import GnuPGInterface
+ import gnupg
- class GnuPG(GnuPGInterface.GnuPG):
- def __init__(self, use_agent = False):
- GnuPGInterface.GnuPG.__init__(self)
+ class GnuPG(gnupg.GPG):
+ def __init__(self, use_agent=False):
+ gnupg.GPG.__init__(self)
+ self.passphrase = None
self.use_agent = use_agent
- self._setup_my_options()
self.always_trust = False
def _setup_my_options(self):
@@ -46,166 +46,56 @@
if self.use_agent:
self.options.extra_args.append('--use-agent')
- def _read_response(self, child_stdout):
- # Internal method: reads all the output from GPG, taking notice
- # only of lines that begin with the magic [GNUPG:] prefix.
- # (See doc/DETAILS in the GPG distribution for info on GPG's
- # output when --status-fd is specified.)
- #
- # Returns a dictionary, mapping GPG's keywords to the arguments
- # for that keyword.
+ def encrypt(self, str_, recipients, always_trust=False):
+ result = super(GnuPG, self).encrypt(str_, recipients,
+ always_trust=always_trust, passphrase=self.passphrase)
- resp = {}
- while True:
- line = helpers.temp_failure_retry(child_stdout.readline)
- if line == "": break
- line = line.rstrip()
- if line[0:9] == '[GNUPG:] ':
- # Chop off the prefix
- line = line[9:]
- L = line.split(None, 1)
- keyword = L[0]
- if len(L) > 1:
- resp[ keyword ] = L[1]
- else:
- resp[ keyword ] = ""
- return resp
+ if result.status == 'invalid recipient':
+ return '', 'NOT_TRUSTED'
- def encrypt(self, str_, recipients, always_trust=False):
- self.options.recipients = recipients # a list!
+ if result.ok:
+ error = ''
+ else:
+ error = result.status
- opt = ['--encrypt']
- if always_trust or self.always_trust:
- opt.append('--always-trust')
- proc = self.run(opt, create_fhs=['stdin', 'stdout', 'status',
- 'stderr'])
- proc.handles['stdin'].write(str_)
- try:
- proc.handles['stdin'].close()
- except IOError:
- pass
-
- output = proc.handles['stdout'].read()
- try:
- proc.handles['stdout'].close()
- except IOError:
- pass
-
- stat = proc.handles['status']
- resp = self._read_response(stat)
- try:
- proc.handles['status'].close()
- except IOError:
- pass
-
- error = proc.handles['stderr'].read()
- proc.handles['stderr'].close()
-
- try: proc.wait()
- except IOError: pass
- if 'INV_RECP' in resp and resp['INV_RECP'].split()[0] == '10':
- # unusable recipient "Key not trusted"
- return '', 'NOT_TRUSTED'
- if 'BEGIN_ENCRYPTION' in resp and 'END_ENCRYPTION' in resp:
- # Encryption succeeded, even if there is output on stderr.
Maybe
- # verbose is on
- error = ''
- return self._stripHeaderFooter(output),
helpers.decode_string(error)
+ return self._stripHeaderFooter(str(result)), error
def decrypt(self, str_, keyID):
- proc = self.run(['--decrypt', '-q', '-u %s'%keyID],
create_fhs=['stdin', 'stdout'])
- enc = self._addHeaderFooter(str_, 'MESSAGE')
- proc.handles['stdin'].write(enc)
- proc.handles['stdin'].close()
+ data = self._addHeaderFooter(str_, 'MESSAGE')
+ result = super(GnuPG, self).decrypt(data,
+ passphrase=self.passphrase)
- output = proc.handles['stdout'].read()
- proc.handles['stdout'].close()
-
- try: proc.wait()
- except IOError: pass
- return output
+ return str(result)
def sign(self, str_, keyID):
- proc = self.run(['-b', '-u %s'%keyID], create_fhs=['stdin',
'stdout', 'status', 'stderr'])
- proc.handles['stdin'].write(str_)
- try:
- proc.handles['stdin'].close()
- except IOError:
- pass
+ result = super(GnuPG, self).sign(str_, keyid=keyID, detach=True,
+ passphrase=self.passphrase)
- output = proc.handles['stdout'].read()
- try:
- proc.handles['stdout'].close()
- proc.handles['stderr'].close()
- except IOError:
- pass
-
- stat = proc.handles['status']
- resp = self._read_response(stat)
- try:
- proc.handles['status'].close()
- except IOError:
- pass
-
- try: proc.wait()
- except IOError: pass
- if 'GOOD_PASSPHRASE' in resp or 'SIG_CREATED' in resp:
- return self._stripHeaderFooter(output)
- if 'KEYEXPIRED' in resp:
- return 'KEYEXPIRED'
+ if result.fingerprint:
+ return self._stripHeaderFooter(str(result))
+# if 'KEYEXPIRED' in resp:
+# return 'KEYEXPIRED'
return 'BAD_PASSPHRASE'
def verify(self, str_, sign):
if str_ is None:
return ''
- f = tmpfile()
- fd = f.fileno()
- f.write(str_)
- f.seek(0)
+ data = '-----BEGIN PGP SIGNED MESSAGE-----' + os.linesep
+ data = data + 'Hash: SHA1' + os.linesep + os.linesep
+ data = data + str_ + os.linesep
+ data = data + self._addHeaderFooter(sign, 'SIGNATURE')
+ result = super(GnuPG, self).verify(data)
- proc = self.run(['--verify', '--enable-special-filenames', '-',
'-&%s'%fd], create_fhs=['stdin', 'status', 'stderr'])
+ if result.valid:
+ return result.key_id
+ return ''
- f.close()
- sign = self._addHeaderFooter(sign, 'SIGNATURE')
- proc.handles['stdin'].write(sign)
- proc.handles['stdin'].close()
- proc.handles['stderr'].close()
-
- stat = proc.handles['status']
- resp = self._read_response(stat)
- proc.handles['status'].close()
-
- try: proc.wait()
- except IOError: pass
-
- keyid = ''
- if 'GOODSIG' in resp:
- keyid = resp['GOODSIG'].split()[0]
- return keyid
-
- def get_keys(self, secret = False):
- if secret:
- opt = '--list-secret-keys'
- else:
- opt = '--list-keys'
- proc = self.run(['--with-colons', opt],
- create_fhs=['stdout'])
- output = proc.handles['stdout'].read()
- proc.handles['stdout'].close()
-
- try: proc.wait()
- except IOError: pass
-
+ def get_keys(self, secret=False):
keys = {}
- lines = output.split('\n')
- for line in lines:
- sline = line.split(':')
- if (sline[0] == 'sec' and secret) or \
- (sline[0] == 'pub' and not secret):
- # decode escaped chars
- name = eval('"' + sline[9].replace('"', '\\"') + '"')
- # make it unicode instance
- keys[sline[4][8:]] = helpers.decode_string(name)
+ 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):
@@ -216,7 +106,7 @@
Remove header and footer from data
"""
if not data: return ''
- lines = data.split('\n')
+ lines = data.splitlines()
while lines[0] != '':
lines.remove(lines[0])
while lines[0] == '':
@@ -233,9 +123,9 @@
"""
Add header and footer from data
"""
- out = "-----BEGIN PGP %s-----\n" % type_
- out = out + "Version: PGP\n"
- out = out + "\n"
- out = out + data + "\n"
- out = out + "-----END PGP %s-----\n" % type_
+ 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
diff -r c3f1f5f7d238 -r b14e72db6e7a src/common/GnuPGInterface.py
--- a/src/common/GnuPGInterface.py Mon Nov 29 18:44:16 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,673 +0,0 @@
-# -*- coding:utf-8 -*-
-## src/common/GnuPGInterface.py
-##
-## Copyright (C) 2001 Frank J. Tobin <ftobin AT neverending.org>
-## Copyright (C) 2005 Nikos Kouremenos <kourem AT gmail.com>
-## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
-## Copyright (C) 2008 Jean-Marie Traissard <jim AT lapin.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/>.
-##
-
-"""
-Interface to GNU Privacy Guard (GnuPG)
-
-GnuPGInterface is a Python module to interface with GnuPG.
-It concentrates on interacting with GnuPG via filehandles,
-providing access to control GnuPG via versatile and extensible means.
-
-This module is based on GnuPG::Interface, a Perl module by the same author.
-
-Normally, using this module will involve creating a
-GnuPG object, setting some options in it's 'options' data member
-(which is of type Options), creating some pipes
_______________________________________________
Commits mailing list
[email protected]
http://lists.gajim.org/cgi-bin/listinfo/commits