sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit f31d1e5c31f69722fc530b1354952a1909ee778e
parent ef0408c88306fb75b7dc987d6ec6560f3573b380
Author: Clint Byrum <clint@ubuntu.com>
Date:   Thu, 17 Nov 2011 00:14:56 -0800

all tests pass on gpgme 1.0.7 and 2.0.0

Diffstat:
M lib/sup/crypto.rb | 43 +++++++++++++++++++++++++++++++++++--------
M test/test_crypto.rb | 34 +++++++++++++++++++++++++++-------
2 files changed, 62 insertions(+), 15 deletions(-)
diff --git a/lib/sup/crypto.rb b/lib/sup/crypto.rb
@@ -64,10 +64,17 @@ EOS
     @gpgme_present =
       begin
         begin
-          GPGME.check_version({:protocol => GPGME::PROTOCOL_OpenPGP})
+          begin
+            GPGME.check_version({:protocol => GPGME::PROTOCOL_OpenPGP})
+          rescue TypeError
+            GPGME.check_version(nil)
+          end
           true
         rescue GPGME::Error
           false
+        rescue ArgumentError
+          # gpgme 2.0.0 raises this due to the hash->string conversion
+          false
         end
       rescue NameError
         false
@@ -81,7 +88,11 @@ EOS
 
     # if gpg2 is available, it will start gpg-agent if required
     if (bin = `which gpg2`.chomp) =~ /\S/
-      GPGME.set_engine_info GPGME::PROTOCOL_OpenPGP, bin, nil
+      if GPGME.respond_to?('set_engine_info')
+        GPGME.set_engine_info GPGME::PROTOCOL_OpenPGP, bin, nil
+      else
+        GPGME.gpgme_set_engine_info GPGME::PROTOCOL_OpenPGP, bin, nil
+      end
     else
       # check if the gpg-options hook uses the passphrase_callback
       # if it doesn't then check if gpg agent is present
@@ -120,14 +131,20 @@ EOS
                                {:operation => "sign", :options => gpg_opts}) || gpg_opts
 
     begin
-      sig = GPGME.detach_sign(format_payload(payload), gpg_opts)
+      if GPGME.respond_to?('detach_sign')
+        sig = GPGME.detach_sign(format_payload(payload), gpg_opts)
+      else
+        crypto = GPGME::Crypto.new
+        gpg_opts[:mode] = GPGME::SIG_MODE_DETACH
+        crypto.sign(format_payload(payload), gpg_opts)
+      end
     rescue GPGME::Error => exc
       raise Error, gpgme_exc_msg(exc.message)
     end
 
     # if the key (or gpg-agent) is not available GPGME does not complain
     # but just returns a zero length string. Let's catch that
-    if sig.length == 0
+    if sig.respond_to?('length') && sig.length == 0
       raise Error, gpgme_exc_msg("GPG failed to generate signature: check that gpg-agent is running and your key is available.")
     end
 
@@ -153,14 +170,20 @@ EOS
     recipients = to + [from]
     recipients = HookManager.run("gpg-expand-keys", { :recipients => recipients }) || recipients
     begin
-      cipher = GPGME.encrypt(recipients, format_payload(payload), gpg_opts)
+      if GPGME.respond_to?('encrypt')
+        cipher = GPGME.encrypt(recipients, format_payload(payload), gpg_opts)
+      else
+        crypto = GPGME::Crypto.new
+        gpg_opts[:recipients] = recipients
+        cipher = crypto.encrypt(format_payload(payload), gpg_opts).read
+      end
     rescue GPGME::Error => exc
       raise Error, gpgme_exc_msg(exc.message)
     end
 
     # if the key (or gpg-agent) is not available GPGME does not complain
     # but just returns a zero length string. Let's catch that
-    if cipher.length == 0
+    if cipher.respond_to?('length') && !cipher.length == 0
       raise Error, gpgme_exc_msg("GPG failed to generate cipher text: check that gpg-agent is running and your key is available.")
     end
 
@@ -262,7 +285,11 @@ EOS
                                {:operation => "decrypt", :options => gpg_opts}) || gpg_opts
     ctx = GPGME::Ctx.new(gpg_opts)
     cipher_data = GPGME::Data.from_str(format_payload(payload))
-    plain_data = GPGME::Data.empty
+    if GPGME::Data.respond_to?('empty')
+      plain_data = GPGME::Data.empty
+    else
+      plain_data = GPGME::Data.empty!
+    end
     begin
       ctx.decrypt_verify(cipher_data, plain_data)
     rescue GPGME::Error => exc
@@ -330,7 +357,7 @@ private
 
   def gpgme_exc_msg msg
     err_msg = "Exception in GPGME call: #{msg}"
-    info err_msg
+    #info err_msg
     err_msg
   end
 
diff --git a/test/test_crypto.rb b/test/test_crypto.rb
@@ -22,11 +22,13 @@
 require 'tmpdir'
 require 'test/unit'
 require 'rmail/message'
+require 'rmail/parser'
 require 'sup/util'
 require 'sup/hook'
 require 'sup/contact'
 require 'sup/person'
 require 'sup/account'
+require 'sup/message-chunks'
 require 'sup/crypto'
 require 'stringio'
 
@@ -37,13 +39,15 @@ CryptoManager.init
 Dir.mktmpdir('sup-test') do|f|
     HookManager.init f
 end
-am = {:default=> {:name => "bob", :email=>"bob@foo.nowhere"}}
+am = {:default=> {:name => "", :email=>ENV['EMAIL']}}
 AccountManager.init am
-print CryptoManager.have_crypto?
 
 class TestCryptoManager < Test::Unit::TestCase
 
     def setup
+        @from_email = ENV['EMAIL']
+        # Change this or import my public key to make these tests work.
+        @to_email = 'clint@ubuntu.com'
     end
 
     def teardown
@@ -51,22 +55,38 @@ class TestCryptoManager < Test::Unit::TestCase
 
     def test_sign
         if CryptoManager.have_crypto? then
-            signed = CryptoManager.sign "bob@foo.nowhere","alice@bar.anywhere","ABCDEFG"
+            signed = CryptoManager.sign @from_email,@to_email,"ABCDEFG"
             assert_instance_of RMail::Message, signed
         end
     end
 
-
     def test_encrypt
         if CryptoManager.have_crypto? then
-            from_email = Person.from_address("bob@foo.nowhere").email
-            to_email = Person.from_address("alice@bar.anywhere").email
+            encrypted = CryptoManager.encrypt @from_email, [@to_email], "ABCDEFG"
+            assert_instance_of RMail::Message, encrypted
+        end
+    end
 
-            encrypted = CryptoManager.encrypt from_email, [to_email], "ABCDEFG"
+    def test_sign_and_encrypt
+        if CryptoManager.have_crypto? then
+            encrypted = CryptoManager.sign_and_encrypt @from_email, [@to_email], "ABCDEFG"
             assert_instance_of RMail::Message, encrypted
         end
     end
 
+    def test_decrypt
+        if CryptoManager.have_crypto? then
+            encrypted = CryptoManager.encrypt @from_email, [@to_email], "ABCDEFG"
+            assert_instance_of RMail::Message, encrypted
+            assert_instance_of String, (encrypted.body[1].body)
+            decrypted = CryptoManager.decrypt encrypted.body[1], true
+            assert_instance_of Array, decrypted
+            assert_instance_of Chunk::CryptoNotice, decrypted[0]
+            assert_instance_of Chunk::CryptoNotice, decrypted[1]
+            assert_instance_of RMail::Message, decrypted[2]
+            assert_equal "ABCDEFG" , decrypted[2].body
+        end
+    end
         
 end