sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit 52d3e7fe4e169241cc6fe92d587da09cf1ff6d49
parent 99caeccbbcddaf33b405338bae624ba0f7bb733c
Author: Hamish Downer <dmishd@gmail.com>
Date:   Thu, 10 Feb 2011 00:27:01 +0000

Better gpg error checking.

The crypto initialize code now checks for a number of common reasons
for GPG not working, all related to the gpg-agent side of things. It
will then give a reasonably friendly error message, helping diagnose
why GPG is not working for you.

In particular it will check whether the environment variable is set,
whether the environment variable points to a file, and whether that
file is a socket.

Diffstat:
M lib/sup/crypto.rb | 56 +++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 43 insertions(+), 13 deletions(-)
diff --git a/lib/sup/crypto.rb b/lib/sup/crypto.rb
@@ -42,19 +42,53 @@ EOS
   def initialize
     @mutex = Mutex.new
 
+    @not_working_reason = nil
+
     # test if the gpgme gem is available
-    @gpgme_present = true
-    begin
-    GPGME.check_version({:protocol => GPGME::PROTOCOL_OpenPGP})
-    rescue NameError, GPGME::Error
-      @gpgme_present = false
+    @gpgme_present =
+      begin
+        begin
+          GPGME.check_version({:protocol => GPGME::PROTOCOL_OpenPGP})
+          true
+        rescue GPGME::Error
+          false
+        end
+      rescue NameError
+        false
+      end
+
+    unless @gpgme_present
+      @not_working_reason = 'gpgme gem not present' 
+      return
+    end
+
+    # check gpg agent stuff
+    if ENV['GPG_AGENT_INFO'].nil?
+      @not_working_reason = "Environment variable 'GPG_AGENT_INFO' not set"
+      return
+    end
+
+    gpg_agent_socket_file = ENV['GPG_AGENT_INFO'].split(':')[0]
+    unless file.exist?(gpg_agent_socket_file)
+      @not_working_reason = "gpg-agent socket file #{gpg_agent_socket_file} does not exist"
+      return
+    end
+
+    s = File.stat(gpg_agent_socket_file)
+    unless s.socket?
+      @not_working_reason = "gpg-agent socket file #{gpg_agent_socket_file} is not a socket"
+      return
+    end
+
+    if (bin = `which gpg2`.chomp) =~ /\S/
+      GPGME.set_engine_info GPGME::PROTOCOL_OpenPGP, bin, nil
     end
   end
 
   def have_crypto?; @gpgme_present end
 
   def sign from, to, payload
-    return unknown_status(cant_find_gpgme) unless @gpgme_present
+    return unknown_status([@not_working_reason]) unless @not_working_reason.nil?
 
     gpg_opts = {:protocol => GPGME::PROTOCOL_OpenPGP, :armor => true, :textmode => true}
     gpg_opts.merge!(gen_sign_user_opts(from))
@@ -85,7 +119,7 @@ EOS
   end
 
   def encrypt from, to, payload, sign=false
-    return unknown_status(cant_find_gpgme) unless @gpgme_present
+    return unknown_status([@not_working_reason]) unless @not_working_reason.nil?
 
     gpg_opts = {:protocol => GPGME::PROTOCOL_OpenPGP, :armor => true, :textmode => true}
     if sign
@@ -173,7 +207,7 @@ EOS
   end
 
   def verify payload, signature, detached=true # both RubyMail::Message objects
-    return unknown_status(cant_find_gpgme) unless @gpgme_present
+    return unknown_status([@not_working_reason]) unless @not_working_reason.nil?
 
     gpg_opts = {:protocol => GPGME::PROTOCOL_OpenPGP}
     gpg_opts = HookManager.run("gpg-options", 
@@ -197,7 +231,7 @@ EOS
 
   ## returns decrypted_message, status, desc, lines
   def decrypt payload, armor=false # a RubyMail::Message object
-    return unknown_status(cant_find_gpgme) unless @gpgme_present
+    return unknown_status([@not_working_reason]) unless @not_working_reason.nil?
 
     gpg_opts = {:protocol => GPGME::PROTOCOL_OpenPGP}
     gpg_opts = HookManager.run("gpg-options", 
@@ -267,10 +301,6 @@ private
     Chunk::CryptoNotice.new :unknown, "Unable to determine validity of cryptographic signature", lines
   end
 
-  def cant_find_gpgme
-    ["Can't find gpgme gem."]
-  end
-
   ## here's where we munge rmail output into the format that signed/encrypted
   ## PGP/GPG messages should be
   def format_payload payload