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

Reply via email to