From 5207ccc6b42d6245c1626d45670a075b8bc84569 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 2 Aug 2014 01:54:30 +0000 Subject: [PATCH 1/5] Update copyright years on Sphinx docs. --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 4986e0b..0bb50b3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -54,7 +54,7 @@ master_doc = 'index' # General information about the project. project = u'gnupg' -copyright = u'2013, Isis Agora Lovecruft' +copyright = u'2013-2014, Isis Agora Lovecruft' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the From 137d3ac5c5fdaa61baa1442137009750b5208a35 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 2 Aug 2014 01:56:20 +0000 Subject: [PATCH 2/5] Fix encrypting to filenames and/or file-like objects. * FIXES Issue#24, which prevented python-gnupg from encrypting to a filename given as a string to the `output` parameter of `gnupg.GPGMeta._encrypt()`. * THANKS TO by Bill Buddington of SecureDrop and Yan Zhu of the Electronic Frontier Foundation (EFF) for finding and reporting the bug. The ticket for this bug can be viewed at: https://github.com/isislovecruft/python-gnupg/issues/24 --- gnupg/_meta.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/gnupg/_meta.py b/gnupg/_meta.py index 00c3a68..3aafacd 100644 --- a/gnupg/_meta.py +++ b/gnupg/_meta.py @@ -766,10 +766,10 @@ class GPGBase(object): **recipients** keys. If False, display trust warnings. (default: True) - :param str output: The output file to write to. If not specified, the - encrypted output is returned, and thus should be - stored as an object in Python. For example: - + :type output: str or file-like object + :param output: The output file to write to. If not specified, the + encrypted output is returned, and thus should be stored + as an object in Python. For example: >>> import shutil >>> import gnupg @@ -808,17 +808,23 @@ class GPGBase(object): """ args = [] + ## FIXME: GnuPG appears to ignore the --output directive when being + ## programmatically driven. We'll handle the IO ourselves to fix this + ## for now. + output_filename = None if output: if getattr(output, 'fileno', None) is not None: ## avoid overwrite confirmation message - if getattr(output, 'name', None) is None: - if os.path.exists(output): - os.remove(output) - args.append('--output %s' % output) - else: + if getattr(output, 'name', None) is not None: + output_filename = output.name if os.path.exists(output.name): os.remove(output.name) - args.append('--output %s' % output.name) + #args.append('--output %s' % output.name) + else: + output_filename = output + if os.path.exists(output): + os.remove(output) + #args.append('--output %s' % output) if armor: args.append('--armor') if always_trust: args.append('--always-trust') @@ -877,4 +883,12 @@ class GPGBase(object): self._handle_io(args, data, result, passphrase=passphrase, binary=True) log.debug("\n%s" % result.data) + + if output_filename: + log.info("Writing encrypted output to file: %s" % output_filename) + with open(output_filename, 'w+') as fh: + fh.write(result.data) + fh.flush() + log.info("Encrypted output written successfully.") + return result From 83784657d571a1db855640fabd06bde07ffc55c1 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 2 Aug 2014 04:02:15 +0000 Subject: [PATCH 3/5] Add new unittest that tests encryption with a filename output. * ADD test_encryption_to_filename which checks that encrypt(..., output='somefilename.gpg') works correctly (when `output` is a string containing the filename). This tests for the bug reported in Issue #24. https://github.com/isislovecruft/python-gnupg/issues/24 --- gnupg/test/test_gnupg.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gnupg/test/test_gnupg.py b/gnupg/test/test_gnupg.py index 9541896..5154cf0 100755 --- a/gnupg/test/test_gnupg.py +++ b/gnupg/test/test_gnupg.py @@ -990,6 +990,27 @@ know, maybe you shouldn't be doing it in the first place. log.debug("new (from decryption): %r" % ddata) self.assertEqual(data, ddata) + def test_encryption_to_filename(self): + """Test that ``encrypt(..., output='somefile.gpg')`` is successful.""" + with open(os.path.join(_files, 'kat.sec')) as katsec: + self.gpg.import_keys(katsec.read()) + fpr = self.gpg.list_keys('kat')[0]['fingerprint'] + output = os.path.join(self.gpg.homedir, 'test-encryption-to-filename.gpg') + + message_filename = os.path.join(_files, 'cypherpunk_manifesto') + message_file = open(message_filename) + message = message_file.read() + message_file.close() + + encrypted = self.gpg.encrypt(message, fpr, output=output) + self.assertTrue(encrypted.ok) + self.assertTrue(os.path.isfile(output)) + + # Check the contents: + with open(output) as fh: + encrypted_message = fh.read() + log.debug("Encrypted file contains:\n\n%s\n" % encrypted_message) + suites = { 'parsers': set(['test_parsers_fix_unsafe', 'test_parsers_fix_unsafe_semicolon', @@ -1034,7 +1055,8 @@ suites = { 'parsers': set(['test_parsers_fix_unsafe', 'test_encryption_decryption_multi_recipient', 'test_decryption', 'test_symmetric_encryption_and_decryption', - 'test_file_encryption_and_decryption']), + 'test_file_encryption_and_decryption', + 'test_encryption_to_filename',]), 'listkeys': set(['test_list_keys_after_generation']), 'keyrings': set(['test_public_keyring', 'test_secret_keyring', From 4d120a22882738305015587379b49c2aff26b275 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 2 Aug 2014 04:14:22 +0000 Subject: [PATCH 4/5] Add unittest which tests encrypt() when `output` is given an open file. * ADD new unittest, `test_encryption_to_filehandle`. --- gnupg/test/test_gnupg.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/gnupg/test/test_gnupg.py b/gnupg/test/test_gnupg.py index 5154cf0..46876f5 100755 --- a/gnupg/test/test_gnupg.py +++ b/gnupg/test/test_gnupg.py @@ -1011,6 +1011,28 @@ know, maybe you shouldn't be doing it in the first place. encrypted_message = fh.read() log.debug("Encrypted file contains:\n\n%s\n" % encrypted_message) + def test_encryption_to_filehandle(self): + """Test that ``encrypt(..., output=filelikething)`` is successful.""" + with open(os.path.join(_files, 'kat.sec')) as katsec: + self.gpg.import_keys(katsec.read()) + fpr = self.gpg.list_keys('kat')[0]['fingerprint'] + output = os.path.join(self.gpg.homedir, 'test-encryption-to-filehandle.gpg') + output_file = open(output, 'w+') + + message_filename = os.path.join(_files, 'cypherpunk_manifesto') + message_file = open(message_filename) + message = message_file.read() + message_file.close() + + encrypted = self.gpg.encrypt(message, fpr, output=output_file) + self.assertTrue(encrypted.ok) + self.assertTrue(os.path.isfile(output)) + + # Check the contents: + with open(output) as fh: + encrypted_message = fh.read() + log.debug("Encrypted file contains:\n\n%s\n" % encrypted_message) + suites = { 'parsers': set(['test_parsers_fix_unsafe', 'test_parsers_fix_unsafe_semicolon', @@ -1056,7 +1078,8 @@ suites = { 'parsers': set(['test_parsers_fix_unsafe', 'test_decryption', 'test_symmetric_encryption_and_decryption', 'test_file_encryption_and_decryption', - 'test_encryption_to_filename',]), + 'test_encryption_to_filename', + 'test_encryption_to_filehandle',]), 'listkeys': set(['test_list_keys_after_generation']), 'keyrings': set(['test_public_keyring', 'test_secret_keyring', From 80741e8703a80f5741c1034cb17112418c101ade Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 2 Aug 2014 04:17:24 +0000 Subject: [PATCH 5/5] Remove `sudo` from `uninstall` directive in Makefile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9dfa649..3fac5ae 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ py3k-install: uninstall: touch installed-files.txt - cat installed-files.txt | sudo xargs rm -rf + cat installed-files.txt | xargs rm -rf py3k-uninstall: uninstall reinstall: uninstall install