From 6c22a5b29578e99ec8079755a2c923e21c29c095 Mon Sep 17 00:00:00 2001 From: Manuel Neuhauser Date: Tue, 1 Oct 2024 08:39:21 -0400 Subject: [PATCH] Add option to delete secret key without confirmation dialog --- ext/gpgme/gpgme_n.c | 32 ++++++++++++++++++++++++++++++++ lib/gpgme/constants.rb | 8 ++++++++ lib/gpgme/ctx.rb | 13 +++++++++++-- lib/gpgme/key.rb | 7 ++++--- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/ext/gpgme/gpgme_n.c b/ext/gpgme/gpgme_n.c index b02aa26..18bcfc9 100644 --- a/ext/gpgme/gpgme_n.c +++ b/ext/gpgme/gpgme_n.c @@ -1484,6 +1484,27 @@ rb_s_gpgme_op_delete (VALUE dummy, VALUE vctx, VALUE vkey, VALUE vallow_secret) return LONG2NUM(err); } +/* This method was added in 1.9.1. */ +#if defined(GPGME_VERSION_NUMBER) && GPGME_VERSION_NUMBER >= 0x010901 +static VALUE +rb_s_gpgme_op_delete_ext (VALUE dummy, VALUE vctx, VALUE vkey, VALUE vflags) +{ + gpgme_ctx_t ctx; + gpgme_key_t key; + gpgme_error_t err; + + CHECK_KEYLIST_NOT_IN_PROGRESS(vctx); + + UNWRAP_GPGME_CTX(vctx, ctx); + if (!ctx) + rb_raise (rb_eArgError, "released ctx"); + UNWRAP_GPGME_KEY(vkey, key); + + err = gpgme_op_delete_ext (ctx, key, NUM2INT(vflags)); + return LONG2NUM(err); +} +#endif + static VALUE rb_s_gpgme_op_delete_start (VALUE dummy, VALUE vctx, VALUE vkey, VALUE vallow_secret) @@ -2547,6 +2568,8 @@ Init_gpgme_n (void) rb_s_gpgme_op_import_result, 1); rb_define_module_function (mGPGME, "gpgme_op_delete", rb_s_gpgme_op_delete, 3); + rb_define_module_function (mGPGME, "gpgme_op_delete_ext", + rb_s_gpgme_op_delete_ext, 3); rb_define_module_function (mGPGME, "gpgme_op_delete_start", rb_s_gpgme_op_delete_start, 3); rb_define_module_function (mGPGME, "gpgme_op_edit", @@ -3156,4 +3179,13 @@ Init_gpgme_n (void) rb_define_const (mGPGME, "GPGME_EXPORT_MODE_PKCS12", INT2FIX(GPGME_EXPORT_MODE_PKCS12)); #endif + +/* These flags were added in 1.9.1. */ +#if defined(GPGME_VERSION_NUMBER) && GPGME_VERSION_NUMBER >= 0x010901 + rb_define_const (mGPGME, "GPGME_DELETE_ALLOW_SECRET", + INT2FIX(GPGME_DELETE_ALLOW_SECRET)); + rb_define_const (mGPGME, "GPGME_DELETE_FORCE", + INT2FIX(GPGME_DELETE_FORCE)); +#endif } + diff --git a/lib/gpgme/constants.rb b/lib/gpgme/constants.rb index 359dbef..565f5d6 100644 --- a/lib/gpgme/constants.rb +++ b/lib/gpgme/constants.rb @@ -265,4 +265,12 @@ module GPGME VALIDITY_FULL => :full, VALIDITY_ULTIMATE => :ultimate } + + if defined?(GPGME_DELETE_ALLOW_SECRET) + DELETE_ALLOW_SECRET = GPGME_DELETE_ALLOW_SECRET + end + + if defined?(GPGME_DELETE_FORCE) + DELETE_FORCE = GPGME_DELETE_FORCE + end end diff --git a/lib/gpgme/ctx.rb b/lib/gpgme/ctx.rb index a1e0600..81d8777 100644 --- a/lib/gpgme/ctx.rb +++ b/lib/gpgme/ctx.rb @@ -447,8 +447,17 @@ def import_result # Delete the key from the key ring. # If allow_secret is false, only public keys are deleted, # otherwise secret keys are deleted as well. - def delete_key(key, allow_secret = false) - err = GPGME::gpgme_op_delete(self, key, allow_secret ? 1 : 0) + # If force is true, the confirmation dialog will not be displayed. + def delete_key(key, allow_secret = false, force = false) + err = nil + if defined?(GPGME::gpgme_op_delete_ext) + flag = 0 + flag ^= GPGME::DELETE_ALLOW_SECRET if allow_secret + flag ^= GPGME::DELETE_FORCE if force + err = GPGME::gpgme_op_delete_ext(self, key, flag) + else + err = GPGME::gpgme_op_delete(self, key, allow_secret ? 1 : 0) + end exc = GPGME::error_to_exception(err) raise exc if exc end diff --git a/lib/gpgme/key.rb b/lib/gpgme/key.rb index f4efd75..c91a8e8 100644 --- a/lib/gpgme/key.rb +++ b/lib/gpgme/key.rb @@ -156,10 +156,11 @@ def export(options = {}) ## # Delete this key. If it's public, and has a secret one it will fail unless - # +allow_secret+ is specified as true. - def delete!(allow_secret = false) + # +allow_secret+ is specified as true. Suppress the confirmation dialog, if + # +force+ is specified as true. + def delete!(allow_secret = false, force = false) GPGME::Ctx.new do |ctx| - ctx.delete_key self, allow_secret + ctx.delete_key self, allow_secret, force end end