]> Kevux Git Server - kevux-tools/commitdiff
Progress: Continue adding GPGME support.
authorKevin Day <Kevin@kevux.org>
Thu, 15 Jan 2026 02:21:56 +0000 (20:21 -0600)
committerKevin Day <Kevin@kevux.org>
Thu, 15 Jan 2026 02:21:56 +0000 (20:21 -0600)
I'm getting closer to determining how to use GPGME to get what I want.
This restructures the GPGME files.

I am isolating this commit so that I can start focusing on adding negotiation support so that a key can be created and sent by both ends.
I need to wrap up a lot of the TODOs.
I also might need to restructure some of the logic to better handle the negotiation or hand shaking where the Public keys are generated and exchanged.

Hopefully GPGME does not saves these in the system users GNUPG directory.

20 files changed:
data/build/tacocat/settings
sources/c/program/kevux/tools/tacocat/main/common/type.h
sources/c/program/kevux/tools/tacocat/main/gpgme.c
sources/c/program/kevux/tools/tacocat/main/print/gpgme.c
sources/c/program/kevux/tools/tacocat/main/print/gpgme.h
sources/c/program/kevux/tools/tacocat/main/send.c
sources/c/program/kevux/tools/tacocat/main/send/step/done.c
sources/c/program/kevux/tools/tacocat/main/send/step/encrypt.c
sources/c/program/kevux/tools/tacocat/main/send/step/encrypt.h
sources/c/program/kevux/tools/tacocat/main/send/step/file.c
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/done.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/done.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/encrypt.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/encrypt.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/file.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/file.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/size.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/size.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/size.c
sources/c/program/kevux/tools/tacocat/main/tacocat.h

index 21628a7fa0ae8433fa7d9a282c7d5575c7b689b7..ce2886b39af7a5ed2dfa73d7c3de1c200c48be49 100644 (file)
@@ -64,6 +64,7 @@ build_sources_headers receive/step/check.h receive/step/control.h receive/step/d
 build_sources_headers send/step/build.h send/step/check.h send/step/done.h send/step/encode.h send/step/encrypt.h send/step/file.h send/step/header.h send/step/packet.h send/step/size.h send/step/wait.h
 
 build_sources_headers-gpgme gpgme.h print/gpgme.h
+build_sources_headers-gpgme send/step/gpgme/done.h send/step/gpgme/encrypt.h send/step/gpgme/file.h send/step/gpgme/size.h
 
 build_sources_library common.c common/define.c common/enumeration.c common/string.c common/type.c
 build_sources_library print/error.c print/message.c print/verbose.c print/warning.c
@@ -72,6 +73,7 @@ build_sources_library receive/step/check.c receive/step/control.c receive/step/d
 build_sources_library send/step/build.c send/step/check.c send/step/done.c send/step/encode.c send/step/encrypt.c send/step/file.c send/step/header.c send/step/packet.c send/step/size.c send/step/wait.c
 
 build_sources_library-gpgme gpgme.c print/gpgme.c
+build_sources_library-gpgme send/step/gpgme/done.c send/step/gpgme/encrypt.c send/step/gpgme/file.c send/step/gpgme/size.c
 
 build_sources_documentation man
 
index f48f2f76b9218ae166336df35968b5b85ae1b6d8..460db2a344fbc5a1327b0090be91785d2a2d90f8 100644 (file)
@@ -461,7 +461,6 @@ extern "C" {
  * Properties:
  *   - context: The GPGME context data.
  *   - engine:  The GPGME engine inforrmation data.
- *   - error:   The GPGME error data.
  *
  *   - version: The GPGME reported version.
  */
@@ -469,7 +468,6 @@ extern "C" {
   typedef struct {
     gpgme_ctx_t context;
     gpgme_engine_info_t engine;
-    gpgme_error_t error;
 
     f_string_constant_t version;
   } kt_tacocat_gpgme_t;
@@ -477,7 +475,6 @@ extern "C" {
   #define kt_tacocat_gpgme_t_initialize { \
     .context = 0, \
     .engine  = 0, \
-    .error   = 0, \
     .version = f_string_empty_s.string, \
   }
 #endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_t_)
index 457dc28c8210b63716edf82f067e3fe92d5b265e..662ebdf9fd942dea7caad690de2ee27e4a32b96c 100644 (file)
@@ -11,34 +11,28 @@ extern "C" {
 
     kt_tacocat_gpgme_t * const gpgme = &main->gpgme;
 
-    gpgme->version = gpgme_check_version(0);
-
-    gpgme->error = gpgme_engine_check_version(GPGME_PROTOCOL_OPENPGP);
+    gpgme_error_t error = 0;
 
-    if (gpgme->error != GPG_ERR_NO_ERROR) {
-      main->setting.state.status = F_status_set_error(F_failure);
+    gpgme->version = gpgme_check_version(0);
 
-      kt_tacocat_print_gpgme_error(&main->program.error, F_status_debug_source_d);
+    error = gpgme_engine_check_version(GPGME_PROTOCOL_OPENPGP);
 
-      return;
+    if (error == GPG_ERR_NO_ERROR) {
+      error = gpgme_get_engine_info(&gpgme->engine);
     }
 
-    gpgme->error = gpgme_get_engine_info(&gpgme->engine);
-
-    if (gpgme->error != GPG_ERR_NO_ERROR) {
-      main->setting.state.status = F_status_set_error(F_failure);
-
-      kt_tacocat_print_gpgme_error(&main->program.error, F_status_debug_source_d);
-
-      return;
+    if (error == GPG_ERR_NO_ERROR) {
+      error = gpgme_new(&gpgme->context);
     }
 
-    gpgme->error = gpgme_new(&gpgme->context);
+    if (error == GPG_ERR_NO_ERROR) {
+      error = gpgme_ctx_set_engine_info(gpgme->context, GPGME_PROTOCOL_OpenPGP, gpgme->engine->file_name, gpgme->engine->home_dir);
+    }
 
-    if (gpgme->error != GPG_ERR_NO_ERROR) {
+    if (error != GPG_ERR_NO_ERROR) {
       main->setting.state.status = F_status_set_error(F_failure);
 
-      kt_tacocat_print_gpgme_error(&main->program.error, F_status_debug_source_d);
+      kt_tacocat_print_gpgme_error(&main->program.error, F_status_debug_source_d, error);
 
       return;
     }
@@ -49,9 +43,6 @@ extern "C" {
     // Disable online access.
     gpgme_set_offline(gpgme->context, F_true);
 
-    // Is this necessary?
-    //err = gpgme_ctx_set_engine_info(ceofcontext, GPGME_PROTOCOL_OpenPGP, enginfo->file_name, enginfo->home_dir);
-
     main->setting.state.status = F_okay;
   }
 #endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_setup_)
index e95d4c7b81a670a45838c30f4c6ff77fb5d07a1c..f0551912d125d4af7edead24ee24e8b854eecd3d 100644 (file)
@@ -5,7 +5,7 @@ extern "C" {
 #endif
 
 #if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_print_gpgme_error_)
-  f_status_t kt_tacocat_print_gpgme_error(fl_print_t * const print, const f_string_t debug) {
+  f_status_t kt_tacocat_print_gpgme_error(fl_print_t * const print, const f_string_t debug, const gpgme_error_t error) {
 
     if (!print || !print->custom) return F_status_set_error(F_output_not);
     if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
@@ -15,9 +15,9 @@ extern "C" {
     f_file_stream_lock(print->to);
 
     fl_print_format("%[%QGPGME error:%] ", print->to, print->set->error, print->prefix, print->set->error);
-    fl_print_format(f_string_format_S_single_s.string, print->to, print->set->notable, gpgme_strerror(main->gpgme.error), print->set->notable);
+    fl_print_format(f_string_format_S_single_s.string, print->to, print->set->notable, gpgme_strerror(error), print->set->notable);
     fl_print_format(" %[(%]", print->to, print->set->error, print->set->error);
-    fl_print_format(f_string_format_S_single_s.string, print->to, print->set->notable, gpgme_strsource(main->gpgme.error), print->set->notable);
+    fl_print_format(f_string_format_S_single_s.string, print->to, print->set->notable, gpgme_strsource(error), print->set->notable);
     fl_print_format("%[)", print->to, print->set->error);
 
     if (debug && *debug) {
index f72cb19311dd61929bfaae6e92b7f5a5604a98ee..3485354a6d66c90e96ab4f35b03b81b55b598388 100644 (file)
@@ -31,6 +31,8 @@ extern "C" {
  *   (optional) The debug details, such as file, line number, and function.
  *
  *   Set to NULL to disable.
+ * @param error
+ *   The GPGME error code.
  *
  * @return
  *   F_okay on success.
@@ -41,7 +43,7 @@ extern "C" {
  * @see fll_error_print()
  */
 #if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_print_gpgme_error_)
-  extern f_status_t kt_tacocat_print_gpgme_error(fl_print_t * const print, const f_string_t debug);
+  extern f_status_t kt_tacocat_print_gpgme_error(fl_print_t * const print, const f_string_t debug, const gpgme_error_t error);
 #endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_print_gpgme_error_)
 
 #ifdef __cplusplus
index ca313fe29e9cc6358089cb37550b505b1b61002a..a45d9d81c5f0ca99023062472c9ab6bfbf80a8f7 100644 (file)
@@ -248,20 +248,17 @@ extern "C" {
 
             // Fallback to ASCII based on current index position.
             if (modded < 10) {
-              set->id.string[set->id.used++] = (modded) + 48;
+              set->id.string[set->id.used++] = modded + 48;
             }
             else if (modded < 36) {
-              set->id.string[set->id.used++] = (modded) + 55; // ASCII 65 - 10 = 55.
+              set->id.string[set->id.used++] = modded + 55; // ASCII 65 - 10 = 55.
             }
             else {
-              set->id.string[set->id.used++] = (modded) + 61; // ASCII 97 - 36 = 61.
+              set->id.string[set->id.used++] = modded + 61; // ASCII 97 - 36 = 61.
             }
           }
         } // for
       }
-      else {
-        // @todo manually generate something, probably use the file name and the port number.
-      }
     }
 
     if (F_status_is_error_not(set->status)) {
index b46e4a9ad5da1371eaaa51f11edb622d1eb48753..c12e9923bda2c399134cb5c8c28e051205a57d8c 100644 (file)
@@ -11,6 +11,12 @@ extern "C" {
 
     //@todo send done packet.
 
+    if (main->setting.flag & kt_tacocat_main_flag_encrypt_d) {
+      #ifdef _en_gpgme_support_
+        kt_tacocat_send_step_gpgme_done(main, set);
+      #endif // _en_gpgme_support_
+    }
+
     if (main->setting.flag & kt_tacocat_main_flag_headers_d) {
       kt_tacocat_print_message_headers(&main->program.message, *set, F_true);
     }
index 3a64f67ca9f6b0491ac6e200c5392a020f2b9d09..807dedfc824b22c30df3fab263ed852ed12f8c88 100644 (file)
 extern "C" {
 #endif
 
-#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_encrypt_size_)
-  void kt_tacocat_send_step_encrypt_size(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+#ifdef _di_kt_tacocat_send_step_encrypt_
+  void kt_tacocat_send_step_encrypt(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
 
     if (!main || !set || F_status_is_error(set->status)) return;
 
-    if (set->encrypt_read) {
-      gpgme_data_release(set->encrypt_read);
-
-      set->encrypt_read = 0;
-    }
-
-    gpgme_error_t error = gpgme_data_new_from_fd(&set->encrypt_read, set->file.id);
-
-    if (error != GPG_ERR_NO_ERROR) {
-      set->status = F_status_set_error(F_memory);
-
-      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
-
-      return;
-    }
-
-    error = gpgme_data_set_encoding(set->encrypt_read, GPGME_DATA_ENCODING_ARMOR);
-
-    if (error != GPG_ERR_NO_ERROR) {
-      set->status = F_status_set_error(F_failure);
-
-      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
-
-      return;
-    }
-
-    // Total is used here to explicitly pass a pointer of off_t rather than a pointer of size_t cast to an off_t.
-    // GPGME provides no way to get the file size of the encrypted data, so load the file and determine the file size as it is loading.
-    off_t total = 0;
-    gpgme_ssize_t bytes = 1;
-
-    for (char buffer[set->file.size_read + 1]; bytes > 0 && total <= F_number_t_size_unsigned_d; total += bytes) {
-      bytes = gpgme_data_read(set->encrypt_read, buffer, set->file.size_read);
-    } // for
-
-    if (bytes == -1) {
-      set->status = F_status_set_error(F_failure);
-
-      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
-
-      return;
-    }
-
-    if ((f_number_unsigned_t) total > F_number_t_size_unsigned_d) {
-      set->status = F_status_set_error(F_too_large);
-
-      kt_tacocat_print_error_on_file_too_large(&main->program.error, set->name, kt_tacocat_send_s, set->network, F_number_t_size_unsigned_d, set->abstruses.array[4].value.is.a_unsigned);
-
-      return;
-    }
-
-    error = gpgme_data_rewind(set->encrypt_read);
-
-    if (error != GPG_ERR_NO_ERROR) {
-      set->status = F_status_set_error(F_failure);
-
-      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_file_s, set->network, set->status, set->name);
 
       return;
     }
-
-    set->abstruses.array[3].value.is.a_unsigned = 0;
-    set->size_total = (f_number_unsigned_t) total;
-
-    if (total) {
-      if (set->size_total < set->file.size_read) {
-        set->abstruses.array[2].value.is.a_unsigned = set->size_total;
-        set->abstruses.array[4].value.is.a_unsigned = 1;
-      }
-      else {
-        set->abstruses.array[2].value.is.a_unsigned = set->file.size_read;
-        set->abstruses.array[4].value.is.a_unsigned = set->size_total / set->file.size_read;
-
-        if (set->abstruses.array[4].value.is.a_unsigned % set->file.size_read) {
-          ++set->abstruses.array[4].value.is.a_unsigned;
-        }
-      }
-    }
-    else {
-      set->abstruses.array[2].value.is.a_unsigned = set->size_total;
-      set->abstruses.array[4].value.is.a_unsigned = 1;
-    }
-  }
-#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_encrypt_size_)
-
-#if !defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_encrypt_size_)
-  void kt_tacocat_send_step_encrypt_size(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
-
-    set->status = F_status_set_error(F_implement_not);
-
-    // @todo replace this with an error on encryption unsupported.
-    kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name);
   }
 #endif // _di_kt_tacocat_send_step_encrypt_
 
index 670c59135342415bd4aebea057e9b8c75f129576..2e85626525ed5427a9012403ac1fede6fa480b98 100644 (file)
@@ -17,7 +17,7 @@ extern "C" {
 #endif
 
 /**
- * Perform the size step of a send request using encryption.
+ * Perform the encrypt step of a send request.
  *
  * This prints on error.
  *
@@ -35,24 +35,13 @@ extern "C" {
  *   This alters set.status:
  *     F_okay on success.
  *
- *     F_done (with error bit) on error that cannot continue, such as out of memory.
- *     F_too_large (with error bit) on file too large.
+ *     Errors (with error bit) from: gpgme_data_release()
  *
- *     Errors (with error bit) from: f_memory_array_increase_by()
- *
- *     Errors (with error bit) from: gpgme_data_new_from_fd()
- *     Errors (with error bit) from: gpgme_data_read()
- *     Errors (with error bit) from: gpgme_data_set_encoding()
- *
- * @see f_memory_array_increase_by()
- *
- * @see gpgme_data_new_from_fd()
- * @see gpgme_data_read()
- * @see gpgme_data_set_encoding()
+ * @see gpgme_data_release()
  */
-#ifndef _di_kt_tacocat_send_step_encrypt_size_
-  extern void kt_tacocat_send_step_encrypt_size(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
-#endif // _di_kt_tacocat_send_step_encrypt_size_
+#ifndef _di_kt_tacocat_send_step_encrypt_
+  extern void kt_tacocat_send_step_encrypt(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_encrypt_
 
 #ifdef __cplusplus
 } // extern "C"
index 3fa7ac920a27157330770699f4a67511f9fdf105..6efa4bcd7d393fcbf989927a36e6f6afa0a37368 100644 (file)
@@ -9,33 +9,40 @@ extern "C" {
 
     if (!main || !set || F_status_is_error(set->status)) return;
 
-    // @todo if (main->setting.flag & kt_tacocat_main_flag_encrypt_d) {
-
     set->status = f_string_dynamic_append(f_fss_payload_object_payload_s, &set->buffer);
 
     if (F_status_is_error_not(set->status)) {
       set->status = f_string_dynamic_append(f_fss_payload_object_end_s, &set->buffer);
     }
 
-    // Always reset the seek position in case a retry happened after the file block is read.
-    if (F_status_is_error_not(set->status)) {
-      off_t seeked = 0;
-
-      set->status = f_file_seek(set->file, SEEK_SET, set->size_done, &seeked);
+    if (main->setting.flag & kt_tacocat_main_flag_encrypt_d) {
+      #ifdef _en_gpgme_support_
+        kt_tacocat_send_step_gpgme_file(main, set);
+        if (F_status_is_error(set->status)) return;
+      #endif // _en_gpgme_support_
     }
+    else {
 
-    if (F_status_is_error_not(set->status)) {
-      set->status = f_file_read_block(set->file, &set->buffer);
-    }
+      // Always reset the seek position in case a retry happened after the file block is read.
+      if (F_status_is_error_not(set->status)) {
+        off_t seeked = 0;
 
-    if (F_status_is_error_not(set->status)) {
-      set->status = f_string_dynamic_terminate_after(&set->buffer);
-    }
+        set->status = f_file_seek(set->file, SEEK_SET, set->size_done, &seeked);
+      }
+
+      if (F_status_is_error_not(set->status)) {
+        set->status = f_file_read_block(set->file, &set->buffer);
+      }
+
+      if (F_status_is_error_not(set->status)) {
+        set->status = f_string_dynamic_terminate_after(&set->buffer);
+      }
 
-    if (F_status_is_error(set->status)) {
-      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_file_s, set->network, set->status, set->name);
+      if (F_status_is_error(set->status)) {
+        kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_file_s, set->network, set->status, set->name);
 
-      return;
+        return;
+      }
     }
 
     set->retry = 0;
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/done.c b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/done.c
new file mode 100644 (file)
index 0000000..d9bc73f
--- /dev/null
@@ -0,0 +1,22 @@
+#include "../../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_done_)
+  void kt_tacocat_send_step_gpgme_done(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    if (set->encrypt_read) {
+      gpgme_data_release(set->encrypt_read);
+
+      set->encrypt_read = 0;
+    }
+  }
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_done_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/done.h b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/done.h
new file mode 100644 (file)
index 0000000..0eac333
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send gpgme step done functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_gpgme_done_h
+#define _kt_tacocat_send_step_gpgme_done_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the done step of a send request using GPGME encryption.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: gpgme_data_release()
+ *
+ * @see gpgme_data_release()
+ */
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_done_)
+  extern void kt_tacocat_send_step_gpgme_done(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_done_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_gpgme_done_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/encrypt.c b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/encrypt.c
new file mode 100644 (file)
index 0000000..478bcde
--- /dev/null
@@ -0,0 +1,34 @@
+#include "../../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_encrypt_)
+  void kt_tacocat_send_step_gpgme_encrypt(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    // @todo
+    /*
+    gpgme_error_t error = gpgme_data_new(&cipher); // gpgme_data_t cipher;
+
+    gpgme_key_t recipient = 0;
+
+    error = gpgme_get_key(context, "FULL_KEY_HERE", &recipient, 0);
+
+    error = gpgme_op_encrypt(context, recipient, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher);
+
+    // gpgme_data_seek(cipher, 0, SEEK_SET);
+    // Then save it in buffer.
+
+    gpgme_key_unref(recipient);
+
+    gpgme_data_release(cipher);
+    */
+  }
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_encrypt_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/encrypt.h b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/encrypt.h
new file mode 100644 (file)
index 0000000..c45fa47
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send gpgme step encrypt functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_gpgme_encrypt_h
+#define _kt_tacocat_send_step_gpgme_encrypt_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the encryption step of a send request using GPGME encryption.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: gpgme_data_release()
+ *
+ * @see gpgme_data_release()
+ */
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_encrypt_)
+  extern void kt_tacocat_send_step_gpgme_encrypt(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_encrypt_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_gpgme_encrypt_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/file.c b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/file.c
new file mode 100644 (file)
index 0000000..7962c00
--- /dev/null
@@ -0,0 +1,58 @@
+#include "../../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_file_)
+  void kt_tacocat_send_step_gpgme_file(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    char buffer[set->file.size_read + 1];
+    buffer[set->file.size_read] = 0;
+
+    // Always reset the seek position in case a retry happened after the file block is read.
+    if (F_status_is_error_not(set->status)) {
+      const gpgme_off_t seeked = gpgme_data_seek(set->encrypt_read, set->size_done, 0);
+
+      if (seeked == -1) {
+        set->status = F_status_set_error(F_failure);
+
+        kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
+
+        return;
+      }
+    }
+
+    const gpgme_ssize_t bytes = gpgme_data_read(set->encrypt_read, buffer, set->file.size_read);
+
+    if (bytes == -1) {
+      set->status = F_status_set_error(F_failure);
+
+      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
+
+      return;
+    }
+
+    {
+      const f_string_static_t encrypted = macro_f_string_static_t_initialize_3(buffer, bytes);
+
+      set->status = f_string_dynamic_append(encrypted, &set->buffer);
+    }
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_string_dynamic_terminate_after(&set->buffer);
+    }
+
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_file_s, set->network, set->status, set->name);
+
+      return;
+    }
+  }
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_file_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/file.h b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/file.h
new file mode 100644 (file)
index 0000000..da69b3f
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send gpgme step file functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_gpgme_file_h
+#define _kt_tacocat_send_step_gpgme_file_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the file step of a send request using GPGME encryption.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     F_failure (with error bit) on any other error.
+ *
+ *     Errors (with error bit) from: f_string_dynamic_append()
+ *     Errors (with error bit) from: f_string_dynamic_terminate_after()
+ *
+ *     Errors (with error bit) from: gpgme_data_seek()
+ *     Errors (with error bit) from: gpgme_data_read()
+ *
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_terminate_after()
+ *
+ * @see gpgme_data_seek()
+ * @see gpgme_data_read()
+ */
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_file_)
+  extern void kt_tacocat_send_step_gpgme_file(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_file_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_gpgme_file_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/size.c b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/size.c
new file mode 100644 (file)
index 0000000..5cf1f47
--- /dev/null
@@ -0,0 +1,99 @@
+#include "../../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_size_)
+  void kt_tacocat_send_step_gpgme_size(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    if (set->encrypt_read) {
+      gpgme_data_release(set->encrypt_read);
+
+      set->encrypt_read = 0;
+    }
+
+    gpgme_error_t error = gpgme_data_new_from_fd(&set->encrypt_read, set->file.id);
+
+    if (error != GPG_ERR_NO_ERROR) {
+      set->status = F_status_set_error(F_memory);
+
+      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
+
+      return;
+    }
+
+    error = gpgme_data_set_encoding(set->encrypt_read, GPGME_DATA_ENCODING_ARMOR);
+
+    if (error != GPG_ERR_NO_ERROR) {
+      set->status = F_status_set_error(F_failure);
+
+      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
+
+      return;
+    }
+
+    // Total is used here to explicitly pass a pointer of off_t rather than a pointer of size_t cast to an off_t.
+    // GPGME provides no way to get the file size of the encrypted data, so load the file and determine the file size as it is loading.
+    off_t total = 0;
+    gpgme_ssize_t bytes = 1;
+
+    for (char buffer[set->file.size_read + 1]; bytes > 0 && total <= F_number_t_size_unsigned_d; total += bytes) {
+      bytes = gpgme_data_read(set->encrypt_read, buffer, set->file.size_read);
+    } // for
+
+    if (bytes == -1) {
+      set->status = F_status_set_error(F_failure);
+
+      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
+
+      return;
+    }
+
+    if ((f_number_unsigned_t) total > F_number_t_size_unsigned_d) {
+      set->status = F_status_set_error(F_too_large);
+
+      kt_tacocat_print_error_on_file_too_large(&main->program.error, set->name, kt_tacocat_send_s, set->network, F_number_t_size_unsigned_d, set->abstruses.array[4].value.is.a_unsigned);
+
+      return;
+    }
+
+    error = gpgme_data_rewind(set->encrypt_read);
+
+    if (error != GPG_ERR_NO_ERROR) {
+      set->status = F_status_set_error(F_failure);
+
+      kt_tacocat_print_error_on_file_send(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_read_s);
+
+      return;
+    }
+
+    set->abstruses.array[3].value.is.a_unsigned = 0;
+    set->size_total = (f_number_unsigned_t) total;
+
+    if (total) {
+      if (set->size_total < set->file.size_read) {
+        set->abstruses.array[2].value.is.a_unsigned = set->size_total;
+        set->abstruses.array[4].value.is.a_unsigned = 1;
+      }
+      else {
+        set->abstruses.array[2].value.is.a_unsigned = set->file.size_read;
+        set->abstruses.array[4].value.is.a_unsigned = set->size_total / set->file.size_read;
+
+        if (set->abstruses.array[4].value.is.a_unsigned % set->file.size_read) {
+          ++set->abstruses.array[4].value.is.a_unsigned;
+        }
+      }
+    }
+    else {
+      set->abstruses.array[2].value.is.a_unsigned = set->size_total;
+      set->abstruses.array[4].value.is.a_unsigned = 1;
+    }
+  }
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_size_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/size.h b/sources/c/program/kevux/tools/tacocat/main/send/step/gpgme/size.h
new file mode 100644 (file)
index 0000000..96f504f
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send gpgme step size functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_gpgme_size_h
+#define _kt_tacocat_send_step_gpgme_size_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the size step of a send request using GPGME encryption.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     F_done (with error bit) on error that cannot continue, such as out of memory.
+ *     F_memory (with error bit) on on out of memory.
+ *     F_too_large (with error bit) on file too large.
+ *
+ *     F_failure (with error bit) on any other error.
+ *
+ *     Errors (with error bit) from: f_memory_array_increase_by()
+ *
+ *     Errors (with error bit) from: gpgme_data_new_from_fd()
+ *     Errors (with error bit) from: gpgme_data_read()
+ *     Errors (with error bit) from: gpgme_data_set_encoding()
+ *
+ * @see f_memory_array_increase_by()
+ *
+ * @see gpgme_data_new_from_fd()
+ * @see gpgme_data_read()
+ * @see gpgme_data_set_encoding()
+ */
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_size_)
+  extern void kt_tacocat_send_step_gpgme_size(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_send_step_gpgme_size_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_gpgme_size_h
index 68c7fc2be0d15b22e6bce893491e38b4b36246fe..6479131a3108b621877e2369d6df1d953b4a22c4 100644 (file)
@@ -20,7 +20,10 @@ extern "C" {
     }
 
     if (main->setting.flag & kt_tacocat_main_flag_encrypt_d) {
-      kt_tacocat_send_step_encrypt_size(main, set);
+      #ifdef _en_gpgme_support_
+        kt_tacocat_send_step_gpgme_size(main, set);
+        if (F_status_is_error(set->status)) return;
+      #endif // _en_gpgme_support_
     } else {
 
       // Total is used here to explicitly pass a pointer of off_t rather than a pointer of size_t cast to an off_t.
index 2684a559532aa4ca95e3c39e2c734326035b8e72..ae715340bcb0d15b344b974514e5ca1d5c917041 100644 (file)
 #ifdef _en_gpgme_support_
   #include <program/kevux/tools/tacocat/main/gpgme.h>
   #include <program/kevux/tools/tacocat/main/print/gpgme.h>
+  #include <program/kevux/tools/tacocat/main/send/step/gpgme/done.h>
+  #include <program/kevux/tools/tacocat/main/send/step/gpgme/encrypt.h>
+  #include <program/kevux/tools/tacocat/main/send/step/gpgme/file.h>
+  #include <program/kevux/tools/tacocat/main/send/step/gpgme/size.h>
 #endif // _en_gpgme_support_
 
 #ifdef __cplusplus