summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <baker.dylan.c@gmail.com>2017-07-26 10:01:51 -0700
committerGitHub <noreply@github.com>2017-07-26 10:01:51 -0700
commit054eab33e52bd9687a4b567e9ea369d447cc33ee (patch)
tree356c9ccf1a59f241b71402e5e2174d56f52a5b22
parent32f2de6877a8ff92cef9a8cef6a1f54be2e4935e (diff)
parentf49cb3ce51f165529b66ba5809b1dda13919126e (diff)
Merge pull request #1083 from dcbaker/submit/add_signature-unicode
db/utils: Support unicode in signatures
-rw-r--r--alot/db/utils.py38
-rw-r--r--tests/crypto_test.py80
-rw-r--r--tests/db/utils_test.py59
-rw-r--r--tests/utilities.py28
4 files changed, 136 insertions, 69 deletions
diff --git a/alot/db/utils.py b/alot/db/utils.py
index ac91098a..3cad7dd2 100644
--- a/alot/db/utils.py
+++ b/alot/db/utils.py
@@ -39,39 +39,39 @@ def add_signature_headers(mail, sigs, error_msg):
:param error_msg: `str` containing an error message, the empty
string indicating no error
'''
- sig_from = ''
+ sig_from = u''
- if len(sigs) == 0:
- error_msg = error_msg or 'no signature found'
- else:
+ if isinstance(error_msg, str):
+ error_msg = error_msg.decode('utf-8')
+
+ if not sigs:
+ error_msg = error_msg or u'no signature found'
+ elif not error_msg:
try:
key = crypto.get_key(sigs[0].fpr)
for uid in key.uids:
if crypto.check_uid_validity(key, uid.email):
- sig_from = uid.uid
+ sig_from = uid.uid.decode('utf-8')
uid_trusted = True
break
else:
# No trusted uid found, we did not break but drop from the
# for loop.
uid_trusted = False
- sig_from = key.uids[0].uid
+ sig_from = key.uids[0].uid.decode('utf-8')
except:
- sig_from = sigs[0].fpr
+ sig_from = sigs[0].fpr.decode('utf-8')
uid_trusted = False
- mail.add_header(
- X_SIGNATURE_VALID_HEADER,
- 'False' if error_msg else 'True',
- )
- mail.add_header(
- X_SIGNATURE_MESSAGE_HEADER,
- u'Invalid: {0}'.format(error_msg)
- if error_msg else
- u'Valid: {0}'.format(sig_from)
- if uid_trusted else
- u'Untrusted: {0}'.format(sig_from)
- )
+ if error_msg:
+ msg = u'Invalid: {}'.format(error_msg)
+ elif uid_trusted:
+ msg = u'Valid: {}'.format(sig_from)
+ else:
+ msg = u'Untrusted: {}'.format(sig_from)
+
+ mail.add_header(X_SIGNATURE_VALID_HEADER, 'False' if error_msg else 'True')
+ mail.add_header(X_SIGNATURE_MESSAGE_HEADER, msg)
def get_params(mail, failobj=None, header='content-type', unquote=True):
diff --git a/tests/crypto_test.py b/tests/crypto_test.py
index 506d5868..e0e52cee 100644
--- a/tests/crypto_test.py
+++ b/tests/crypto_test.py
@@ -66,29 +66,6 @@ def tearDownModule():
os.kill(int(pid), signal.SIGKILL)
-def make_key(revoked=False, expired=False, invalid=False, can_encrypt=True,
- can_sign=True):
- mock_key = mock.create_autospec(gpgme.Key)
- mock_key.uids = [mock.Mock(uid=u'mocked')]
- mock_key.revoked = revoked
- mock_key.expired = expired
- mock_key.invalid = invalid
- mock_key.can_encrypt = can_encrypt
- mock_key.can_sign = can_sign
-
- return mock_key
-
-
-def make_uid(email, revoked=False, invalid=False, validity=gpgme.VALIDITY_FULL):
- uid = mock.Mock()
- uid.email = email
- uid.revoked = revoked
- uid.invalid = invalid
- uid.validity = validity
-
- return uid
-
-
class TestHashAlgorithmHelper(unittest.TestCase):
"""Test cases for the helper function RFC3156_canonicalize."""
@@ -154,49 +131,49 @@ class TestValidateKey(unittest.TestCase):
def test_valid(self):
try:
- crypto.validate_key(make_key())
+ crypto.validate_key(utilities.make_key())
except GPGProblem as e:
raise AssertionError(e)
def test_revoked(self):
with self.assertRaises(GPGProblem) as caught:
- crypto.validate_key(make_key(revoked=True))
+ crypto.validate_key(utilities.make_key(revoked=True))
self.assertEqual(caught.exception.code, GPGCode.KEY_REVOKED)
def test_expired(self):
with self.assertRaises(GPGProblem) as caught:
- crypto.validate_key(make_key(expired=True))
+ crypto.validate_key(utilities.make_key(expired=True))
self.assertEqual(caught.exception.code, GPGCode.KEY_EXPIRED)
def test_invalid(self):
with self.assertRaises(GPGProblem) as caught:
- crypto.validate_key(make_key(invalid=True))
+ crypto.validate_key(utilities.make_key(invalid=True))
self.assertEqual(caught.exception.code, GPGCode.KEY_INVALID)
def test_encrypt(self):
with self.assertRaises(GPGProblem) as caught:
- crypto.validate_key(make_key(can_encrypt=False), encrypt=True)
+ crypto.validate_key(utilities.make_key(can_encrypt=False), encrypt=True)
self.assertEqual(caught.exception.code, GPGCode.KEY_CANNOT_ENCRYPT)
def test_encrypt_no_check(self):
try:
- crypto.validate_key(make_key(can_encrypt=False))
+ crypto.validate_key(utilities.make_key(can_encrypt=False))
except GPGProblem as e:
raise AssertionError(e)
def test_sign(self):
with self.assertRaises(GPGProblem) as caught:
- crypto.validate_key(make_key(can_sign=False), sign=True)
+ crypto.validate_key(utilities.make_key(can_sign=False), sign=True)
self.assertEqual(caught.exception.code, GPGCode.KEY_CANNOT_SIGN)
def test_sign_no_check(self):
try:
- crypto.validate_key(make_key(can_sign=False))
+ crypto.validate_key(utilities.make_key(can_sign=False))
except GPGProblem as e:
raise AssertionError(e)
@@ -204,43 +181,44 @@ class TestValidateKey(unittest.TestCase):
class TestCheckUIDValidity(unittest.TestCase):
def test_valid_single(self):
- key = make_key()
- key.uids[0] = make_uid(mock.sentinel.EMAIL)
+ key = utilities.make_key()
+ key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL)
ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL)
self.assertTrue(ret)
def test_valid_multiple(self):
- key = make_key()
+ key = utilities.make_key()
key.uids = [
- make_uid(mock.sentinel.EMAIL),
- make_uid(mock.sentinel.EMAIL1),
+ utilities.make_uid(mock.sentinel.EMAIL),
+ utilities.make_uid(mock.sentinel.EMAIL1),
]
ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL1)
self.assertTrue(ret)
def test_invalid_email(self):
- key = make_key()
- key.uids[0] = make_uid(mock.sentinel.EMAIL)
+ key = utilities.make_key()
+ key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL)
ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL1)
self.assertFalse(ret)
def test_invalid_revoked(self):
- key = make_key()
- key.uids[0] = make_uid(mock.sentinel.EMAIL, revoked=True)
+ key = utilities.make_key()
+ key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL, revoked=True)
ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL)
self.assertFalse(ret)
def test_invalid_invalid(self):
- key = make_key()
- key.uids[0] = make_uid(mock.sentinel.EMAIL, invalid=True)
+ key = utilities.make_key()
+ key.uids[0] = utilities.make_uid(mock.sentinel.EMAIL, invalid=True)
ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL)
self.assertFalse(ret)
def test_invalid_not_enough_trust(self):
- key = make_key()
- key.uids[0] = make_uid(mock.sentinel.EMAIL,
- validity=gpgme.VALIDITY_UNDEFINED)
+ key = utilities.make_key()
+ key.uids[0] = utilities.make_uid(
+ mock.sentinel.EMAIL,
+ validity=gpgme.VALIDITY_UNDEFINED)
ret = crypto.check_uid_validity(key, mock.sentinel.EMAIL)
self.assertFalse(ret)
@@ -304,8 +282,8 @@ class TestGetKey(unittest.TestCase):
return context_mock
def test_ambiguous_one_valid(self):
- invalid_key = make_key(invalid=True)
- valid_key = make_key()
+ invalid_key = utilities.make_key(invalid=True)
+ valid_key = utilities.make_key()
with mock.patch('alot.crypto.gpgme.Context',
mock.Mock(return_value=self._context_mock())), \
@@ -318,7 +296,8 @@ class TestGetKey(unittest.TestCase):
with mock.patch('alot.crypto.gpgme.Context',
mock.Mock(return_value=self._context_mock())), \
mock.patch('alot.crypto.list_keys',
- mock.Mock(return_value=[make_key(), make_key()])):
+ mock.Mock(return_value=[utilities.make_key(),
+ utilities.make_key()])):
with self.assertRaises(crypto.GPGProblem) as cm:
crypto.get_key('placeholder')
self.assertEqual(cm.exception.code, GPGCode.AMBIGUOUS_NAME)
@@ -327,8 +306,9 @@ class TestGetKey(unittest.TestCase):
with mock.patch('alot.crypto.gpgme.Context',
mock.Mock(return_value=self._context_mock())), \
mock.patch('alot.crypto.list_keys',
- mock.Mock(return_value=[make_key(invalid=True),
- make_key(invalid=True)])):
+ mock.Mock(return_value=[
+ utilities.make_key(invalid=True),
+ utilities.make_key(invalid=True)])):
with self.assertRaises(crypto.GPGProblem) as cm:
crypto.get_key('placeholder')
self.assertEqual(cm.exception.code, GPGCode.NOT_FOUND)
diff --git a/tests/db/utils_test.py b/tests/db/utils_test.py
index d07dd56a..48daef30 100644
--- a/tests/db/utils_test.py
+++ b/tests/db/utils_test.py
@@ -11,7 +11,10 @@ import os
import os.path
import unittest
+import mock
+
from alot.db import utils
+from ..utilities import make_key, make_uid
class TestGetParams(unittest.TestCase):
@@ -321,3 +324,59 @@ class TestDecodeHeader(unittest.TestCase):
expected = u'first\nsecond third fourth fifth'
actual = utils.decode_header(text, normalize=True)
self.assertEqual(actual, expected)
+
+
+class TestAddSignatureHeaders(unittest.TestCase):
+
+ class FakeMail(object):
+ def __init__(self):
+ self.headers = []
+
+ def add_header(self, header, value):
+ self.headers.append((header, value))
+
+ def check(self, key, valid):
+ mail = self.FakeMail()
+
+ with mock.patch('alot.db.utils.crypto.get_key',
+ mock.Mock(return_value=key)), \
+ mock.patch('alot.db.utils.crypto.check_uid_validity',
+ mock.Mock(return_value=valid)):
+ utils.add_signature_headers(mail, [mock.Mock(fpr='')], u'')
+
+ return mail
+
+ def test_length_0(self):
+ mail = self.FakeMail()
+ utils.add_signature_headers(mail, [], u'')
+ self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'False'), mail.headers)
+ self.assertIn(
+ (utils.X_SIGNATURE_MESSAGE_HEADER, u'Invalid: no signature found'),
+ mail.headers)
+
+ def test_valid(self):
+ key = make_key()
+ mail = self.check(key, True)
+
+ self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers)
+ self.assertIn(
+ (utils.X_SIGNATURE_MESSAGE_HEADER, u'Valid: mocked'), mail.headers)
+
+ def test_untrusted(self):
+ key = make_key()
+ mail = self.check(key, False)
+
+ self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers)
+ self.assertIn(
+ (utils.X_SIGNATURE_MESSAGE_HEADER, u'Untrusted: mocked'), mail.headers)
+
+ def test_unicode_as_bytes(self):
+ mail = self.FakeMail()
+ key = make_key()
+ key.uids = [make_uid('andreá@example.com',
+ uid=u'Andreá'.encode('utf-8'))]
+ mail = self.check(key, True)
+
+ self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers)
+ self.assertIn(
+ (utils.X_SIGNATURE_MESSAGE_HEADER, u'Valid: Andreá'), mail.headers)
diff --git a/tests/utilities.py b/tests/utilities.py
index ed169b59..45433c99 100644
--- a/tests/utilities.py
+++ b/tests/utilities.py
@@ -21,6 +21,9 @@ from __future__ import absolute_import
import functools
import unittest
+import gpgme
+import mock
+
def _tear_down_class_wrapper(original, cls):
"""Ensure that doClassCleanups is called after tearDownClass."""
@@ -143,3 +146,28 @@ class ModuleCleanup(object):
raise
return wrapper
+
+
+def make_uid(email, uid=u'mocked', revoked=False, invalid=False,
+ validity=gpgme.VALIDITY_FULL):
+ uid_ = mock.Mock()
+ uid_.email = email
+ uid_.uid = uid
+ uid_.revoked = revoked
+ uid_.invalid = invalid
+ uid_.validity = validity
+
+ return uid_
+
+
+def make_key(revoked=False, expired=False, invalid=False, can_encrypt=True,
+ can_sign=True):
+ mock_key = mock.create_autospec(gpgme.Key)
+ mock_key.uids = [make_uid(u'foo@example.com')]
+ mock_key.revoked = revoked
+ mock_key.expired = expired
+ mock_key.invalid = invalid
+ mock_key.can_encrypt = can_encrypt
+ mock_key.can_sign = can_sign
+
+ return mock_key